Merge branch 'android-x86_64-fugu-3.10-nyc-mr1' into android-x86_64-fugu-3.10

September 2017.1

Bug: 63174165
Change-Id: Ie8d685edcbffbea72bcedcd02478b78017775b07
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 45f824c..d1fc6a4 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1159,11 +1159,20 @@
 	Functional default: enabled if accept_ra is enabled.
 			    disabled if accept_ra is disabled.
 
+accept_ra_rt_info_min_plen - INTEGER
+	Minimum prefix length of Route Information in RA.
+
+	Route Information w/ prefix smaller than this variable shall
+	be ignored.
+
+	Functional default: 0 if accept_ra_rtr_pref is enabled.
+			    -1 if accept_ra_rtr_pref is disabled.
+
 accept_ra_rt_info_max_plen - INTEGER
 	Maximum prefix length of Route Information in RA.
 
-	Route Information w/ prefix larger than or equal to this
-	variable shall be ignored.
+	Route Information w/ prefix larger than this variable shall
+	be ignored.
 
 	Functional default: 0 if accept_ra_rtr_pref is enabled.
 			    -1 if accept_ra_rtr_pref is disabled.
diff --git a/arch/x86/configs/fugu_defconfig b/arch/x86/configs/fugu_defconfig
index c5dc2333..acef58f 100644
--- a/arch/x86/configs/fugu_defconfig
+++ b/arch/x86/configs/fugu_defconfig
@@ -85,6 +85,8 @@
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
 CONFIG_NET_KEY=y
 CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
@@ -411,6 +413,7 @@
 CONFIG_SERIAL_MFD_HSU_EXT=y
 CONFIG_SERIAL_MFD_HSU_EXT_CONSOLE=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder"
 # CONFIG_DMIID is not set
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
@@ -423,11 +426,11 @@
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_SDCARD_FS=y
 CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_FILE_DIRECT=y
 CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
 CONFIG_SQUASHFS_XATTR=y
 # CONFIG_SQUASHFS_ZLIB is not set
 CONFIG_SQUASHFS_LZ4=y
+CONFIG_PSTORE_PMSG=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
@@ -467,6 +470,7 @@
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=32768
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_DISABLE=y
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index d050393..dcd2477 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -15,6 +15,7 @@
 #include <linux/random.h>
 #include <linux/uaccess.h>
 #include <linux/elf.h>
+#include <linux/security.h>
 
 #include <asm/ia32.h>
 #include <asm/syscalls.h>
@@ -120,13 +121,13 @@
 
 	find_start_end(flags, &begin, &end);
 
-	if (len > end)
+	if (len > end - mmap_min_addr)
 		return -ENOMEM;
 
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
-		if (end - len >= addr &&
+		if (end - len >= addr && addr >= mmap_min_addr &&
 		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
@@ -151,7 +152,7 @@
 	struct vm_unmapped_area_info info;
 
 	/* requested length too big for entire address space */
-	if (len > TASK_SIZE)
+	if (len > TASK_SIZE - mmap_min_addr)
 		return -ENOMEM;
 
 	if (flags & MAP_FIXED)
@@ -165,14 +166,14 @@
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
-		if (TASK_SIZE - len >= addr &&
+		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
 				(!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
 	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
 	info.length = len;
-	info.low_limit = PAGE_SIZE;
+	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
 	info.high_limit = mm->mmap_base;
 	info.align_mask = filp ? get_align_mask() : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
diff --git a/build.config b/build.config
index e1127ee..9dd4426 100644
--- a/build.config
+++ b/build.config
@@ -4,6 +4,7 @@
 DEFCONFIG=fugu_defconfig
 EXTRA_CMDS=''
 KERNEL_DIR=private/x86_64-asus
+POST_DEFCONFIG_CMDS="check_defconfig"
 LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8/bin
 FILES="
 arch/x86/boot/bzImage
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index bdfc6c6..a82fc02 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -19,6 +19,18 @@
 	  Android process, using Binder to identify, invoke and pass arguments
 	  between said processes.
 
+config ANDROID_BINDER_DEVICES
+	string "Android Binder devices"
+	depends on ANDROID_BINDER_IPC
+	default "binder"
+	---help---
+	  Default value for the binder.devices parameter.
+
+	  The binder.devices parameter is a comma-separated list of strings
+	  that specifies the names of the binder device nodes that will be
+	  created. Each binder device has its own context manager, and is
+	  therefore logically separated from the other devices.
+
 config ANDROID_BINDER_IPC_32BIT
 	bool
 	depends on !64BIT && ANDROID_BINDER_IPC
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 4f9b583..23d0e68 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -50,14 +50,13 @@
 static DEFINE_MUTEX(binder_deferred_lock);
 static DEFINE_MUTEX(binder_mmap_lock);
 
+static HLIST_HEAD(binder_devices);
 static HLIST_HEAD(binder_procs);
 static HLIST_HEAD(binder_deferred_list);
 static HLIST_HEAD(binder_dead_nodes);
 
 static struct dentry *binder_debugfs_dir_entry_root;
 static struct dentry *binder_debugfs_dir_entry_proc;
-static struct binder_node *binder_context_mgr_node;
-static kuid_t binder_context_mgr_uid = INVALID_UID;
 static int binder_last_id;
 static struct workqueue_struct *binder_deferred_workqueue;
 
@@ -116,6 +115,9 @@
 static bool binder_debug_no_lock;
 module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
 
+static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
+module_param_named(devices, binder_devices_param, charp, S_IRUGO);
+
 static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
 static int binder_stop_on_user_error;
 
@@ -146,6 +148,17 @@
 			binder_stop_on_user_error = 2; \
 	} while (0)
 
+#define to_flat_binder_object(hdr) \
+	container_of(hdr, struct flat_binder_object, hdr)
+
+#define to_binder_fd_object(hdr) container_of(hdr, struct binder_fd_object, hdr)
+
+#define to_binder_buffer_object(hdr) \
+	container_of(hdr, struct binder_buffer_object, hdr)
+
+#define to_binder_fd_array_object(hdr) \
+	container_of(hdr, struct binder_fd_array_object, hdr)
+
 enum binder_stat_types {
 	BINDER_STAT_PROC,
 	BINDER_STAT_THREAD,
@@ -159,7 +172,7 @@
 
 struct binder_stats {
 	int br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];
+	int bc[_IOC_NR(BC_REPLY_SG) + 1];
 	int obj_created[BINDER_STAT_COUNT];
 	int obj_deleted[BINDER_STAT_COUNT];
 };
@@ -187,6 +200,7 @@
 	int to_node;
 	int data_size;
 	int offsets_size;
+	const char *context_name;
 };
 struct binder_transaction_log {
 	int next;
@@ -211,6 +225,18 @@
 	return e;
 }
 
+struct binder_context {
+	struct binder_node *binder_context_mgr_node;
+	kuid_t binder_context_mgr_uid;
+	const char *name;
+};
+
+struct binder_device {
+	struct hlist_node hlist;
+	struct miscdevice miscdev;
+	struct binder_context context;
+};
+
 struct binder_work {
 	struct list_head entry;
 	enum {
@@ -283,6 +309,7 @@
 	struct binder_node *target_node;
 	size_t data_size;
 	size_t offsets_size;
+	size_t extra_buffers_size;
 	uint8_t data[0];
 };
 
@@ -326,6 +353,7 @@
 	int ready_threads;
 	long default_priority;
 	struct dentry *debugfs_entry;
+	struct binder_context *context;
 };
 
 enum {
@@ -722,7 +750,9 @@
 
 static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
 					      size_t data_size,
-					      size_t offsets_size, int is_async)
+					      size_t offsets_size,
+					      size_t extra_buffers_size,
+					      int is_async)
 {
 	struct rb_node *n = proc->free_buffers.rb_node;
 	struct binder_buffer *buffer;
@@ -730,7 +760,7 @@
 	struct rb_node *best_fit = NULL;
 	void *has_page_addr;
 	void *end_page_addr;
-	size_t size;
+	size_t size, data_offsets_size;
 
 	if (proc->vma == NULL) {
 		pr_err("%d: binder_alloc_buf, no vma\n",
@@ -738,15 +768,20 @@
 		return NULL;
 	}
 
-	size = ALIGN(data_size, sizeof(void *)) +
+	data_offsets_size = ALIGN(data_size, sizeof(void *)) +
 		ALIGN(offsets_size, sizeof(void *));
 
-	if (size < data_size || size < offsets_size) {
+	if (data_offsets_size < data_size || data_offsets_size < offsets_size) {
 		binder_user_error("%d: got transaction with invalid size %zd-%zd\n",
 				proc->pid, data_size, offsets_size);
 		return NULL;
 	}
-
+	size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *));
+	if (size < data_offsets_size || size < extra_buffers_size) {
+		binder_user_error("%d: got transaction with invalid extra_buffers_size %zd\n",
+				  proc->pid, extra_buffers_size);
+		return NULL;
+	}
 	if (is_async &&
 	    proc->free_async_space < size + sizeof(struct binder_buffer)) {
 		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
@@ -815,6 +850,7 @@
 		      proc->pid, size, buffer);
 	buffer->data_size = data_size;
 	buffer->offsets_size = offsets_size;
+	buffer->extra_buffers_size = extra_buffers_size;
 	buffer->async_transaction = is_async;
 	if (is_async) {
 		proc->free_async_space -= size + sizeof(struct binder_buffer);
@@ -889,7 +925,8 @@
 	buffer_size = binder_buffer_size(proc, buffer);
 
 	size = ALIGN(buffer->data_size, sizeof(void *)) +
-		ALIGN(buffer->offsets_size, sizeof(void *));
+		ALIGN(buffer->offsets_size, sizeof(void *)) +
+		ALIGN(buffer->extra_buffers_size, sizeof(void *));
 
 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
 		     "%d: binder_free_buf %pK size %zd buffer_size %zd\n",
@@ -1003,8 +1040,10 @@
 		if (internal) {
 			if (target_list == NULL &&
 			    node->internal_strong_refs == 0 &&
-			    !(node == binder_context_mgr_node &&
-			    node->has_strong_ref)) {
+			    !(node->proc &&
+			      node == node->proc->context->
+				      binder_context_mgr_node &&
+			      node->has_strong_ref)) {
 				pr_err("invalid inc strong node for %d\n",
 					node->debug_id);
 				return -EINVAL;
@@ -1105,6 +1144,7 @@
 	struct rb_node **p = &proc->refs_by_node.rb_node;
 	struct rb_node *parent = NULL;
 	struct binder_ref *ref, *new_ref;
+	struct binder_context *context = proc->context;
 
 	while (*p) {
 		parent = *p;
@@ -1127,7 +1167,7 @@
 	rb_link_node(&new_ref->rb_node_node, parent, p);
 	rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
 
-	new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
+	new_ref->desc = (node == context->binder_context_mgr_node) ? 0 : 1;
 	for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
 		ref = rb_entry(n, struct binder_ref, rb_node_desc);
 		if (ref->desc > new_ref->desc)
@@ -1317,11 +1357,158 @@
 	}
 }
 
+/**
+ * binder_validate_object() - checks for a valid metadata object in a buffer.
+ * @buffer:	binder_buffer that we're parsing.
+ * @offset:	offset in the buffer at which to validate an object.
+ *
+ * Return:	If there's a valid metadata object at @offset in @buffer, the
+ *		size of that object. Otherwise, it returns zero.
+ */
+static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
+{
+	/* Check if we can read a header first */
+	struct binder_object_header *hdr;
+	size_t object_size = 0;
+
+	if (offset > buffer->data_size - sizeof(*hdr) ||
+	    buffer->data_size < sizeof(*hdr) ||
+	    !IS_ALIGNED(offset, sizeof(u32)))
+		return 0;
+
+	/* Ok, now see if we can read a complete object. */
+	hdr = (struct binder_object_header *)(buffer->data + offset);
+	switch (hdr->type) {
+	case BINDER_TYPE_BINDER:
+	case BINDER_TYPE_WEAK_BINDER:
+	case BINDER_TYPE_HANDLE:
+	case BINDER_TYPE_WEAK_HANDLE:
+		object_size = sizeof(struct flat_binder_object);
+		break;
+	case BINDER_TYPE_FD:
+		object_size = sizeof(struct binder_fd_object);
+		break;
+	case BINDER_TYPE_PTR:
+		object_size = sizeof(struct binder_buffer_object);
+		break;
+	case BINDER_TYPE_FDA:
+		object_size = sizeof(struct binder_fd_array_object);
+		break;
+	default:
+		return 0;
+	}
+	if (offset <= buffer->data_size - object_size &&
+	    buffer->data_size >= object_size)
+		return object_size;
+	else
+		return 0;
+}
+
+/**
+ * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer.
+ * @b:		binder_buffer containing the object
+ * @index:	index in offset array at which the binder_buffer_object is
+ *		located
+ * @start:	points to the start of the offset array
+ * @num_valid:	the number of valid offsets in the offset array
+ *
+ * Return:	If @index is within the valid range of the offset array
+ *		described by @start and @num_valid, and if there's a valid
+ *		binder_buffer_object at the offset found in index @index
+ *		of the offset array, that object is returned. Otherwise,
+ *		%NULL is returned.
+ *		Note that the offset found in index @index itself is not
+ *		verified; this function assumes that @num_valid elements
+ *		from @start were previously verified to have valid offsets.
+ */
+static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer *b,
+							binder_size_t index,
+							binder_size_t *start,
+							binder_size_t num_valid)
+{
+	struct binder_buffer_object *buffer_obj;
+	binder_size_t *offp;
+
+	if (index >= num_valid)
+		return NULL;
+
+	offp = start + index;
+	buffer_obj = (struct binder_buffer_object *)(b->data + *offp);
+	if (buffer_obj->hdr.type != BINDER_TYPE_PTR)
+		return NULL;
+
+	return buffer_obj;
+}
+
+/**
+ * binder_validate_fixup() - validates pointer/fd fixups happen in order.
+ * @b:			transaction buffer
+ * @objects_start	start of objects buffer
+ * @buffer:		binder_buffer_object in which to fix up
+ * @offset:		start offset in @buffer to fix up
+ * @last_obj:		last binder_buffer_object that we fixed up in
+ * @last_min_offset:	minimum fixup offset in @last_obj
+ *
+ * Return:		%true if a fixup in buffer @buffer at offset @offset is
+ *			allowed.
+ *
+ * For safety reasons, we only allow fixups inside a buffer to happen
+ * at increasing offsets; additionally, we only allow fixup on the last
+ * buffer object that was verified, or one of its parents.
+ *
+ * Example of what is allowed:
+ *
+ * A
+ *   B (parent = A, offset = 0)
+ *   C (parent = A, offset = 16)
+ *     D (parent = C, offset = 0)
+ *   E (parent = A, offset = 32) // min_offset is 16 (C.parent_offset)
+ *
+ * Examples of what is not allowed:
+ *
+ * Decreasing offsets within the same parent:
+ * A
+ *   C (parent = A, offset = 16)
+ *   B (parent = A, offset = 0) // decreasing offset within A
+ *
+ * Referring to a parent that wasn't the last object or any of its parents:
+ * A
+ *   B (parent = A, offset = 0)
+ *   C (parent = A, offset = 0)
+ *   C (parent = A, offset = 16)
+ *     D (parent = B, offset = 0) // B is not A or any of A's parents
+ */
+static bool binder_validate_fixup(struct binder_buffer *b,
+				  binder_size_t *objects_start,
+				  struct binder_buffer_object *buffer,
+				  binder_size_t fixup_offset,
+				  struct binder_buffer_object *last_obj,
+				  binder_size_t last_min_offset)
+{
+	if (!last_obj) {
+		/* Nothing to fix up in */
+		return false;
+	}
+
+	while (last_obj != buffer) {
+		/*
+		 * Safe to retrieve the parent of last_obj, since it
+		 * was already previously verified by the driver.
+		 */
+		if ((last_obj->flags & BINDER_BUFFER_FLAG_HAS_PARENT) == 0)
+			return false;
+		last_min_offset = last_obj->parent_offset + sizeof(uintptr_t);
+		last_obj = (struct binder_buffer_object *)
+			(b->data + *(objects_start + last_obj->parent));
+	}
+	return (fixup_offset >= last_min_offset);
+}
+
 static void binder_transaction_buffer_release(struct binder_proc *proc,
 					      struct binder_buffer *buffer,
 					      binder_size_t *failed_at)
 {
-	binder_size_t *offp, *off_end;
+	binder_size_t *offp, *off_start, *off_end;
 	int debug_id = buffer->debug_id;
 
 	binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1332,28 +1519,30 @@
 	if (buffer->target_node)
 		binder_dec_node(buffer->target_node, 1, 0);
 
-	offp = (binder_size_t *)(buffer->data +
-				 ALIGN(buffer->data_size, sizeof(void *)));
+	off_start = (binder_size_t *)(buffer->data +
+				      ALIGN(buffer->data_size, sizeof(void *)));
 	if (failed_at)
 		off_end = failed_at;
 	else
-		off_end = (void *)offp + buffer->offsets_size;
-	for (; offp < off_end; offp++) {
-		struct flat_binder_object *fp;
+		off_end = (void *)off_start + buffer->offsets_size;
+	for (offp = off_start; offp < off_end; offp++) {
+		struct binder_object_header *hdr;
+		size_t object_size = binder_validate_object(buffer, *offp);
 
-		if (*offp > buffer->data_size - sizeof(*fp) ||
-		    buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			pr_err("transaction release %d bad offset %lld, size %zd\n",
+		if (object_size == 0) {
+			pr_err("transaction release %d bad object at offset %lld, size %zd\n",
 			       debug_id, (u64)*offp, buffer->data_size);
 			continue;
 		}
-		fp = (struct flat_binder_object *)(buffer->data + *offp);
-		switch (fp->type) {
+		hdr = (struct binder_object_header *)(buffer->data + *offp);
+		switch (hdr->type) {
 		case BINDER_TYPE_BINDER:
 		case BINDER_TYPE_WEAK_BINDER: {
-			struct binder_node *node = binder_get_node(proc, fp->binder);
+			struct flat_binder_object *fp;
+			struct binder_node *node;
 
+			fp = to_flat_binder_object(hdr);
+			node = binder_get_node(proc, fp->binder);
 			if (node == NULL) {
 				pr_err("transaction release %d bad node %016llx\n",
 				       debug_id, (u64)fp->binder);
@@ -1362,13 +1551,17 @@
 			binder_debug(BINDER_DEBUG_TRANSACTION,
 				     "        node %d u%016llx\n",
 				     node->debug_id, (u64)node->ptr);
-			binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
+			binder_dec_node(node, hdr->type == BINDER_TYPE_BINDER,
+					0);
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
-			struct binder_ref *ref = binder_get_ref(proc, fp->handle,
-						fp->type == BINDER_TYPE_HANDLE);
+			struct flat_binder_object *fp;
+			struct binder_ref *ref;
 
+			fp = to_flat_binder_object(hdr);
+			ref = binder_get_ref(proc, fp->handle,
+					     hdr->type == BINDER_TYPE_HANDLE);
 			if (ref == NULL) {
 				pr_err("transaction release %d bad handle %d\n",
 				 debug_id, fp->handle);
@@ -1377,32 +1570,348 @@
 			binder_debug(BINDER_DEBUG_TRANSACTION,
 				     "        ref %d desc %d (node %d)\n",
 				     ref->debug_id, ref->desc, ref->node->debug_id);
-			binder_dec_ref(&ref, fp->type == BINDER_TYPE_HANDLE);
+			binder_dec_ref(&ref, hdr->type == BINDER_TYPE_HANDLE);
 		} break;
 
-		case BINDER_TYPE_FD:
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %d\n", fp->handle);
-			if (failed_at)
-				task_close_fd(proc, fp->handle);
-			break;
+		case BINDER_TYPE_FD: {
+			struct binder_fd_object *fp = to_binder_fd_object(hdr);
 
+			binder_debug(BINDER_DEBUG_TRANSACTION,
+				     "        fd %d\n", fp->fd);
+			if (failed_at)
+				task_close_fd(proc, fp->fd);
+		} break;
+		case BINDER_TYPE_PTR:
+			/*
+			 * Nothing to do here, this will get cleaned up when the
+			 * transaction buffer gets freed
+			 */
+			break;
+		case BINDER_TYPE_FDA: {
+			struct binder_fd_array_object *fda;
+			struct binder_buffer_object *parent;
+			uintptr_t parent_buffer;
+			u32 *fd_array;
+			size_t fd_index;
+			binder_size_t fd_buf_size;
+
+			fda = to_binder_fd_array_object(hdr);
+			parent = binder_validate_ptr(buffer, fda->parent,
+						     off_start,
+						     offp - off_start);
+			if (!parent) {
+				pr_err("transaction release %d bad parent offset",
+				       debug_id);
+				continue;
+			}
+			/*
+			 * Since the parent was already fixed up, convert it
+			 * back to kernel address space to access it
+			 */
+			parent_buffer = parent->buffer -
+				proc->user_buffer_offset;
+
+			fd_buf_size = sizeof(u32) * fda->num_fds;
+			if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
+				pr_err("transaction release %d invalid number of fds (%lld)\n",
+				       debug_id, (u64)fda->num_fds);
+				continue;
+			}
+			if (fd_buf_size > parent->length ||
+			    fda->parent_offset > parent->length - fd_buf_size) {
+				/* No space for all file descriptors here. */
+				pr_err("transaction release %d not enough space for %lld fds in buffer\n",
+				       debug_id, (u64)fda->num_fds);
+				continue;
+			}
+			fd_array = (u32 *)(parent_buffer + fda->parent_offset);
+			for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
+				task_close_fd(proc, fd_array[fd_index]);
+		} break;
 		default:
 			pr_err("transaction release %d bad object type %x\n",
-				debug_id, fp->type);
+				debug_id, hdr->type);
 			break;
 		}
 	}
 }
 
+static int binder_translate_binder(struct flat_binder_object *fp,
+				   struct binder_transaction *t,
+				   struct binder_thread *thread)
+{
+	struct binder_node *node;
+	struct binder_ref *ref;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+
+	node = binder_get_node(proc, fp->binder);
+	if (!node) {
+		node = binder_new_node(proc, fp->binder, fp->cookie);
+		if (!node)
+			return -ENOMEM;
+
+		node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+		node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+	}
+	if (fp->cookie != node->cookie) {
+		binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
+				  proc->pid, thread->pid, (u64)fp->binder,
+				  node->debug_id, (u64)fp->cookie,
+				  (u64)node->cookie);
+		return -EINVAL;
+	}
+	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
+		return -EPERM;
+
+	ref = binder_get_ref_for_node(target_proc, node);
+	if (!ref)
+		return -EINVAL;
+
+	if (fp->hdr.type == BINDER_TYPE_BINDER)
+		fp->hdr.type = BINDER_TYPE_HANDLE;
+	else
+		fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
+	fp->binder = 0;
+	fp->handle = ref->desc;
+	fp->cookie = 0;
+	binder_inc_ref(ref, fp->hdr.type == BINDER_TYPE_HANDLE, &thread->todo);
+
+	trace_binder_transaction_node_to_ref(t, node, ref);
+	binder_debug(BINDER_DEBUG_TRANSACTION,
+		     "        node %d u%016llx -> ref %d desc %d\n",
+		     node->debug_id, (u64)node->ptr,
+		     ref->debug_id, ref->desc);
+
+	return 0;
+}
+
+static int binder_translate_handle(struct flat_binder_object *fp,
+				   struct binder_transaction *t,
+				   struct binder_thread *thread)
+{
+	struct binder_ref *ref;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+
+	ref = binder_get_ref(proc, fp->handle,
+			     fp->hdr.type == BINDER_TYPE_HANDLE);
+	if (!ref) {
+		binder_user_error("%d:%d got transaction with invalid handle, %d\n",
+				  proc->pid, thread->pid, fp->handle);
+		return -EINVAL;
+	}
+	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
+		return -EPERM;
+
+	if (ref->node->proc == target_proc) {
+		if (fp->hdr.type == BINDER_TYPE_HANDLE)
+			fp->hdr.type = BINDER_TYPE_BINDER;
+		else
+			fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
+		fp->binder = ref->node->ptr;
+		fp->cookie = ref->node->cookie;
+		binder_inc_node(ref->node, fp->hdr.type == BINDER_TYPE_BINDER,
+				0, NULL);
+		trace_binder_transaction_ref_to_node(t, ref);
+		binder_debug(BINDER_DEBUG_TRANSACTION,
+			     "        ref %d desc %d -> node %d u%016llx\n",
+			     ref->debug_id, ref->desc, ref->node->debug_id,
+			     (u64)ref->node->ptr);
+	} else {
+		struct binder_ref *new_ref;
+
+		new_ref = binder_get_ref_for_node(target_proc, ref->node);
+		if (!new_ref)
+			return -EINVAL;
+
+		fp->binder = 0;
+		fp->handle = new_ref->desc;
+		fp->cookie = 0;
+		binder_inc_ref(new_ref, fp->hdr.type == BINDER_TYPE_HANDLE,
+			       NULL);
+		trace_binder_transaction_ref_to_ref(t, ref, new_ref);
+		binder_debug(BINDER_DEBUG_TRANSACTION,
+			     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
+			     ref->debug_id, ref->desc, new_ref->debug_id,
+			     new_ref->desc, ref->node->debug_id);
+	}
+	return 0;
+}
+
+static int binder_translate_fd(int fd,
+			       struct binder_transaction *t,
+			       struct binder_thread *thread,
+			       struct binder_transaction *in_reply_to)
+{
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+	int target_fd;
+	struct file *file;
+	int ret;
+	bool target_allows_fd;
+
+	if (in_reply_to)
+		target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS);
+	else
+		target_allows_fd = t->buffer->target_node->accept_fds;
+	if (!target_allows_fd) {
+		binder_user_error("%d:%d got %s with fd, %d, but target does not allow fds\n",
+				  proc->pid, thread->pid,
+				  in_reply_to ? "reply" : "transaction",
+				  fd);
+		ret = -EPERM;
+		goto err_fd_not_accepted;
+	}
+
+	file = fget(fd);
+	if (!file) {
+		binder_user_error("%d:%d got transaction with invalid fd, %d\n",
+				  proc->pid, thread->pid, fd);
+		ret = -EBADF;
+		goto err_fget;
+	}
+	ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
+	if (ret < 0) {
+		ret = -EPERM;
+		goto err_security;
+	}
+
+	target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+	if (target_fd < 0) {
+		ret = -ENOMEM;
+		goto err_get_unused_fd;
+	}
+	task_fd_install(target_proc, target_fd, file);
+	trace_binder_transaction_fd(t, fd, target_fd);
+	binder_debug(BINDER_DEBUG_TRANSACTION, "        fd %d -> %d\n",
+		     fd, target_fd);
+
+	return target_fd;
+
+err_get_unused_fd:
+err_security:
+	fput(file);
+err_fget:
+err_fd_not_accepted:
+	return ret;
+}
+
+static int binder_translate_fd_array(struct binder_fd_array_object *fda,
+				     struct binder_buffer_object *parent,
+				     struct binder_transaction *t,
+				     struct binder_thread *thread,
+				     struct binder_transaction *in_reply_to)
+{
+	binder_size_t fdi, fd_buf_size, num_installed_fds;
+	int target_fd;
+	uintptr_t parent_buffer;
+	u32 *fd_array;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+
+	fd_buf_size = sizeof(u32) * fda->num_fds;
+	if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
+		binder_user_error("%d:%d got transaction with invalid number of fds (%lld)\n",
+				  proc->pid, thread->pid, (u64)fda->num_fds);
+		return -EINVAL;
+	}
+	if (fd_buf_size > parent->length ||
+	    fda->parent_offset > parent->length - fd_buf_size) {
+		/* No space for all file descriptors here. */
+		binder_user_error("%d:%d not enough space to store %lld fds in buffer\n",
+				  proc->pid, thread->pid, (u64)fda->num_fds);
+		return -EINVAL;
+	}
+	/*
+	 * Since the parent was already fixed up, convert it
+	 * back to the kernel address space to access it
+	 */
+	parent_buffer = parent->buffer - target_proc->user_buffer_offset;
+	fd_array = (u32 *)(parent_buffer + fda->parent_offset);
+	if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
+		binder_user_error("%d:%d parent offset not aligned correctly.\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+	for (fdi = 0; fdi < fda->num_fds; fdi++) {
+		target_fd = binder_translate_fd(fd_array[fdi], t, thread,
+						in_reply_to);
+		if (target_fd < 0)
+			goto err_translate_fd_failed;
+		fd_array[fdi] = target_fd;
+	}
+	return 0;
+
+err_translate_fd_failed:
+	/*
+	 * Failed to allocate fd or security error, free fds
+	 * installed so far.
+	 */
+	num_installed_fds = fdi;
+	for (fdi = 0; fdi < num_installed_fds; fdi++)
+		task_close_fd(target_proc, fd_array[fdi]);
+	return target_fd;
+}
+
+static int binder_fixup_parent(struct binder_transaction *t,
+			       struct binder_thread *thread,
+			       struct binder_buffer_object *bp,
+			       binder_size_t *off_start,
+			       binder_size_t num_valid,
+			       struct binder_buffer_object *last_fixup_obj,
+			       binder_size_t last_fixup_min_off)
+{
+	struct binder_buffer_object *parent;
+	u8 *parent_buffer;
+	struct binder_buffer *b = t->buffer;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+
+	if (!(bp->flags & BINDER_BUFFER_FLAG_HAS_PARENT))
+		return 0;
+
+	parent = binder_validate_ptr(b, bp->parent, off_start, num_valid);
+	if (!parent) {
+		binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+
+	if (!binder_validate_fixup(b, off_start,
+				   parent, bp->parent_offset,
+				   last_fixup_obj,
+				   last_fixup_min_off)) {
+		binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+
+	if (parent->length < sizeof(binder_uintptr_t) ||
+	    bp->parent_offset > parent->length - sizeof(binder_uintptr_t)) {
+		/* No space for a pointer here! */
+		binder_user_error("%d:%d got transaction with invalid parent offset\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+	parent_buffer = (u8 *)(parent->buffer -
+			       target_proc->user_buffer_offset);
+	*(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer;
+
+	return 0;
+}
+
 static void binder_transaction(struct binder_proc *proc,
 			       struct binder_thread *thread,
-			       struct binder_transaction_data *tr, int reply)
+			       struct binder_transaction_data *tr, int reply,
+			       binder_size_t extra_buffers_size)
 {
+	int ret;
 	struct binder_transaction *t;
 	struct binder_work *tcomplete;
-	binder_size_t *offp, *off_end;
+	binder_size_t *offp, *off_end, *off_start;
 	binder_size_t off_min;
+	u8 *sg_bufp, *sg_buf_end;
 	struct binder_proc *target_proc;
 	struct binder_thread *target_thread = NULL;
 	struct binder_node *target_node = NULL;
@@ -1411,6 +1920,9 @@
 	struct binder_transaction *in_reply_to = NULL;
 	struct binder_transaction_log_entry *e;
 	uint32_t return_error;
+	struct binder_buffer_object *last_fixup_obj = NULL;
+	binder_size_t last_fixup_min_off = 0;
+	struct binder_context *context = proc->context;
 
 	e = binder_transaction_log_add(&binder_transaction_log);
 	e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
@@ -1419,6 +1931,7 @@
 	e->target_handle = tr->target.handle;
 	e->data_size = tr->data_size;
 	e->offsets_size = tr->offsets_size;
+	e->context_name = proc->context->name;
 
 	if (reply) {
 		in_reply_to = thread->transaction_stack;
@@ -1471,7 +1984,7 @@
 			}
 			target_node = ref->node;
 		} else {
-			target_node = binder_context_mgr_node;
+			target_node = context->binder_context_mgr_node;
 			if (target_node == NULL) {
 				return_error = BR_DEAD_REPLY;
 				goto err_no_context_mgr_node;
@@ -1537,20 +2050,22 @@
 
 	if (reply)
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n",
+			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_thread->pid,
 			     (u64)tr->data.ptr.buffer,
 			     (u64)tr->data.ptr.offsets,
-			     (u64)tr->data_size, (u64)tr->offsets_size);
+			     (u64)tr->data_size, (u64)tr->offsets_size,
+			     (u64)extra_buffers_size);
 	else
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n",
+			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_node->debug_id,
 			     (u64)tr->data.ptr.buffer,
 			     (u64)tr->data.ptr.offsets,
-			     (u64)tr->data_size, (u64)tr->offsets_size);
+			     (u64)tr->data_size, (u64)tr->offsets_size,
+			     (u64)extra_buffers_size);
 
 	if (!reply && !(tr->flags & TF_ONE_WAY))
 		t->from = thread;
@@ -1566,7 +2081,8 @@
 	trace_binder_transaction(reply, t, target_node);
 
 	t->buffer = binder_alloc_buf(target_proc, tr->data_size,
-		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
+		tr->offsets_size, extra_buffers_size,
+		!reply && (t->flags & TF_ONE_WAY));
 	if (t->buffer == NULL) {
 		return_error = BR_FAILED_REPLY;
 		goto err_binder_alloc_buf_failed;
@@ -1579,8 +2095,9 @@
 	if (target_node)
 		binder_inc_node(target_node, 1, 0, NULL);
 
-	offp = (binder_size_t *)(t->buffer->data +
-				 ALIGN(tr->data_size, sizeof(void *)));
+	off_start = (binder_size_t *)(t->buffer->data +
+				      ALIGN(tr->data_size, sizeof(void *)));
+	offp = off_start;
 
 	if (copy_from_user_preempt_disabled(t->buffer->data, (const void __user *)(uintptr_t)
 			   tr->data.ptr.buffer, tr->data_size)) {
@@ -1602,171 +2119,139 @@
 		return_error = BR_FAILED_REPLY;
 		goto err_bad_offset;
 	}
-	off_end = (void *)offp + tr->offsets_size;
+	if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) {
+		binder_user_error("%d:%d got transaction with unaligned buffers size, %lld\n",
+				  proc->pid, thread->pid,
+				  extra_buffers_size);
+		return_error = BR_FAILED_REPLY;
+		goto err_bad_offset;
+	}
+	off_end = (void *)off_start + tr->offsets_size;
+	sg_bufp = (u8 *)(PTR_ALIGN(off_end, sizeof(void *)));
+	sg_buf_end = sg_bufp + extra_buffers_size;
 	off_min = 0;
 	for (; offp < off_end; offp++) {
-		struct flat_binder_object *fp;
+		struct binder_object_header *hdr;
+		size_t object_size = binder_validate_object(t->buffer, *offp);
 
-		if (*offp > t->buffer->data_size - sizeof(*fp) ||
-		    *offp < off_min ||
-		    t->buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			binder_user_error("%d:%d got transaction with invalid offset, %lld (min %lld, max %lld)\n",
+		if (object_size == 0 || *offp < off_min) {
+			binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
 					  proc->pid, thread->pid, (u64)*offp,
 					  (u64)off_min,
-					  (u64)(t->buffer->data_size -
-					  sizeof(*fp)));
+					  (u64)t->buffer->data_size);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_offset;
 		}
-		fp = (struct flat_binder_object *)(t->buffer->data + *offp);
-		off_min = *offp + sizeof(struct flat_binder_object);
-		switch (fp->type) {
+
+		hdr = (struct binder_object_header *)(t->buffer->data + *offp);
+		off_min = *offp + object_size;
+		switch (hdr->type) {
 		case BINDER_TYPE_BINDER:
 		case BINDER_TYPE_WEAK_BINDER: {
-			struct binder_ref *ref;
-			struct binder_node *node = binder_get_node(proc, fp->binder);
+			struct flat_binder_object *fp;
 
-			if (node == NULL) {
-				node = binder_new_node(proc, fp->binder, fp->cookie);
-				if (node == NULL) {
-					return_error = BR_FAILED_REPLY;
-					goto err_binder_new_node_failed;
-				}
-				node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
-				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
-			}
-			if (fp->cookie != node->cookie) {
-				binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
-					proc->pid, thread->pid,
-					(u64)fp->binder, node->debug_id,
-					(u64)fp->cookie, (u64)node->cookie);
+			fp = to_flat_binder_object(hdr);
+			ret = binder_translate_binder(fp, t, thread);
+			if (ret < 0) {
 				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
+				goto err_translate_failed;
 			}
-			if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
-			}
-			ref = binder_get_ref_for_node(target_proc, node);
-			if (ref == NULL) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
-			}
-			if (fp->type == BINDER_TYPE_BINDER)
-				fp->type = BINDER_TYPE_HANDLE;
-			else
-				fp->type = BINDER_TYPE_WEAK_HANDLE;
-			fp->binder = 0;
-			fp->handle = ref->desc;
-			fp->cookie = 0;
-			binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
-				       &thread->todo);
-
-			trace_binder_transaction_node_to_ref(t, node, ref);
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%016llx -> ref %d desc %d\n",
-				     node->debug_id, (u64)node->ptr,
-				     ref->debug_id, ref->desc);
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
-			struct binder_ref *ref = binder_get_ref(proc, fp->handle,
-						fp->type == BINDER_TYPE_HANDLE);
+			struct flat_binder_object *fp;
 
-			if (ref == NULL) {
-				binder_user_error("%d:%d got transaction with invalid handle, %d\n",
-						proc->pid,
-						thread->pid, fp->handle);
+			fp = to_flat_binder_object(hdr);
+			ret = binder_translate_handle(fp, t, thread);
+			if (ret < 0) {
 				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_failed;
-			}
-			if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_failed;
-			}
-			if (ref->node->proc == target_proc) {
-				if (fp->type == BINDER_TYPE_HANDLE)
-					fp->type = BINDER_TYPE_BINDER;
-				else
-					fp->type = BINDER_TYPE_WEAK_BINDER;
-				fp->binder = ref->node->ptr;
-				fp->cookie = ref->node->cookie;
-				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
-				trace_binder_transaction_ref_to_node(t, ref);
-				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> node %d u%016llx\n",
-					     ref->debug_id, ref->desc, ref->node->debug_id,
-					     (u64)ref->node->ptr);
-			} else {
-				struct binder_ref *new_ref;
-
-				new_ref = binder_get_ref_for_node(target_proc, ref->node);
-				if (new_ref == NULL) {
-					return_error = BR_FAILED_REPLY;
-					goto err_binder_get_ref_for_node_failed;
-				}
-				fp->binder = 0;
-				fp->handle = new_ref->desc;
-				fp->cookie = 0;
-				binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
-				trace_binder_transaction_ref_to_ref(t, ref,
-								    new_ref);
-				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
-					     ref->debug_id, ref->desc, new_ref->debug_id,
-					     new_ref->desc, ref->node->debug_id);
+				goto err_translate_failed;
 			}
 		} break;
 
 		case BINDER_TYPE_FD: {
-			int target_fd;
-			struct file *file;
+			struct binder_fd_object *fp = to_binder_fd_object(hdr);
+			int target_fd = binder_translate_fd(fp->fd, t, thread,
+							    in_reply_to);
 
-			if (reply) {
-				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
-					binder_user_error("%d:%d got reply with fd, %d, but target does not allow fds\n",
-						proc->pid, thread->pid, fp->handle);
-					return_error = BR_FAILED_REPLY;
-					goto err_fd_not_allowed;
-				}
-			} else if (!target_node->accept_fds) {
-				binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fds\n",
-					proc->pid, thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_fd_not_allowed;
-			}
-
-			file = fget(fp->handle);
-			if (file == NULL) {
-				binder_user_error("%d:%d got transaction with invalid fd, %d\n",
-					proc->pid, thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_fget_failed;
-			}
-			if (security_binder_transfer_file(proc->tsk, target_proc->tsk, file) < 0) {
-				fput(file);
-				return_error = BR_FAILED_REPLY;
-				goto err_get_unused_fd_failed;
-			}
-			target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
 			if (target_fd < 0) {
-				fput(file);
 				return_error = BR_FAILED_REPLY;
-				goto err_get_unused_fd_failed;
+				goto err_translate_failed;
 			}
-			task_fd_install(target_proc, target_fd, file);
-			trace_binder_transaction_fd(t, fp->handle, target_fd);
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %d -> %d\n", fp->handle, target_fd);
-			/* TODO: fput? */
-			fp->binder = 0;
-			fp->handle = target_fd;
+			fp->pad_binder = 0;
+			fp->fd = target_fd;
 		} break;
+		case BINDER_TYPE_FDA: {
+			struct binder_fd_array_object *fda =
+				to_binder_fd_array_object(hdr);
+			struct binder_buffer_object *parent =
+				binder_validate_ptr(t->buffer, fda->parent,
+						    off_start,
+						    offp - off_start);
+			if (!parent) {
+				binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				goto err_bad_parent;
+			}
+			if (!binder_validate_fixup(t->buffer, off_start,
+						   parent, fda->parent_offset,
+						   last_fixup_obj,
+						   last_fixup_min_off)) {
+				binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				goto err_bad_parent;
+			}
+			ret = binder_translate_fd_array(fda, parent, t, thread,
+							in_reply_to);
+			if (ret < 0) {
+				return_error = BR_FAILED_REPLY;
+				goto err_translate_failed;
+			}
+			last_fixup_obj = parent;
+			last_fixup_min_off =
+				fda->parent_offset + sizeof(u32) * fda->num_fds;
+		} break;
+		case BINDER_TYPE_PTR: {
+			struct binder_buffer_object *bp =
+				to_binder_buffer_object(hdr);
+			size_t buf_left = sg_buf_end - sg_bufp;
 
+			if (bp->length > buf_left) {
+				binder_user_error("%d:%d got transaction with too large buffer\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				goto err_bad_offset;
+			}
+			if (copy_from_user_preempt_disabled(
+					sg_bufp,
+					(const void __user *)(uintptr_t)
+					bp->buffer, bp->length)) {
+				binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				goto err_copy_data_failed;
+			}
+			/* Fixup buffer pointer to target proc address space */
+			bp->buffer = (uintptr_t)sg_bufp +
+				target_proc->user_buffer_offset;
+			sg_bufp += ALIGN(bp->length, sizeof(u64));
+
+			ret = binder_fixup_parent(t, thread, bp, off_start,
+						  offp - off_start,
+						  last_fixup_obj,
+						  last_fixup_min_off);
+			if (ret < 0) {
+				return_error = BR_FAILED_REPLY;
+				goto err_translate_failed;
+			}
+			last_fixup_obj = bp;
+			last_fixup_min_off = 0;
+		} break;
 		default:
 			binder_user_error("%d:%d got transaction with invalid object type, %x\n",
-				proc->pid, thread->pid, fp->type);
+				proc->pid, thread->pid, hdr->type);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_object_type;
 		}
@@ -1804,14 +2289,10 @@
 	}
 	return;
 
-err_get_unused_fd_failed:
-err_fget_failed:
-err_fd_not_allowed:
-err_binder_get_ref_for_node_failed:
-err_binder_get_ref_failed:
-err_binder_new_node_failed:
+err_translate_failed:
 err_bad_object_type:
 err_bad_offset:
+err_bad_parent:
 err_copy_data_failed:
 	trace_binder_transaction_failed_buffer_release(t->buffer);
 	binder_transaction_buffer_release(target_proc, t->buffer, offp);
@@ -1855,6 +2336,7 @@
 			binder_size_t *consumed)
 {
 	uint32_t cmd;
+	struct binder_context *context = proc->context;
 	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
@@ -1881,10 +2363,10 @@
 			if (get_user_preempt_disabled(target, (uint32_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(uint32_t);
-			if (target == 0 && binder_context_mgr_node &&
+			if (target == 0 && context->binder_context_mgr_node &&
 			    (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
 				ref = binder_get_ref_for_node(proc,
-					       binder_context_mgr_node);
+					context->binder_context_mgr_node);
 				if (ref->desc != target) {
 					binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
 						proc->pid, thread->pid,
@@ -2036,6 +2518,18 @@
 			break;
 		}
 
+		case BC_TRANSACTION_SG:
+		case BC_REPLY_SG: {
+			struct binder_transaction_data_sg tr;
+
+			if (copy_from_user_preempt_disabled(&tr, ptr,
+							    sizeof(tr)))
+				return -EFAULT;
+			ptr += sizeof(tr);
+			binder_transaction(proc, thread, &tr.transaction_data,
+					   cmd == BC_REPLY_SG, tr.buffers_size);
+			break;
+		}
 		case BC_TRANSACTION:
 		case BC_REPLY: {
 			struct binder_transaction_data tr;
@@ -2043,7 +2537,8 @@
 			if (copy_from_user_preempt_disabled(&tr, ptr, sizeof(tr)))
 				return -EFAULT;
 			ptr += sizeof(tr);
-			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
+			binder_transaction(proc, thread, &tr,
+					   cmd == BC_REPLY, 0);
 			break;
 		}
 
@@ -2798,9 +3293,11 @@
 {
 	int ret = 0;
 	struct binder_proc *proc = filp->private_data;
+	struct binder_context *context = proc->context;
+
 	kuid_t curr_euid = current_euid();
 
-	if (binder_context_mgr_node != NULL) {
+	if (context->binder_context_mgr_node) {
 		pr_err("BINDER_SET_CONTEXT_MGR already set\n");
 		ret = -EBUSY;
 		goto out;
@@ -2808,27 +3305,27 @@
 	ret = security_binder_set_context_mgr(proc->tsk);
 	if (ret < 0)
 		goto out;
-	if (uid_valid(binder_context_mgr_uid)) {
-		if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
+	if (uid_valid(context->binder_context_mgr_uid)) {
+		if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
 			pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
 			       from_kuid(&init_user_ns, curr_euid),
 			       from_kuid(&init_user_ns,
-					binder_context_mgr_uid));
+					 context->binder_context_mgr_uid));
 			ret = -EPERM;
 			goto out;
 		}
 	} else {
-		binder_context_mgr_uid = curr_euid;
+		context->binder_context_mgr_uid = curr_euid;
 	}
-	binder_context_mgr_node = binder_new_node(proc, 0, 0);
-	if (binder_context_mgr_node == NULL) {
+	context->binder_context_mgr_node = binder_new_node(proc, 0, 0);
+	if (!context->binder_context_mgr_node) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	binder_context_mgr_node->local_weak_refs++;
-	binder_context_mgr_node->local_strong_refs++;
-	binder_context_mgr_node->has_strong_ref = 1;
-	binder_context_mgr_node->has_weak_ref = 1;
+	context->binder_context_mgr_node->local_weak_refs++;
+	context->binder_context_mgr_node->local_strong_refs++;
+	context->binder_context_mgr_node->has_strong_ref = 1;
+	context->binder_context_mgr_node->has_weak_ref = 1;
 out:
 	return ret;
 }
@@ -2956,7 +3453,7 @@
 	const char *failure_string;
 	struct binder_buffer *buffer;
 
-	if (proc->tsk != current)
+	if (proc->tsk != current->group_leader)
 		return -EINVAL;
 
 	if ((vma->vm_end - vma->vm_start) > SZ_4M)
@@ -3054,6 +3551,7 @@
 static int binder_open(struct inode *nodp, struct file *filp)
 {
 	struct binder_proc *proc;
+	struct binder_device *binder_dev;
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
 		     current->group_leader->pid, current->pid);
@@ -3061,11 +3559,14 @@
 	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
 	if (proc == NULL)
 		return -ENOMEM;
-	get_task_struct(current);
-	proc->tsk = current;
+	get_task_struct(current->group_leader);
+	proc->tsk = current->group_leader;
 	INIT_LIST_HEAD(&proc->todo);
 	init_waitqueue_head(&proc->wait);
 	proc->default_priority = task_nice(current);
+	binder_dev = container_of(filp->private_data, struct binder_device,
+				  miscdev);
+	proc->context = &binder_dev->context;
 
 	binder_lock(__func__);
 
@@ -3081,8 +3582,17 @@
 		char strbuf[11];
 
 		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+		/*
+		 * proc debug entries are shared between contexts, so
+		 * this will fail if the process tries to open the driver
+		 * again with a different context. The priting code will
+		 * anyway print all contexts that a given PID has, so this
+		 * is not a problem.
+		 */
 		proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
-			binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
+			binder_debugfs_dir_entry_proc,
+			(void *)(unsigned long)proc->pid,
+			&binder_proc_fops);
 	}
 
 	return 0;
@@ -3175,6 +3685,7 @@
 static void binder_deferred_release(struct binder_proc *proc)
 {
 	struct binder_transaction *t;
+	struct binder_context *context = proc->context;
 	struct rb_node *n;
 	int threads, nodes, incoming_refs, outgoing_refs, buffers,
 		active_transactions, page_count;
@@ -3184,11 +3695,12 @@
 
 	hlist_del(&proc->proc_node);
 
-	if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
+	if (context->binder_context_mgr_node &&
+	    context->binder_context_mgr_node->proc == proc) {
 		binder_debug(BINDER_DEBUG_DEAD_BINDER,
 			     "%s: %d context_mgr_node gone\n",
 			     __func__, proc->pid);
-		binder_context_mgr_node = NULL;
+		context->binder_context_mgr_node = NULL;
 	}
 
 	threads = 0;
@@ -3481,6 +3993,7 @@
 	size_t header_pos;
 
 	seq_printf(m, "proc %d\n", proc->pid);
+	seq_printf(m, "context %s\n", proc->context->name);
 	header_pos = m->count;
 
 	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
@@ -3550,7 +4063,9 @@
 	"BC_EXIT_LOOPER",
 	"BC_REQUEST_DEATH_NOTIFICATION",
 	"BC_CLEAR_DEATH_NOTIFICATION",
-	"BC_DEAD_BINDER_DONE"
+	"BC_DEAD_BINDER_DONE",
+	"BC_TRANSACTION_SG",
+	"BC_REPLY_SG",
 };
 
 static const char * const binder_objstat_strings[] = {
@@ -3605,6 +4120,7 @@
 	int count, strong, weak;
 
 	seq_printf(m, "proc %d\n", proc->pid);
+	seq_printf(m, "context %s\n", proc->context->name);
 	count = 0;
 	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
 		count++;
@@ -3712,23 +4228,18 @@
 static int binder_proc_show(struct seq_file *m, void *unused)
 {
 	struct binder_proc *itr;
-	struct binder_proc *proc = m->private;
+	int pid = (unsigned long)m->private;
 	int do_lock = !binder_debug_no_lock;
-	bool valid_proc = false;
 
 	if (do_lock)
 		binder_lock(__func__);
 
 	hlist_for_each_entry(itr, &binder_procs, proc_node) {
-		if (itr == proc) {
-			valid_proc = true;
-			break;
+		if (itr->pid == pid) {
+			seq_puts(m, "binder proc state:\n");
+			print_binder_proc(m, itr, 1);
 		}
 	}
-	if (valid_proc) {
-		seq_puts(m, "binder proc state:\n");
-		print_binder_proc(m, proc, 1);
-	}
 	if (do_lock)
 		binder_unlock(__func__);
 	return 0;
@@ -3738,11 +4249,11 @@
 					struct binder_transaction_log_entry *e)
 {
 	seq_printf(m,
-		   "%d: %s from %d:%d to %d:%d node %d handle %d size %d:%d\n",
+		   "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d\n",
 		   e->debug_id, (e->call_type == 2) ? "reply" :
 		   ((e->call_type == 1) ? "async" : "call "), e->from_proc,
-		   e->from_thread, e->to_proc, e->to_thread, e->to_node,
-		   e->target_handle, e->data_size, e->offsets_size);
+		   e->from_thread, e->to_proc, e->to_thread, e->context_name,
+		   e->to_node, e->target_handle, e->data_size, e->offsets_size);
 }
 
 static int binder_transaction_log_show(struct seq_file *m, void *unused)
@@ -3770,20 +4281,44 @@
 	.release = binder_release,
 };
 
-static struct miscdevice binder_miscdev = {
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "binder",
-	.fops = &binder_fops
-};
-
 BINDER_DEBUG_ENTRY(state);
 BINDER_DEBUG_ENTRY(stats);
 BINDER_DEBUG_ENTRY(transactions);
 BINDER_DEBUG_ENTRY(transaction_log);
 
+static int __init init_binder_device(const char *name)
+{
+	int ret;
+	struct binder_device *binder_device;
+
+	binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
+	if (!binder_device)
+		return -ENOMEM;
+
+	binder_device->miscdev.fops = &binder_fops;
+	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
+	binder_device->miscdev.name = name;
+
+	binder_device->context.binder_context_mgr_uid = INVALID_UID;
+	binder_device->context.name = name;
+
+	ret = misc_register(&binder_device->miscdev);
+	if (ret < 0) {
+		kfree(binder_device);
+		return ret;
+	}
+
+	hlist_add_head(&binder_device->hlist, &binder_devices);
+
+	return ret;
+}
+
 static int __init binder_init(void)
 {
 	int ret;
+	char *device_name, *device_names;
+	struct binder_device *device;
+	struct hlist_node *tmp;
 
 	binder_deferred_workqueue = create_singlethread_workqueue("binder");
 	if (!binder_deferred_workqueue)
@@ -3793,7 +4328,7 @@
 	if (binder_debugfs_dir_entry_root)
 		binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
 						 binder_debugfs_dir_entry_root);
-	ret = misc_register(&binder_miscdev);
+
 	if (binder_debugfs_dir_entry_root) {
 		debugfs_create_file("state",
 				    S_IRUGO,
@@ -3821,6 +4356,37 @@
 				    &binder_transaction_log_failed,
 				    &binder_transaction_log_fops);
 	}
+
+	/*
+	 * Copy the module_parameter string, because we don't want to
+	 * tokenize it in-place.
+	 */
+	device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
+	if (!device_names) {
+		ret = -ENOMEM;
+		goto err_alloc_device_names_failed;
+	}
+	strcpy(device_names, binder_devices_param);
+
+	while ((device_name = strsep(&device_names, ","))) {
+		ret = init_binder_device(device_name);
+		if (ret)
+			goto err_init_binder_device_failed;
+	}
+
+	return ret;
+
+err_init_binder_device_failed:
+	hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
+		misc_deregister(&device->miscdev);
+		hlist_del(&device->hlist);
+		kfree(device);
+	}
+err_alloc_device_names_failed:
+	debugfs_remove_recursive(binder_debugfs_dir_entry_root);
+
+	destroy_workqueue(binder_deferred_workqueue);
+
 	return ret;
 }
 
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 1c6fca2..1602a79 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -411,6 +411,18 @@
 	{             -1,   -1,   -1,  -1},
 };
 
+static struct em28xx_reg_seq pctv_292e[] = {
+	{EM2874_R80_GPIO,         0xff, 0xff,      0},
+	{0x0d,                    0xff, 0xff,    950},
+	{EM2874_R80_GPIO,         0xbd, 0xff,    100},
+	{EM2874_R80_GPIO,         0xfd, 0xff,    410},
+	{EM2874_R80_GPIO,         0x7d, 0xff,    300},
+	{EM2874_R80_GPIO,         0x7c, 0xff,     60},
+	{0x0d,                    0x42, 0xff,     50},
+	{EM2874_R5F_TS_ENABLE,    0x85, 0xff,      0},
+	{                  -1,      -1,   -1,     -1},
+};
+
 /* 2040:0265 Hauppauge WinTV-dualHD DVB
  * reg 0x80/0x84:
  * GPIO_0: Yellow LED tuner 1, 0=on, 1=off
@@ -2038,6 +2050,18 @@
 		.i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
+	/* 2013:025f PCTV tripleStick (292e).
+	 * 2040:0264 Hauppauge WinTV-SoloHD Isoc, 2040:8264 Bulk
+	 * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157 */
+	[EM28178_BOARD_PCTV_292E] = {
+		.name          = "PCTV tripleStick (292e)",
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+		.tuner_type    = TUNER_ABSENT,
+		.tuner_gpio    = pctv_292e,
+		.has_dvb       = 1,
+		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+	},
 	/* 2040:0265 Hauppauge WinTV-dualHD (DVB version).
 	 * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157 */
 	[EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = {
@@ -2223,6 +2247,12 @@
 			.driver_info = EM2884_BOARD_PCTV_510E },
 	{ USB_DEVICE(0x2013, 0x0251),
 			.driver_info = EM2884_BOARD_PCTV_520E },
+	{ USB_DEVICE(0x2013, 0x025f),
+			.driver_info = EM28178_BOARD_PCTV_292E },
+	{ USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD Isoc */
+			.driver_info = EM28178_BOARD_PCTV_292E },
+	{ USB_DEVICE(0x2040, 0x8264), /* Hauppauge WinTV-soloHD Bulk */
+			.driver_info = EM28178_BOARD_PCTV_292E },
 	{ USB_DEVICE(0x2040, 0x0265), /* ISOC */
 			.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
 	{ USB_DEVICE(0x2040, 0x8265), /* BULK */
@@ -2999,6 +3029,12 @@
 			dev->wait_after_write = 0;
 			dev->eeprom_addrwidth_16bit = 1;
 			break;
+		case CHIP_ID_EM28178:
+			chip_name = "em28178";
+			dev->reg_gpio_num = EM2874_R80_GPIO;
+			dev->wait_after_write = 0;
+			dev->eeprom_addrwidth_16bit = 1;
+			break;
 		case CHIP_ID_EM2883:
 			chip_name = "em2882/3";
 			dev->wait_after_write = 0;
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 14bceea..09a6472 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -526,7 +526,8 @@
 	u32 vid;
 
 	if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874
-		|| dev->chip_id == CHIP_ID_EM28174) {
+		|| dev->chip_id == CHIP_ID_EM28174
+		|| dev->chip_id == CHIP_ID_EM28178) {
 		/* Digital only device - don't load any alsa module */
 		dev->audio_mode.has_audio = false;
 		dev->has_audio_class = false;
@@ -647,9 +648,10 @@
 {
 	int rc;
 
-	if (dev->chip_id == CHIP_ID_EM2874 ||
-	    dev->chip_id == CHIP_ID_EM2884 ||
-	    dev->chip_id == CHIP_ID_EM28174) {
+	if (dev->chip_id == CHIP_ID_EM2874  ||
+	    dev->chip_id == CHIP_ID_EM2884  ||
+	    dev->chip_id == CHIP_ID_EM28174 ||
+	    dev->chip_id == CHIP_ID_EM28178) {
 		/* The Transport Stream Enable Register moved in em2874 */
 		if(dev->dvb_xfer_bulk) {
 			/* TS1 Maximum Transfer Size = 188 * EM28XX_DVB_BULK_PACKET_MULTIPLIER */
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index d9706b5..c9a73f5 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -706,6 +706,20 @@
 #endif
 }
 
+static int em28xx_pctv_292e_set_lna(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct em28xx *dev = fe->dvb->priv;
+	u8 lna;
+
+	if (c->lna == 1)
+		lna = 0x01;
+	else
+		lna = 0x00;
+
+	return em28xx_write_reg_bits(dev, EM2874_R80_GPIO, lna, 0x01);
+}
+
 static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
 {
 	/* Values extracted from a USB trace of the Terratec Windows driver */
@@ -1326,6 +1340,67 @@
 			goto out_free;
 		}
 		break;
+	case EM28178_BOARD_PCTV_292E:
+		{
+			struct i2c_adapter *adapter;
+			struct i2c_client *client;
+			struct i2c_board_info info;
+			struct si2168_config si2168_config;
+			struct si2157_config si2157_config;
+
+			/* attach demod */
+			memset(&si2168_config, 0, sizeof(si2168_config));
+			si2168_config.i2c_adapter = &adapter;
+			si2168_config.fe = &dvb->fe[0];
+			si2168_config.ts_mode = SI2168_TS_PARALLEL;
+			memset(&info, 0, sizeof(struct i2c_board_info));
+			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+			info.addr = 0x64;
+			info.platform_data = &si2168_config;
+			request_module(info.type);
+			client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
+			if (client == NULL || client->dev.driver == NULL) {
+				result = -ENODEV;
+				goto out_free;
+			}
+
+			if (!try_module_get(client->dev.driver->owner)) {
+				i2c_unregister_device(client);
+				result = -ENODEV;
+				goto out_free;
+			}
+
+			dvb->i2c_client_demod = client;
+
+			/* attach tuner */
+			memset(&si2157_config, 0, sizeof(si2157_config));
+			si2157_config.fe = dvb->fe[0];
+			si2157_config.if_port = 1;
+			memset(&info, 0, sizeof(struct i2c_board_info));
+			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+			info.addr = 0x60;
+			info.platform_data = &si2157_config;
+			request_module(info.type);
+			client = i2c_new_device(adapter, &info);
+			if (client == NULL || client->dev.driver == NULL) {
+				module_put(dvb->i2c_client_demod->dev.driver->owner);
+				i2c_unregister_device(dvb->i2c_client_demod);
+				result = -ENODEV;
+				goto out_free;
+			}
+
+			if (!try_module_get(client->dev.driver->owner)) {
+				i2c_unregister_device(client);
+				module_put(dvb->i2c_client_demod->dev.driver->owner);
+				i2c_unregister_device(dvb->i2c_client_demod);
+				result = -ENODEV;
+				goto out_free;
+			}
+
+			dvb->i2c_client_tuner = client;
+			dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna;
+		}
+		break;
 	case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
 		{
 			struct i2c_adapter *adapter;
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index e16e2bc..d013490 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -443,6 +443,7 @@
 	case CHIP_ID_EM2884:
 	case CHIP_ID_EM2874:
 	case CHIP_ID_EM28174:
+	case CHIP_ID_EM28178:
 		return em2874_ir_change_protocol(rc_dev, rc_type);
 	default:
 		printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
@@ -634,6 +635,7 @@
 		case CHIP_ID_EM2884:
 		case CHIP_ID_EM2874:
 		case CHIP_ID_EM28174:
+		case CHIP_ID_EM28178:
 			ir->get_key = em2874_polling_getkey;
 			rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC |
 					     RC_BIT_RC6_0;
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 18e715d..04db2c4 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -242,6 +242,7 @@
 	CHIP_ID_EM2874 = 65,
 	CHIP_ID_EM2884 = 68,
 	CHIP_ID_EM28174 = 113,
+	CHIP_ID_EM28178 = 114,
 };
 
 /*
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index e9d7ece..c0ee29b 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -130,8 +130,9 @@
 #define EM2884_BOARD_PCTV_520E			  86
 #define EM2884_BOARD_TERRATEC_HTC_USB_XS	  87
 #define EM2884_BOARD_C3TECH_DIGITAL_DUO		  88
-#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB  89
-#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_ATSC 90
+#define EM28178_BOARD_PCTV_292E                   89
+#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB  90
+#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_ATSC 91
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index 4079316..aff0d9e 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -98,7 +98,6 @@
 DHDCFLAGS += -DWL_CFG80211_ACL
 DHDCFLAGS += -DDISABLE_11H_SOFTAP
 DHDCFLAGS += -DSET_RANDOM_MAC_SOFTAP
-DHDCFLAGS += -DCUSTOM_FORCE_NODFS_FLAG
 DHDCFLAGS += -DCUSTOM_SET_SHORT_DWELL_TIME
 
 ##########################
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
index b55cf8c..9bce123 100644
--- a/drivers/platform/x86/intel_scu_ipcutil.c
+++ b/drivers/platform/x86/intel_scu_ipcutil.c
@@ -36,6 +36,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/hardirq.h>
 
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
@@ -2961,6 +2962,11 @@
 
 	pr_debug("%s: Set kernel panic reason to OSNIB\n", __func__);
 
+	if (in_interrupt()) {
+		pr_err("Invoked in interrupt cxt\n");
+		goto out;
+	}
+
 	ret = intel_scu_ipc_read_osnib_wd(&wd);
 	if (ret) {
 		pr_err("Fail reading kernel panic bit\n");
diff --git a/drivers/staging/imgtec/adf/adf_ext.h b/drivers/staging/imgtec/adf/adf_ext.h
index 68e972f..49d82d2 100644
--- a/drivers/staging/imgtec/adf/adf_ext.h
+++ b/drivers/staging/imgtec/adf/adf_ext.h
@@ -90,18 +90,6 @@
 	struct adf_post_ext __user *post_ext;
 } __packed;
 
-/* These shouldn't be stripped by the uapi process in the bionic headers,
- * but currently are being. Redefine them so the custom ioctl interface is
- * actually useful. Fixed in Lollipop.
- */
-#ifndef ADF_IOCTL_TYPE
-#define ADF_IOCTL_TYPE 'D'
-#endif
-
-#ifndef ADF_IOCTL_NR_CUSTOM
-#define ADF_IOCTL_NR_CUSTOM 128
-#endif
-
 #define ADF_IOCTL_NR_VALIDATE_IMG (ADF_IOCTL_NR_CUSTOM + 0)
 
 #define ADF_VALIDATE_CONFIG_EXT \
diff --git a/drivers/staging/imgtec/adf_common.c b/drivers/staging/imgtec/adf_common.c
index 1f1f28f..8d04909 100644
--- a/drivers/staging/imgtec/adf_common.c
+++ b/drivers/staging/imgtec/adf_common.c
@@ -1,5 +1,8 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -38,7 +41,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #include "adf_common.h"
 
@@ -223,8 +225,7 @@
 {
 	int err;
 
-	if (!access_ok(VERIFY_READ, arg,
-	     sizeof(struct adf_validate_config_ext))) {
+	if (!access_ok(VERIFY_READ, arg, sizeof(*arg))) {
 		err = -EFAULT;
 		goto err_out;
 	}
@@ -264,8 +265,7 @@
 	BUILD_BUG_ON_MSG(sizeof(struct adf_validate_config_ext) != 32,
 		"adf_validate_config_ext has unexpected size");
 
-	if (!access_ok(VERIFY_READ, arg_compat,
-		sizeof(struct adf_validate_config_ext32))) {
+	if (!access_ok(VERIFY_READ, arg_compat, sizeof(*arg_compat))) {
 		err = -EFAULT;
 		goto err_out;
 	}
diff --git a/drivers/staging/imgtec/adf_common.h b/drivers/staging/imgtec/adf_common.h
index 5fddbc8..3c4e4e5 100644
--- a/drivers/staging/imgtec/adf_common.h
+++ b/drivers/staging/imgtec/adf_common.h
@@ -1,5 +1,8 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -38,7 +41,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #include <video/adf.h>
 #include <adf/adf_ext.h>
diff --git a/drivers/staging/imgtec/adf_fbdev.c b/drivers/staging/imgtec/adf_fbdev.c
index fc8799a..0434754 100644
--- a/drivers/staging/imgtec/adf_fbdev.c
+++ b/drivers/staging/imgtec/adf_fbdev.c
@@ -1,5 +1,8 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -38,7 +41,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #include <linux/version.h>
 #include <linux/console.h>
@@ -86,7 +88,6 @@
 
 struct adf_fbdev_dmabuf {
 	struct sg_table	sg_table;
-	unsigned long paddr;
 	size_t offset;
 	size_t length;
 	void *vaddr;
@@ -130,8 +131,10 @@
 	struct adf_fbdev_dmabuf *fbdev_dmabuf;
 	struct scatterlist *sg;
 	size_t unitary_size;
+	struct page *page;
+	u32 offset = 0;
 	int i, err;
-	u32 id = 0;
+	u32 id;
 
 	spin_lock(&interface->alloc_lock);
 
@@ -155,14 +158,12 @@
 	 */
 	BUG_ON((unitary_size % PAGE_SIZE) != 0);
 
-	fbdev_dmabuf = kmalloc(sizeof(struct adf_fbdev_dmabuf), GFP_KERNEL);
+	fbdev_dmabuf = kmalloc(sizeof(*fbdev_dmabuf), GFP_KERNEL);
 	if (!fbdev_dmabuf)
 		return ERR_PTR(-ENOMEM);
 
-	/* We only need one scatterlist entry per buffer because fbdev memory
-	 * is always physically contiguous.
-	 */
-	err = sg_alloc_table(&fbdev_dmabuf->sg_table, 1, GFP_KERNEL);
+	err = sg_alloc_table(&fbdev_dmabuf->sg_table, unitary_size / PAGE_SIZE,
+			     GFP_KERNEL);
 	if (err) {
 		kfree(fbdev_dmabuf);
 		return ERR_PTR(err);
@@ -182,20 +183,23 @@
 	fbdev_dmabuf->length = unitary_size;
 	fbdev_dmabuf->vaddr  = interface->fb_info->screen_base +
 			       fbdev_dmabuf->offset;
-	fbdev_dmabuf->paddr  = interface->fb_info->fix.smem_start +
-			       fbdev_dmabuf->offset;
 
-	sg_set_page(fbdev_dmabuf->sg_table.sgl,
-		    pfn_to_page(PFN_DOWN(fbdev_dmabuf->paddr)),
-		    fbdev_dmabuf->length, 0);
-
-	/* Shadow what ion is doing currently to ensure sg_dma_address() is
-	 * valid. This is not strictly correct as the dma address should
-	 * only be valid after mapping (ownership changed), and we haven't
-	 * mapped the scatter list yet.
-	 */
 	for_each_sg(fbdev_dmabuf->sg_table.sgl, sg,
 		    fbdev_dmabuf->sg_table.nents, i) {
+		page = vmalloc_to_page(fbdev_dmabuf->vaddr + offset);
+		if (!page) {
+			pr_err("Failed to map fbdev vaddr to pages\n");
+			kfree(fbdev_dmabuf);
+			return ERR_PTR(-EFAULT);
+		}
+		sg_set_page(sg, page, PAGE_SIZE, 0);
+		offset += PAGE_SIZE;
+
+		/* Shadow what ion is doing currently to ensure sg_dma_address()
+		 * is valid. This is not strictly correct as the dma address
+		 * should only be valid after mapping (ownership changed), and
+		 * we haven't mapped the scatter list yet.
+		 */
 		sg_dma_address(sg) = sg_phys(sg);
 	}
 
@@ -241,11 +245,39 @@
 static int adf_fbdev_d_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
 {
 	struct adf_fbdev_dmabuf *fbdev_dmabuf = dmabuf->priv;
+	unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+	unsigned long addr = vma->vm_start;
+	unsigned long remainder, len;
+	struct scatterlist *sg;
+	struct page *page;
+	u32 i;
 
-	return remap_pfn_range(vma, vma->vm_start,
-			       PFN_DOWN(fbdev_dmabuf->paddr),
-			       vma->vm_end - vma->vm_start,
-			       vma->vm_page_prot);
+	for_each_sg(fbdev_dmabuf->sg_table.sgl, sg,
+		    fbdev_dmabuf->sg_table.nents, i) {
+		page = sg_page(sg);
+		if (!page) {
+			pr_err("Failed to retrieve pages\n");
+			return -EFAULT;
+		}
+		remainder = vma->vm_end - addr;
+		len = sg_dma_len(sg);
+		if (offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			continue;
+		} else if (offset) {
+			page += offset / PAGE_SIZE;
+			len = sg_dma_len(sg) - offset;
+			offset = 0;
+		}
+		len = min(len, remainder);
+		remap_pfn_range(vma, addr, page_to_pfn(page), len,
+				vma->vm_page_prot);
+		addr += len;
+		if (addr >= vma->vm_end)
+			return 0;
+	}
+
+	return 0;
 }
 
 static void adf_fbdev_d_release(struct dma_buf *dmabuf)
@@ -253,6 +285,9 @@
 	adf_fbdev_free_buffer(dmabuf->priv);
 }
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) && \
+    !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
+
 static int
 adf_fbdev_d_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
 			     enum dma_data_direction dir)
@@ -270,6 +305,9 @@
 	/* Framebuffer memory is cache coherent. No-op. */
 }
 
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) &&
+          !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318) */
+
 static void *
 adf_fbdev_d_kmap(struct dma_buf *dmabuf, unsigned long page_offset)
 {
@@ -306,8 +344,11 @@
 	.unmap_dma_buf		= adf_fbdev_d_unmap_dma_buf,
 	.mmap			= adf_fbdev_d_mmap,
 	.release		= adf_fbdev_d_release,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) && \
+    !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
 	.begin_cpu_access	= adf_fbdev_d_begin_cpu_access,
 	.end_cpu_access		= adf_fbdev_d_end_cpu_access,
+#endif
 	.kmap_atomic		= adf_fbdev_d_kmap,
 	.kunmap_atomic		= adf_fbdev_d_kunmap,
 	.kmap			= adf_fbdev_d_kmap,
diff --git a/drivers/staging/imgtec/config_kernel.h b/drivers/staging/imgtec/config_kernel.h
index 6266eff..5d327d7 100644
--- a/drivers/staging/imgtec/config_kernel.h
+++ b/drivers/staging/imgtec/config_kernel.h
@@ -1,3 +1,4 @@
+#define RGX_FW_HEAP_SHIFT  25
 #define RGX_FW_FILENAME "rgx.fw.signed"
 #define LINUX 
 #define PVR_BUILD_DIR "intel_android"
@@ -9,49 +10,94 @@
 #define RELEASE 
 #define RGX_BVNC_CORE_KM_HEADER "cores/rgxcore_km_1.72.4.12.h"
 #define RGX_BNC_CONFIG_KM_HEADER "configs/rgxconfig_km_1.V.4.12.h"
+#define SUPPORT_MULTIBVNC_RUNTIME_BVNC_ACQUISITION 
 #define SUPPORT_DBGDRV_EVENT_OBJECTS 
 #define PDUMP_STREAMBUF_MAX_SIZE_MB 16
-#define SYS_USING_INTERRUPTS 
 #define PVRSRV_NEED_PVR_DPF 
+#define PVRSRV_NEED_PVR_STACKTRACE 
 #define SUPPORT_GPUTRACE_EVENTS 
 #define SUPPORT_DISPLAY_CLASS 
 #define GPUVIRT_VALIDATION_NUM_OS 8
-#define PVRSRV_GPUVIRT_NUM_OSID  2
-#define PVRSRV_GPUVIRT_OSID 0
-#define PVRSRV_GPUVIRT_OSID_STR ""
-#define PVRSRV_GPUVIRT_FWHEAP_SIZE  4194304
-#define PVRSRV_GPUVIRT_FWHEAP_BASE  0
+#define PVRSRV_GPUVIRT_NUM_OSID 2
+#define SUPPORT_VDM_CONTEXT_STORE_BUFFER_AB 
 #define SUPPORT_LINUX_X86_WRITECOMBINE 
 #define SUPPORT_LINUX_X86_PAT 
 #define PVR_LINUX_USING_WORKQUEUES 
 #define PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE 
 #define PVR_LINUX_TIMERS_USING_WORKQUEUES 
 #define PVR_LDM_DRIVER_REGISTRATION_NAME "pvrsrvkm"
-#define LDM_PCI 
 #define PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN 256
-#define SUPPORT_SYSTEM_INTERRUPT_HANDLING 
+#define SUPPORT_MMU_PENDING_FAULT_PROTECTION 
 #define PVR_DUMMY_PAGE_INIT_VALUE 0x00
+#define CACHEFLUSH_UM_TYPE CACHEFLUSH_UM_X86_ONLY
 #define PVRSRV_UNMAP_ON_SPARSE_CHANGE 
 #define SUPPORT_PERCONTEXT_FREELIST 
 #define HWR_DEFAULT_ENABLED 
-#define SUPPORT_POWMON_WO_GPIO_PIN 
+#define PVRSRV_APPHINT_HWRDEBUGDUMPLIMIT APPHNT_BLDVAR_DBGDUMPLIMIT
+#define PVRSRV_APPHINT_ENABLETRUSTEDDEVICEACECONFIG IMG_FALSE
+#define PVRSRV_APPHINT_HTBUFFERSIZE 0x1000
+#define PVRSRV_APPHINT_GENERAL_NON4K_HEAP_PAGE_SIZE 0x4000
+#define PVRSRV_APPHINT_ENABLESIGNATURECHECKS APPHNT_BLDVAR_ENABLESIGNATURECHECKS
+#define PVRSRV_APPHINT_SIGNATURECHECKSBUFSIZE RGXFW_SIG_BUFFER_SIZE_MIN
+#define PVRSRV_APPHINT_DISABLECLOCKGATING 0
+#define PVRSRV_APPHINT_DISABLEDMOVERLAP 0
+#define PVRSRV_APPHINT_ENABLECDMKILLINGRANDMODE 0
+#define PVRSRV_APPHINT_ENABLEFWCONTEXTSWITCH RGXFWIF_INICFG_CTXSWITCH_DM_ALL
+#define PVRSRV_APPHINT_ENABLERDPOWERISLAND RGX_RD_POWER_ISLAND_DEFAULT
+#define PVRSRV_APPHINT_FIRMWAREPERF FW_PERF_CONF_NONE
+#define PVRSRV_APPHINT_FWCONTEXTSWITCHPROFILE RGXFWIF_CTXSWITCH_PROFILE_MEDIUM_EN
+#define PVRSRV_APPHINT_HWPERFDISABLECUSTOMCOUNTERFILTER 0
+#define PVRSRV_APPHINT_HWPERFFWBUFSIZEINKB RGXFW_HWPERF_L1_SIZE_DEFAULT
+#define PVRSRV_APPHINT_HWPERFHOSTBUFSIZEINKB HWPERF_HOST_TL_STREAM_SIZE_DEFAULT
+#define PVRSRV_APPHINT_JONESDISABLEMASK 0
+#define PVRSRV_APPHINT_NEWFILTERINGMODE 1
+#define PVRSRV_APPHINT_TRUNCATEMODE 0
+#define PVRSRV_APPHINT_USEMETAT1 RGX_META_T1_OFF
+#define PVRSRV_APPHINT_RGXBVNC ""
+#define PVRSRV_APPHINT_ENABLETRUSTEDDEVICEACECONFIG IMG_FALSE
+#define PVRSRV_APPHINT_CLEANUPTHREADPRIORITY 0
+#define PVRSRV_APPHINT_CLEANUPTHREADWEIGHT 0
+#define PVRSRV_APPHINT_WATCHDOGTHREADPRIORITY 0
+#define PVRSRV_APPHINT_WATCHDOGTHREADWEIGHT 0
+#define PVRSRV_APPHINT_ASSERTONHWRTRIGGER IMG_FALSE
+#define PVRSRV_APPHINT_ASSERTOUTOFMEMORY IMG_FALSE
+#define PVRSRV_APPHINT_CHECKMLIST APPHNT_BLDVAR_DEBUG
+#define PVRSRV_APPHINT_DISABLEFEDLOGGING IMG_FALSE
+#define PVRSRV_APPHINT_ENABLEAPM RGX_ACTIVEPM_DEFAULT
+#define PVRSRV_APPHINT_ENABLEHTBLOGGROUP 0
+#define PVRSRV_APPHINT_ENABLELOGGROUP 0
+#define PVRSRV_APPHINT_FIRMWARELOGTYPE 0
+#define PVRSRV_APPHINT_HTBOPERATIONMODE HTB_OPMODE_DROPLATEST
+#define PVRSRV_APPHINT_HWPERFFWFILTER 0
+#define PVRSRV_APPHINT_HWPERFHOSTFILTER 0
+#define PVRSRV_APPHINT_TIMECORRCLOCK 2
+#define PVRSRV_APPHINT_ENABLEFWPOISONONFREE IMG_FALSE
+#define PVRSRV_APPHINT_FWPOISONONFREEVALUE 0xBD
+#define PVRSRV_APPHINT_ZEROFREELIST IMG_FALSE
+#define PVRSRV_APPHINT_DUSTREQUESTINJECT IMG_FALSE
+#define PVRSRV_APPHINT_DISABLEPDUMPPANIC IMG_FALSE
 #define PVRSRV_ENABLE_PROCESS_STATS 
 #define SUPPORT_SHARED_SLC 
+#define PVRSRV_ENABLE_CCCB_UTILISATION_INFO 
+#define PVRSRV_ENABLE_CCCB_UTILISATION_INFO_THRESHOLD 90
+#define PVRSRV_ENABLE_MEMTRACK_STATS_FILE 
 #define PVR_LINUX_PHYSMEM_MAX_POOL_PAGES 5120
 #define PVR_LINUX_PHYSMEM_MAX_EXCESS_POOL_PAGES 16384
 #define PVR_LINUX_PHYSMEM_ZERO_ALL_PAGES
+#define PVR_DIRTY_BYTES_FLUSH_THRESHOLD 1048576
 #define PVR_DIRTY_PAGECOUNT_FLUSH_THRESHOLD  256
 #define PVR_LINUX_HIGHORDER_ALLOCATION_THRESHOLD  256 
 #define PVR_LINUX_PHYSMEM_MAX_ALLOC_ORDER_NUM  2 
 #define PVR_LINUX_KMALLOC_ALLOCATION_THRESHOLD  16384 
 #define SUPPORT_KERNEL_SRVINIT 
+#define SUPPORT_NATIVE_FENCE_SYNC 
+#define PVR_DRM_NAME "pvr"
 #define DEVICE_MEMSETCPY_ALIGN_IN_BYTES 8
-#define SUPPORT_DRM 
 #define ANDROID 
 #define SUPPORT_ION 
-#define SUPPORT_NATIVE_FENCE_SYNC 
 #define PVR_ANDROID_ION_HEADER "../drivers/staging/android/ion/ion.h"
 #define PVR_ANDROID_ION_PRIV_HEADER "../drivers/staging/android/ion/ion_priv.h"
 #define PVR_ANDROID_ION_USE_SG_LENGTH 
 #define PVR_ANDROID_SYNC_HEADER "../drivers/staging/android/sync.h"
+#define SUPPORT_DRM 
 #define SUPPORT_DRM_EXT 
diff --git a/drivers/staging/imgtec/debugfs_dma_buf.c b/drivers/staging/imgtec/debugfs_dma_buf.c
index 74ef584..68360c1 100644
--- a/drivers/staging/imgtec/debugfs_dma_buf.c
+++ b/drivers/staging/imgtec/debugfs_dma_buf.c
@@ -1,5 +1,8 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File           debugfs_dma_buf.c
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -38,7 +41,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #include "debugfs_dma_buf.h"
 
@@ -47,6 +49,8 @@
 #include <linux/kernel.h>
 #include <linux/debugfs.h>
 
+#include "kernel_compatibility.h"
+
 static struct dentry *g_debugfs_dentry;
 static struct dma_buf *g_dma_buf;
 
@@ -56,6 +60,7 @@
 	size_t istart = *ppos / PAGE_SIZE, iend, i = istart;
 	ssize_t wb = 0, res = 0;
 	struct dma_buf *dma_buf = g_dma_buf;
+	int err;
 
 	if (!dma_buf)
 		goto err_out;
@@ -71,8 +76,7 @@
 	 * remaining dma buffer size or the available um buffer size. */
 	iend = istart + min((size_t)(dma_buf->size - *ppos), count) / PAGE_SIZE;
 
-	res = dma_buf_begin_cpu_access(dma_buf, istart * PAGE_SIZE,
-				       PAGE_ALIGN(count), DMA_FROM_DEVICE);
+	res = dma_buf_begin_cpu_access(dma_buf, DMA_FROM_DEVICE);
 	if (res)
 		goto err_put;
 
@@ -102,8 +106,9 @@
 	res = wb;
 
 err_access:
-	dma_buf_end_cpu_access(dma_buf, istart * PAGE_SIZE,
-			       PAGE_ALIGN(count), DMA_FROM_DEVICE);
+	do {
+		err = dma_buf_end_cpu_access(dma_buf, DMA_FROM_DEVICE);
+	} while (err == -EAGAIN || err == -EINTR);
 err_put:
 	dma_buf_put(dma_buf);
 err_out:
diff --git a/drivers/staging/imgtec/debugfs_dma_buf.h b/drivers/staging/imgtec/debugfs_dma_buf.h
index ab51269..55a163d 100644
--- a/drivers/staging/imgtec/debugfs_dma_buf.h
+++ b/drivers/staging/imgtec/debugfs_dma_buf.h
@@ -1,5 +1,8 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File           debugfs_dma_buf.h
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -38,7 +41,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #ifndef _DEBUGFS_DMA_BUF_H
 #define _DEBUGFS_DMA_BUF_H
diff --git a/drivers/staging/imgtec/intel/bufferclass_video.h b/drivers/staging/imgtec/intel/bufferclass_video.h
index ece1729..d196ee3 100644
--- a/drivers/staging/imgtec/intel/bufferclass_video.h
+++ b/drivers/staging/imgtec/intel/bufferclass_video.h
@@ -43,7 +43,8 @@
 
 #include "img_defs.h"
 #include "bufferclass_interface.h"
-#include "imgpixfmts_km.h"
+#include <powervr/imgpixfmts.h>
+#include <powervr/mem_types.h>
 
 #if defined(__cplusplus)
 extern "C"
@@ -156,12 +157,12 @@
 void BCFreeKernelMem(void *pvMem);
 
 BCE_ERROR BCAllocDiscontigMemory(unsigned long ulSize,
-				 BCE_HANDLE unref__ * phMemHandle,
+				 BCE_HANDLE __maybe_unused * phMemHandle,
 				 IMG_CPU_VIRTADDR * pLinAddr,
 				 IMG_SYS_PHYADDR ** ppPhysAddr);
 
 void BCFreeDiscontigMemory(unsigned long ulSize,
-			   BCE_HANDLE unref__ hMemHandle,
+			   BCE_HANDLE __maybe_unused hMemHandle,
 			   IMG_CPU_VIRTADDR LinAddr,
 			   IMG_SYS_PHYADDR * pPhysAddr);
 
diff --git a/drivers/staging/imgtec/intel/bufferclass_video_linux.c b/drivers/staging/imgtec/intel/bufferclass_video_linux.c
index e308909..6305d65 100644
--- a/drivers/staging/imgtec/intel/bufferclass_video_linux.c
+++ b/drivers/staging/imgtec/intel/bufferclass_video_linux.c
@@ -38,6 +38,7 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+#include <linux/compiler.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -83,16 +84,9 @@
 		*tfile,
 		uint32_t handle);
 
-MODULE_SUPPORTED_DEVICE(DEVNAME);
-
-#if defined(LDM_PLATFORM) || defined(LDM_PCI)
 static struct class *psPvrClass;
-#endif
-
 static int AssignedMajorNumber;
 
-#define unref__ __attribute__ ((unused))
-
 #if defined(LMA)
 #define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024)
 #define PVR_BUFFERCLASS_MEMSIZE      (4 * 1024 * 1024)
@@ -130,10 +124,7 @@
 BCVideoModInit(void)
 {
 	int i, j;
-	/*LDM_PCI is defined, while LDM_PLATFORM and LMA are not defined.*/
-#if defined(LDM_PLATFORM) || defined(LDM_PCI)
 	struct device *psDev;
-#endif
 
 #if defined(LMA)
 	struct pci_dev *psPCIDev;
@@ -160,7 +151,6 @@
 	       AssignedMajorNumber);
 #endif
 
-#if defined(LDM_PLATFORM) || defined(LDM_PCI)
 	psPvrClass = class_create(THIS_MODULE, "bc_video");
 	if (IS_ERR(psPvrClass)) {
 		printk(KERN_ERR DRVNAME
@@ -180,7 +170,6 @@
 		       PTR_ERR(psDev));
 		goto ExitDestroyClass;
 	}
-#endif
 
 #if defined(LMA)
 	g_ulMemBase =
@@ -215,10 +204,8 @@
 
 	return 0;
 
-#if defined(LDM_PLATFORM) || defined(LDM_PCI)
 ExitDestroyClass:
 	class_destroy(psPvrClass);
-#endif
 ExitUnregister:
 	unregister_chrdev(AssignedMajorNumber, DEVNAME);
 	//ExitDisable:
@@ -233,10 +220,9 @@
 BCVideoModCleanup(void)
 {
 	int i;
-#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
 	device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
 	class_destroy(psPvrClass);
-#endif
 
 	for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
 		if (BC_Video_Deinit(i) != BCE_OK) {
@@ -275,7 +261,7 @@
 
 BCE_ERROR
 BCAllocDiscontigMemory(unsigned long ulSize,
-		       BCE_HANDLE unref__ * phMemHandle,
+		       BCE_HANDLE __maybe_unused * phMemHandle,
 		       IMG_CPU_VIRTADDR * pLinAddr,
 		       IMG_SYS_PHYADDR ** ppPhysAddr)
 {
@@ -312,7 +298,7 @@
 
 void
 BCFreeDiscontigMemory(unsigned long ulSize,
-		      BCE_HANDLE unref__ hMemHandle,
+		      BCE_HANDLE __maybe_unused hMemHandle,
 		      IMG_CPU_VIRTADDR LinAddr, IMG_SYS_PHYADDR * pPhysAddr)
 {
 	kfree(pPhysAddr);
@@ -323,7 +309,7 @@
 
 BCE_ERROR
 BCAllocContigMemory(unsigned long ulSize,
-		    BCE_HANDLE unref__ * phMemHandle,
+		    BCE_HANDLE __maybe_unused * phMemHandle,
 		    IMG_CPU_VIRTADDR * pLinAddr, IMG_CPU_PHYADDR * pPhysAddr)
 {
 #if defined(LMA)
@@ -384,7 +370,7 @@
 
 void
 BCFreeContigMemory(unsigned long ulSize,
-		   BCE_HANDLE unref__ hMemHandle,
+		   BCE_HANDLE __maybe_unused hMemHandle,
 		   IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr)
 {
 #if defined(LMA)
@@ -434,7 +420,7 @@
 
 
 BCE_ERROR
-BCClosePVRServices(BCE_HANDLE unref__ hPVRServices)
+BCClosePVRServices(BCE_HANDLE __maybe_unused hPVRServices)
 {
 	return (BCE_OK);
 }
@@ -468,7 +454,6 @@
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	stride = p->stride;
@@ -544,7 +529,7 @@
 	if (id < 0 ||
 		id >= BC_VIDEO_DEVICE_MAX_ID ||
 	    bc_video_id_usage[id] != 1) {
-		return 0;;
+		return 0;
 	}
 	bc_video_id_usage[id] = 0;
 
@@ -619,7 +604,6 @@
 			return err;
 		}
 		return 0;
-		break;
 	}
 	case BC_Video_ioctl_get_buffer_index: {
 		int idx;
@@ -635,7 +619,6 @@
 		}
 		printk(KERN_ERR DRVNAME ": BCIOGET_BUFFERIDX- buffer not found\n");
 		return -EINVAL;
-		break;
 	}
 	case BC_Video_ioctl_request_buffers: {
 		bc_buf_params_t p;
@@ -648,7 +631,6 @@
 		}
 		psBridge->outputparam = id;
 		return BC_CreateBuffers(id, &p, IMG_FALSE);
-		break;
 	}
 	case BC_Video_ioctl_set_buffer_phyaddr: {
 		bc_buf_ptr_t p;
@@ -692,14 +674,12 @@
 		if (bo)
 			ttm_bo_unref(&bo);
 		return 0;
-		break;
 	}
 	case BC_Video_ioctl_release_buffer_device: {
 		bc_video_id_usage[id] = 0;
 
 		BCVideoDestroyBuffers(id);
 		return 0;
-		break;
 	}
 	case BC_Video_ioctl_alloc_buffer: {
 		bc_buf_ptr_t p;
@@ -765,7 +745,6 @@
 		psBridge->outputparam = (int)(uintptr_t) pvBuf;
 
 		return 0;
-		break;
 	}
 	case BC_Video_ioctl_free_buffer: {
 		bc_buf_ptr_t p;
@@ -780,7 +759,6 @@
 
 		vfree(devinfo->psSystemBuffer[p.index].sCPUVAddr);
 		return 0;
-		break;
 	}
 	case BC_Video_ioctl_get_buffer_handle: {
 		int idx;
@@ -825,7 +803,6 @@
 			return err;
 		}
 		return 0;
-		break;
 	}
 	case BC_Video_ioctl_get_buffer_index: {
 		int idx;
@@ -841,7 +818,6 @@
 		}
 		printk(KERN_ERR DRVNAME ": BCIOGET_BUFFERIDX- buffer not found\n");
 		return -EINVAL;
-		break;
 	}
 	case BC_Video_ioctl_request_buffers: {
 		bc_buf_params_t p;
@@ -851,11 +827,9 @@
 			return BC_CreateBuffers(id, &p, IMG_TRUE);
 		else
 			return BC_CreateBuffers(id, &p, IMG_FALSE);
-		break;
 	}
 	case BC_Video_ioctl_release_buffer_device: {
 		return BCVideoDestroyBuffers(id);
-		break;
 	}
 	case BC_Video_ioctl_set_buffer_phyaddr: {
 		bc_buf_ptr_t p;
@@ -915,7 +889,6 @@
 			kfree(ppsPages);
 		}
 		return 0;
-		break;
 	}
 	default:
 		return err;
@@ -939,7 +912,7 @@
 	IOCTL_DEF(DRM_IOCTL_BUFFER_CLASS_VIDEO, BCVideoBridge, DRM_AUTH)
 };
 
-static int bc_max_ioctl = DRM_ARRAY_SIZE(sBCdrmIoctls);
+static int bc_max_ioctl = ARRAY_SIZE(sBCdrmIoctls);
 
 void BCVideoQueryIoctls(struct drm_ioctl_desc *ioctls)
 {
diff --git a/drivers/staging/imgtec/intel/display/tng/drv/mrfld_display.c b/drivers/staging/imgtec/intel/display/tng/drv/mrfld_display.c
index c578f99..f6e37c0 100644
--- a/drivers/staging/imgtec/intel/display/tng/drv/mrfld_display.c
+++ b/drivers/staging/imgtec/intel/display/tng/drv/mrfld_display.c
@@ -312,6 +312,48 @@
 		return;
 #endif
 
+	if ((!psb_intel_crtc->in_mode_setting) && (pipe == 1) &&
+			dev_priv->psb_hotplug_state) {
+		if (mode == DRM_MODE_DPMS_OFF) {
+			flush_workqueue(dev_priv->power_wq);
+
+			DCLockMutex();
+			DC_MRFLD_onPowerOff(1);
+			/* give time to the last flip to take effective, if we
+			 * disable hardware too quickly, overlay hardware may
+			 * crash, causing pipe hang next time when we try to
+			 * use overlay
+			 */
+			msleep(50);
+
+			drm_handle_vblank(dev, 1);
+			/* Turn off vsync interrupt. */
+			drm_vblank_off(dev, 1);
+
+			/* Make the pending flip request as completed. */
+			DCUnAttachPipe(1);
+			DCUnLockMutex();
+
+			android_hdmi_suspend_display(dev);
+		} else {
+			android_hdmi_resume_display(dev);
+
+			/*
+			 * Devices connect status will be changed
+			 * when system suspend,re-detect once here.
+			 */
+			if (android_hdmi_is_connected(dev)) {
+				DCLockMutex();
+				DCAttachPipe(1);
+				DC_MRFLD_onPowerOn(1);
+				mid_hdmi_audio_resume(dev);
+				DCUnLockMutex();
+			}
+		}
+
+		return;
+	}
+
 	power_island = pipe_to_island(pipe);
 
 	if (!power_island_get(power_island))
@@ -477,6 +519,10 @@
 		   if it's on this pipe */
 		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
 
+		if (psb_intel_crtc->in_mode_setting && (pipe == 1) &&
+				!dev_priv->hdmi_first_boot)
+			android_hdmi_resume_display(dev);
+
 		break;
 	case DRM_MODE_DPMS_OFF:
 		DCLockMutex();
diff --git a/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c b/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c
index 9c1aaae..4f3e23a 100644
--- a/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c
+++ b/drivers/staging/imgtec/intel/display/tng/drv/ospm/video_ospm.c
@@ -160,7 +160,8 @@
 	struct drm_psb_private *dev_priv = psb_priv(dev);
 	struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
 
-	if (atomic_read(&msvdx_priv->vc1_workaround_ctx)) {
+	if (!(msvdx_priv->msvdx_ctx->ctx_type & VA_RT_FORMAT_PROTECTED) &&
+			atomic_read(&msvdx_priv->slc_workaround_ctx)) {
 		uint32_t reg, data;
 
 		/* soc.gfx_wrapper.gbypassenable_sw = 1 */
diff --git a/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_display.c b/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_display.c
index 265e62d..41506c5 100644
--- a/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_display.c
+++ b/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_display.c
@@ -183,13 +183,19 @@
 static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
 {
 	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+	psb_intel_crtc->in_mode_setting = true;
 	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
 static void psb_intel_crtc_commit(struct drm_crtc *crtc)
 {
 	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
 	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+	psb_intel_crtc->in_mode_setting = false;
 }
 
 void psb_intel_encoder_prepare(struct drm_encoder *encoder)
diff --git a/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_drv.h b/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_drv.h
index 173d2f6..b424166 100644
--- a/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_drv.h
+++ b/drivers/staging/imgtec/intel/display/tng/drv/psb_intel_drv.h
@@ -238,6 +238,7 @@
 	/* Saved Crtc HW states */
 	struct psb_intel_crtc_state *crtc_state;
 #endif
+	bool in_mode_setting;
 };
 
 #define to_psb_intel_crtc(x)	\
diff --git a/drivers/staging/imgtec/intel/display/tng/interface/drm_shared.h b/drivers/staging/imgtec/intel/display/tng/interface/drm_shared.h
index 6bbf686..612eced5 100644
--- a/drivers/staging/imgtec/intel/display/tng/interface/drm_shared.h
+++ b/drivers/staging/imgtec/intel/display/tng/interface/drm_shared.h
@@ -18,12 +18,12 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  **************************************************************************/
+#include <powervr/mem_types.h>
 #include <img_types.h>
 
 #ifndef _DRM_SHARED_H_
 #define _DRM_SHARED_H_
 
-
 /* Controlling the kernel modesetting buffers */
 
 #define DRM_PSB_KMS_OFF		0x00
diff --git a/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/dfrgx_utilstats.c b/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/dfrgx_utilstats.c
index 7eda403..2175007 100644
--- a/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/dfrgx_utilstats.c
+++ b/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/dfrgx_utilstats.c
@@ -35,9 +35,8 @@
 #include "osfunc.h"
 #include "rgxdebug.h"
 #include "dfrgx_utilstats.h"
-#include "pvr_tlcommon.h"
 #include "img_types.h"
-#include "pvrsrv.h"
+#include "pvrsrv_ext.h"
 #include "rgxdevice.h"
 #include "rgxinit.h"
 
diff --git a/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/rgxdf.c b/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/rgxdf.c
index d375fd4..c394d9d 100644
--- a/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/rgxdf.c
+++ b/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_devfreq/rgxdf.c
@@ -45,7 +45,7 @@
 #include "rgxdf.h"
 #include "device.h"
 #include "rgxdevice.h"
-#include "pvrsrv.h"
+#include "pvrsrv_ext.h"
 #include "rgx_fwif_km.h"
 #include "pdump_km.h"
 #include "osfunc.h"
@@ -56,6 +56,17 @@
 #include "rgxfwutils.h"
 #include "img_types.h"
 
+/* Between DDK 1.6 and 1.7 the Services API changed, to replace device
+ * indices with PVRSRV_DEVICE_NODE pointers. Define a helper macro to allow
+ * this code to work with both versions.
+ */
+#include "pvrversion.h"
+#if PVRVERSION_MAJ == 1 && PVRVERSION_MIN < 7
+# define DEVICE_NODE_OR_INDEX(psDeviceNode) ((psDeviceNode)->sDevId.ui32DeviceIndex)
+#else
+# define DEVICE_NODE_OR_INDEX(psDeviceNode) psDeviceNode
+#endif
+
 extern struct drm_device *gpsPVRDRMDev;
 
 static PVRSRV_DEVICE_NODE* pDevNode = NULL;
@@ -145,7 +156,7 @@
 	int isPowered = IMG_FALSE;
 
 	if(psDeviceNode)
-		isPowered = PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+		isPowered = PVRSRVIsDevicePowered(DEVICE_NODE_OR_INDEX(psDeviceNode));
 
 	return isPowered;
 }
@@ -180,7 +191,7 @@
 		goto out;
 	}
 
-	eError = PVRSRVDevicePreClockSpeedChange(psDeviceNode->sDevId.ui32DeviceIndex, IMG_FALSE, NULL);
+	eError = PVRSRVDevicePreClockSpeedChange(DEVICE_NODE_OR_INDEX(psDeviceNode), IMG_FALSE, NULL);
 out:
 	return eError;
 }
@@ -197,7 +208,7 @@
 	}
 
 
-	PVRSRVDevicePostClockSpeedChange(psDeviceNode->sDevId.ui32DeviceIndex, IMG_FALSE, NULL);
+	PVRSRVDevicePostClockSpeedChange(DEVICE_NODE_OR_INDEX(psDeviceNode), IMG_FALSE, NULL);
 
 out:
 	return eError;
diff --git a/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_drm/dc_mrfld.h b/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_drm/dc_mrfld.h
index 6f8cb41..4b20841 100644
--- a/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_drm/dc_mrfld.h
+++ b/drivers/staging/imgtec/intel/graphics/rgx/services/3rdparty/intel_drm/dc_mrfld.h
@@ -27,7 +27,8 @@
 #define __DC_MRFLD_H__
 
 #include <drm/drmP.h>
-#include <imgpixfmts_km.h>
+#include <powervr/mem_types.h>
+#include <powervr/imgpixfmts.h>
 #include "kerneldisplay.h"
 #include "psb_drm.h"
 #include "displayclass_interface.h"
diff --git a/drivers/staging/imgtec/intel/ion_support_intel.c b/drivers/staging/imgtec/intel/ion_support_intel.c
index 4742f6e..5967d0f 100644
--- a/drivers/staging/imgtec/intel/ion_support_intel.c
+++ b/drivers/staging/imgtec/intel/ion_support_intel.c
@@ -106,18 +106,13 @@
 	PVR_UNREFERENCED_PARAMETER(ulAlign);
 	PVR_UNREFERENCED_PARAMETER(ulFlags);
 
-	/* It's not really correct to hijack the PMR lock like this, but this
-	 * seems better than relying on the bridge lock since that could be
-	 * taken around a call to ion_alloc(). The PMR lock being held around
-	 * a call to ion_alloc() is much less likely.
-	 */
-	if (!PMRIsLockedByMe() || !gpsDCBufferPMR)
+	if (!gpsDCBufferPMR)
 	{
 		err = -ENOTTY;
 		goto err_out;
 	}
 
-	eError = PMRLockSysPhysAddresses(gpsDCBufferPMR, PAGE_SHIFT);
+	eError = PMRLockSysPhysAddresses(gpsDCBufferPMR);
 	if (eError != PVRSRV_OK)
 	{
 		err = -EFAULT;
@@ -327,7 +322,7 @@
 	IMG_DEVMEM_SIZE_T uSize;
 	struct file *psFile;
 	PVRSRV_ERROR eError;
-	DC_BUFFER *psBuffer;
+	DC_BUFFER *psBuffer = NULL;
 	int err = -EFAULT;
 
 	if (uiCmd != ION_IOC_ALLOC_FROM_DC_BUFFER)
@@ -358,11 +353,12 @@
 	eError = PVRSRVLookupHandle(psConnection->psHandleBase,
 								(void **)&psBuffer,
 								(IMG_HANDLE)sData.dc_buffer,
-								PVRSRV_HANDLE_TYPE_DC_BUFFER);
+								PVRSRV_HANDLE_TYPE_DC_BUFFER,
+								IMG_TRUE);
 	if (eError != PVRSRV_OK)
+	{
 		goto err_unlock;
-
-	PMRLock();
+	}
 
 	eError = DCBufferAcquire(psBuffer, &gpsDCBufferPMR);
 	if (eError != PVRSRV_OK)
@@ -393,9 +389,14 @@
 	err = 0;
 err_unlock_pmr:
 	DCBufferRelease(gpsDCBufferPMR);
-	PMRUnlock();
 	gpsDCBufferPMR = NULL;
 err_unlock:
+	if(psBuffer)
+	{
+		PVRSRVReleaseHandle(psConnection->psHandleBase,
+							(IMG_HANDLE)sData.dc_buffer,
+							PVRSRV_HANDLE_TYPE_DC_BUFFER);
+	}
 	OSReleaseBridgeLock();
 err_fput:
 	fput(psFile);
diff --git a/drivers/staging/imgtec/intel/otm_hdmi/os/android/android_hdmi.c b/drivers/staging/imgtec/intel/otm_hdmi/os/android/android_hdmi.c
index a688e19..d36c238 100644
--- a/drivers/staging/imgtec/intel/otm_hdmi/os/android/android_hdmi.c
+++ b/drivers/staging/imgtec/intel/otm_hdmi/os/android/android_hdmi.c
@@ -2586,12 +2586,10 @@
 
 void android_hdmi_connector_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_device *dev = connector->dev;
-	bool hdmi_audio_busy = false;
-	u32 dspcntr_val;
-	struct drm_psb_private *dev_priv = dev->dev_private;
 #if (defined CONFIG_PM_RUNTIME) && (!defined MERRIFIELD) \
 	&& (defined CONFIG_SUPPORT_MIPI)
+	struct drm_device *dev = connector->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	bool panel_on = false, panel_on2 = false;
 	struct mdfld_dsi_config **dsi_configs;
 #endif
@@ -2601,35 +2599,12 @@
 				OSPM_UHB_FORCE_POWER_ON))
 		return ;
 
-	/* Check HDMI Audio Status */
-	hdmi_audio_busy = mid_hdmi_audio_is_busy(dev);
+	drm_helper_connector_dpms(connector, mode);
 
-	pr_debug("[DPMS] audio busy: 0x%x\n", hdmi_audio_busy);
-
-	/* if hdmi audio is busy, just turn off hdmi display plane */
-	if (hdmi_audio_busy) {
-		dspcntr_val = PSB_RVDC32(DSPBCNTR);
-		connector->dpms = mode;
-
-		if (mode != DRM_MODE_DPMS_ON) {
-			if (!dev_priv->hdmi_first_boot) {
-				REG_WRITE(DSPBCNTR, dspcntr_val &
-						~DISPLAY_PLANE_ENABLE);
-				DISP_PLANEB_STATUS = DISPLAY_PLANE_DISABLE;
-			}
-		} else {
-			REG_WRITE(DSPBCNTR, dspcntr_val |
-							DISPLAY_PLANE_ENABLE);
-			DISP_PLANEB_STATUS = DISPLAY_PLANE_ENABLE;
-		}
-	} else {
-		drm_helper_connector_dpms(connector, mode);
-
-		if (mode != DRM_MODE_DPMS_ON)
-			DISP_PLANEB_STATUS = DISPLAY_PLANE_DISABLE;
-		else
-			DISP_PLANEB_STATUS = DISPLAY_PLANE_ENABLE;
-	}
+	if (mode != DRM_MODE_DPMS_ON)
+		DISP_PLANEB_STATUS = DISPLAY_PLANE_DISABLE;
+	else
+		DISP_PLANEB_STATUS = DISPLAY_PLANE_ENABLE;
 
 #if (defined CONFIG_PM_RUNTIME) && (!defined MERRIFIELD) \
 	&& (defined CONFIG_SUPPORT_MIPI)
diff --git a/drivers/staging/imgtec/intel/pci_support.c b/drivers/staging/imgtec/intel/pci_support.c
index 2595c76..1d3c2c7 100644
--- a/drivers/staging/imgtec/intel/pci_support.c
+++ b/drivers/staging/imgtec/intel/pci_support.c
@@ -40,10 +40,10 @@
 */ /**************************************************************************/
 
 #include <linux/pci.h>
-#include <linux/version.h>
 
 #if defined(CONFIG_MTRR)
 #include <asm/mtrr.h>
+#include <linux/version.h>
 #endif
 
 #include "pci_support.h"
@@ -457,7 +457,7 @@
 
 	pci_disable_device(psPVRPCI->psPCIDev);
 
-	OSFreeMem((void *)psPVRPCI);
+	OSFreeMem(psPVRPCI);
 	/*not nulling pointer, copy on stack*/
 
 	return PVRSRV_OK;
@@ -540,16 +540,8 @@
 			return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
 	}
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
 	pci_restore_state(psPVRPCI->psPCIDev);
-#else
-	err = pci_restore_state(psPVRPCI->psPCIDev);
-	if (err != 0)
-	{
-		printk(KERN_ERR "OSPCIResumeDev: pci_restore_state failed (%d)", err);
-		return PVRSRV_ERROR_PCI_CALL_FAILED;
-	}
-#endif
+
 	err = pci_enable_device(psPVRPCI->psPCIDev);
 	if (err != 0)
 	{
diff --git a/drivers/staging/imgtec/intel/pci_support.h b/drivers/staging/imgtec/intel/pci_support.h
index 4322098..c420ff9 100644
--- a/drivers/staging/imgtec/intel/pci_support.h
+++ b/drivers/staging/imgtec/intel/pci_support.h
@@ -45,6 +45,13 @@
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
+#if defined(LINUX)
+#include <linux/pci.h>
+#define TO_PCI_COOKIE(dev) to_pci_dev((struct device *)(dev))
+#else
+#define TO_PCI_COOKIE(dev) (dev)
+#endif
+
 typedef enum _HOST_PCI_INIT_FLAGS_
 {
 	HOST_PCI_INIT_FLAG_BUS_MASTER	= 0x00000001,
diff --git a/drivers/staging/imgtec/intel/pvr_drm_shared.h b/drivers/staging/imgtec/intel/pvr_drm.h
similarity index 70%
rename from drivers/staging/imgtec/intel/pvr_drm_shared.h
rename to drivers/staging/imgtec/intel/pvr_drm.h
index 69cd4b9..0527590 100644
--- a/drivers/staging/imgtec/intel/pvr_drm_shared.h
+++ b/drivers/staging/imgtec/intel/pvr_drm.h
@@ -40,12 +40,44 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#if !defined(__PVR_DRM_SHARED_H__)
-#define __PVR_DRM_SHARED_H__
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
 
-#if defined(SUPPORT_DRM)
 #include <linux/types.h>
 
+#if defined(__KERNEL__)
+#include <drm/drm.h>
+#elif defined(SUPPORT_ANDROID_PLATFORM) && \
+     !defined(PVR_ANDROID_OLD_LIBDRM_HEADER_PATH)
+#include <drm.h>
+#else
+#include <libdrm/drm.h>
+#endif
+
+/*
+ * The fields, types and ordering must match those of PVRSRV_BRIDGE_PACKAGE but
+ * the names must match those of the common version of this structure found in a
+ * header of the same name in the common Services code.
+ */
+struct drm_pvr_srvkm_cmd {
+	__u32 bridge_id;
+	__u32 bridge_func_id;
+	__u32 size;
+	void *in_data_ptr;
+	__u32 in_data_size;
+	void *out_data_ptr;
+	__u32 out_data_size;
+};
+
+struct drm_pvr_dbgdrv_cmd {
+	__u32 cmd;
+	__u32 pad;
+	__u64 in_data_ptr;
+	__u64 out_data_ptr;
+	__u32 in_data_size;
+	__u32 out_data_size;
+};
+
 /* 
  * DRM command numbers, relative to DRM_COMMAND_BASE. 
  * These defines must be prefixed with "DRM_".
@@ -54,5 +86,13 @@
 #define DRM_PVR_IS_MASTER_CMD	0x15 /* Used to check for master */
 #define DRM_PVR_DBGDRV_CMD		0x1E /* Debug driver (PDUMP) ioctls */
 
-#endif /* defined(SUPPORT_DRM) */
-#endif /* defined(__PVR_DRM_SHARED_H__) */
+#define DRM_IOCTL_PVR_SRVKM_CMD \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_SRVKM_CMD, struct drm_pvr_srvkm_cmd)
+
+#define DRM_IOCTL_PVR_IS_MASTER_CMD \
+	DRM_IO(DRM_COMMAND_BASE + DRM_PVR_IS_MASTER_CMD)
+
+#define	DRM_IOCTL_PVR_DBGDRV_CMD \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_DBGDRV_CMD, struct drm_pvr_dbgdrv_cmd)
+
+#endif /* defined(__PVR_DRM_H__) */
diff --git a/drivers/staging/imgtec/intel/pvr_drm_ext.c b/drivers/staging/imgtec/intel/pvr_drm_ext.c
index 9163358..70a0bc1 100644
--- a/drivers/staging/imgtec/intel/pvr_drm_ext.c
+++ b/drivers/staging/imgtec/intel/pvr_drm_ext.c
@@ -38,6 +38,7 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/version.h>
 #include <drm/drmP.h>
@@ -46,17 +47,13 @@
 #include "img_defs.h"
 #include "lock.h"
 #include "pvr_drm_ext.h"
-#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+#include "pvrsrv_ext.h"
 #include "pvrsrv_interface.h"
-#include "pvr_bridge.h"
 #include "srvkm.h"
 #include "dc_mrfld.h"
 #include "drm_shared.h"
-#include "linkage.h"
-
-#if defined(PDUMP)
-#include "linuxsrv.h"
-#endif
+#include "module_common.h"
 
 #include <linux/module.h>
 #include "pvrmodule.h"
@@ -67,16 +64,6 @@
 #error Mismatch in IOCTL numbers
 #endif
 
-#define DRM_IOCTL_PVR_SRVKM_CMD \
-	DRM_IOW(DRM_COMMAND_BASE + DRM_PVR_SRVKM_CMD, PVRSRV_BRIDGE_PACKAGE)
-
-#define DRM_IOCTL_PVR_IS_MASTER_CMD \
-	DRM_IO(DRM_COMMAND_BASE + DRM_PVR_IS_MASTER_CMD)
-
-#if defined(PDUMP)
-#define	DRM_IOCTL_PVR_DBGDRV_CMD \
-	DRM_IOW(DRM_COMMAND_BASE + DRM_PVR_DBGDRV_CMD, IOCTL_PACKAGE)
-#endif
 
 static int
 PVRDRMIsMaster(struct drm_device *dev, void *arg, struct drm_file *pFile)
@@ -102,17 +89,80 @@
 };
 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) */
 
+typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
+
 DECLARE_WAIT_QUEUE_HEAD(sWaitForInit);
 
 static bool bInitComplete;
 static bool bInitFailed;
 
-struct pci_dev *gpsPVRLDMDev;
+static struct pci_dev *gpsPVRLDMDev;
 
 struct drm_device *gpsPVRDRMDev;
+static PVRSRV_DEVICE_NODE *gpsDeviceNode;
 
 #define PVR_DRM_FILE struct drm_file *
 
+int PVRCore_Init(void)
+{
+	int error = 0;
+
+	if ((error = PVRSRVCommonDriverInit()) != 0)
+	{
+		return error;
+	}
+
+	error = PVRSRVDeviceCreate(&gpsPVRLDMDev->dev, &gpsDeviceNode);
+	if (error != 0)
+	{
+		DRM_DEBUG("%s: unable to init PVR service (%d)", __FUNCTION__, error);
+		return error;
+	}
+
+	error = PVRSRVCommonDeviceInit(gpsDeviceNode);
+	if (error != 0)
+	{
+		return error;
+	}
+
+	return 0;
+}
+
+void PVRCore_Cleanup(void)
+{
+	PVRSRVCommonDeviceDeinit(gpsDeviceNode);
+	PVRSRVDeviceDestroy(gpsDeviceNode);
+	gpsDeviceNode = NULL;
+
+	PVRSRVCommonDriverDeinit();
+}
+
+int PVRSRVOpen(struct drm_device __maybe_unused *dev, struct drm_file *pDRMFile)
+{
+	int err;
+
+	if (!try_module_get(THIS_MODULE))
+	{
+		DRM_DEBUG("%s: Failed to get module", __FUNCTION__);
+		return -ENOENT;
+	}
+
+	err = PVRSRVCommonDeviceOpen(gpsDeviceNode, pDRMFile);
+	if (err)
+	{
+		module_put(THIS_MODULE);
+	}
+
+	return err;
+}
+
+void PVRSRVRelease(struct drm_device __maybe_unused *dev, struct drm_file *pDRMFile)
+{
+	PVRSRVCommonDeviceRelease(gpsDeviceNode, pDRMFile);
+
+	module_put(THIS_MODULE);
+}
+
 int PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
 {
 	int iRes = 0;
@@ -121,19 +171,11 @@
 
 	gpsPVRDRMDev = dev;
 	gpsPVRLDMDev = dev->pdev;
-
-#if defined(PDUMP)
-	iRes = dbgdrv_init();
-	if (iRes != 0)
-	{
-		goto exit;
-	}
-#endif
 	
 	iRes = PVRCore_Init();
 	if (iRes != 0)
 	{
-		goto exit_dbgdrv_cleanup;
+		goto exit;
 	}
 
 	if (MerrifieldDCInit(dev) != PVRSRV_OK)
@@ -146,11 +188,6 @@
 
 exit_pvrcore_cleanup:
 	PVRCore_Cleanup();
-
-exit_dbgdrv_cleanup:
-#if defined(PDUMP)
-	dbgdrv_cleanup();
-#endif
 exit:
 	if (iRes != 0)
 	{
@@ -174,10 +211,6 @@
 
 	PVRCore_Cleanup();
 
-#if defined(PDUMP)
-	dbgdrv_cleanup();
-#endif
-
 	return 0;
 }
 
@@ -224,7 +257,7 @@
 {
 	int i;
 
-	for (i = 0; i < DRM_ARRAY_SIZE(pvr_ioctls); i++)
+	for (i = 0; i < ARRAY_SIZE(pvr_ioctls); i++)
 	{
 		unsigned int slot = DRM_IOCTL_NR(pvr_ioctls[i].cmd) - DRM_COMMAND_BASE;
 		ioctls[slot] = pvr_ioctls[i];
@@ -349,3 +382,59 @@
 {
 	return PVRSRV_MMap(pFile, ps_vma);
 }
+
+PVRSRV_ERROR PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+									  PVRSRV_DEVICE_TYPE *peDeviceType,
+									  PVRSRV_DEVICE_CLASS *peDeviceClass,
+									  IMG_UINT32 *pui32DeviceIndex)
+{
+	IMG_UINT32 i;
+
+	if (!pui32NumDevices || !peDeviceType || !peDeviceClass || !pui32DeviceIndex)
+	{
+		DRM_ERROR("%s: Invalid params", __func__);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Setup input buffer to be `empty' */
+	for (i = 0; i < PVRSRV_MAX_DEVICES; i++)
+	{
+		peDeviceType[i] = PVRSRV_DEVICE_TYPE_UNKNOWN;
+	}
+
+	/* Only a single device is supported */
+	peDeviceType[0] = PVRSRV_DEVICE_TYPE_RGX;
+	peDeviceClass[0] = PVRSRV_DEVICE_CLASS_3D;
+	pui32DeviceIndex[0] = 0;
+	*pui32NumDevices = 1;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(IMG_UINT32 ui32DevIndex,
+									   PVRSRV_DEVICE_TYPE eDeviceType,
+									   IMG_HANDLE *phDevCookie)
+{
+	if (phDevCookie)
+	{
+		DRM_ERROR("%s: Invalid params", __func__);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if ((eDeviceType == PVRSRV_DEVICE_TYPE_RGX) ||
+		(eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN && ui32DevIndex == 0))
+	{
+		PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+		/*
+		 * Return the head of the list, which will only contain a single entry,
+		 * as only a single device is supported.
+		 */
+		*phDevCookie = (IMG_HANDLE) psPVRSRVData->psDeviceNodeList;
+
+		return PVRSRV_OK;
+	}
+
+	DRM_ERROR("%s: requested device is not present", __func__);
+	return PVRSRV_ERROR_INIT_FAILURE;
+}
diff --git a/drivers/staging/imgtec/intel/pvr_drm_ext.h b/drivers/staging/imgtec/intel/pvr_drm_ext.h
index a163927..537e52e 100644
--- a/drivers/staging/imgtec/intel/pvr_drm_ext.h
+++ b/drivers/staging/imgtec/intel/pvr_drm_ext.h
@@ -46,6 +46,7 @@
 void PVRSRVRelease(struct drm_device *dev, struct drm_file *pDRMFile);
 
 int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile);
+int PVRSRV_MMap(struct file *file, struct vm_area_struct *ps_vma);
 
 int PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
 int PVRSRVDrmRelease(struct inode *inode, struct file *filp);
diff --git a/drivers/staging/imgtec/intel/pvrsrv_ext.h b/drivers/staging/imgtec/intel/pvrsrv_ext.h
index b2a1264..e3efd4d 100644
--- a/drivers/staging/imgtec/intel/pvrsrv_ext.h
+++ b/drivers/staging/imgtec/intel/pvrsrv_ext.h
@@ -39,9 +39,31 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#if !defined(_PVRSRV_EXT_H_)
-#define _PVRSRV_EXT_H_
+#if !defined(__PRVRSRV_EXT_H__)
+#define __PRVRSRV_EXT_H__
 
+#include "img_types.h"
+#include "pvrsrv_error.h"
 #include "pvrsrv.h"
 
-#endif /* !defined(_PVRSRV_EXT_H_) */
+typedef enum PVRSRV_DEVICE_TYPE
+{
+	PVRSRV_DEVICE_TYPE_UNKNOWN = 0,
+	PVRSRV_DEVICE_TYPE_RGX = 10,
+} PVRSRV_DEVICE_TYPE;
+
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+	PVRSRV_DEVICE_CLASS_3D = 0,
+} PVRSRV_DEVICE_CLASS;
+
+PVRSRV_ERROR PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+									  PVRSRV_DEVICE_TYPE *peDeviceType,
+									  PVRSRV_DEVICE_CLASS *peDeviceClass,
+									  IMG_UINT32 *pui32DeviceIndex);
+
+PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(IMG_UINT32 ui32DevIndex,
+									   PVRSRV_DEVICE_TYPE eDeviceType,
+									   IMG_HANDLE *phDevCookie);
+
+#endif /* !defined(__PRVRSRV_EXT_H__) */
diff --git a/drivers/staging/imgtec/intel/sysconfig.c b/drivers/staging/imgtec/intel/sysconfig.c
index 2ed7b76..dfd5c03 100644
--- a/drivers/staging/imgtec/intel/sysconfig.c
+++ b/drivers/staging/imgtec/intel/sysconfig.c
@@ -68,56 +68,77 @@
 	struct drm_device *psDRMDev;
 } PLAT_DATA;
 
-PLAT_DATA *gpsPlatData = NULL;
 extern struct drm_device *gpsPVRDRMDev;
 
 /* Unused globals to keep link with 3rdparty components happy */
 IMG_BOOL gbSystemActivePMEnabled;
 IMG_BOOL gbSystemActivePMInit;
 
-/*
-	PCIInitDev
-*/
-static PVRSRV_ERROR PCIInitDev(PLAT_DATA *psPlatData)
+
+PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
 {
-	PVRSRV_DEVICE_CONFIG *psDevice = &sSysConfig.pasDevices[0];
-	PVRSRV_ERROR eError;
+	PVRSRV_DEVICE_CONFIG *psDevice = &sDevices[0];
+	PLAT_DATA *psPlatData;
 	IMG_UINT32 ui32MaxOffset;
 	IMG_UINT32 ui32BaseAddr = 0;
+	PVRSRV_ERROR eError;
+
+	if (psDevice->pvOSDevice)
+	{
+		return PVRSRV_ERROR_INVALID_DEVICE;
+	}
+
+	psPlatData = OSAllocZMem(sizeof(*psPlatData));
+	if (!psPlatData)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psDevice->hSysData = (IMG_HANDLE) psPlatData;
 
 	psPlatData->psDRMDev = gpsPVRDRMDev;
 	if (!psPlatData->psDRMDev)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: DRM device not initialized"));
-		return PVRSRV_ERROR_NOT_SUPPORTED;
+		PVR_DPF((PVR_DBG_ERROR, "%s: DRM device not initialized", __func__));
+		eError = PVRSRV_ERROR_NOT_SUPPORTED;
+		goto ErrorFreePlatData;
 	}
 
 	if (!IS_MRFLD(psPlatData->psDRMDev))
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device 0x%08x not supported", psPlatData->psDRMDev->pci_device));
-		return PVRSRV_ERROR_NOT_SUPPORTED;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Device 0x%08x not supported", __func__,
+				 psPlatData->psDRMDev->pci_device));
+		eError = PVRSRV_ERROR_NOT_SUPPORTED;
+		goto ErrorFreePlatData;
 	}
 
 	psPlatData->hRGXPCI = OSPCISetDev((void *)psPlatData->psDRMDev->pdev, 0);
 	if (!psPlatData->hRGXPCI)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Failed to acquire PCI device"));
-		return PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire PCI device", __func__));
+		eError = PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+		goto ErrorFreePlatData;
 	}
 
 	ui32MaxOffset = OSPCIAddrRangeLen(psPlatData->hRGXPCI, 0);
 	if (ui32MaxOffset < (RGX_REG_OFFSET + RGX_REG_SIZE))
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region 0x%08x isn't big enough", ui32MaxOffset));
-		return PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Device memory region 0x%08x isn't big enough",
+				 __func__, ui32MaxOffset));
+		eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+		goto ErrorFreePlatData;
 	}
-	PVR_DPF((PVR_DBG_WARNING,"PCIInitDev: Device memory region len 0x%08x", ui32MaxOffset));
+	PVR_DPF((PVR_DBG_WARNING, "%s: Device memory region len 0x%08x",
+			 __func__, ui32MaxOffset));
 
 	/* Reserve the address range */
 	if (OSPCIRequestAddrRange(psPlatData->hRGXPCI, 0) != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region not available"));
-		return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Device memory region not available",
+				 __func__));
+		eError = PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+		goto ErrorFreePlatData;
 
 	}
 
@@ -125,17 +146,27 @@
 
 	if (OSPCIIRQ(psPlatData->hRGXPCI, &psDevice->ui32IRQ) != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Couldn't get IRQ"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't get IRQ", __func__));
 		eError = PVRSRV_ERROR_INVALID_DEVICE;
 		goto e4;
 	}
-	PVR_DPF((PVR_DBG_WARNING, "PCIInitDev: BaseAddr 0x%08x, EndAddr 0x%llx, IRQ %d",
-			ui32BaseAddr, OSPCIAddrRangeEnd(psPlatData->hRGXPCI, 0), psDevice->ui32IRQ));
+	PVR_DPF((PVR_DBG_WARNING, "%s: BaseAddr 0x%08x, EndAddr 0x%llx, IRQ %d",
+			 __func__, ui32BaseAddr, OSPCIAddrRangeEnd(psPlatData->hRGXPCI, 0),
+			 psDevice->ui32IRQ));
 
 	psDevice->sRegsCpuPBase.uiAddr = ui32BaseAddr + RGX_REG_OFFSET;
 	psDevice->ui32RegsSize = RGX_REG_SIZE;
-	PVR_DPF((PVR_DBG_WARNING, "PCIInitDev: sRegsCpuPBase 0x%llx, size 0x%x",
-			psDevice->sRegsCpuPBase.uiAddr, psDevice->ui32RegsSize));
+	PVR_DPF((PVR_DBG_WARNING, "%s: sRegsCpuPBase 0x%llx, size 0x%x",
+			__func__, psDevice->sRegsCpuPBase.uiAddr, psDevice->ui32RegsSize));
+
+	/* Setup other system specific stuff */
+#if defined(SUPPORT_ION)
+	IonInit(NULL);
+#endif
+
+	psDevice->pvOSDevice = pvOSDevice;
+
+	*ppsDevConfig = psDevice;
 
 	return PVRSRV_OK;
 
@@ -143,88 +174,35 @@
 	OSPCIReleaseAddrRange(psPlatData->hRGXPCI, 0);
 	OSPCIReleaseDev(psPlatData->hRGXPCI);
 
+ErrorFreePlatData:
+	OSFreeMem(psPlatData);
+	psDevice->hSysData = NULL;
+
 	return eError;
 }
 
-/*!
-******************************************************************************
-
- @Function		PCIDeInitDev
-
- @Description
-
- Uninitialise the PCI device when it is no loger required
-
- @Input		psSysData :	System data
-
- @Return	none
-
-******************************************************************************/
-static void PCIDeInitDev(PLAT_DATA *psPlatData)
+void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
+	PLAT_DATA *psPlatData = (PLAT_DATA *) psDevConfig->hSysData;
+
 	OSPCIReleaseAddrRange(psPlatData->hRGXPCI, 0);
 	OSPCIReleaseDev(psPlatData->hRGXPCI);
-}
-
-
-PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig, void *hDevice)
-{
-	PLAT_DATA *psPlatData;
-	PVRSRV_ERROR eError;
-
-	PVR_UNREFERENCED_PARAMETER(hDevice);
-
-	psPlatData = OSAllocZMem(sizeof(*psPlatData));
-
-	/* Query the Emu for reg and IRQ information */
-	eError = PCIInitDev(psPlatData);
-	if (eError != PVRSRV_OK)
-	{
-		goto e0;
-	}
-
-	/* Save data for this device */
-	sSysConfig.pasDevices[0].hSysData = (IMG_HANDLE) psPlatData;
-
-	/* Save private data for the physical memory heap */
-	gsPhysHeapConfig[0].hPrivData = (IMG_HANDLE) psPlatData;
-
-#if defined(SUPPORT_TRUSTED_DEVICE)
-	#error "Not supported services/3rdparty/intel_drm/sysconfig.c"
-	gsPhysHeapConfig[1].hPrivData = NULL;
-#endif
-
-	*ppsSysConfig = &sSysConfig;
-
-	gpsPlatData = psPlatData;
-
-
-	/* Setup other system specific stuff */
-#if defined(SUPPORT_ION)
-	IonInit(NULL);
-#endif
-
-	return PVRSRV_OK;
-e0:
-	return eError;
-}
-
-void SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig)
-{
-	PLAT_DATA *psPlatData = gpsPlatData;
-
-	PVR_UNREFERENCED_PARAMETER(psSysConfig);
-	PCIDeInitDev(psPlatData);
-	OSFreeMem(psPlatData);
 
 #if defined(SUPPORT_ION)
 	IonDeinit();
 #endif
+
+	OSFreeMem(psPlatData);
+	psDevConfig->hSysData = NULL;
+
+	psDevConfig->pvOSDevice = NULL;
 }
 
-PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile)
+PVRSRV_ERROR SysDebugInfo(PVRSRV_DEVICE_CONFIG *psDevConfig,
+				DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				void *pvDumpDebugFile)
 {
-	PVR_UNREFERENCED_PARAMETER(psSysConfig);
+	PVR_UNREFERENCED_PARAMETER(psDevConfig);
 	PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
 	PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
 	return PVRSRV_OK;
@@ -263,6 +241,7 @@
 }
 
 static PVRSRV_ERROR SysDevicePrePowerState(
+		IMG_HANDLE hSysData,
 		PVRSRV_DEV_POWER_STATE eNewPowerState,
 		PVRSRV_DEV_POWER_STATE eCurrentPowerState,
 		IMG_BOOL bForced)
@@ -283,6 +262,7 @@
 }
 
 static PVRSRV_ERROR SysDevicePostPowerState(
+		IMG_HANDLE hSysData,
 		PVRSRV_DEV_POWER_STATE eNewPowerState,
 		PVRSRV_DEV_POWER_STATE eCurrentPowerState,
 		IMG_BOOL bForced)
@@ -304,8 +284,9 @@
 
 typedef int (*psb_irq_handler_t)(void *data);
 
-PVRSRV_ERROR SysInstallDeviceLISR(IMG_UINT32 ui32IRQ,
-				  IMG_CHAR *pszName,
+PVRSRV_ERROR SysInstallDeviceLISR(IMG_HANDLE hSysData,
+				  IMG_UINT32 ui32IRQ,
+				  const IMG_CHAR *pszName,
 				  PFN_LISR pfnLISR,
 				  void *pvData,
 				  IMG_HANDLE *phLISRData)
@@ -322,11 +303,6 @@
 
 }
 
-SYS_PHYS_ADDRESS_MASK SysDevicePhysAddressMask(void)
-{
-	return SYS_PHYS_ADDRESS_64_BIT;
-}
-
 /******************************************************************************
  End of file (sysconfig.c)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/intel/sysconfig.h b/drivers/staging/imgtec/intel/sysconfig.h
index 9ae9ea2..1f27526 100644
--- a/drivers/staging/imgtec/intel/sysconfig.h
+++ b/drivers/staging/imgtec/intel/sysconfig.h
@@ -59,11 +59,13 @@
 		IMG_DEV_PHYADDR *psDevPAddr);
 
 static PVRSRV_ERROR SysDevicePostPowerState(
+		IMG_HANDLE hSysData,
 		PVRSRV_DEV_POWER_STATE eNewPowerState,
 		PVRSRV_DEV_POWER_STATE eCurrentPowerState,
 		IMG_BOOL bForced);
 
 static PVRSRV_ERROR SysDevicePrePowerState(
+		IMG_HANDLE hSysData,
 		PVRSRV_DEV_POWER_STATE eNewPowerState,
 		PVRSRV_DEV_POWER_STATE eCurrentPowerState,
 		IMG_BOOL bForced);
@@ -112,13 +114,14 @@
 static PVRSRV_DEVICE_CONFIG sDevices[] =
 {
 	{
-		.eDeviceType		= PVRSRV_DEVICE_TYPE_RGX,
-		.pszName		= "RGX",
+		.pszName		= "moorefield",
+		.pszVersion		= NULL,
 
 		/* Device setup information */
 		.sRegsCpuPBase		= { 0 },
 		.ui32RegsSize		= 0,
 		.ui32IRQ		= 0,
+		.eCacheSnoopingMode	= PVRSRV_DEVICE_SNOOP_CPU_ONLY,
 
 		/* No power management on no HW system */
 		.pfnPrePowerState	= SysDevicePrePowerState,
@@ -127,33 +130,21 @@
 		.hDevData		= &sRGXData,
 		.hSysData		= NULL,
 
-		.aui32PhysHeapID	= { 0, 0, 0 },
-	}
-};
-
-static PVRSRV_SYSTEM_CONFIG sSysConfig =
-{
-	.pszSystemName			= "Merrifield with Rogue",
-	.uiDeviceCount			= sizeof(sDevices) /
-					  sizeof(PVRSRV_DEVICE_CONFIG),
-	.pasDevices			= &sDevices[0],
-
-	/* Physcial memory heaps */
-	.ui32PhysHeapCount		= sizeof(gsPhysHeapConfig) /
+		/* Physical memory heaps */
+		.ui32PhysHeapCount	= sizeof(gsPhysHeapConfig) /
 					  sizeof(PHYS_HEAP_CONFIG),
-	.pasPhysHeaps			= &(gsPhysHeapConfig[0]),
+		.pasPhysHeaps		= &gsPhysHeapConfig[0],
 
-	/* No power management on no HW system */
-	.pfnSysPrePowerState		= NULL,
-	.pfnSysPostPowerState		= NULL,
+		.aui32PhysHeapID	= { 0, 0, 0 },
 
-	.pui32BIFTilingHeapConfigs	=
-		&gauiBIFTilingHeapXStrides[0],
-	.ui32BIFTilingHeapCount		=
-		IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides),
-
-	/* no cache snooping */
-	.eCacheSnoopingMode		= PVRSRV_SYSTEM_SNOOP_CPU_ONLY,
+		/* BIF Tiling mode configuration */
+		.eBIFTilingMode		= RGXFWIF_BIFTILINGMODE_256x16,
+		.pui32BIFTilingHeapConfigs =
+			&gauiBIFTilingHeapXStrides[0],
+		.ui32BIFTilingHeapCount	=
+			IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides),
+		.pfnSysDevFeatureDepInit = NULL
+	}
 };
 
 #define VENDOR_ID_MERRIFIELD	0x8086
diff --git a/drivers/staging/imgtec/intel/sysinfo.h b/drivers/staging/imgtec/intel/sysinfo.h
index f1ea269..d1a8b0a 100644
--- a/drivers/staging/imgtec/intel/sysinfo.h
+++ b/drivers/staging/imgtec/intel/sysinfo.h
@@ -53,14 +53,6 @@
 #define FATAL_ERROR_DETECTION_POLL_MS  (10000)
 #define WAIT_TRY_COUNT                 (10000)
 
-#define SYS_DEVICE_COUNT 3 /* RGX, DISPLAY (external), BUFFER (external) */
-
-#if defined(SUPPORT_TRUSTED_DEVICE)
-#define SYS_PHYS_HEAP_COUNT		2
-#else
-#define SYS_PHYS_HEAP_COUNT		1
-#endif
-
 #define SYS_RGX_DEV_VENDOR_ID		0x8086
 #define SYS_RGX_DEV_DEVICE_ID		0x1180
 
@@ -74,18 +66,4 @@
 */
 #define RGX_CORE_CLOCK_SPEED_DEFAULT	(400000000)
 
-#if defined(__linux__)
-#define SYS_RGX_DEV_NAME    "Merrifield"
-#if defined(SUPPORT_DRM)
-/*
- * Use the static bus ID for the platform DRM device.
- */
-#if defined(PVR_DRM_DEV_BUS_ID)
-#define	SYS_RGX_DEV_DRM_BUS_ID	PVR_DRM_DEV_BUS_ID
-#else
-#define SYS_RGX_DEV_DRM_BUS_ID	"platform:Merrifield"
-#endif	/* defined(PVR_DRM_DEV_BUS_ID) */
-#endif	/* defined(SUPPORT_DRM) */
-#endif
-
 #endif	/* !defined(__SYSINFO_H__) */
diff --git a/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c b/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c
index 18aa72a..5ee6d39 100644
--- a/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c
+++ b/drivers/staging/imgtec/intel/video/common/psb_ttm_glue.c
@@ -50,8 +50,15 @@
 extern int sepapp_drm_playback(bool ied_status);
 static int ied_enabled;
 
-static void ann_rm_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type);
-static void ann_add_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type);
+enum slc_setting {
+	enable_slc,
+	disable_slc,
+};
+
+static void ann_workaround_ctx_set_slc(struct drm_psb_private *dev_priv,
+		uint64_t ctx_type, enum slc_setting slc_set);
+
+#define MB_SIZE 16
 
 #ifdef MERRIFIELD
 struct psb_fpriv *psb_fpriv(struct drm_file *file_priv)
@@ -295,7 +302,8 @@
 				  (found_ctx->ctx_type >> 8) & 0xff,
 				  (found_ctx->ctx_type & 0xff));
 		if (IS_ANN(dev))
-			ann_rm_workaround_ctx(dev_priv, found_ctx->ctx_type);
+			ann_workaround_ctx_set_slc(dev_priv, ctx_type,
+					enable_slc);
 #ifndef CONFIG_DRM_VXD_BYT
 		/* if current ctx points to it, set to NULL */
 		if ((VAEntrypointEncSlice ==
@@ -459,7 +467,8 @@
 		video_ctx->ctx_type = ctx_type;
 		video_ctx->cur_sequence = 0xffffffff;
 		if (IS_ANN(dev))
-			ann_add_workaround_ctx(dev_priv, ctx_type);
+			ann_workaround_ctx_set_slc(dev_priv, ctx_type,
+					disable_slc);
 #ifdef CONFIG_SLICE_HEADER_PARSING
 		video_ctx->frame_end_seq = 0xffffffff;
 		if (ctx_type & VA_RT_FORMAT_PROTECTED) {
@@ -520,14 +529,17 @@
 		else {
 			mutex_lock(&g_ied_mutex);
 			DRM_INFO("Video: ied_ref: %d\n", g_ied_ref);
-			while (g_ied_ref) {
-				ret = sepapp_drm_playback(false);
-				if (ret) {
-					DRM_ERROR("IED Clean-up \
-						Failed:0x%x\n", ret);
-					break;
+			/* To make sure no IED session still working. */
+			if (list_empty(&dev_priv->video_ctx)) {
+				while (g_ied_ref) {
+					ret = sepapp_drm_playback(false);
+					if (ret) {
+						DRM_ERROR("IED Clean-up \
+							Failed:0x%x\n", ret);
+						break;
+					}
+					g_ied_ref--;
 				}
-				g_ied_ref--;
 			}
 			mutex_unlock(&g_ied_mutex);
 		}
@@ -750,19 +762,22 @@
 	return 0;
 }
 
-/* SLC bug: there is green corruption for vc1 decode if width is not 64 aligned
- * Recode the number of VC1 ctx whose width is not 64 aligned
+/*
+ * SLC bug: there is green corruption for VC1/VP8/H.264 decode if:
+ * 1. VC1/VP8 width is not 64 aligned. Recode the number of VC1 ctx whose width
+ * is not 64 aligned;
+ * 2. H.264 resolution <= 720p.
  */
-static void ann_add_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type)
+static void ann_workaround_ctx_set_slc(struct drm_psb_private *dev_priv,
+		uint64_t ctx_type, enum slc_setting slc_set)
 {
 
 	struct msvdx_private *msvdx_priv;
 	int profile = (ctx_type >> 8) & 0xff;
-
-	if (profile != VAProfileVC1Simple &&
-	    profile != VAProfileVC1Main &&
-	    profile != VAProfileVC1Advanced)
-		return;
+	/* ctx_type >> 32 is width_in_mb */
+	uint64_t width = ((ctx_type >> 32) & 0xffff) * MB_SIZE;
+	/* ctx_type >> 48 is height_in_mb */
+	uint64_t height = ((ctx_type >> 48) & 0xffff) * MB_SIZE;
 
 	if (unlikely(!dev_priv))
 		return;
@@ -771,41 +786,32 @@
 	if (unlikely(!msvdx_priv))
 		return;
 
-	PSB_DEBUG_GENERAL(
-	    "add vc1 ctx, ctx_type is 0x%llx\n",
-		ctx_type);
+	switch (profile) {
+	case VAProfileVC1Simple:
+	case VAProfileVC1Main:
+	case VAProfileVC1Advanced:
+	case VAProfileVP8Version0_3:
+		if (width % 64) {
+			if (slc_set == disable_slc)
+				atomic_inc(&msvdx_priv->slc_workaround_ctx);
+			else
+				atomic_dec(&msvdx_priv->slc_workaround_ctx);
+		}
+		break;
 
-	/* ctx_type >> 32 is width_in_mb */
-	if ((ctx_type >> 32) % 4) {
-		atomic_inc(&msvdx_priv->vc1_workaround_ctx);
-		PSB_DEBUG_GENERAL("add workaround ctx %p in ctx\n", msvdx_priv);
-	}
-}
+	case VAProfileH264Baseline:
+	case VAProfileH264Main:
+	case VAProfileH264High:
+		if (((height == 128) && (width > 112) && (width <= 128)) ||
+				((width <= 1280) && (height <= 736))) {
+			if (slc_set == disable_slc)
+				atomic_inc(&msvdx_priv->slc_workaround_ctx);
+			else
+				atomic_dec(&msvdx_priv->slc_workaround_ctx);
+		}
+		break;
 
-static void ann_rm_workaround_ctx(struct drm_psb_private *dev_priv, uint64_t ctx_type)
-{
-
-	struct msvdx_private *msvdx_priv;
-	int profile = (ctx_type >> 8) & 0xff;
-
-	if (profile != VAProfileVC1Simple &&
-	    profile != VAProfileVC1Main &&
-	    profile != VAProfileVC1Advanced)
-		return;
-
-	if (unlikely(!dev_priv))
-		return;
-
-	msvdx_priv = dev_priv->msvdx_private;
-	if (unlikely(!msvdx_priv))
-		return;
-
-	PSB_DEBUG_GENERAL(
-	    "rm vc1 ctx, ctx_type is 0x%llx\n",
-		ctx_type);
-	/* ctx_type >> 32 is width_in_mb */
-	if ((ctx_type >> 32) % 4) {
-		atomic_dec(&msvdx_priv->vc1_workaround_ctx);
-		PSB_DEBUG_GENERAL("dec workaround ctx %p in ctx\n", msvdx_priv);
+	default:
+		break;
 	}
 }
diff --git a/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h b/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h
index 0dc8fed..6cb6376 100644
--- a/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h
+++ b/drivers/staging/imgtec/intel/video/decode/psb_msvdx.h
@@ -276,7 +276,7 @@
 	uint32_t term_buf_addr;
 #endif
 
-	atomic_t vc1_workaround_ctx;
+	atomic_t slc_workaround_ctx;
 
 #ifdef CONFIG_ION
 	struct list_head ion_buffers_list;
diff --git a/drivers/staging/imgtec/powervr/buffer_attribs.h b/drivers/staging/imgtec/powervr/buffer_attribs.h
new file mode 100644
index 0000000..4c75e7c
--- /dev/null
+++ b/drivers/staging/imgtec/powervr/buffer_attribs.h
@@ -0,0 +1,84 @@
+/*************************************************************************/ /*!
+@File
+@Title          3D types for use by IMG APIs
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        MIT
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _POWERVR_BUFFER_ATTRIBS_H_
+#define _POWERVR_BUFFER_ATTRIBS_H_
+
+/**
+ * Memory layouts
+ * Defines how pixels are laid out within a surface.
+ */
+typedef enum
+{
+	IMG_MEMLAYOUT_STRIDED,       /**< Resource is strided, one row at a time */
+	IMG_MEMLAYOUT_TWIDDLED,      /**< Resource is 2D twiddled, classic style */
+	IMG_MEMLAYOUT_3DTWIDDLED,    /**< Resource is 3D twiddled, classic style */
+	IMG_MEMLAYOUT_TILED,         /**< Resource is tiled, tiling config specified elsewhere. */
+	IMG_MEMLAYOUT_PAGETILED,     /**< Resource is pagetiled */
+} IMG_MEMLAYOUT;
+
+/**
+ * Rotation types
+ */
+typedef enum
+{
+	IMG_ROTATION_0DEG = 0,
+	IMG_ROTATION_90DEG = 1,
+	IMG_ROTATION_180DEG = 2,
+	IMG_ROTATION_270DEG = 3,
+	IMG_ROTATION_FLIP_Y = 4,
+
+	IMG_ROTATION_BAD = 255,
+} IMG_ROTATION;
+
+/**
+ * Alpha types.
+ */
+typedef enum
+{
+	IMG_COLOURSPACE_FORMAT_UNKNOWN   =  0x00000000,  /**< Colourspace Format: Unknown */
+	IMG_COLOURSPACE_FORMAT_LINEAR    =  0x00010000,  /**< Colourspace Format: Linear */
+	IMG_COLOURSPACE_FORMAT_NONLINEAR =  0x00020000,  /**< Colourspace Format: Non-Linear */
+	IMG_COLOURSPACE_FORMAT_MASK      =  0x000F0000,  /**< Colourspace Format Mask */
+} IMG_COLOURSPACE_FORMAT;
+
+/**
+ * Types of framebuffer compression
+ */
+typedef enum
+{
+	IMG_FB_COMPRESSION_NONE,
+	IMG_FB_COMPRESSION_DIRECT_8x8,
+	IMG_FB_COMPRESSION_DIRECT_16x4,
+	IMG_FB_COMPRESSION_DIRECT_32x2,
+	IMG_FB_COMPRESSION_INDIRECT_8x8,
+	IMG_FB_COMPRESSION_INDIRECT_16x4,
+	IMG_FB_COMPRESSION_INDIRECT_4TILE_8x8,
+	IMG_FB_COMPRESSION_INDIRECT_4TILE_16x4
+} IMG_FB_COMPRESSION;
+
+
+#endif /* _POWERVR_BUFFER_ATTRIBS_H_ */
diff --git a/drivers/staging/imgtec/powervr/imgpixfmts.h b/drivers/staging/imgtec/powervr/imgpixfmts.h
new file mode 100644
index 0000000..ec9b615
--- /dev/null
+++ b/drivers/staging/imgtec/powervr/imgpixfmts.h
@@ -0,0 +1,77 @@
+/*************************************************************************/ /*!
+@File
+@Title          Pixel formats
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        MIT
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/ /**************************************************************************/
+
+/****************************************************************************
+ **
+ ** WARNING: This file is autogenerated - DO NOT EDIT.
+ **
+ ** See fmts_systable.txt to add new formats.
+ ****************************************************************************/
+
+#if !defined(_IMGPIXFMTS_H_)
+#define _IMGPIXFMTS_H_
+
+#include "powervr/imgyuv.h"
+
+typedef enum _IMG_PIXFMT_
+{
+	IMG_PIXFMT_UNKNOWN = 0,
+	IMG_PIXFMT_R8G8B8A8_UNORM = 32,
+	IMG_PIXFMT_R8G8B8X8_UNORM = 37,
+	IMG_PIXFMT_D32_FLOAT = 51,
+	IMG_PIXFMT_R8G8_UNORM = 62,
+	IMG_PIXFMT_R8_UNORM = 76,
+	IMG_PIXFMT_S8_UINT = 81,
+	IMG_PIXFMT_B5G6R5_UNORM = 85,
+	IMG_PIXFMT_R5G6B5_UNORM = 86,
+	IMG_PIXFMT_B5G5R5A1_UNORM = 87,
+	IMG_PIXFMT_B5G5R5X1_UNORM = 88,
+	IMG_PIXFMT_B8G8R8A8_UNORM = 89,
+	IMG_PIXFMT_B8G8R8X8_UNORM = 90,
+	IMG_PIXFMT_L8_UNORM = 136,
+	IMG_PIXFMT_L8A8_UNORM = 138,
+	IMG_PIXFMT_B4G4R4A4_UNORM = 145,
+	IMG_PIXFMT_UYVY = 171,
+	IMG_PIXFMT_VYUY = 172,
+	IMG_PIXFMT_YUYV = 173,
+	IMG_PIXFMT_YVYU = 174,
+	IMG_PIXFMT_YVU420_2PLANE = 175,
+	IMG_PIXFMT_YUV420_2PLANE = 176,
+	IMG_PIXFMT_YVU420_2PLANE_MACRO_BLOCK = 177,
+	IMG_PIXFMT_YUV420_3PLANE = 178,
+	IMG_PIXFMT_YVU420_3PLANE = 179,
+	IMG_PIXFMT_V8U8Y8A8 = 184,
+	IMG_PIXFMT_YUV8_422_2PLANE_PACK8 = 207,
+	IMG_PIXFMT_YUV8_444_3PLANE_PACK8 = 208,
+	IMG_PIXFMT_YVU8_420_2PLANE_PACK8_P = 245,
+	IMG_PIXFMT_YUV8_420_2PLANE_PACK8_P = 249,
+	IMG_PIXFMT_UYVY10_422_1PLANE_PACK10_CUST1 = 252,
+} IMG_PIXFMT;
+
+
+
+#endif /* _IMGPIXFMTS_H_ */
diff --git a/drivers/staging/imgtec/powervr/imgyuv.h b/drivers/staging/imgtec/powervr/imgyuv.h
new file mode 100644
index 0000000..a91ee10
--- /dev/null
+++ b/drivers/staging/imgtec/powervr/imgyuv.h
@@ -0,0 +1,58 @@
+/*************************************************************************/ /*!
+@File
+@Title          YUV defines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        MIT
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(_IMGYUV_H_)
+#define _IMGYUV_H_
+
+typedef enum
+{
+	IMG_COLORSPACE_UNDEFINED = 0,
+	IMG_COLORSPACE_BT601_CONFORMANT_RANGE = 1,
+	IMG_COLORSPACE_BT601_FULL_RANGE = 2,
+	IMG_COLORSPACE_BT709_CONFORMANT_RANGE = 3,
+	IMG_COLORSPACE_BT709_FULL_RANGE = 4,
+	IMG_COLORSPACE_BT2020_CONFORMANT_RANGE = 5,
+	IMG_COLORSPACE_BT2020_FULL_RANGE = 6,
+	IMG_COLORSPACE_BT601_CONFORMANT_RANGE_INVERSE = 7,
+	IMG_COLORSPACE_BT601_FULL_RANGE_INVERSE = 8,
+	IMG_COLORSPACE_BT709_CONFORMANT_RANGE_INVERSE = 9,
+	IMG_COLORSPACE_BT709_FULL_RANGE_INVERSE = 10,
+	IMG_COLORSPACE_BT2020_CONFORMANT_RANGE_INVERSE = 11,
+	IMG_COLORSPACE_BT2020_FULL_RANGE_INVERSE = 12
+} IMG_YUV_COLORSPACE;
+
+typedef enum
+{
+	IMG_CHROMA_INTERP_UNDEFINED = 0,
+	IMG_CHROMA_INTERP_ZERO = 1,
+	IMG_CHROMA_INTERP_QUARTER = 2,
+	IMG_CHROMA_INTERP_HALF = 3,
+	IMG_CHROMA_INTERP_THREEQUARTERS = 4
+} IMG_YUV_CHROMA_INTERP;
+
+
+#endif /* _IMGYUV_H_ */
diff --git a/drivers/staging/imgtec/powervr/mem_types.h b/drivers/staging/imgtec/powervr/mem_types.h
new file mode 100644
index 0000000..ee8a289
--- /dev/null
+++ b/drivers/staging/imgtec/powervr/mem_types.h
@@ -0,0 +1,62 @@
+/*************************************************************************/ /*!
+@File
+@Title          Public types
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        MIT
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _POWERVR_TYPES_H_
+#define _POWERVR_TYPES_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(_MSC_VER)
+	#include "msvc_types.h"
+#elif defined(LINUX) && defined(__KERNEL__)
+	#include <linux/types.h>
+#else
+	#include <stdint.h>
+#endif
+
+typedef void *IMG_CPU_VIRTADDR;
+
+/* device virtual address */
+typedef struct _IMG_DEV_VIRTADDR
+{
+	uint64_t  uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var)		(uint64_t)(var)
+	
+} IMG_DEV_VIRTADDR;
+
+typedef uint64_t IMG_DEVMEM_SIZE_T;
+typedef uint64_t IMG_DEVMEM_ALIGN_T;
+typedef uint64_t IMG_DEVMEM_OFFSET_T;
+typedef uint32_t IMG_DEVMEM_LOG2ALIGN_T;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/drivers/staging/imgtec/powervr/sync_external.h b/drivers/staging/imgtec/powervr/sync_external.h
new file mode 100644
index 0000000..f74ab15
--- /dev/null
+++ b/drivers/staging/imgtec/powervr/sync_external.h
@@ -0,0 +1,86 @@
+/*************************************************************************/ /*!
+@File
+@Title          Services external synchronisation interface header
+@Description    Defines synchronisation structures that are visible internally
+                and externally
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        MIT
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SYNC_EXTERNAL_
+#define _SYNC_EXTERNAL_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <powervr/mem_types.h>
+
+/*!
+ * Maximum byte length for a sync prim name
+ */
+#define SYNC_MAX_CLASS_NAME_LEN 32
+
+/*!
+ * Number of sync primitives in operations
+ */
+#define	PVRSRV_MAX_SYNC_PRIMS 32
+
+typedef void* PVRSRV_CLIENT_SYNC_PRIM_HANDLE;
+typedef void* SYNC_BRIDGE_HANDLE;
+typedef struct SYNC_PRIM_CONTEXT *PSYNC_PRIM_CONTEXT;
+typedef struct _SYNC_OP_COOKIE_ *PSYNC_OP_COOKIE;
+
+/*!
+ * Client sync prim definition holding a CPU accessible address
+ *
+ *   Structure: #PVRSRV_CLIENT_SYNC_PRIM
+ *   Typedef: ::PVRSRV_CLIENT_SYNC_PRIM
+ */
+typedef struct PVRSRV_CLIENT_SYNC_PRIM
+{
+	volatile uint32_t	*pui32LinAddr;	/*!< User pointer to the primitive */
+} PVRSRV_CLIENT_SYNC_PRIM;
+
+/*!
+ * Bundled information for a sync prim operation
+ *
+ *   Structure: #PVRSRV_CLIENT_SYNC_PRIM_OP
+ *   Typedef: ::PVRSRV_CLIENT_SYNC_PRIM_OP
+ */
+typedef struct PVRSRV_CLIENT_SYNC_PRIM_OP
+{
+	#define PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK	(1 << 0)
+	#define PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE	(1 << 1)
+	#define PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE (PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE | (1<<2))
+	uint32_t                    ui32Flags;       /*!< Operation flags: PVRSRV_CLIENT_SYNC_PRIM_OP_XXX */
+	PVRSRV_CLIENT_SYNC_PRIM    *psSync;          /*!< Pointer to the client sync primitive */
+	uint32_t                    ui32FenceValue;  /*!< The Fence value (only used if PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK is set) */
+	uint32_t                    ui32UpdateValue; /*!< The Update value (only used if PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE is set) */
+} PVRSRV_CLIENT_SYNC_PRIM_OP;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _SYNC_EXTERNAL_ */
diff --git a/drivers/staging/imgtec/pvr_drm.c b/drivers/staging/imgtec/pvr_drm.c
new file mode 100644
index 0000000..7daabe0
--- /dev/null
+++ b/drivers/staging/imgtec/pvr_drm.c
@@ -0,0 +1,266 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
+/*************************************************************************/ /*!
+@File
+@Title          PowerVR DRM driver
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <drm/drm.h>
+#include <drm/drmP.h> /* include before drm_crtc.h for kernels older than 3.9 */
+#include <drm/drm_crtc.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/version.h>
+
+#include "module_common.h"
+#include "pvr_drm.h"
+#include "pvr_drv.h"
+#include "pvrversion.h"
+#include "services_kernel_client.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
+#define DRIVER_RENDER 0
+#define DRM_RENDER_ALLOW 0
+#endif
+
+#define PVR_DRM_DRIVER_NAME PVR_DRM_NAME
+#define PVR_DRM_DRIVER_DESC "Imagination Technologies PVR DRM"
+#define	PVR_DRM_DRIVER_DATE "20110701"
+
+
+static int pvr_pm_suspend(struct device *dev)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+
+	DRM_DEBUG_DRIVER("device %p\n", dev);
+
+	return PVRSRVCommonDeviceSuspend(ddev->dev_private);
+}
+
+static int pvr_pm_resume(struct device *dev)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+
+	DRM_DEBUG_DRIVER("device %p\n", dev);
+
+	return PVRSRVCommonDeviceResume(ddev->dev_private);
+}
+
+const struct dev_pm_ops pvr_pm_ops = {
+	.suspend = pvr_pm_suspend,
+	.resume = pvr_pm_resume,
+};
+
+
+static int pvr_drm_load(struct drm_device *ddev, unsigned long flags)
+{
+	struct _PVRSRV_DEVICE_NODE_ *dev_node;
+	enum PVRSRV_ERROR srv_err;
+	int err;
+
+	DRM_DEBUG_DRIVER("device %p\n", ddev->dev);
+
+	/*
+	 * The equivalent is done for PCI modesetting drivers by
+	 * drm_get_pci_dev()
+	 */
+	if (ddev->platformdev)
+		platform_set_drvdata(ddev->platformdev, ddev);
+
+	srv_err = PVRSRVDeviceCreate(ddev->dev, &dev_node);
+	if (srv_err != PVRSRV_OK) {
+		DRM_ERROR("failed to create device node for device %p (%s)\n",
+			  ddev->dev, PVRSRVGetErrorStringKM(srv_err));
+		if (srv_err == PVRSRV_ERROR_PROBE_DEFER)
+			err = -EPROBE_DEFER;
+		else
+			err = -ENODEV;
+		goto err_exit;
+	}
+
+	err = PVRSRVCommonDeviceInit(dev_node);
+	if (err) {
+		DRM_ERROR("device %p initialisation failed (err=%d)\n",
+			  ddev->dev, err);
+		goto err_device_destroy;
+	}
+
+	drm_mode_config_init(ddev);
+	ddev->dev_private = dev_node;
+
+	return 0;
+
+err_device_destroy:
+	PVRSRVDeviceDestroy(dev_node);
+err_exit:
+	return err;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
+static int pvr_drm_unload(struct drm_device *ddev)
+#else
+static void pvr_drm_unload(struct drm_device *ddev)
+#endif
+{
+	DRM_DEBUG_DRIVER("device %p\n", ddev->dev);
+
+	drm_mode_config_cleanup(ddev);
+
+	PVRSRVCommonDeviceDeinit(ddev->dev_private);
+
+	PVRSRVDeviceDestroy(ddev->dev_private);
+	ddev->dev_private = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
+	return 0;
+#endif
+}
+
+static int pvr_drm_open(struct drm_device *ddev, struct drm_file *dfile)
+{
+	int err;
+
+	if (!try_module_get(THIS_MODULE)) {
+		DRM_ERROR("failed to get module reference\n");
+		return -ENOENT;
+	}
+
+	err = PVRSRVCommonDeviceOpen(ddev->dev_private, dfile);
+	if (err)
+		module_put(THIS_MODULE);
+
+	return err;
+}
+
+static void pvr_drm_release(struct drm_device *ddev, struct drm_file *dfile)
+{
+	PVRSRVCommonDeviceRelease(ddev->dev_private, dfile);
+
+	module_put(THIS_MODULE);
+}
+
+/*
+ * The DRM global lock is taken for ioctls unless the DRM_UNLOCKED flag is set.
+ * If you revise one of the driver specific ioctls, or add a new one, that has
+ * DRM_UNLOCKED set then consider whether the gPVRSRVLock mutex needs to be
+ * taken.
+ */
+static struct drm_ioctl_desc pvr_drm_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(PVR_SRVKM_CMD, PVRSRV_BridgeDispatchKM, DRM_RENDER_ALLOW | DRM_UNLOCKED),
+#if defined(PDUMP)
+	DRM_IOCTL_DEF_DRV(PVR_DBGDRV_CMD, dbgdrv_ioctl, DRM_RENDER_ALLOW | DRM_AUTH | DRM_UNLOCKED),
+#endif
+};
+
+#if defined(CONFIG_COMPAT)
+#if defined(PDUMP)
+static drm_ioctl_compat_t *pvr_drm_compat_ioctls[] = {
+	[DRM_PVR_DBGDRV_CMD] = dbgdrv_ioctl_compat,
+};
+#endif
+
+static long pvr_compat_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+
+	if (nr < DRM_COMMAND_BASE)
+		return drm_compat_ioctl(file, cmd, arg);
+
+#if defined(PDUMP)
+	if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(pvr_drm_compat_ioctls)) {
+		drm_ioctl_compat_t *pfnBridge;
+
+		pfnBridge = pvr_drm_compat_ioctls[nr - DRM_COMMAND_BASE];
+		if (pfnBridge)
+			return pfnBridge(file, cmd, arg);
+	}
+#endif
+
+	return drm_ioctl(file, cmd, arg);
+}
+#endif /* defined(CONFIG_COMPAT) */
+
+static const struct file_operations pvr_drm_fops = {
+	.owner			= THIS_MODULE,
+	.open			= drm_open,
+	.release		= drm_release,
+	/*
+	 * FIXME:
+	 * Wrap this in a function that checks enough data has been
+	 * supplied with the ioctl (e.g. _IOCDIR(nr) != _IOC_NONE &&
+	 * _IOC_SIZE(nr) == size).
+	 */
+	.unlocked_ioctl		= drm_ioctl,
+#if defined(CONFIG_COMPAT)
+	.compat_ioctl		= pvr_compat_ioctl,
+#endif
+	.mmap			= PVRSRV_MMap,
+	.poll			= drm_poll,
+	.read			= drm_read,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
+	.fasync			= drm_fasync,
+#endif
+};
+
+const struct drm_driver pvr_drm_generic_driver = {
+	.driver_features	= DRIVER_MODESET | DRIVER_RENDER,
+
+	.dev_priv_size		= 0,
+	.load			= pvr_drm_load,
+	.unload			= pvr_drm_unload,
+	.open			= pvr_drm_open,
+	.postclose		= pvr_drm_release,
+
+	.ioctls			= pvr_drm_ioctls,
+	.num_ioctls		= ARRAY_SIZE(pvr_drm_ioctls),
+	.fops			= &pvr_drm_fops,
+
+	.name			= PVR_DRM_DRIVER_NAME,
+	.desc			= PVR_DRM_DRIVER_DESC,
+	.date			= PVR_DRM_DRIVER_DATE,
+	.major			= PVRVERSION_MAJ,
+	.minor			= PVRVERSION_MIN,
+	.patchlevel		= PVRVERSION_BUILD,
+};
diff --git a/drivers/staging/imgtec/rogue/debug_request_ids.h b/drivers/staging/imgtec/pvr_drv.h
similarity index 72%
rename from drivers/staging/imgtec/rogue/debug_request_ids.h
rename to drivers/staging/imgtec/pvr_drv.h
index f76c932..e92cfe9 100644
--- a/drivers/staging/imgtec/rogue/debug_request_ids.h
+++ b/drivers/staging/imgtec/pvr_drv.h
@@ -1,9 +1,10 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File
-@Title          Debug requester ID's
+@Title          PowerVR DRM driver
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header contains the defines for the debug ID's for all the
-				services components
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,17 +42,28 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
- 
-#ifndef __DEBUG_REQUEST_IDS__
-#define __DEBUG_REQUEST_IDS__
 
-/* Services controlled devices should be 1st */
-#define DEBUG_REQUEST_RGX			(0)
-#define DEBUG_REQUEST_DC			(1)
-#define DEBUG_REQUEST_SERVERSYNC	(2)
-#define DEBUG_REQUEST_SYS           (3)
-#define DEBUG_REQUEST_ANDROIDSYNC   (4)
-#define DEBUG_REQUEST_DRMDISPLAY    (5)
-#define DEBUG_REQUEST_LINUXFENCE    (6)
+#if !defined(__PVR_DRV_H__)
+#define __PVR_DRV_H__
 
-#endif /* __DEBUG_REQUEST_IDS__ */
+#include <drm/drmP.h>
+#include <linux/pm.h>
+
+struct file;
+struct vm_area_struct;
+
+extern const struct dev_pm_ops pvr_pm_ops;
+extern const struct drm_driver pvr_drm_generic_driver;
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+int dbgdrv_ioctl(struct drm_device *dev, void *arg, struct drm_file *file);
+int dbgdrv_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg,
+			    struct drm_file *file);
+int PVRSRV_MMap(struct file *file, struct vm_area_struct *ps_vma);
+
+#endif /* !defined(__PVR_DRV_H__) */
diff --git a/drivers/staging/imgtec/pvr_sync.c b/drivers/staging/imgtec/pvr_sync.c
index e78af6a..4b66695 100644
--- a/drivers/staging/imgtec/pvr_sync.c
+++ b/drivers/staging/imgtec/pvr_sync.c
@@ -1,6 +1,9 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File           pvr_sync.c
 @Title          Kernel driver for Android's sync mechanism
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,7 +42,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #include "pvr_sync.h"
 #include "pvr_fd_sync_kernel.h"
@@ -66,15 +68,9 @@
 #endif
 #endif
 
-/*
- * get_unused_fd was first removed from vanilla kernels in 3.19 and
- * get_unused_fd_flags was first exported from vanilla kernels in 3.7.
- */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
-#define get_unused_fd() get_unused_fd_flags(0)
-#endif
+#include "kernel_compatibility.h"
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0))
 
 static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
 {
@@ -89,7 +85,7 @@
 #define for_each_sync_pt(s, f, c) \
 	list_for_each_entry((s), &(f)->pt_list_head, pt_list)
 
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) */
 
 static inline int sync_pt_get_status(struct sync_pt *pt)
 {
@@ -104,7 +100,7 @@
 	     (c)++,   (s) = (c) < (f)->num_fences ? \
 		(struct sync_pt *)(f)->cbs[c].sync_pt : NULL)
 
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) */
 
 /* #define DEBUG_OUTPUT 1 */
 
@@ -135,10 +131,10 @@
 
 struct pvr_sync_append_data {
 	u32					nr_updates;
-	PRGXFWIF_UFO_ADDR			*update_ufo_addresses;
+	struct _RGXFWIF_DEV_VIRTADDR_		*update_ufo_addresses;
 	u32					*update_values;
 	u32					nr_checks;
-	PRGXFWIF_UFO_ADDR			*check_ufo_addresses;
+	struct _RGXFWIF_DEV_VIRTADDR_		*check_ufo_addresses;
 	u32					*check_values;
 
 	/* The cleanup list is needed for rollback (as that's the only op
@@ -305,9 +301,6 @@
 
 /* Global data for the sync driver */
 static struct {
-	/* Services connection */
-	void *device_cookie;
-
 	/* Complete notify handle */
 	void *command_complete_handle;
 
@@ -363,6 +356,8 @@
 static LIST_HEAD(sync_fence_put_list);
 static DEFINE_SPINLOCK(sync_fence_put_list_spinlock);
 
+static void pvr_sync_update_all_timelines(void *command_complete_handle);
+
 static inline void set_sync_value(struct pvr_sync_native_sync_prim *sync,
 				  u32 value)
 {
@@ -432,6 +427,7 @@
 		unsigned int cleanup_count = 0;
 		unsigned int info1_pos = 0;
 		struct list_head *pos;
+
 		info1[0] = 0;
 
 		list_for_each(pos, &kernel->cleanup_sync_list) {
@@ -489,12 +485,13 @@
 {
 	struct pvr_sync_native_sync_prim *sync;
 	enum PVRSRV_ERROR error = PVRSRV_OK;
+	u32 sync_addr;
 
 	mutex_lock(&sync_pool_mutex);
 
 	if (list_empty(&sync_pool_free_list)) {
 		/* If there is nothing in the pool, create a new sync prim. */
-		sync = kmalloc(sizeof(struct pvr_sync_native_sync_prim),
+		sync = kmalloc(sizeof(*sync),
 			       GFP_KERNEL);
 		if (!sync) {
 			pr_err("pvr_sync: %s: Failed to allocate sync data\n",
@@ -511,7 +508,13 @@
 			goto err_free;
 		}
 
-		sync->vaddr = SyncPrimGetFirmwareAddr(sync->client_sync);
+		error = SyncPrimGetFirmwareAddr(sync->client_sync, &sync_addr);
+		if (error != PVRSRV_OK) {
+			pr_err("pvr_sync: %s: Failed to get FW address (%s)\n",
+			       __func__, PVRSRVGetErrorStringKM(error));
+			goto err_sync_prim_free;
+		}
+		sync->vaddr = sync_addr;
 
 		list_add_tail(&sync->list, &sync_pool_active_list);
 		++sync_pool_created;
@@ -527,7 +530,6 @@
 	sync->type = type;
 
 	strncpy(sync->class, class_name, sizeof(sync->class));
-	/* make sure string is null terminated */
 	sync->class[sizeof(sync->class) - 1] = '\0';
 	/* Its crucial to reset the sync to zero */
 	set_sync_value(sync, 0);
@@ -538,6 +540,9 @@
 	mutex_unlock(&sync_pool_mutex);
 	return error;
 
+err_sync_prim_free:
+	SyncPrimFree(sync->client_sync);
+
 err_free:
 	kfree(sync);
 	goto err_unlock;
@@ -585,9 +590,9 @@
 }
 
 static void pvr_sync_debug_request(void *hDebugRequestHandle,
-								   u32 ui32VerbLevel,
-								   DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-								   void *pvDumpDebugFile)
+				   u32 ui32VerbLevel,
+				   DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				   void *pvDumpDebugFile)
 {
 	struct pvr_sync_native_sync_prim *sync;
 
@@ -622,12 +627,12 @@
 					  type_names[sync->type]);
 		}
 #if 0
-		PVR_DUMPDEBUG_LOG(g_pfnDumpDebugPrintf,
+		PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf,
 				  "Dumping all unused syncs");
 		list_for_each_entry(sync, &sync_pool_free_list, list) {
 			BUG_ON(sync->type >= ARRAY_SIZE(type_names));
 
-			PVR_DUMPDEBUG_LOG(g_pfnDumpDebugPrintf,
+			PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf,
 					  "\tID = %d, FWAddr = 0x%08x: Current = 0x%08x, Next = 0x%08x, %s (%s)",
 					  sync->id, sync->vaddr,
 					  get_sync_value(sync),
@@ -649,7 +654,7 @@
 
 	pvr_pt_b = (struct pvr_sync_pt *)
 		sync_pt_create(sync_pt_parent(sync_pt),
-			       sizeof(struct pvr_sync_pt));
+			       sizeof(*pvr_pt_b));
 	if (!pvr_pt_b) {
 		pr_err("pvr_sync: %s: Failed to dup sync pt\n", __func__);
 		goto err_out;
@@ -820,9 +825,8 @@
 	 *
 	 * 123456789012345678901234567890123456789012345678901234567890123
 	 *
-	 * ID     FW ADDR    C/N # REF CLEANUP_COUNT
-	 *                               TAKEN
-	 * 123456 0xdeadbeef 0/1 # r=2 1 123456
+	 * ID     FW ADDR    C/N # REF TAKEN  CLEANUP_COUNT
+	 * 123456 0xdeadbeef 0/1 # r=2 123456 1
 	 */
 	if (kernel) {
 		unsigned int cleanup_count = 0;
@@ -840,6 +844,7 @@
 			 atomic_read(&pvr_pt->sync_data->kref.refcount),
 			 cleanup_count,
 			 pvr_pt->sync_data->timeline_update_value);
+
 	} else {
 		snprintf(str, size, "idle # r=%d %u",
 			 atomic_read(&pvr_pt->sync_data->kref.refcount),
@@ -856,14 +861,14 @@
 	struct pvr_sync_data *sync_data = NULL;
 	enum PVRSRV_ERROR error;
 
-	sync_data = kzalloc(sizeof(struct pvr_sync_data), GFP_KERNEL);
+	sync_data = kzalloc(sizeof(*sync_data), GFP_KERNEL);
 	if (!sync_data)
 		goto err_out;
 
 	kref_init(&sync_data->kref);
 
 	sync_data->kernel =
-		kzalloc(sizeof(struct pvr_sync_kernel_pair),
+		kzalloc(sizeof(*sync_data->kernel),
 		GFP_KERNEL);
 
 	if (!sync_data->kernel)
@@ -943,7 +948,7 @@
 	struct pvr_sync_data *sync_data = pvr_pt->sync_data;
 	struct pvr_sync_kernel_pair *kernel = sync_data->kernel;
 
-	if (size < sizeof(struct pvr_sync_pt_info))
+	if (size < sizeof(*info))
 		return -ENOMEM;
 
 	info->ui32TlTaken = sync_data->timeline_update_value;
@@ -960,7 +965,7 @@
 		info->ui32NextOp = 0;
 	}
 
-	return sizeof(struct pvr_sync_pt_info);
+	return sizeof(*info);
 }
 
 /* foreign sync handling */
@@ -1016,7 +1021,7 @@
 		goto err_out;
 	}
 
-	kernel = kmalloc(sizeof(struct pvr_sync_kernel_pair), GFP_KERNEL);
+	kernel = kmalloc(sizeof(*kernel), GFP_KERNEL);
 	if (!kernel) {
 		pr_err("pvr_sync: %s: Failed to allocate sync kernel\n",
 		       __func__);
@@ -1025,7 +1030,7 @@
 
 	INIT_LIST_HEAD(&kernel->cleanup_sync_list);
 
-	sync_fence = kmalloc(sizeof(struct pvr_sync_fence), GFP_KERNEL);
+	sync_fence = kmalloc(sizeof(*sync_fence), GFP_KERNEL);
 	if (!sync_fence) {
 		pr_err("pvr_sync: %s: Failed to allocate pvr sync fence\n",
 		       __func__);
@@ -1044,8 +1049,8 @@
 
 	kernel->fence_sync->next_value++;
 
-	error = sync_pool_get(&cleanup_sync,
-			      fence->name, SYNC_PT_FOREIGN_CLEANUP_TYPE);
+	error = sync_pool_get(&cleanup_sync, fence->name,
+		SYNC_PT_FOREIGN_CLEANUP_TYPE);
 	if (error != PVRSRV_OK) {
 		pr_err("pvr_sync: %s: Failed to allocate cleanup sync prim (%s)\n",
 		       __func__, PVRSRVGetErrorStringKM(error));
@@ -1057,7 +1062,7 @@
 	list_add(&cleanup_sync->cleanup_list, &kernel->cleanup_sync_list);
 
 	/* The custom waiter structure is freed in the waiter callback */
-	waiter = kmalloc(sizeof(struct pvr_sync_fence_waiter), GFP_KERNEL);
+	waiter = kmalloc(sizeof(*waiter), GFP_KERNEL);
 	if (!waiter) {
 		pr_err("pvr_sync: %s: Failed to allocate waiter\n", __func__);
 		goto err_free_cleanup_sync;
@@ -1120,7 +1125,7 @@
 	sync_data->kernel->fence_sync->next_value++;
 
 	pvr_pt = (struct pvr_sync_pt *)
-		sync_pt_create(timeline->obj, sizeof(struct pvr_sync_pt));
+		sync_pt_create(timeline->obj, sizeof(*pvr_pt));
 
 	if (!pvr_pt) {
 		pr_err("pvr_sync: %s: Failed to create sync pt\n", __func__);
@@ -1149,23 +1154,23 @@
 static const struct file_operations pvr_sync_fops;
 
 enum PVRSRV_ERROR pvr_sync_append_fences(
-	const char                  *name,
-	const s32                   check_fence_fd,
-	const s32                   update_timeline_fd,
-	const u32                   nr_updates,
-	const PRGXFWIF_UFO_ADDR     *update_ufo_addresses,
-	const u32                   *update_values,
-	const u32                   nr_checks,
-	const PRGXFWIF_UFO_ADDR     *check_ufo_addresses,
-	const u32                   *check_values,
-	struct pvr_sync_append_data **append_sync_data)
+	const char				*name,
+	const s32				check_fence_fd,
+	const s32				update_timeline_fd,
+	const u32				nr_updates,
+	const struct _RGXFWIF_DEV_VIRTADDR_	*update_ufo_addresses,
+	const u32				*update_values,
+	const u32				nr_checks,
+	const struct _RGXFWIF_DEV_VIRTADDR_	*check_ufo_addresses,
+	const u32				*check_values,
+	struct pvr_sync_append_data		**append_sync_data)
 {
 	struct pvr_sync_native_sync_prim **cleanup_sync_pos;
 	struct pvr_sync_pt *update_point = NULL;
 	struct sync_fence *update_fence = NULL;
 	struct pvr_sync_append_data *sync_data;
-	PRGXFWIF_UFO_ADDR *update_address_pos;
-	PRGXFWIF_UFO_ADDR *check_address_pos;
+	struct _RGXFWIF_DEV_VIRTADDR_ *update_address_pos;
+	struct _RGXFWIF_DEV_VIRTADDR_ *check_address_pos;
 	struct pvr_sync_timeline *timeline;
 	unsigned int num_used_sync_updates;
 	unsigned int num_used_sync_checks;
@@ -1180,7 +1185,7 @@
 	}
 
 	sync_data =
-		kzalloc(sizeof(struct pvr_sync_append_data), GFP_KERNEL);
+		kzalloc(sizeof(*sync_data), GFP_KERNEL);
 	if (!sync_data) {
 		err = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto err_out;
@@ -1239,7 +1244,12 @@
 			goto err_free_append_data;
 		}
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) && \
+    defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
+		update_fence = sync_fence_create(name, &update_point->pt.base);
+#else
 		update_fence = sync_fence_create(name, &update_point->pt);
+#endif
 		if (!update_fence) {
 			struct pvr_sync_native_sync_prim *fence_prim =
 				update_point->sync_data->kernel->fence_sync;
@@ -1302,11 +1312,11 @@
 
 			pvr_pt = (struct pvr_sync_pt *)sync_pt;
 			sync_kernel = pvr_pt->sync_data->kernel;
-			if (!sync_kernel)
-				continue;
 
-			if (is_sync_met(sync_kernel->fence_sync))
+			if (!sync_kernel ||
+			    is_sync_met(sync_kernel->fence_sync)) {
 				continue;
+			}
 
 			/* We will use the above sync for "check" only. In this
 			 * case also insert a "cleanup" update command into the
@@ -1347,9 +1357,8 @@
 
 	if (sync_data->nr_updates > 0) {
 		sync_data->update_ufo_addresses =
-			kzalloc(sizeof(PRGXFWIF_UFO_ADDR) *
-					sync_data->nr_updates,
-				GFP_KERNEL);
+			kzalloc(sizeof(*sync_data->update_ufo_addresses) *
+					sync_data->nr_updates, GFP_KERNEL);
 		if (!sync_data->update_ufo_addresses) {
 			pr_err("pvr_sync: %s: Failed to allocate update UFO address list\n",
 				__func__);
@@ -1358,8 +1367,8 @@
 		}
 
 		sync_data->update_values =
-			kzalloc(sizeof(u32) * sync_data->nr_updates,
-				GFP_KERNEL);
+			kzalloc(sizeof(*sync_data->update_values) *
+				sync_data->nr_updates, GFP_KERNEL);
 		if (!sync_data->update_values) {
 			pr_err("pvr_sync: %s: Failed to allocate update value list\n",
 				__func__);
@@ -1371,9 +1380,8 @@
 	if (sync_data->nr_checks > 0) {
 
 		sync_data->check_ufo_addresses =
-			kzalloc(sizeof(PRGXFWIF_UFO_ADDR) *
-					sync_data->nr_checks,
-				GFP_KERNEL);
+			kzalloc(sizeof(*sync_data->check_ufo_addresses) *
+					sync_data->nr_checks, GFP_KERNEL);
 		if (!sync_data->check_ufo_addresses) {
 			pr_err("pvr_sync: %s: Failed to allocate check UFO address list\n",
 				__func__);
@@ -1382,8 +1390,8 @@
 		}
 
 		sync_data->check_values =
-			kzalloc(sizeof(u32) * sync_data->nr_checks,
-				GFP_KERNEL);
+			kzalloc(sizeof(*sync_data->check_values) *
+				sync_data->nr_checks, GFP_KERNEL);
 		if (!sync_data->check_values) {
 			pr_err("pvr_sync: %s: Failed to allocate check value list\n",
 				__func__);
@@ -1394,7 +1402,7 @@
 
 	if (sync_data->nr_cleanup_syncs > 0) {
 		sync_data->cleanup_syncs =
-			kzalloc(sizeof(struct pvr_sync_native_sync_prim *) *
+			kzalloc(sizeof(*sync_data->cleanup_syncs) *
 				sync_data->nr_cleanup_syncs, GFP_KERNEL);
 		if (!sync_data->cleanup_syncs) {
 			pr_err("pvr_sync: %s: Failed to allocate cleanup rollback list\n",
@@ -1410,7 +1418,6 @@
 	check_value_pos = sync_data->check_values;
 	cleanup_sync_pos = sync_data->cleanup_syncs;
 
-
 	/* Everything should be allocated/sanity checked. No errors are
 	 * possible after this point.
 	 */
@@ -1464,8 +1471,8 @@
 				struct pvr_sync_native_sync_prim *fence_sync =
 					foreign_sync_kernel->fence_sync;
 				struct pvr_sync_native_sync_prim *cleanup_sync =
-					foreign_sync_kernel->current_cleanup_sync;
-
+					foreign_sync_kernel->
+						current_cleanup_sync;
 
 				(*check_address_pos++).ui32Addr =
 					fence_sync->vaddr;
@@ -1477,7 +1484,8 @@
 				*update_value_pos++ =
 					++cleanup_sync->next_value;
 				*cleanup_sync_pos++ = cleanup_sync;
-				foreign_sync_kernel->current_cleanup_sync = NULL;
+				foreign_sync_kernel->current_cleanup_sync =
+					NULL;
 			}
 		}
 	}
@@ -1525,17 +1533,17 @@
 	/* Append original check and update sync values/addresses */
 	if (update_ufo_addresses)
 		memcpy(update_address_pos, update_ufo_addresses,
-			   sizeof(PRGXFWIF_UFO_ADDR) * nr_updates);
+			sizeof(*update_ufo_addresses) * nr_updates);
 	if (update_values)
 		memcpy(update_value_pos, update_values,
-			   sizeof(u32) * nr_updates);
+			sizeof(*update_values) * nr_updates);
 
 	if (check_ufo_addresses)
 		memcpy(check_address_pos, check_ufo_addresses,
-			   sizeof(PRGXFWIF_UFO_ADDR) * nr_checks);
+			sizeof(*check_ufo_addresses) * nr_checks);
 	if (check_values)
 		memcpy(check_value_pos, check_values,
-			   sizeof(u32) * nr_checks);
+			sizeof(*check_values) * nr_checks);
 
 	*append_sync_data = sync_data;
 
@@ -1554,7 +1562,7 @@
 }
 
 void pvr_sync_get_updates(const struct pvr_sync_append_data *sync_data,
-	u32 *nr_fences, PRGXFWIF_UFO_ADDR **ufo_addrs, u32 **values)
+	u32 *nr_fences, struct _RGXFWIF_DEV_VIRTADDR_ **ufo_addrs, u32 **values)
 {
 	*nr_fences = sync_data->nr_updates;
 	*ufo_addrs = sync_data->update_ufo_addresses;
@@ -1562,7 +1570,7 @@
 }
 
 void pvr_sync_get_checks(const struct pvr_sync_append_data *sync_data,
-	u32 *nr_fences, PRGXFWIF_UFO_ADDR **ufo_addrs, u32 **values)
+	u32 *nr_fences, struct _RGXFWIF_DEV_VIRTADDR_ **ufo_addrs, u32 **values)
 {
 	*nr_fences = sync_data->nr_checks;
 	*ufo_addrs = sync_data->check_ufo_addresses;
@@ -1673,6 +1681,8 @@
 		complete_sync(sync_data->update_sync);
 	if (sync_data->update_timeline_sync)
 		complete_sync(sync_data->update_timeline_sync);
+
+	pvr_sync_update_all_timelines(NULL);
 }
 
 /* ioctl and fops handling */
@@ -1689,19 +1699,19 @@
 
 	timeline_wrapper = (struct pvr_sync_timeline_wrapper *)
 		sync_timeline_create(&pvr_sync_timeline_ops,
-			sizeof(struct pvr_sync_timeline_wrapper), task_comm);
+			sizeof(*timeline_wrapper), task_comm);
 	if (!timeline_wrapper) {
 		pr_err("pvr_sync: %s: sync_timeline_create failed\n", __func__);
 		goto err_out;
 	}
 
-	timeline = kmalloc(sizeof(struct pvr_sync_timeline), GFP_KERNEL);
+	timeline = kmalloc(sizeof(*timeline), GFP_KERNEL);
 	if (!timeline) {
 		pr_err("pvr_sync: %s: Out of memory\n", __func__);
 		goto err_free_timeline_wrapper;
 	}
 
-	timeline->kernel = kzalloc(sizeof(struct pvr_sync_kernel_pair),
+	timeline->kernel = kzalloc(sizeof(*timeline->kernel),
 				   GFP_KERNEL);
 	if (!timeline->kernel) {
 		pr_err("pvr_sync: %s: Out of memory\n", __func__);
@@ -1711,10 +1721,8 @@
 	INIT_LIST_HEAD(&timeline->kernel->cleanup_sync_list);
 
 	OSAcquireBridgeLock();
-	PMRLock();
 	error = sync_pool_get(&timeline->kernel->fence_sync,
 			      task_comm, SYNC_TL_TYPE);
-	PMRUnlock();
 	OSReleaseBridgeLock();
 
 	if (error != PVRSRV_OK) {
@@ -1788,7 +1796,7 @@
 
 	mutex_lock(&sync_pool_mutex);
 	strlcpy(timeline->kernel->fence_sync->class, data.szName,
-	        sizeof(timeline->kernel->fence_sync->class));
+		sizeof(timeline->kernel->fence_sync->class));
 	mutex_unlock(&sync_pool_mutex);
 err:
 	return err;
@@ -1845,7 +1853,12 @@
 	}
 
 	data.name[sizeof(data.name) - 1] = '\0';
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) && \
+    defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
+	fence = sync_fence_create(data.name, &sync_pt->base);
+#else
 	fence = sync_fence_create(data.name, sync_pt);
+#endif
 	if (!fence) {
 		pr_err("pvr_sync: %s: Failed to create a fence (%d)\n",
 		       __func__, fd);
@@ -1959,7 +1972,6 @@
 		/* Check if this sync is not used anymore. */
 		if (!is_sync_met(kernel->fence_sync))
 			continue;
-
 		list_for_each(pos, &kernel->cleanup_sync_list) {
 			struct pvr_sync_native_sync_prim *cleanup_sync =
 				list_entry(pos,
@@ -2132,7 +2144,7 @@
 	mutex_unlock(&timeline_list_mutex);
 }
 
-enum PVRSRV_ERROR pvr_sync_init(void)
+enum PVRSRV_ERROR pvr_sync_init(void *device_cookie)
 {
 	enum PVRSRV_ERROR error;
 	int err;
@@ -2141,25 +2153,17 @@
 
 	atomic_set(&pvr_sync_data.sync_id, 0);
 
-	error = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_RGX,
-					  &pvr_sync_data.device_cookie);
-	if (error != PVRSRV_OK) {
-		pr_err("pvr_sync: %s: Failed to initialise services (%s)\n",
-		       __func__, PVRSRVGetErrorStringKM(error));
-		goto err_out;
-	}
-
-	error = AcquireGlobalEventObjectServer(
+	error = PVRSRVAcquireGlobalEventObjectKM(
 		&pvr_sync_data.event_object_handle);
 	if (error != PVRSRV_OK) {
 		pr_err("pvr_sync: %s: Failed to acquire global event object (%s)\n",
 			__func__, PVRSRVGetErrorStringKM(error));
-		goto err_release_device_data;
+		goto err_out;
 	}
 
 	OSAcquireBridgeLock();
 
-	error = SyncPrimContextCreate(pvr_sync_data.device_cookie,
+	error = SyncPrimContextCreate(device_cookie,
 				      &pvr_sync_data.sync_prim_context);
 	if (error != PVRSRV_OK) {
 		pr_err("pvr_sync: %s: Failed to create sync prim context (%s)\n",
@@ -2194,7 +2198,7 @@
 	error = PVRSRVRegisterCmdCompleteNotify(
 			&pvr_sync_data.command_complete_handle,
 			&pvr_sync_update_all_timelines,
-			&pvr_sync_data.device_cookie);
+			&device_cookie);
 	if (error != PVRSRV_OK) {
 		pr_err("pvr_sync: %s: Failed to register MISR notification (%s)\n",
 		       __func__, PVRSRVGetErrorStringKM(error));
@@ -2203,6 +2207,7 @@
 
 	error = PVRSRVRegisterDbgRequestNotify(
 			&pvr_sync_data.debug_notify_handle,
+			device_cookie,
 			pvr_sync_debug_request,
 			DEBUG_REQUEST_ANDROIDSYNC,
 			NULL);
@@ -2237,9 +2242,7 @@
 	SyncPrimContextDestroy(pvr_sync_data.sync_prim_context);
 	OSReleaseBridgeLock();
 err_release_event_object:
-	ReleaseGlobalEventObjectServer(pvr_sync_data.event_object_handle);
-err_release_device_data:
-	PVRSRVReleaseDeviceDataKM(pvr_sync_data.device_cookie);
+	PVRSRVReleaseGlobalEventObjectKM(pvr_sync_data.event_object_handle);
 err_out:
 
 	return error;
@@ -2270,7 +2273,5 @@
 
 	OSReleaseBridgeLock();
 
-	ReleaseGlobalEventObjectServer(pvr_sync_data.event_object_handle);
-
-	PVRSRVReleaseDeviceDataKM(pvr_sync_data.device_cookie);
+	PVRSRVReleaseGlobalEventObjectKM(pvr_sync_data.event_object_handle);
 }
diff --git a/drivers/staging/imgtec/pvr_sync.h b/drivers/staging/imgtec/pvr_sync.h
index 1765308..4df9cba 100644
--- a/drivers/staging/imgtec/pvr_sync.h
+++ b/drivers/staging/imgtec/pvr_sync.h
@@ -1,6 +1,9 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File           pvr_sync.h
 @Title          Kernel driver for Android's sync mechanism
+@Codingstyle    LinuxKernel
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,40 +42,39 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 #ifndef _PVR_SYNC_H
 #define _PVR_SYNC_H
 
 #include "pvr_fd_sync_kernel.h"
-#include "rgx_fwif_shared.h"
 
 /* Services internal interface */
-enum PVRSRV_ERROR pvr_sync_init(void);
+enum PVRSRV_ERROR pvr_sync_init(void *device_cookie);
 void pvr_sync_deinit(void);
 
+struct _RGXFWIF_DEV_VIRTADDR_;
 struct pvr_sync_append_data;
 
 enum PVRSRV_ERROR
 pvr_sync_append_fences(
-	const char			*name,
-	const s32			check_fence_fd,
-	const s32			update_timeline_fd,
-	const u32			nr_updates,
-	const PRGXFWIF_UFO_ADDR		*update_ufo_addresses,
-	const u32			*update_values,
-	const u32			nr_checks,
-	const PRGXFWIF_UFO_ADDR		*check_ufo_addresses,
-	const u32			*check_values,
-	struct pvr_sync_append_data	**append_sync_data);
+	const char				*name,
+	const s32				check_fence_fd,
+	const s32				update_timeline_fd,
+	const u32				nr_updates,
+	const struct _RGXFWIF_DEV_VIRTADDR_	*update_ufo_addresses,
+	const u32				*update_values,
+	const u32				nr_checks,
+	const struct _RGXFWIF_DEV_VIRTADDR_	*check_ufo_addresses,
+	const u32				*check_values,
+	struct pvr_sync_append_data		**append_sync_data);
 
 void pvr_sync_get_updates(const struct pvr_sync_append_data *sync_data,
 	u32 *nr_fences,
-	PRGXFWIF_UFO_ADDR **ufo_addrs,
+	struct _RGXFWIF_DEV_VIRTADDR_ **ufo_addrs,
 	u32 **values);
 void pvr_sync_get_checks(const struct pvr_sync_append_data *sync_data,
 	u32 *nr_fences,
-	PRGXFWIF_UFO_ADDR **ufo_addrs,
+	struct _RGXFWIF_DEV_VIRTADDR_ **ufo_addrs,
 	u32 **values);
 
 void pvr_sync_rollback_append_fences(struct pvr_sync_append_data *sync_data);
diff --git a/drivers/staging/imgtec/pvrversion.h b/drivers/staging/imgtec/pvrversion.h
index d4da954..f13ee3d 100644
--- a/drivers/staging/imgtec/pvrversion.h
+++ b/drivers/staging/imgtec/pvrversion.h
@@ -49,20 +49,20 @@
 #define PVR_STR2(X) PVR_STR(X)
 
 #define PVRVERSION_MAJ               1
-#define PVRVERSION_MIN               6
+#define PVRVERSION_MIN               8
 
 #define PVRVERSION_FAMILY           "rogueddk"
-#define PVRVERSION_BRANCHNAME       "1.6"
-#define PVRVERSION_BUILD             4278818
+#define PVRVERSION_BRANCHNAME       "1.8"
+#define PVRVERSION_BUILD             4688949
 #define PVRVERSION_BSCONTROL        "Rogue_DDK_Android"
 
-#define PVRVERSION_STRING           "Rogue_DDK_Android rogueddk 1.6@" PVR_STR2(PVRVERSION_BUILD)
-#define PVRVERSION_STRING_SHORT     "1.6@" PVR_STR2(PVRVERSION_BUILD) ""
+#define PVRVERSION_STRING           "Rogue_DDK_Android rogueddk 1.8@" PVR_STR2(PVRVERSION_BUILD)
+#define PVRVERSION_STRING_SHORT     "1.8@" PVR_STR2(PVRVERSION_BUILD) ""
 
 #define COPYRIGHT_TXT               "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
 
-#define PVRVERSION_BUILD_HI          427
-#define PVRVERSION_BUILD_LO          8818
+#define PVRVERSION_BUILD_HI          468
+#define PVRVERSION_BUILD_LO          8949
 #define PVRVERSION_STRING_NUMERIC    PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
 
 #define PVRVERSION_PACK(MAJ,MIN) ((((MAJ)&0xFFFF) << 16) | (((MIN)&0xFFFF) << 0))
diff --git a/drivers/staging/imgtec/rogue/Makefile b/drivers/staging/imgtec/rogue/Makefile
index aea8ce5..1c89aec 100644
--- a/drivers/staging/imgtec/rogue/Makefile
+++ b/drivers/staging/imgtec/rogue/Makefile
@@ -13,12 +13,12 @@
 obj-$(CONFIG_POWERVR_ROGUE) += pvrsrvkm.o
 
 pvrsrvkm-y += allocmem.o
-pvrsrvkm-y += cache_generic.o
+pvrsrvkm-y += cache_km.o
 pvrsrvkm-y += connection_server.o
 pvrsrvkm-y += debugmisc_server.o
 pvrsrvkm-y += devicemem.o
 pvrsrvkm-y += devicemem_heapcfg.o
-pvrsrvkm-y += devicemem_mmap_stub.o
+pvrsrvkm-y += osmmap_stub.o
 pvrsrvkm-y += devicemem_server.o
 pvrsrvkm-y += devicemem_utils.o
 pvrsrvkm-y += event.o
@@ -27,9 +27,9 @@
 pvrsrvkm-y += hash.o
 pvrsrvkm-y += htbserver.o
 pvrsrvkm-y += htbuffer.o
+pvrsrvkm-y += km_apphint.o
 pvrsrvkm-y += lists.o
 pvrsrvkm-y += mem_utils.o
-pvrsrvkm-y += mm.o
 pvrsrvkm-y += mmu_common.o
 pvrsrvkm-y += module_common.o
 pvrsrvkm-y += osconnection_server.o
@@ -46,7 +46,7 @@
 pvrsrvkm-y += pvr_bridge_k.o
 pvrsrvkm-y += pvr_debug.o
 pvrsrvkm-y += pvr_debugfs.o
-pvrsrvkm-y += pvr_hwperf.o
+pvrsrvkm-y += pvr_notifier.o
 pvrsrvkm-y += pvrsrv.o
 pvrsrvkm-y += ra.o
 pvrsrvkm-y += rgx_compat_bvnc.o
@@ -60,18 +60,22 @@
 pvrsrvkm-y += rgxkicksync.o
 pvrsrvkm-y += rgxlayer_km_impl.o
 pvrsrvkm-y += rgxmem.o
+pvrsrvkm-y += rgxmipsmmuinit.o
 pvrsrvkm-y += rgxmmuinit.o
 pvrsrvkm-y += rgxpower.o
+pvrsrvkm-y += rgxray.o
 pvrsrvkm-y += rgxregconfig.o
+pvrsrvkm-y += rgxsignals.o
 pvrsrvkm-y += rgxstartstop.o
-pvrsrvkm-y += rgxsync.o
 pvrsrvkm-y += rgxta3d.o
+pvrsrvkm-y += rgxtdmtransfer.o
 pvrsrvkm-y += rgxtimecorr.o
 pvrsrvkm-y += rgxtimerquery.o
 pvrsrvkm-y += rgxtransfer.o
 pvrsrvkm-y += rgxutils.o
 pvrsrvkm-y += srvcore.o
 pvrsrvkm-y += sync.o
+pvrsrvkm-y += sync_checkpoint.o
 pvrsrvkm-y += sync_server.o
 pvrsrvkm-y += tlclient.o
 pvrsrvkm-y += tlintern.o
@@ -80,8 +84,6 @@
 pvrsrvkm-y += uniq_key_splay_tree.o
 
 # Kernel srvinit
-pvrsrvkm-y += htbinit.o
-pvrsrvkm-y += os_srvinit_param.o
 pvrsrvkm-y += rgx_compat_bvnc.o
 pvrsrvkm-y += rgx_hwperf_table.o
 pvrsrvkm-y += rgxfwimageutils.o
@@ -89,13 +91,12 @@
 pvrsrvkm-y += rgxlayer_impl.o
 pvrsrvkm-y += rgxsrvinit.o
 pvrsrvkm-y += rgxsrvinit_script.o
-pvrsrvkm-y += srvinit_km.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/dpdump_bridge/client_pdump_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/dpdumpctrl_bridge/client_pdumpctrl_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/drgxpdump_bridge/client_rgxpdump_bridge.o
 pvrsrvkm-y += generated/rgxinit_bridge/client_rgxinit_direct_bridge.o
 
-pvrsrvkm-y += drm_pci_module.o
+pvrsrvkm-$(CONFIG_DRM) += ../pvr_drm.o
 
 pvrsrvkm-$(CONFIG_DMA_SHARED_BUFFER) += physmem_dmabuf.o
 
@@ -144,14 +145,14 @@
 pvrsrvkm-y += generated/mm_bridge/client_mm_direct_bridge.o
 pvrsrvkm-y += generated/cmm_bridge/server_cmm_bridge.o
 pvrsrvkm-y += generated/rgxtq_bridge/server_rgxtq_bridge.o
-pvrsrvkm-y += generated/rgxinit_bridge/server_rgxinit_bridge.o
 pvrsrvkm-y += generated/rgxta3d_bridge/server_rgxta3d_bridge.o
 pvrsrvkm-y += generated/rgxcmp_bridge/server_rgxcmp_bridge.o
+pvrsrvkm-y += generated/rgxsignals_bridge/server_rgxsignals_bridge.o
 pvrsrvkm-y += generated/srvcore_bridge/server_srvcore_bridge.o
 pvrsrvkm-y += generated/sync_bridge/server_sync_bridge.o
 pvrsrvkm-y += generated/sync_bridge/client_sync_direct_bridge.o
-pvrsrvkm-y += generated/cachegeneric_bridge/server_cachegeneric_bridge.o
-pvrsrvkm-y += generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.o
+pvrsrvkm-y += generated/cache_bridge/client_cache_direct_bridge.o
+pvrsrvkm-y += generated/cache_bridge/server_cache_bridge.o
 pvrsrvkm-y += generated/breakpoint_bridge/server_breakpoint_bridge.o
 pvrsrvkm-y += generated/debugmisc_bridge/server_debugmisc_bridge.o
 pvrsrvkm-y += generated/pvrtl_bridge/server_pvrtl_bridge.o
@@ -162,6 +163,8 @@
 pvrsrvkm-y += generated/htbuffer_bridge/server_htbuffer_bridge.o
 pvrsrvkm-y += generated/htbuffer_bridge/client_htbuffer_direct_bridge.o
 pvrsrvkm-y += generated/rgxkicksync_bridge/server_rgxkicksync_bridge.o
+pvrsrvkm-y += generated/rgxray_bridge/server_rgxray_bridge.o
+pvrsrvkm-y += generated/rgxtq2_bridge/server_rgxtq2_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_RESOURCE_INFO) += generated/ri_bridge/server_ri_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_RESOURCE_INFO) += generated/ri_bridge/client_ri_direct_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_DEVICEMEM_HISTORY) += generated/devicememhistory_bridge/server_devicememhistory_bridge.o
@@ -169,6 +172,7 @@
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/pdumpmm_bridge/server_pdumpmm_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/pdumpmm_bridge/client_pdumpmm_direct_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/pdump_bridge/server_pdump_bridge.o
+pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/pdumpctrl_bridge/client_pdumpctrl_direct_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/pdumpctrl_bridge/server_pdumpctrl_bridge.o
 pvrsrvkm-$(CONFIG_POWERVR_ROGUE_PDUMP) += generated/rgxpdump_bridge/server_rgxpdump_bridge.o
 pvrsrvkm-$(CONFIG_DMA_SHARED_BUFFER) += generated/dmabuf_bridge/server_dmabuf_bridge.o
diff --git a/drivers/staging/imgtec/rogue/allocmem.c b/drivers/staging/imgtec/rogue/allocmem.c
index d0f3985..ffabcf5 100644
--- a/drivers/staging/imgtec/rogue/allocmem.c
+++ b/drivers/staging/imgtec/rogue/allocmem.c
@@ -71,7 +71,7 @@
 			 * a whole number of pages, poison the minimum size known to have
 			 * been allocated.
 			 */
-			OSMemSet((void*)pvAddr, OS_MEM_POISON_VALUE, PVR_LINUX_KMALLOC_ALLOCATION_THRESHOLD);
+			OSCachedMemSet((void*)pvAddr, OS_MEM_POISON_VALUE, PVR_LINUX_KMALLOC_ALLOCATION_THRESHOLD);
 #endif
 			vfree(pvAddr);
 }
@@ -80,7 +80,7 @@
 {
 #if defined(DEBUG)
 			/* Poison whole memory block */
-			OSMemSet((void*)pvAddr, OS_MEM_POISON_VALUE, ksize(pvAddr));
+			OSCachedMemSet((void*)pvAddr, OS_MEM_POISON_VALUE, ksize(pvAddr));
 #endif
 			kfree(pvAddr);
 }
@@ -118,7 +118,11 @@
 	return pvRet;
 }
 
-IMG_INTERNAL void OSFreeMem(void *pvMem)
+/*
+ * The parentheses around OSFreeMem prevent the macro in allocmem.h from
+ * applying, as it would break the function's definition.
+ */
+IMG_INTERNAL void (OSFreeMem)(void *pvMem)
 {
 	if (pvMem != NULL)
 	{
@@ -349,7 +353,11 @@
 }
 #endif
 
-IMG_INTERNAL void OSFreeMem(void *pvMem)
+/*
+ * The parentheses around OSFreeMem prevent the macro in allocmem.h from
+ * applying, as it would break the function's definition.
+ */
+IMG_INTERNAL void (OSFreeMem)(void *pvMem)
 {
 	if (pvMem != NULL)
 	{
@@ -357,7 +365,10 @@
 		{
 #if !defined(PVR_DISABLE_KMALLOC_MEMSTATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-			PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_KMALLOC, ksize(pvMem));
+			{
+				IMG_UINT32 *puiTemp = (IMG_UINT32*) (((IMG_BYTE*)pvMem) + (ksize(pvMem) - ALLOCMEM_MEMSTATS_PADDING));
+				PVRSRVStatsDecrMemKAllocStat(ksize(pvMem), *puiTemp);
+			}
 #else
 			PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_KMALLOC,
 			                                (IMG_UINT64)(uintptr_t) pvMem);
@@ -415,7 +426,11 @@
 	return pvRet;
 }
 
-IMG_INTERNAL void OSFreeMemNoStats(void *pvMem)
+/*
+ * The parentheses around OSFreeMemNoStats prevent the macro in allocmem.h from
+ * applying, as it would break the function's definition.
+ */
+IMG_INTERNAL void (OSFreeMemNoStats)(void *pvMem)
 {
 	if (pvMem != NULL)
 	{
diff --git a/drivers/staging/imgtec/rogue/allocmem.h b/drivers/staging/imgtec/rogue/allocmem.h
index f5c18d2..decef99 100644
--- a/drivers/staging/imgtec/rogue/allocmem.h
+++ b/drivers/staging/imgtec/rogue/allocmem.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@File
+@File           allocmem.h
 @Title          memory allocation header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @Description    Memory-Allocation API definitions
@@ -45,13 +45,32 @@
 #define __ALLOCMEM_H__
 
 #include "img_types.h"
+#include "pvr_debug.h"
 
 #if defined (__cplusplus)
 extern "C" {
 #endif
 
 #if !defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) || !defined(DEBUG) || !defined(PVRSRV_ENABLE_PROCESS_STATS) || !defined(PVRSRV_ENABLE_MEMORY_STATS)
+/**************************************************************************/ /*!
+@Function       OSAllocMem
+@Description    Allocates CPU memory. Contents are uninitialized.
+                If passed a size of zero, function should not assert,
+                but just return a NULL pointer.
+@Input          ui32Size        Size of required allocation (in bytes)
+@Return         Pointer to allocated memory on success.
+                Otherwise NULL.
+ */ /**************************************************************************/
 void *OSAllocMem(IMG_UINT32 ui32Size);
+/**************************************************************************/ /*!
+@Function       OSAllocZMem
+@Description    Allocates CPU memory and initializes the contents to zero.
+                If passed a size of zero, function should not assert,
+                but just return a NULL pointer.
+@Input          ui32Size        Size of required allocation (in bytes)
+@Return         Pointer to allocated memory on success.
+                Otherwise NULL.
+ */ /**************************************************************************/
 void *OSAllocZMem(IMG_UINT32 ui32Size);
 #else
 void *_OSAllocMem(IMG_UINT32 ui32Size, void *pvAllocFromFile, IMG_UINT32 ui32AllocFromLine);
@@ -62,24 +81,87 @@
     _OSAllocZMem ((_size), (__FILE__), (__LINE__));
 #endif
 
+/**************************************************************************/ /*!
+@Function       OSAllocMemNoStats
+@Description    Allocates CPU memory. Contents are uninitialized.
+                If passed a size of zero, function should not assert,
+                but just return a NULL pointer.
+                The allocated memory is not accounted for by process stats.
+                Process stats are an optional feature (enabled only when
+                PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
+                of memory allocated to help in debugging. Where this is not
+                required, OSAllocMem() and OSAllocMemNoStats() equate to
+                the same operation.
+@Input          ui32Size        Size of required allocation (in bytes)
+@Return         Pointer to allocated memory on success.
+                Otherwise NULL.
+ */ /**************************************************************************/
 void *OSAllocMemNoStats(IMG_UINT32 ui32Size);
 
+/**************************************************************************/ /*!
+@Function       OSAllocZMemNoStats
+@Description    Allocates CPU memory and initializes the contents to zero.
+                If passed a size of zero, function should not assert,
+                but just return a NULL pointer.
+                The allocated memory is not accounted for by process stats.
+                Process stats are an optional feature (enabled only when
+                PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
+                of memory allocated to help in debugging. Where this is not
+                required, OSAllocZMem() and OSAllocZMemNoStats() equate to
+                the same operation.
+@Input          ui32Size        Size of required allocation (in bytes)
+@Return         Pointer to allocated memory on success.
+                Otherwise NULL.
+ */ /**************************************************************************/
 void *OSAllocZMemNoStats(IMG_UINT32 ui32Size);
 
+/**************************************************************************/ /*!
+@Function       OSFreeMem
+@Description    Frees previously allocated CPU memory.
+@Input          pvCpuVAddr       Pointer to the memory to be freed.
+@Return         None.
+ */ /**************************************************************************/
 void OSFreeMem(void *pvCpuVAddr);
 
-#define OSFREEMEM(_ptr) do \
-	{ OSFreeMem((_ptr)); \
-		(_ptr) = (void*)0; \
-		MSC_SUPPRESS_4127\
-	} while (0)
-
+/**************************************************************************/ /*!
+@Function       OSFreeMemNoStats
+@Description    Frees previously allocated CPU memory.
+                The freed memory does not update the figures in process stats.
+                Process stats are an optional feature (enabled only when
+                PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
+                of memory allocated to help in debugging. Where this is not
+                required, OSFreeMem() and OSFreeMemNoStats() equate to the
+                same operation.
+@Input          pvCpuVAddr       Pointer to the memory to be freed.
+@Return         None.
+ */ /**************************************************************************/
 void OSFreeMemNoStats(void *pvCpuVAddr);
 
-#define OSFREEMEMNOSTATS(_ptr) do \
-	{ OSFreeMemNoStats((_ptr)); \
-		(_ptr) = (void*)0; \
-		MSC_SUPPRESS_4127\
+/*
+ * These macros allow us to catch double-free bugs on DEBUG builds and
+ * prevent crashes on RELEASE builds.
+ */
+
+#if defined(DEBUG)
+#define double_free_sentinel (void*) &OSFreeMem
+#define ALLOCMEM_ASSERT(exp) PVR_ASSERT(exp)
+#else
+#define double_free_sentinel NULL
+#define ALLOCMEM_ASSERT(exp) do {} while(0)
+#endif
+
+#define OSFreeMem(_ptr) do { \
+		ALLOCMEM_ASSERT((_ptr) != double_free_sentinel); \
+		(OSFreeMem)(_ptr); \
+		(_ptr) = double_free_sentinel; \
+		MSC_SUPPRESS_4127 \
+	} while (0)
+
+#define OSFreeMemNoStats(_ptr) do { \
+		ALLOCMEM_ASSERT((_ptr) != double_free_sentinel); \
+		(OSFreeMemNoStats)(_ptr); \
+		(_ptr) = double_free_sentinel; \
+		MSC_SUPPRESS_4127 \
 	} while (0)
 
 #if defined (__cplusplus)
diff --git a/drivers/staging/imgtec/rogue/cache_generic.c b/drivers/staging/imgtec/rogue/cache_generic.c
deleted file mode 100644
index 38eff4a..0000000
--- a/drivers/staging/imgtec/rogue/cache_generic.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*************************************************************************/ /*!
-@File           cache_generic.c
-@Title          CPU generic cache management
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Implements server side code for CPU cache management in a
-                CPU agnostic manner.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#include "cache_generic.h"
-#include "cache_internal.h"
-#include "device.h"
-#include "pvr_debug.h"
-#include "pvrsrv.h"
-#include "osfunc.h"
-#include "pmr.h"
-
-#if defined(SUPPORT_RANGEBASED_CACHEFLUSH)
-//#define CACHEOP_NO_CACHE_LINE_ALIGNED_ROUNDING
-static IMG_UINT32 guiCacheLineSize = 0;
-static size_t guiOSPageSize = 0;
-
-/* Perform requested CacheOp on the CPU data cache for successive cache
-   line worth of bytes up to page or in-page cache-line boundary */
-static INLINE void CacheOpCPURangeBased (PVRSRV_CACHE_OP uiCacheOp,
-										 IMG_BYTE *pbCpuVirtAddr,
-										 IMG_CPU_PHYADDR sCpuPhyAddr,
-										 IMG_DEVMEM_OFFSET_T uiPgAlignedOffset,
-										 IMG_DEVMEM_OFFSET_T uiCLAlignedStartOffset,
-										 IMG_DEVMEM_OFFSET_T uiCLAlignedEndOffset)
-{
-	IMG_BYTE *pbCpuVirtAddrEnd;
-	IMG_BYTE *pbCpuVirtAddrStart;
-	IMG_CPU_PHYADDR sCpuPhyAddrEnd;
-	IMG_CPU_PHYADDR sCpuPhyAddrStart;
-	IMG_DEVMEM_SIZE_T uiRelFlushSize;
-	IMG_DEVMEM_OFFSET_T uiRelFlushOffset;
-	IMG_DEVMEM_SIZE_T uiNextPgAlignedOffset;
-
-	/* These quantities allows us to perform cache operations
-	   at cache-line granularity thereby ensuring we do not
-	   perform more than is necessary */
-	PVR_ASSERT(uiPgAlignedOffset < uiCLAlignedEndOffset);
-	uiRelFlushSize = (IMG_DEVMEM_SIZE_T)guiOSPageSize;
-	uiRelFlushOffset = 0;
-
-	if (uiCLAlignedStartOffset > uiPgAlignedOffset)
-	{
-		/* Zero unless initially starting at an in-page offset */
-		uiRelFlushOffset = uiCLAlignedStartOffset - uiPgAlignedOffset;
-		uiRelFlushSize -= uiRelFlushOffset;
-	}
-
-	/* uiRelFlushSize is guiOSPageSize unless current outstanding CacheOp
-	   size is smaller. The 1st case handles in-page CacheOp range and
-	   the 2nd case handles multiple-page CacheOp range with a last
-	   CacheOp size that is less than guiOSPageSize */
-	uiNextPgAlignedOffset = uiPgAlignedOffset + (IMG_DEVMEM_SIZE_T)guiOSPageSize;
-	if (uiNextPgAlignedOffset < uiPgAlignedOffset)
-	{
-		/* uiNextPgAlignedOffset is greater than uiCLAlignedEndOffset
-		   by implication of this wrap-round; this only happens when
-		   uiPgAlignedOffset is the last page aligned offset */
-		uiRelFlushSize = uiRelFlushOffset ?
-				uiCLAlignedEndOffset - uiCLAlignedStartOffset :
-				uiCLAlignedEndOffset - uiPgAlignedOffset;
-	}
-	else
-	{
-		if (uiNextPgAlignedOffset > uiCLAlignedEndOffset)
-		{
-			uiRelFlushSize = uiRelFlushOffset ?
-					uiCLAlignedEndOffset - uiCLAlignedStartOffset :
-					uiCLAlignedEndOffset - uiPgAlignedOffset;
-		}
-	}
-
-	/* More efficient to request cache maintenance operation for full
-	   relative range as opposed to multiple cache-aligned ranges */
-	pbCpuVirtAddrStart = pbCpuVirtAddr + uiRelFlushOffset;
-	pbCpuVirtAddrEnd = pbCpuVirtAddrStart + uiRelFlushSize;
-	sCpuPhyAddrStart.uiAddr = sCpuPhyAddr.uiAddr + uiRelFlushOffset;
-	sCpuPhyAddrEnd.uiAddr = sCpuPhyAddrStart.uiAddr + uiRelFlushSize;
-
-	switch (uiCacheOp)
-	{
-		case PVRSRV_CACHE_OP_CLEAN:
-			OSCleanCPUCacheRangeKM(pbCpuVirtAddrStart, pbCpuVirtAddrEnd,
-									sCpuPhyAddrStart, sCpuPhyAddrEnd);
-			break;
-		case PVRSRV_CACHE_OP_INVALIDATE:
-			OSInvalidateCPUCacheRangeKM(pbCpuVirtAddrStart, pbCpuVirtAddrEnd,
-									sCpuPhyAddrStart, sCpuPhyAddrEnd);
-			break;
-		case PVRSRV_CACHE_OP_FLUSH:
-			OSFlushCPUCacheRangeKM(pbCpuVirtAddrStart, pbCpuVirtAddrEnd,
-									sCpuPhyAddrStart, sCpuPhyAddrEnd);
-			break;
-		default:
-			PVR_DPF((PVR_DBG_ERROR,	"%s: Invalid cache operation type %d",
-					__FUNCTION__, uiCacheOp));
-			PVR_ASSERT(0);
-			break;
-	}
-}
-
-PVRSRV_ERROR CacheOpQueue(PMR *psPMR,
-						  IMG_DEVMEM_OFFSET_T uiOffset,
-						  IMG_DEVMEM_SIZE_T uiSize,
-						  PVRSRV_CACHE_OP uiCacheOp)
-{
-	IMG_HANDLE hPrivOut;
-	IMG_BOOL bPMRIsSparse;
-	IMG_UINT32 ui32PageIndex;
-	IMG_UINT32 ui32NumOfPages;
-	IMG_DEVMEM_SIZE_T uiOutSize;
-	IMG_DEVMEM_SIZE_T uiPgAlignedSize;
-	IMG_DEVMEM_OFFSET_T uiCLAlignedEndOffset;
-	IMG_DEVMEM_OFFSET_T uiPgAlignedEndOffset;
-	IMG_DEVMEM_OFFSET_T uiCLAlignedStartOffset;
-	IMG_DEVMEM_OFFSET_T uiPgAlignedStartOffset;
-	IMG_DEVMEM_OFFSET_T uiPgAlignedOffsetNext;
-	PVRSRV_CACHE_OP_ADDR_TYPE uiCacheOpAddrType;
-	IMG_BOOL abValid[PMR_MAX_TRANSLATION_STACK_ALLOC];
-	IMG_CPU_PHYADDR asCpuPhyAddr[PMR_MAX_TRANSLATION_STACK_ALLOC];
-	IMG_UINT32 OS_PAGE_SHIFT = (IMG_UINT32) OSGetPageShift();
-	IMG_CPU_PHYADDR *psCpuPhyAddr = asCpuPhyAddr;
-	IMG_BOOL bIsPMRDataRetrieved = IMG_FALSE;
-	PVRSRV_ERROR eError = PVRSRV_OK;
-	IMG_BYTE *pbCpuVirtAddr = NULL;
-	IMG_BOOL *pbValid = abValid;
-
-	if (uiCacheOp == PVRSRV_CACHE_OP_NONE)
-	{
-		PVR_ASSERT(0);
-		return PVRSRV_OK;
-	}
-	else
-	{
-		/* Carry out full dcache operation if size (in pages) qualifies */
-		if ((uiSize >> OS_PAGE_SHIFT) > PVR_DIRTY_PAGECOUNT_FLUSH_THRESHOLD)
-		{
-			eError = OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
-			if (eError == PVRSRV_OK)
-			{
-				return PVRSRV_OK;
-			}
-		}
-
-		if (! guiCacheLineSize)
-		{
-			guiCacheLineSize = OSCPUCacheAttributeSize(PVR_DCACHE_LINE_SIZE);
-			PVR_ASSERT(guiCacheLineSize != 0);
-
-			guiOSPageSize = OSGetPageSize();
-			PVR_ASSERT(guiOSPageSize != 0);
-		}
-	}
-
-	/* Need this for kernel mapping */
-	bPMRIsSparse = PMR_IsSparse(psPMR);
-
-	/* Round the incoming offset down to the nearest cache-line / page aligned-address */
-	uiCLAlignedEndOffset = uiOffset + uiSize;
-	uiCLAlignedEndOffset = PVR_ALIGN(uiCLAlignedEndOffset, (IMG_DEVMEM_SIZE_T)guiCacheLineSize);
-	uiCLAlignedStartOffset = (uiOffset & ~((IMG_DEVMEM_OFFSET_T)guiCacheLineSize-1));
-
-	uiPgAlignedEndOffset = uiCLAlignedEndOffset;
-	uiPgAlignedEndOffset = PVR_ALIGN(uiPgAlignedEndOffset, (IMG_DEVMEM_SIZE_T)guiOSPageSize);
-	uiPgAlignedStartOffset = (uiOffset & ~((IMG_DEVMEM_OFFSET_T)guiOSPageSize-1));
-	uiPgAlignedSize = uiPgAlignedEndOffset - uiPgAlignedStartOffset;
-
-#if defined(CACHEOP_NO_CACHE_LINE_ALIGNED_ROUNDING)
-	/* For internal debug if cache-line optimised
-	   flushing is suspected of causing data corruption */
-	uiCLAlignedStartOffset = uiPgAlignedStartOffset;
-	uiCLAlignedEndOffset = uiPgAlignedEndOffset;
-#endif
-
-	/* Which type of address(es) do we need for this CacheOp */
-	uiCacheOpAddrType = OSCPUCacheOpAddressType(uiCacheOp);
-
-	/* Type of allocation backing the PMR data */
-	ui32NumOfPages = uiPgAlignedSize >> OS_PAGE_SHIFT;
-	if (ui32NumOfPages > PMR_MAX_TRANSLATION_STACK_ALLOC)
-	{
-		/* The pbValid array is allocated first as it is needed in
-		   both physical/virtual cache maintenance methods */
-		pbValid = OSAllocZMem(ui32NumOfPages * sizeof(IMG_BOOL));
-		if (pbValid != NULL)
-		{
-			if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
-			{
-				psCpuPhyAddr = OSAllocZMem(ui32NumOfPages * sizeof(IMG_CPU_PHYADDR));
-				if (psCpuPhyAddr == NULL)
-				{
-					psCpuPhyAddr = asCpuPhyAddr;
-					OSFreeMem(pbValid);
-					pbValid = abValid;
-				}
-			}
-		}
-		else
-		{
-			pbValid = abValid;
-		}
-	}
-
-	/* We always retrieve PMR data in bulk, up-front if number of pages is within
-	   PMR_MAX_TRANSLATION_STACK_ALLOC limits else we check to ensure that a 
-	   dynamic buffer has been allocated to satisfy requests outside limits */
-	if (ui32NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC || pbValid != abValid)
-	{
-		if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
-		{
-			/* Look-up PMR CpuPhyAddr once, if possible */
-			eError = PMR_CpuPhysAddr(psPMR,
-									 OS_PAGE_SHIFT,
-									 ui32NumOfPages,
-									 uiPgAlignedStartOffset,
-									 psCpuPhyAddr,
-									 pbValid);
-			if (eError == PVRSRV_OK)
-			{
-				bIsPMRDataRetrieved = IMG_TRUE;
-			}
-		}
-	}
-
-	/* For each device page, carry out the requested cache maintenance operation */
-	for (uiPgAlignedOffsetNext = uiPgAlignedStartOffset, ui32PageIndex = 0;
-		 uiPgAlignedOffsetNext < uiPgAlignedEndOffset;
-		 uiPgAlignedOffsetNext += (IMG_DEVMEM_OFFSET_T) guiOSPageSize, ui32PageIndex += 1)
-	{
-		if (bIsPMRDataRetrieved == IMG_FALSE)
-		{
-			/* Never cross page boundary without looking up corresponding
-			   PMR page physical address and/or page validity if these
-			   were not looked-up, in bulk, up-front */	
-			ui32PageIndex = 0;
-			if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
-			{
-				eError = PMR_CpuPhysAddr(psPMR,
-										 OS_PAGE_SHIFT,
-										 1,
-										 uiPgAlignedOffsetNext,
-										 psCpuPhyAddr,
-										 pbValid);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_ASSERT(0);
-					goto e0;
-				}
-			}
-			else
-			{
-				PMR_IsOffsetValid(psPMR,
-								  uiPgAlignedOffsetNext,
-								  pbValid);
-			}
-		}
-
-		/* Skip invalid PMR pages (i.e. sparse) */
-		if (pbValid[ui32PageIndex] == IMG_FALSE)
-		{
-			continue;
-		}
-
-		/* Skip virtual address acquire if CacheOp can be maintained
-		   entirely using PMR physical addresses */
-		if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL)
-		{
-			if (bPMRIsSparse)
-			{
-				eError =
-					PMRAcquireSparseKernelMappingData(psPMR,
-													  uiPgAlignedOffsetNext,
-													  guiOSPageSize,
-													  (void **)&pbCpuVirtAddr,
-													  (size_t*)&uiOutSize,
-													  &hPrivOut);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_ASSERT(0);
-					goto e0;
-				}
-			}
-			else
-			{
-				eError =
-					PMRAcquireKernelMappingData(psPMR,
-												uiPgAlignedOffsetNext,
-												guiOSPageSize,
-												(void **)&pbCpuVirtAddr,
-												(size_t*)&uiOutSize,
-												&hPrivOut);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_ASSERT(0);
-					goto e0;
-				}
-			}
-		}
-
-		/* Issue actual cache maintenance for PMR */
-		CacheOpCPURangeBased(uiCacheOp,
-							 pbCpuVirtAddr,
-							 (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL) ?
-								psCpuPhyAddr[ui32PageIndex] : psCpuPhyAddr[0],
-							 uiPgAlignedOffsetNext,
-							 uiCLAlignedStartOffset,
-							 uiCLAlignedEndOffset);
-
-		/* Skip virtual address release if CacheOp can be maintained
-		   entirely using PMR physical addresses */
-		if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL)
-		{
-			eError = PMRReleaseKernelMappingData(psPMR, hPrivOut);
-			PVR_ASSERT(eError == PVRSRV_OK);
-		}
-	}
-
-e0:
-	if (psCpuPhyAddr != asCpuPhyAddr)
-	{
-		OSFreeMem(psCpuPhyAddr);
-	}
-
-	if (pbValid != abValid)
-	{
-		OSFreeMem(pbValid);
-	}
-
-	return eError;
-}
-#else
-PVRSRV_ERROR CacheOpQueue(PMR *psPMR,
-						  IMG_DEVMEM_OFFSET_T uiOffset,
-						  IMG_DEVMEM_SIZE_T uiSize,
-						  PVRSRV_CACHE_OP uiCacheOp)
-{
-	PVRSRV_DATA *psData = PVRSRVGetPVRSRVData();
-	psData->uiCacheOp = SetCacheOp(psData->uiCacheOp, uiCacheOp);
-	return PVRSRV_OK;
-}
-#endif
diff --git a/drivers/staging/imgtec/rogue/cache_km.c b/drivers/staging/imgtec/rogue/cache_km.c
new file mode 100644
index 0000000..37100d6
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/cache_km.c
@@ -0,0 +1,2219 @@
+/*************************************************************************/ /*!
+@File           cache_km.c
+@Title          CPU data cache management
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements server side code for CPU cache maintenance management.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && defined(CONFIG_SW_SYNC)
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#include <linux/sw_sync.h>
+#else
+#include <../drivers/staging/android/sw_sync.h>
+#endif
+#include <linux/file.h>
+#include <linux/fs.h>
+#endif
+#include "pmr.h"
+#include "device.h"
+#include "pvrsrv.h"
+#include "osfunc.h"
+#include "cache_km.h"
+#include "pvr_debug.h"
+#include "lock_types.h"
+#include "allocmem.h"
+#include "process_stats.h"
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+/* Top-level file-local build definitions */
+#if defined(DEBUG) && defined(LINUX)
+	#define CACHEOP_DEBUG
+#endif
+
+/* Type of cache maintenance mechanism being used */
+#if (CACHEFLUSH_KM_TYPE == CACHEFLUSH_KM_RANGEBASED_DEFERRED)
+	#define SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED
+	#define SUPPORT_RANGEBASED_CACHEFLUSH
+#elif (CACHEFLUSH_KM_TYPE == CACHEFLUSH_KM_RANGEBASED)
+	#define SUPPORT_RANGEBASED_CACHEFLUSH
+#elif (CACHEFLUSH_KM_TYPE == CACHEFLUSH_KM_GLOBAL)
+	/* Nothing to do here */
+#else
+	#error "Unknown CACHEFLUSH_KM_TYPE"
+#endif
+
+typedef struct _CACHEOP_WORK_ITEM_
+{
+	DLLIST_NODE sNode;
+	PMR *psPMR;
+	struct file *psTimeline;
+	IMG_UINT32 ui32OpSeqNum;
+	IMG_DEVMEM_SIZE_T uiSize;
+	PVRSRV_CACHE_OP uiCacheOp;
+	IMG_DEVMEM_OFFSET_T uiOffset;
+	IMG_BOOL bSignalEventObject;
+#if defined(CACHEOP_DEBUG)
+	IMG_UINT64	ui64QueuedTime;
+	IMG_UINT64	ui64ExecuteTime;
+	IMG_BOOL bRBF;
+	IMG_BOOL bUMF;
+	IMG_PID pid;
+#if defined(PVR_RI_DEBUG)
+	RGXFWIF_DM eFenceOpType;
+#endif
+#endif
+} CACHEOP_WORK_ITEM;
+
+/* Copy of CPU page & dcache-line size */
+static size_t guiOSPageSize;
+static IMG_UINT32 guiCacheLineSize;
+
+/* 
+  System-wide CacheOp sequence numbers
+  - ghCommonCacheOpSeqNum:
+		This common sequence, numbers mostly CacheOp requests
+		from UM/KM but might also number fence checks and
+		completed CacheOps depending on SUPPORT_XXX configs.
+  - ghCompletedCacheOpSeqNum:
+		This tracks last CacheOp request that was executed
+		in all SUPPORT_XXX configurations and is used for
+		fence checks exclusively.
+*/
+static ATOMIC_T ghCommonCacheOpSeqNum;
+static ATOMIC_T ghCompletedCacheOpSeqNum;
+
+#if defined(CACHEOP_DEBUG)
+#define CACHEOP_MAX_STATS_ITEMS 128
+#define INCR_WRAP(x) ((x+1) >= CACHEOP_MAX_STATS_ITEMS ? 0 : (x+1))
+#define DECR_WRAP(x) ((x-1) < 0 ? (CACHEOP_MAX_STATS_ITEMS-1) : (x-1))
+#if defined(PVR_RI_DEBUG)
+/* Refer to CacheOpStatExecLogHeader() for header item names */
+#define CACHEOP_RI_PRINTF_HEADER "%-10s %-10s %-5s %-8s %-16s %-10s %-10s %-18s %-12s"
+#define CACHEOP_RI_PRINTF_FENCE	 "%-10s %-10s %-5s %-8d %-16s %-10s %-10s %-18llu 0x%-10x\n"
+#define CACHEOP_RI_PRINTF		 "%-10s %-10s %-5s %-8d 0x%-14llx 0x%-8llx 0x%-8llx %-18llu 0x%-10x\n"
+#else
+#define CACHEOP_PRINTF_HEADER	 "%-10s %-10s %-5s %-10s %-10s %-18s %-12s"
+#define CACHEOP_PRINTF_FENCE	 "%-10s %-10s %-5s %-10s %-10s %-18llu 0x%-10x\n"
+#define CACHEOP_PRINTF		 	 "%-10s %-10s %-5s 0x%-8llx 0x%-8llx %-18llu 0x%-10x\n"
+#endif
+
+/* Divide a number by 10 using shifts only */
+static INLINE IMG_UINT64 DivBy10(IMG_UINT64 uiNum)
+{
+	IMG_UINT64 uiQuot;
+	IMG_UINT64 uiRem;
+
+	uiQuot = (uiNum >> 1) + (uiNum >> 2);
+	uiQuot = uiQuot + (uiQuot >> 4);
+	uiQuot = uiQuot + (uiQuot >> 8);
+	uiQuot = uiQuot + (uiQuot >> 16);
+	uiQuot = uiQuot >> 3;
+	uiRem  = uiNum - (((uiQuot << 2) + uiQuot) << 1);
+
+	return uiQuot + (uiRem > 9);
+}
+
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED)
+typedef struct _CACHEOP_STAT_STALL_ITEM_
+{
+	IMG_UINT32 ui32OpSeqNum;
+	IMG_UINT32 ui32RetryCount;
+	IMG_UINT64 ui64QueuedTime;
+	IMG_UINT64 ui64ExecuteTime;
+} CACHEOP_STAT_STALL_ITEM;
+
+/* These are used in an atomic way so will never
+   hold values outside of the valid range */
+static IMG_INT32 gi32CacheOpStatStallWriteIdx;
+static IMG_HANDLE ghCacheOpStatStallLock;
+static void *pvCacheOpStatStallEntry;
+
+static CACHEOP_STAT_STALL_ITEM gasCacheOpStatStalled[CACHEOP_MAX_STATS_ITEMS];
+
+static INLINE void CacheOpStatStallLogHeader(IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN])
+{
+	OSSNPrintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN,
+				"%-10s %-12s %-10s",
+				"SeqNo",
+				"Time (ns)",
+				"RetryCount");
+}
+
+static INLINE void CacheOpStatStallLogWrite(IMG_UINT32 ui32FenceOpSeqNum,
+											IMG_UINT64 ui64QueuedTime,
+											IMG_UINT64 ui64ExecuteTime,
+											IMG_UINT32 ui32RetryCount)
+{
+	IMG_INT32 i32WriteOffset = gi32CacheOpStatStallWriteIdx;
+	gi32CacheOpStatStallWriteIdx = INCR_WRAP(gi32CacheOpStatStallWriteIdx);
+	gasCacheOpStatStalled[i32WriteOffset].ui32RetryCount = ui32RetryCount;
+	gasCacheOpStatStalled[i32WriteOffset].ui32OpSeqNum = ui32FenceOpSeqNum;
+	gasCacheOpStatStalled[i32WriteOffset].ui64QueuedTime = ui64QueuedTime;
+	gasCacheOpStatStalled[i32WriteOffset].ui64ExecuteTime = ui64ExecuteTime;
+}
+
+static void CacheOpStatStallLogRead(void *pvFilePtr, void *pvData,
+							 OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
+{
+	IMG_INT32 i32ReadOffset;
+	IMG_INT32 i32WriteOffset;
+	IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN]={0};
+
+	PVR_UNREFERENCED_PARAMETER(pvData);
+
+	CacheOpStatStallLogHeader(szBuffer);
+	pfnOSStatsPrintf(pvFilePtr, "%s\n", szBuffer);
+
+	OSLockAcquire(ghCacheOpStatStallLock);
+
+	i32WriteOffset = gi32CacheOpStatStallWriteIdx;
+	for (i32ReadOffset = DECR_WRAP(i32WriteOffset);
+		 i32ReadOffset != i32WriteOffset; 
+		 i32ReadOffset = DECR_WRAP(i32ReadOffset))
+	{
+		IMG_UINT64 ui64QueuedTime, ui64ExecuteTime;
+
+		if (gasCacheOpStatStalled[i32ReadOffset].ui32OpSeqNum == 0)
+		{
+			break;
+		}
+
+		/* Convert from nano-seconds to micro-seconds */
+		ui64ExecuteTime = gasCacheOpStatStalled[i32ReadOffset].ui64ExecuteTime;
+		ui64QueuedTime = gasCacheOpStatStalled[i32ReadOffset].ui64QueuedTime;
+		ui64ExecuteTime = DivBy10(DivBy10(DivBy10(ui64ExecuteTime)));
+		ui64QueuedTime = DivBy10(DivBy10(DivBy10(ui64QueuedTime)));
+
+		pfnOSStatsPrintf(pvFilePtr,
+						"%-10x 0x%-10llx %-10x\n",
+						gasCacheOpStatStalled[i32ReadOffset].ui32OpSeqNum,
+						ui64QueuedTime < ui64ExecuteTime ?
+								ui64ExecuteTime - ui64QueuedTime :
+								ui64QueuedTime - ui64ExecuteTime,
+						gasCacheOpStatStalled[i32ReadOffset].ui32RetryCount);
+	}
+
+	OSLockRelease(ghCacheOpStatStallLock);
+}
+#endif
+
+typedef struct _CACHEOP_STAT_EXEC_ITEM_
+{
+	IMG_UINT32 ui32OpSeqNum;
+	PVRSRV_CACHE_OP uiCacheOp;
+	IMG_DEVMEM_SIZE_T uiOffset;
+	IMG_DEVMEM_SIZE_T uiSize;
+	IMG_UINT64 ui64QueuedTime;
+	IMG_UINT64 ui64ExecuteTime;
+	IMG_BOOL bHasTimeline;
+	IMG_BOOL bIsFence;
+	IMG_BOOL bRBF;
+	IMG_BOOL bUMF;
+#if defined(PVR_RI_DEBUG)
+	IMG_DEV_VIRTADDR sDevVAddr;
+	RGXFWIF_DM eFenceOpType;
+	IMG_PID pid;
+#endif
+} CACHEOP_STAT_EXEC_ITEM;
+
+/* These are used in an atomic way so will never
+   hold values outside of the valid range */
+static IMG_INT32 gi32CacheOpStatExecWriteIdx;
+static IMG_HANDLE ghCacheOpStatExecLock;
+static void *pvCacheOpStatExecEntry;
+
+static CACHEOP_STAT_EXEC_ITEM gasCacheOpStatExecuted[CACHEOP_MAX_STATS_ITEMS];
+
+static INLINE void CacheOpStatExecLogHeader(IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN])
+{
+	OSSNPrintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN,
+#if defined(PVR_RI_DEBUG)
+				CACHEOP_RI_PRINTF_HEADER,
+#else
+				CACHEOP_PRINTF_HEADER,
+#endif
+				"CacheOp",
+				"Type",
+				"Mode",
+#if defined(PVR_RI_DEBUG)
+				"Pid",
+				"DevVAddr",
+#endif
+				"Offset",
+				"Size",
+				"Time (us)",
+				"SeqNo");
+}
+
+static INLINE void CacheOpStatExecLogWrite(DLLIST_NODE *psNode)
+{
+	CACHEOP_WORK_ITEM *psCacheOpWorkItem;
+	IMG_UINT64 ui64ExecuteTime;
+	IMG_UINT64 ui64QueuedTime;
+	IMG_INT32 i32WriteOffset;
+
+	psCacheOpWorkItem = IMG_CONTAINER_OF(psNode, CACHEOP_WORK_ITEM, sNode);	
+	if (psCacheOpWorkItem->ui32OpSeqNum == 0)
+	{
+		/* This breaks the logic of read-out, so we
+		   do not queue items with zero sequence
+		   number */
+		return;
+	}
+
+	i32WriteOffset = gi32CacheOpStatExecWriteIdx;
+	gi32CacheOpStatExecWriteIdx = INCR_WRAP(gi32CacheOpStatExecWriteIdx);
+
+	gasCacheOpStatExecuted[i32WriteOffset].uiSize = psCacheOpWorkItem->uiSize;
+	gasCacheOpStatExecuted[i32WriteOffset].uiOffset	= psCacheOpWorkItem->uiOffset;
+	gasCacheOpStatExecuted[i32WriteOffset].uiCacheOp = psCacheOpWorkItem->uiCacheOp;
+	gasCacheOpStatExecuted[i32WriteOffset].ui32OpSeqNum	= psCacheOpWorkItem->ui32OpSeqNum;
+	gasCacheOpStatExecuted[i32WriteOffset].ui64QueuedTime = psCacheOpWorkItem->ui64QueuedTime;
+	gasCacheOpStatExecuted[i32WriteOffset].ui64ExecuteTime = psCacheOpWorkItem->ui64ExecuteTime;
+	gasCacheOpStatExecuted[i32WriteOffset].bHasTimeline	= psCacheOpWorkItem->psPMR == NULL;
+	gasCacheOpStatExecuted[i32WriteOffset].bRBF = psCacheOpWorkItem->bRBF;
+	gasCacheOpStatExecuted[i32WriteOffset].bUMF = psCacheOpWorkItem->bUMF;
+	gasCacheOpStatExecuted[i32WriteOffset].bIsFence	 =
+			psCacheOpWorkItem->psPMR == NULL && psCacheOpWorkItem->psTimeline == NULL;
+#if defined(PVR_RI_DEBUG)
+	gasCacheOpStatExecuted[i32WriteOffset].pid = psCacheOpWorkItem->pid;
+	PVR_ASSERT(gasCacheOpStatExecuted[i32WriteOffset].pid);
+
+	if (psCacheOpWorkItem->psPMR != NULL)
+	{
+		PVRSRV_ERROR eError;
+
+		/* Get more detailed information regarding the sub allocations that
+		   PMR has from RI manager for process that requested the CacheOp */
+		eError = RIDumpProcessListKM(psCacheOpWorkItem->psPMR,
+									 gasCacheOpStatExecuted[i32WriteOffset].pid,
+									 gasCacheOpStatExecuted[i32WriteOffset].uiOffset,
+									 &gasCacheOpStatExecuted[i32WriteOffset].sDevVAddr);
+		if (eError != PVRSRV_OK)
+		{
+			return;
+		}
+	}
+
+	if (gasCacheOpStatExecuted[i32WriteOffset].bIsFence)
+	{
+		gasCacheOpStatExecuted[i32WriteOffset].eFenceOpType = psCacheOpWorkItem->eFenceOpType;
+	}
+#endif
+
+	ui64ExecuteTime = gasCacheOpStatExecuted[i32WriteOffset].ui64ExecuteTime;
+	ui64QueuedTime = gasCacheOpStatExecuted[i32WriteOffset].ui64QueuedTime;
+
+	/* This operation queues this CacheOp in per-PID process statistics database */
+	PVRSRVStatsUpdateCacheOpStats(gasCacheOpStatExecuted[i32WriteOffset].uiCacheOp,
+					gasCacheOpStatExecuted[i32WriteOffset].ui32OpSeqNum,
+#if defined(PVR_RI_DEBUG)
+					gasCacheOpStatExecuted[i32WriteOffset].sDevVAddr,
+					gasCacheOpStatExecuted[i32WriteOffset].eFenceOpType,
+#endif
+					gasCacheOpStatExecuted[i32WriteOffset].uiOffset,
+					gasCacheOpStatExecuted[i32WriteOffset].uiSize,
+					ui64QueuedTime < ui64ExecuteTime ?
+						ui64ExecuteTime - ui64QueuedTime:
+						ui64QueuedTime - ui64ExecuteTime,
+					gasCacheOpStatExecuted[i32WriteOffset].bRBF,
+					gasCacheOpStatExecuted[i32WriteOffset].bUMF,
+					gasCacheOpStatExecuted[i32WriteOffset].bIsFence,
+					gasCacheOpStatExecuted[i32WriteOffset].bHasTimeline,
+					psCacheOpWorkItem->pid);
+}
+
+static void CacheOpStatExecLogRead(void *pvFilePtr, void *pvData,
+								OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
+{
+	IMG_INT32 i32ReadOffset;
+	IMG_INT32 i32WriteOffset;
+	IMG_CHAR *pszCacheOpType;
+	IMG_CHAR *pszFlushSource;
+	IMG_CHAR *pszFlushype;
+	IMG_UINT64 ui64QueuedTime, ui64ExecuteTime;
+	IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN]={0};
+
+	PVR_UNREFERENCED_PARAMETER(pvData);
+
+	CacheOpStatExecLogHeader(szBuffer);
+	pfnOSStatsPrintf(pvFilePtr, "%s\n", szBuffer);
+
+	OSLockAcquire(ghCacheOpStatExecLock);
+
+	i32WriteOffset = gi32CacheOpStatExecWriteIdx;
+	for (i32ReadOffset = DECR_WRAP(i32WriteOffset);
+		 i32ReadOffset != i32WriteOffset;
+		 i32ReadOffset = DECR_WRAP(i32ReadOffset))
+	{
+		if (gasCacheOpStatExecuted[i32ReadOffset].ui32OpSeqNum == 0)
+		{
+			break;
+		}
+
+		/* Convert from nano-seconds to micro-seconds */
+		ui64ExecuteTime = gasCacheOpStatExecuted[i32ReadOffset].ui64ExecuteTime;
+		ui64QueuedTime = gasCacheOpStatExecuted[i32ReadOffset].ui64QueuedTime;
+		ui64ExecuteTime = DivBy10(DivBy10(DivBy10(ui64ExecuteTime)));
+		ui64QueuedTime = DivBy10(DivBy10(DivBy10(ui64QueuedTime)));
+
+		if (gasCacheOpStatExecuted[i32ReadOffset].bIsFence)
+		{
+			IMG_CHAR *pszFenceType = "";
+			pszCacheOpType = "Fence";
+
+#if defined(PVR_RI_DEBUG)
+			switch (gasCacheOpStatExecuted[i32ReadOffset].eFenceOpType)
+			{
+				case RGXFWIF_DM_GP:
+					pszFenceType = "GP";
+					break;
+
+				case RGXFWIF_DM_TDM:
+					/* Also case RGXFWIF_DM_2D: */
+					pszFenceType = "TDM/2D";
+					break;
+
+				case RGXFWIF_DM_TA:
+					pszFenceType = "TA";
+					break;
+
+				case RGXFWIF_DM_3D:
+					pszFenceType = "3D";
+					break;
+
+				case RGXFWIF_DM_CDM:
+					pszFenceType = "CDM";
+					break;
+
+				case RGXFWIF_DM_RTU:
+					pszFenceType = "RTU";
+					break;
+
+				case RGXFWIF_DM_SHG:
+					pszFenceType = "SHG";
+					break;
+
+				default:
+					PVR_ASSERT(0);
+					break;
+			}
+#endif
+			pfnOSStatsPrintf(pvFilePtr,
+#if defined(PVR_RI_DEBUG)
+							CACHEOP_RI_PRINTF_FENCE,
+#else
+							CACHEOP_PRINTF_FENCE,
+#endif
+							pszCacheOpType,
+							pszFenceType,
+							"",
+#if defined(PVR_RI_DEBUG)
+							gasCacheOpStatExecuted[i32ReadOffset].pid,
+							"",
+#endif
+							"",
+							"",
+							ui64QueuedTime < ui64ExecuteTime ?
+										ui64ExecuteTime - ui64QueuedTime :
+										ui64QueuedTime - ui64ExecuteTime,
+							gasCacheOpStatExecuted[i32ReadOffset].ui32OpSeqNum);
+		}
+		else if (gasCacheOpStatExecuted[i32ReadOffset].bHasTimeline)
+		{
+			pfnOSStatsPrintf(pvFilePtr,
+#if defined(PVR_RI_DEBUG)
+							CACHEOP_RI_PRINTF_FENCE,
+#else
+							CACHEOP_PRINTF_FENCE,
+#endif
+							"Timeline",
+							"",
+							"",
+#if defined(PVR_RI_DEBUG)
+							gasCacheOpStatExecuted[i32ReadOffset].pid,
+							"",
+#endif
+							"",
+							"",
+							ui64QueuedTime < ui64ExecuteTime ?
+										ui64ExecuteTime - ui64QueuedTime :
+										ui64QueuedTime - ui64ExecuteTime,
+							gasCacheOpStatExecuted[i32ReadOffset].ui32OpSeqNum);
+		}
+		else
+		{
+			if (gasCacheOpStatExecuted[i32ReadOffset].bRBF)
+			{
+				IMG_DEVMEM_SIZE_T ui64NumOfPages;
+
+				ui64NumOfPages = gasCacheOpStatExecuted[i32ReadOffset].uiSize >> OSGetPageShift();
+				if (ui64NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC)
+				{
+					pszFlushype = "RBF.Fast";
+				}
+				else
+				{
+					pszFlushype = "RBF.Slow";
+				}
+			}
+			else
+			{
+				pszFlushype = "GF";
+			}
+
+			if (gasCacheOpStatExecuted[i32ReadOffset].bUMF)
+			{
+				pszFlushSource = "UM";
+			}
+			else
+			{
+				pszFlushSource = "KM";
+			}
+
+			switch (gasCacheOpStatExecuted[i32ReadOffset].uiCacheOp)
+			{
+				case PVRSRV_CACHE_OP_NONE:
+					pszCacheOpType = "None";
+					break;
+				case PVRSRV_CACHE_OP_CLEAN:
+					pszCacheOpType = "Clean";
+					break;
+				case PVRSRV_CACHE_OP_INVALIDATE:
+					pszCacheOpType = "Invalidate";
+					break;
+				case PVRSRV_CACHE_OP_FLUSH:
+					pszCacheOpType = "Flush";
+					break;
+				default:
+					pszCacheOpType = "Unknown";
+					break;
+			}
+
+			pfnOSStatsPrintf(pvFilePtr,
+#if defined(PVR_RI_DEBUG)
+							CACHEOP_RI_PRINTF,
+#else
+							CACHEOP_PRINTF,
+#endif
+							pszCacheOpType,
+							pszFlushype,
+							pszFlushSource,
+#if defined(PVR_RI_DEBUG)
+							gasCacheOpStatExecuted[i32ReadOffset].pid,
+							gasCacheOpStatExecuted[i32ReadOffset].sDevVAddr.uiAddr,
+#endif
+							gasCacheOpStatExecuted[i32ReadOffset].uiOffset,
+							gasCacheOpStatExecuted[i32ReadOffset].uiSize,
+							ui64QueuedTime < ui64ExecuteTime ?
+										ui64ExecuteTime - ui64QueuedTime :
+										ui64QueuedTime - ui64ExecuteTime,
+							gasCacheOpStatExecuted[i32ReadOffset].ui32OpSeqNum);
+		}
+	}
+
+	OSLockRelease(ghCacheOpStatExecLock);
+}
+
+static PVRSRV_ERROR CacheOpStatExecLog(void *pvData)
+{
+	DLLIST_NODE *psListNode = (DLLIST_NODE *) pvData;
+	DLLIST_NODE *psCurrentNode, *psNextNode;
+
+	OSLockAcquire(ghCacheOpStatExecLock);
+
+	CacheOpStatExecLogWrite(psListNode);
+	dllist_foreach_node (psListNode, psCurrentNode, psNextNode)
+	{
+		CacheOpStatExecLogWrite(psCurrentNode);
+	}
+
+	OSLockRelease(ghCacheOpStatExecLock);
+
+	return PVRSRV_OK;
+}
+#endif /* defined(CACHEOP_DEBUG) */
+
+//#define CACHEOP_NO_CACHE_LINE_ALIGNED_ROUNDING
+#define CACHEOP_SEQ_MIDPOINT (IMG_UINT32) 0x7FFFFFFF
+#define CACHEOP_DPFL PVR_DBG_MESSAGE
+
+/* Perform requested CacheOp on the CPU data cache for successive cache
+   line worth of bytes up to page or in-page cache-line boundary */
+static INLINE void CacheOpCPURangeBased(PVRSRV_DEVICE_NODE *psDevNode,
+										PVRSRV_CACHE_OP uiCacheOp,
+										IMG_BYTE *pbCpuVirtAddr,
+										IMG_CPU_PHYADDR sCpuPhyAddr,
+										IMG_DEVMEM_OFFSET_T uiPgAlignedOffset,
+										IMG_DEVMEM_OFFSET_T uiCLAlignedStartOffset,
+										IMG_DEVMEM_OFFSET_T uiCLAlignedEndOffset)
+{
+	IMG_BYTE *pbCpuVirtAddrEnd;
+	IMG_BYTE *pbCpuVirtAddrStart;
+	IMG_CPU_PHYADDR sCpuPhyAddrEnd;
+	IMG_CPU_PHYADDR sCpuPhyAddrStart;
+	IMG_DEVMEM_SIZE_T uiRelFlushSize;
+	IMG_DEVMEM_OFFSET_T uiRelFlushOffset;
+	IMG_DEVMEM_SIZE_T uiNextPgAlignedOffset;
+
+	/* These quantities allows us to perform cache operations
+	   at cache-line granularity thereby ensuring we do not
+	   perform more than is necessary */
+	PVR_ASSERT(uiPgAlignedOffset < uiCLAlignedEndOffset);
+	uiRelFlushSize = (IMG_DEVMEM_SIZE_T)guiOSPageSize;
+	uiRelFlushOffset = 0;
+
+	if (uiCLAlignedStartOffset > uiPgAlignedOffset)
+	{
+		/* Zero unless initially starting at an in-page offset */
+		uiRelFlushOffset = uiCLAlignedStartOffset - uiPgAlignedOffset;
+		uiRelFlushSize -= uiRelFlushOffset;
+	}
+
+	/* uiRelFlushSize is guiOSPageSize unless current outstanding CacheOp
+	   size is smaller. The 1st case handles in-page CacheOp range and
+	   the 2nd case handles multiple-page CacheOp range with a last
+	   CacheOp size that is less than guiOSPageSize */
+	uiNextPgAlignedOffset = uiPgAlignedOffset + (IMG_DEVMEM_SIZE_T)guiOSPageSize;
+	if (uiNextPgAlignedOffset < uiPgAlignedOffset)
+	{
+		/* uiNextPgAlignedOffset is greater than uiCLAlignedEndOffset
+		   by implication of this wrap-round; this only happens when
+		   uiPgAlignedOffset is the last page aligned offset */
+		uiRelFlushSize = uiRelFlushOffset ?
+				uiCLAlignedEndOffset - uiCLAlignedStartOffset :
+				uiCLAlignedEndOffset - uiPgAlignedOffset;
+	}
+	else
+	{
+		if (uiNextPgAlignedOffset > uiCLAlignedEndOffset)
+		{
+			uiRelFlushSize = uiRelFlushOffset ?
+					uiCLAlignedEndOffset - uiCLAlignedStartOffset :
+					uiCLAlignedEndOffset - uiPgAlignedOffset;
+		}
+	}
+
+	/* More efficient to request cache maintenance operation for full
+	   relative range as opposed to multiple cache-aligned ranges */
+	pbCpuVirtAddrStart = pbCpuVirtAddr + uiRelFlushOffset;
+	pbCpuVirtAddrEnd = pbCpuVirtAddrStart + uiRelFlushSize;
+	sCpuPhyAddrStart.uiAddr = sCpuPhyAddr.uiAddr + uiRelFlushOffset;
+	sCpuPhyAddrEnd.uiAddr = sCpuPhyAddrStart.uiAddr + uiRelFlushSize;
+
+	switch (uiCacheOp)
+	{
+		case PVRSRV_CACHE_OP_CLEAN:
+			OSCleanCPUCacheRangeKM(psDevNode, pbCpuVirtAddrStart, pbCpuVirtAddrEnd,
+									sCpuPhyAddrStart, sCpuPhyAddrEnd);
+			break;
+		case PVRSRV_CACHE_OP_INVALIDATE:
+			OSInvalidateCPUCacheRangeKM(psDevNode, pbCpuVirtAddrStart, pbCpuVirtAddrEnd,
+									sCpuPhyAddrStart, sCpuPhyAddrEnd);
+			break;
+		case PVRSRV_CACHE_OP_FLUSH:
+			OSFlushCPUCacheRangeKM(psDevNode, pbCpuVirtAddrStart, pbCpuVirtAddrEnd,
+									sCpuPhyAddrStart, sCpuPhyAddrEnd);
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,	"%s: Invalid cache operation type %d",
+					__FUNCTION__, uiCacheOp));
+			PVR_ASSERT(0);
+			break;
+	}
+}
+
+/* This function assumes the PMR is locked */
+static PVRSRV_ERROR CacheOpRangeBased (PMR *psPMR,
+									   IMG_DEVMEM_OFFSET_T uiOffset,
+									   IMG_DEVMEM_SIZE_T uiSize,
+									   PVRSRV_CACHE_OP uiCacheOp,
+									   IMG_BOOL *bUsedGlobalFlush)
+{
+	IMG_HANDLE hPrivOut;
+	IMG_BOOL bPMRIsSparse;
+	IMG_UINT32 ui32PageIndex;
+	IMG_UINT32 ui32NumOfPages;
+	IMG_DEVMEM_SIZE_T uiOutSize;
+	IMG_DEVMEM_SIZE_T uiPgAlignedSize;
+	IMG_DEVMEM_OFFSET_T uiCLAlignedEndOffset;
+	IMG_DEVMEM_OFFSET_T uiPgAlignedEndOffset;
+	IMG_DEVMEM_OFFSET_T uiCLAlignedStartOffset;
+	IMG_DEVMEM_OFFSET_T uiPgAlignedStartOffset;
+	IMG_DEVMEM_OFFSET_T uiPgAlignedOffsetNext;
+	PVRSRV_CACHE_OP_ADDR_TYPE uiCacheOpAddrType;
+	IMG_BOOL abValid[PMR_MAX_TRANSLATION_STACK_ALLOC];
+	IMG_CPU_PHYADDR asCpuPhyAddr[PMR_MAX_TRANSLATION_STACK_ALLOC];
+	IMG_UINT32 OS_PAGE_SHIFT = (IMG_UINT32) OSGetPageShift();
+	IMG_CPU_PHYADDR *psCpuPhyAddr = asCpuPhyAddr;
+	IMG_BOOL bIsPMRDataRetrieved = IMG_FALSE;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_BYTE *pbCpuVirtAddr = NULL;
+	IMG_BOOL *pbValid = abValid;
+
+	if (uiCacheOp == PVRSRV_CACHE_OP_NONE)
+	{
+		PVR_ASSERT(0);
+		return PVRSRV_OK;
+	}
+	else
+	{
+		/* Carry out full dcache operation if size (in pages) qualifies */
+		if (uiSize >= PVR_DIRTY_BYTES_FLUSH_THRESHOLD)
+		{
+			/* Flush, so we can skip subsequent invalidates */
+			eError = OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
+			if (eError == PVRSRV_OK)
+			{
+				*bUsedGlobalFlush = IMG_TRUE;
+				return PVRSRV_OK;
+			}
+		}
+	}
+
+	/* Need this for kernel mapping */
+	bPMRIsSparse = PMR_IsSparse(psPMR);
+
+	/* Round the incoming offset down to the nearest cache-line / page aligned-address */
+	uiCLAlignedEndOffset = uiOffset + uiSize;
+	uiCLAlignedEndOffset = PVR_ALIGN(uiCLAlignedEndOffset, (IMG_DEVMEM_SIZE_T)guiCacheLineSize);
+	uiCLAlignedStartOffset = (uiOffset & ~((IMG_DEVMEM_OFFSET_T)guiCacheLineSize-1));
+
+	uiPgAlignedEndOffset = uiCLAlignedEndOffset;
+	uiPgAlignedEndOffset = PVR_ALIGN(uiPgAlignedEndOffset, (IMG_DEVMEM_SIZE_T)guiOSPageSize);
+	uiPgAlignedStartOffset = (uiOffset & ~((IMG_DEVMEM_OFFSET_T)guiOSPageSize-1));
+	uiPgAlignedSize = uiPgAlignedEndOffset - uiPgAlignedStartOffset;
+
+#if defined(CACHEOP_NO_CACHE_LINE_ALIGNED_ROUNDING)
+	/* For internal debug if cache-line optimised
+	   flushing is suspected of causing data corruption */
+	uiCLAlignedStartOffset = uiPgAlignedStartOffset;
+	uiCLAlignedEndOffset = uiPgAlignedEndOffset;
+#endif
+
+	/* Which type of address(es) do we need for this CacheOp */
+	uiCacheOpAddrType = OSCPUCacheOpAddressType(uiCacheOp);
+
+	/* Type of allocation backing the PMR data */
+	ui32NumOfPages = uiPgAlignedSize >> OS_PAGE_SHIFT;
+	if (ui32NumOfPages > PMR_MAX_TRANSLATION_STACK_ALLOC)
+	{
+		/* The pbValid array is allocated first as it is needed in
+		   both physical/virtual cache maintenance methods */
+		pbValid = OSAllocZMem(ui32NumOfPages * sizeof(IMG_BOOL));
+		if (pbValid != NULL)
+		{
+			if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
+			{
+				psCpuPhyAddr = OSAllocZMem(ui32NumOfPages * sizeof(IMG_CPU_PHYADDR));
+				if (psCpuPhyAddr == NULL)
+				{
+					psCpuPhyAddr = asCpuPhyAddr;
+					OSFreeMem(pbValid);
+					pbValid = abValid;
+				}
+			}
+		}
+		else
+		{
+			pbValid = abValid;
+		}
+	}
+
+	/* We always retrieve PMR data in bulk, up-front if number of pages is within
+	   PMR_MAX_TRANSLATION_STACK_ALLOC limits else we check to ensure that a 
+	   dynamic buffer has been allocated to satisfy requests outside limits */
+	if (ui32NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC || pbValid != abValid)
+	{
+		if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
+		{
+			/* Look-up PMR CpuPhyAddr once, if possible */
+			eError = PMR_CpuPhysAddr(psPMR,
+									 OS_PAGE_SHIFT,
+									 ui32NumOfPages,
+									 uiPgAlignedStartOffset,
+									 psCpuPhyAddr,
+									 pbValid);
+			if (eError == PVRSRV_OK)
+			{
+				bIsPMRDataRetrieved = IMG_TRUE;
+			}
+		}
+		else
+		{
+			/* Look-up PMR per-page validity once, if possible */
+			eError = PMR_IsOffsetValid(psPMR,
+									   OS_PAGE_SHIFT,
+									   ui32NumOfPages,
+									   uiPgAlignedStartOffset,
+									   pbValid);
+			bIsPMRDataRetrieved = eError == PVRSRV_OK ? IMG_TRUE : IMG_FALSE;
+		}
+	}
+
+	/* For each device page, carry out the requested cache maintenance operation */
+	for (uiPgAlignedOffsetNext = uiPgAlignedStartOffset, ui32PageIndex = 0;
+		 uiPgAlignedOffsetNext < uiPgAlignedEndOffset;
+		 uiPgAlignedOffsetNext += (IMG_DEVMEM_OFFSET_T) guiOSPageSize, ui32PageIndex += 1)
+	{
+		if (bIsPMRDataRetrieved == IMG_FALSE)
+		{
+			/* Never cross page boundary without looking up corresponding
+			   PMR page physical address and/or page validity if these
+			   were not looked-up, in bulk, up-front */	
+			ui32PageIndex = 0;
+			if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
+			{
+				eError = PMR_CpuPhysAddr(psPMR,
+										 OS_PAGE_SHIFT,
+										 1,
+										 uiPgAlignedOffsetNext,
+										 psCpuPhyAddr,
+										 pbValid);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_ASSERT(0);
+					goto e0;
+				}
+			}
+			else
+			{
+				eError = PMR_IsOffsetValid(psPMR,
+										  OS_PAGE_SHIFT,
+										  1,
+										  uiPgAlignedOffsetNext,
+										  pbValid);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_ASSERT(0);
+					goto e0;
+				}
+			}
+		}
+
+		/* Skip invalid PMR pages (i.e. sparse) */
+		if (pbValid[ui32PageIndex] == IMG_FALSE)
+		{
+			continue;
+		}
+
+		/* Skip virtual address acquire if CacheOp can be maintained
+		   entirely using PMR physical addresses */
+		if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL)
+		{
+			if (bPMRIsSparse)
+			{
+				eError =
+					PMRAcquireSparseKernelMappingData(psPMR,
+													  uiPgAlignedOffsetNext,
+													  guiOSPageSize,
+													  (void **)&pbCpuVirtAddr,
+													  (size_t*)&uiOutSize,
+													  &hPrivOut);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_ASSERT(0);
+					goto e0;
+				}
+			}
+			else
+			{
+				eError =
+					PMRAcquireKernelMappingData(psPMR,
+												uiPgAlignedOffsetNext,
+												guiOSPageSize,
+												(void **)&pbCpuVirtAddr,
+												(size_t*)&uiOutSize,
+												&hPrivOut);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_ASSERT(0);
+					goto e0;
+				}
+			}
+		}
+
+		/* Issue actual cache maintenance for PMR */
+		CacheOpCPURangeBased(PMR_DeviceNode(psPMR),
+							uiCacheOp,
+							pbCpuVirtAddr,
+							(uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL) ?
+								psCpuPhyAddr[ui32PageIndex] : psCpuPhyAddr[0],
+							uiPgAlignedOffsetNext,
+							uiCLAlignedStartOffset,
+							uiCLAlignedEndOffset);
+
+		/* Skip virtual address release if CacheOp can be maintained
+		   entirely using PMR physical addresses */
+		if (uiCacheOpAddrType != PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL)
+		{
+			eError = PMRReleaseKernelMappingData(psPMR, hPrivOut);
+			PVR_ASSERT(eError == PVRSRV_OK);
+		}
+	}
+
+e0:
+	if (psCpuPhyAddr != asCpuPhyAddr)
+	{
+		OSFreeMem(psCpuPhyAddr);
+	}
+
+	if (pbValid != abValid)
+	{
+		OSFreeMem(pbValid);
+	}
+
+	return eError;
+}
+
+static INLINE IMG_BOOL CacheOpFenceCheck(IMG_UINT32 ui32UpdateSeqNum,
+										 IMG_UINT32 ui32FenceSeqNum)
+{
+	IMG_UINT32 ui32RebasedUpdateNum;
+	IMG_UINT32 ui32RebasedFenceNum;
+	IMG_UINT32 ui32Rebase;
+
+	if (ui32FenceSeqNum == 0)
+	{
+		return IMG_TRUE;
+	}
+
+	/*
+	   The problem statement is how to compare two values
+	   on a numerical sequentially incrementing timeline in
+	   the presence of wrap around arithmetic semantics using
+	   a single ui32 counter & atomic (increment) operations.
+
+	   The rationale for the solution here is to rebase the
+	   incoming values to the sequence midpoint and perform
+	   comparisons there; this allows us to handle overflow
+	   or underflow wrap-round using only a single integer.
+
+	   NOTE: We assume that the absolute value of the 
+	   difference between the two incoming values in _not_ 
+	   greater than CACHEOP_SEQ_MIDPOINT. This assumption
+	   holds as it implies that it is very _unlikely_ that 2
+	   billion CacheOp requests could have been made between
+	   a single client's CacheOp request & the corresponding
+	   fence check. This code sequence is hopefully a _more_
+	   hand optimised (branchless) version of this:
+
+	   	   x = ui32CompletedOpSeqNum
+	   	   y = ui32FenceOpSeqNum
+
+		   if (|x - y| < CACHEOP_SEQ_MIDPOINT)
+			   return (x - y) >= 0 ? true : false
+		   else
+			   return (y - x) >= 0 ? true : false
+	 */
+	ui32Rebase = CACHEOP_SEQ_MIDPOINT - ui32UpdateSeqNum;
+
+	/* ui32Rebase could be either positive/negative, in
+	   any case we still perform operation using unsigned
+	   semantics as 2's complement notation always means
+	   we end up with the correct result */
+	ui32RebasedUpdateNum = ui32Rebase + ui32UpdateSeqNum;
+	ui32RebasedFenceNum = ui32Rebase + ui32FenceSeqNum;
+
+	return (ui32RebasedUpdateNum >= ui32RebasedFenceNum);
+}
+
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH)
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED)
+/* Wait 8hrs when no deferred CacheOp is required;
+   for fence checks, wait 10ms then retry */
+#define CACHEOP_THREAD_WAIT_TIMEOUT 28800000000ULL
+#define CACHEOP_FENCE_WAIT_TIMEOUT  10000ULL
+
+typedef struct _CACHEOP_CLEANUP_WORK_ITEM_
+{
+	PVRSRV_CLEANUP_THREAD_WORK sCleanupWorkItem;
+	DLLIST_NODE *psListNode;
+} CACHEOP_CLEANUP_WORK_ITEM;
+
+/* These are used to track pending CacheOps */
+static IMG_DEVMEM_SIZE_T guiPendingDevmemSize;
+static IMG_BOOL gbPendingTimeline;
+
+static INLINE PVRSRV_ERROR CacheOpFree(void *pvData)
+{
+	CACHEOP_CLEANUP_WORK_ITEM *psCacheOpCleanupItem = pvData;
+	DLLIST_NODE *psListNode = psCacheOpCleanupItem->psListNode;
+	CACHEOP_WORK_ITEM *psCacheOpWorkItem;
+	DLLIST_NODE *psNodeIter;
+
+	while (! dllist_is_empty(psListNode))
+	{
+		psNodeIter = dllist_get_next_node(psListNode);
+		dllist_remove_node(psNodeIter);
+
+		psCacheOpWorkItem = IMG_CONTAINER_OF(psNodeIter, CACHEOP_WORK_ITEM, sNode);
+		if (psCacheOpWorkItem->psPMR)
+		{
+			PMRUnlockSysPhysAddresses(psCacheOpWorkItem->psPMR);
+		}
+
+		OSFreeMem(psCacheOpWorkItem);
+	}
+
+	/* Finally free pseudo head node which is also a valid CacheOp work item */
+	psCacheOpWorkItem = IMG_CONTAINER_OF(psListNode, CACHEOP_WORK_ITEM, sNode);
+	if (psCacheOpWorkItem->psPMR)
+	{
+		PMRUnlockSysPhysAddresses(psCacheOpWorkItem->psPMR);
+	}
+
+	OSFreeMem(psCacheOpWorkItem);
+	OSFreeMem(psCacheOpCleanupItem);
+
+	return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR CacheOpCleanup(DLLIST_NODE *psListNode)
+{
+	CACHEOP_CLEANUP_WORK_ITEM *psCacheOpCleanupItem;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	psCacheOpCleanupItem = OSAllocMem(sizeof(CACHEOP_CLEANUP_WORK_ITEM));
+	if (! psCacheOpCleanupItem)
+	{
+		PVR_DPF((CACHEOP_DPFL,
+				"%s: performing sync cleanup",
+				__FUNCTION__));
+		eError = CacheOpFree(psListNode);
+	}
+	else
+	{
+		psCacheOpCleanupItem->psListNode = psListNode;
+		psCacheOpCleanupItem->sCleanupWorkItem.ui32RetryCount = 0;
+		psCacheOpCleanupItem->sCleanupWorkItem.pfnFree = CacheOpFree;
+		psCacheOpCleanupItem->sCleanupWorkItem.pvData = psCacheOpCleanupItem;
+		psCacheOpCleanupItem->sCleanupWorkItem.bDependsOnHW = IMG_FALSE;
+		PVRSRVCleanupThreadAddWork(&psCacheOpCleanupItem->sCleanupWorkItem);
+	}
+
+	return eError;
+}
+
+static INLINE PVRSRV_ERROR CacheOpEnqueue(PVRSRV_DATA *psPVRSRVData,
+										CACHEOP_WORK_ITEM *psData,
+										IMG_UINT32 *psSeqNum)
+{
+	OSLockAcquire(psPVRSRVData->hCacheOpThreadWorkListLock);
+
+	/* Queue this CacheOp work item into the pending list, update queue size */
+	dllist_add_to_tail(&psPVRSRVData->sCacheOpThreadWorkList, &psData->sNode);
+	gbPendingTimeline = psData->psTimeline ? IMG_TRUE : gbPendingTimeline;
+	guiPendingDevmemSize += psData->uiSize;
+
+	/* Advance the system-wide CacheOp common sequence value */
+	*psSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+	if (! *psSeqNum)
+	{
+		/* Zero is _not_ a valid sequence value, doing so 
+		   simplifies subsequent fence checking when no
+		   cache maintenance operation is outstanding as
+		   in this case a fence value of zero is supplied */
+		*psSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+	}
+	psData->ui32OpSeqNum = *psSeqNum;
+
+	OSLockRelease(psPVRSRVData->hCacheOpThreadWorkListLock);
+
+	return PVRSRV_OK;
+}
+
+static INLINE DLLIST_NODE *CacheOpDequeue(PVRSRV_DATA *psPVRSRVData,
+										  IMG_UINT64 *uiQueueDevmemSize,
+										  IMG_BOOL   *bHasTimeline)
+{
+	DLLIST_NODE *psListNode = NULL;
+
+	OSLockAcquire(psPVRSRVData->hCacheOpThreadWorkListLock);
+
+	if (! dllist_is_empty(&psPVRSRVData->sCacheOpThreadWorkList))
+	{
+		/* Replace entire pending list with a (re)initialized list */
+		psListNode = psPVRSRVData->sCacheOpThreadWorkList.psNextNode;
+		dllist_remove_node(&psPVRSRVData->sCacheOpThreadWorkList);
+		dllist_init(&psPVRSRVData->sCacheOpThreadWorkList);
+
+		/* These capture information about this dequeued list */
+		*uiQueueDevmemSize = (IMG_UINT64) guiPendingDevmemSize;
+		guiPendingDevmemSize = (IMG_DEVMEM_SIZE_T) 0;
+		*bHasTimeline = gbPendingTimeline;
+		gbPendingTimeline = IMG_FALSE;
+	}
+
+	OSLockRelease(psPVRSRVData->hCacheOpThreadWorkListLock);
+
+	return psListNode;
+}
+
+static PVRSRV_ERROR CacheOpExecGlobal(PVRSRV_DATA *psPVRSRVData,
+										DLLIST_NODE *psListNode)
+{
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32CacheOpSeqNum;
+	CACHEOP_WORK_ITEM *psCacheOpWorkItem;
+	DLLIST_NODE *psCurrentNode, *psNextNode;
+#if defined(CACHEOP_DEBUG)
+	IMG_UINT64 uiTimeNow;
+#endif
+
+	eError = OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+#if defined(CACHEOP_DEBUG)
+	uiTimeNow = OSClockns64();
+#endif
+
+	/* The head node is a _valid_ CacheOp work item so process it first */
+	psCacheOpWorkItem = IMG_CONTAINER_OF(psListNode, CACHEOP_WORK_ITEM, sNode);
+#if defined(CACHEOP_DEBUG)
+	psCacheOpWorkItem->ui64ExecuteTime = uiTimeNow;
+	psCacheOpWorkItem->bRBF = IMG_FALSE;
+	psCacheOpWorkItem->bUMF = IMG_FALSE;
+#endif
+
+	/* Process other queue CacheOp work items if present */
+	dllist_foreach_node (psListNode, psCurrentNode, psNextNode)
+	{
+		psCacheOpWorkItem = IMG_CONTAINER_OF(psCurrentNode, CACHEOP_WORK_ITEM, sNode);
+#if defined(CACHEOP_DEBUG)
+		psCacheOpWorkItem->ui64ExecuteTime = uiTimeNow;
+		psCacheOpWorkItem->bRBF = IMG_FALSE;
+		psCacheOpWorkItem->bUMF = IMG_FALSE;
+#endif
+	}
+
+	/* Last CacheOp item updates ghCompletedCacheOpSeqNum */
+	ui32CacheOpSeqNum = psCacheOpWorkItem->ui32OpSeqNum;
+	OSAtomicWrite(&ghCompletedCacheOpSeqNum, ui32CacheOpSeqNum);
+
+	/* Signal any waiting threads blocked on CacheOp fence checks;
+	   update completed sequence number to last queue work item */
+	eError = OSEventObjectSignal(psPVRSRVData->hCacheOpUpdateEventObject);
+	PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+
+	return eError;
+}
+
+static PVRSRV_ERROR CacheOpExecRangeBased(PVRSRV_DATA *psPVRSRVData,
+										  DLLIST_NODE *psListNode)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	CACHEOP_WORK_ITEM *psCacheOpWorkItem;
+	DLLIST_NODE *psNodeIter = psListNode;
+	IMG_BOOL bSkipRemainingCacheOps = IMG_FALSE;
+#if defined(CACHEOP_DEBUG)
+	CACHEOP_WORK_ITEM *psPrevWorkItem = NULL;
+#endif
+
+	do
+	{
+		/* Lookup corresponding work item & perform cache maintenance operation if
+		   it is a non-timeline work-item (i.e. pmr is null) else notify timeline */
+		psCacheOpWorkItem = IMG_CONTAINER_OF(psNodeIter, CACHEOP_WORK_ITEM, sNode);
+		if (psCacheOpWorkItem->psPMR != NULL)
+		{
+			if (bSkipRemainingCacheOps == IMG_FALSE)
+			{
+				eError = CacheOpRangeBased(psCacheOpWorkItem->psPMR,
+										   psCacheOpWorkItem->uiOffset,
+										   psCacheOpWorkItem->uiSize,
+										   psCacheOpWorkItem->uiCacheOp,
+										   &bSkipRemainingCacheOps);
+				if (eError != PVRSRV_OK)
+				{
+					/* This _should_ not fail but if it does, not much
+					   we can do about it; for now we log it but still
+					   increment the completed CacheOp seq number */
+					PVR_DPF((CACHEOP_DPFL, 
+							 "CacheOp failed: PMR:%p Offset:%llx Size:%llx CacheOp:%d",
+							 psCacheOpWorkItem->psPMR,
+							 psCacheOpWorkItem->uiOffset,
+							 psCacheOpWorkItem->uiSize,
+							 psCacheOpWorkItem->uiCacheOp));
+					PVR_ASSERT(0);
+				}
+			}
+
+#if defined(CACHEOP_DEBUG)
+			psCacheOpWorkItem->ui64ExecuteTime = bSkipRemainingCacheOps ?
+				(psPrevWorkItem ? psPrevWorkItem->ui64ExecuteTime : OSClockns64()) : OSClockns64();
+			psCacheOpWorkItem->bRBF = !bSkipRemainingCacheOps;
+			psCacheOpWorkItem->bUMF = IMG_FALSE;
+			psPrevWorkItem = psCacheOpWorkItem;
+#endif
+
+			/* Currently executed CacheOp item updates ghCompletedCacheOpSeqNum */
+			OSAtomicWrite(&ghCompletedCacheOpSeqNum, psCacheOpWorkItem->ui32OpSeqNum);
+
+			if (psCacheOpWorkItem->bSignalEventObject == IMG_TRUE)
+			{
+				/* It is possible that multiple CacheOp work items from two or more
+				   threads might be present within processed queue so we have to
+				   signal when these CacheOps are  processed to unblock waiting threads */
+				eError = OSEventObjectSignal(psPVRSRVData->hCacheOpUpdateEventObject);
+				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+			}
+		}
+		else
+		{
+			PVR_ASSERT(psCacheOpWorkItem->psTimeline != NULL);
+
+			OSAtomicWrite(&ghCompletedCacheOpSeqNum, psCacheOpWorkItem->ui32OpSeqNum);
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && defined(CONFIG_SW_SYNC)
+			sw_sync_timeline_inc(psCacheOpWorkItem->psTimeline->private_data, 1);
+			fput(psCacheOpWorkItem->psTimeline);
+#endif
+
+#if defined(CACHEOP_DEBUG)
+			psCacheOpWorkItem->ui64ExecuteTime = OSClockns64();
+#endif
+		}
+
+		/* This terminates on NULL or 1 item queue */
+		psNodeIter = dllist_get_next_node(psNodeIter);
+	} while (psNodeIter && psNodeIter != psListNode);
+
+	return eError;
+}
+
+static void CacheOpExecQueuedList(PVRSRV_DATA *psPVRSRVData)
+{
+	PVRSRV_ERROR eError;
+	DLLIST_NODE *psListNode;
+	IMG_BOOL bUseGlobalCachOp;
+	IMG_BOOL bHasTimeline = IMG_FALSE;
+	IMG_UINT64 ui64Size = (IMG_UINT64) 0;
+	IMG_UINT64 ui64FlushThreshold = PVR_DIRTY_BYTES_FLUSH_THRESHOLD;
+
+	/* Obtain the current queue of pending CacheOps, this also provides
+	   information pertaining to the queue such as if one or more 
+	   CacheOps in the queue is a timeline request and the total
+	   CacheOp size */
+	psListNode = CacheOpDequeue(psPVRSRVData, &ui64Size, &bHasTimeline);
+	if (psListNode == NULL)
+	{
+		/* This should _not_ happen but if it does, wake-up waiting threads */
+		eError = OSEventObjectSignal(psPVRSRVData->hCacheOpUpdateEventObject);
+		PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+		return;
+	}
+
+	/* Perform a global cache operation if queue size (in pages)
+	   qualifies and there is no work item in the queue which is a
+	   timeline request */
+	bUseGlobalCachOp = ui64Size >= ui64FlushThreshold;
+	if (bUseGlobalCachOp == IMG_TRUE && bHasTimeline == IMG_FALSE)
+	{
+		eError = CacheOpExecGlobal(psPVRSRVData, psListNode);
+		if (eError == PVRSRV_OK)
+		{
+			goto e0;
+		}
+	}
+
+	/* Else use range-based cache maintenance per queue item */
+	eError = CacheOpExecRangeBased(psPVRSRVData, psListNode);
+
+e0:
+#if defined(CACHEOP_DEBUG)
+	eError = CacheOpStatExecLog(psListNode);
+#endif
+
+	/* Once done, defer CacheOp cleanup */
+	eError = CacheOpCleanup(psListNode);
+}
+
+static void CacheOpThread(void *pvData)
+{
+	PVRSRV_DATA *psPVRSRVData = pvData;
+	IMG_HANDLE  hOSEvent;
+	PVRSRV_ERROR eError;
+
+	PVR_DPF((CACHEOP_DPFL, "%s: thread starting...", __FUNCTION__));
+
+	/* Store the process id (pid) of the CacheOp-up thread */
+	psPVRSRVData->CacheOpThreadPid = OSGetCurrentProcessID();
+
+	/* Open CacheOp thread event object, abort driver if event object open fails */
+	eError = OSEventObjectOpen(psPVRSRVData->hCacheOpThreadEventObject, &hOSEvent);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* While driver is in good state and not being unloaded, perform pending cache maintenance */
+	while ((psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK) && (!psPVRSRVData->bUnload))
+	{
+		/* Wait here until when signalled for queued (pending) CacheOp work items */
+		eError = OSEventObjectWaitTimeout(hOSEvent, CACHEOP_THREAD_WAIT_TIMEOUT);
+		if (eError == PVRSRV_ERROR_TIMEOUT)
+		{
+			PVR_DPF((CACHEOP_DPFL, "%s: wait timeout", __FUNCTION__));
+		}
+		else if (eError == PVRSRV_OK)
+		{
+			PVR_DPF((CACHEOP_DPFL, "%s: wait OK, signal received", __FUNCTION__));
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: wait error %d", __FUNCTION__, eError));
+		}
+
+		CacheOpExecQueuedList(psPVRSRVData);
+	}
+
+	eError = OSEventObjectClose(hOSEvent);
+	PVR_LOG_IF_ERROR(eError, "OSEventObjectClose");
+
+	PVR_DPF((CACHEOP_DPFL, "%s: thread terminating...", __FUNCTION__));
+}
+
+static PVRSRV_ERROR CacheOpExecQueue (PMR **ppsPMR,
+									  IMG_DEVMEM_OFFSET_T *puiOffset,
+									  IMG_DEVMEM_SIZE_T *puiSize,
+									  PVRSRV_CACHE_OP *puiCacheOp,
+									  IMG_UINT32 ui32NumCacheOps,
+									  IMG_UINT32 *pui32OpSeqNum)
+{
+	IMG_UINT32 ui32Idx;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+	if (psPVRSRVData->bUnload)
+	{
+		PVR_DPF((CACHEOP_DPFL, 
+				"%s: driver unloading, performing CacheOp synchronously",
+				__FUNCTION__));
+
+		for (ui32Idx = 0; ui32Idx < ui32NumCacheOps; ui32Idx++)
+		{
+			(void)CacheOpExec(ppsPMR[ui32Idx],
+							  puiOffset[ui32Idx],
+							  puiSize[ui32Idx],
+							  puiCacheOp[ui32Idx]);
+		}
+
+		/* No CacheOp fence dependencies */
+		*pui32OpSeqNum = 0;
+	}
+	else
+	{
+		IMG_DEVMEM_SIZE_T uiLogicalSize;
+		CACHEOP_WORK_ITEM *psCacheOpWorkItem = NULL;
+
+		for (ui32Idx = 0; ui32Idx < ui32NumCacheOps; ui32Idx++)
+		{
+			/* As PVRSRV_CACHE_OP_INVALIDATE is used to transfer
+			   device memory buffer ownership back to processor
+			   we cannot defer it so must action it immediately */
+			if (puiCacheOp[ui32Idx] & PVRSRV_CACHE_OP_INVALIDATE)
+			{
+				eError = CacheOpExec (ppsPMR[ui32Idx],
+									  puiOffset[ui32Idx],
+									  puiSize[ui32Idx],
+									  puiCacheOp[ui32Idx]);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((CACHEOP_DPFL,
+							"%s: PVRSRV_CACHE_OP_INVALIDATE failed (%u)",
+							__FUNCTION__, eError));
+				}
+
+				/* Clear CacheOp fence dependencies if single entry; in a
+				   multiple entry batch, preserve fence dependency update */
+				*pui32OpSeqNum = (ui32Idx == 0) ? 0 : *pui32OpSeqNum;
+				continue;
+			}
+
+			/* Ensure request is valid before deferring to CacheOp thread */
+			eError = PMR_LogicalSize(ppsPMR[ui32Idx], &uiLogicalSize);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((CACHEOP_DPFL,
+						"%s: PMR_LogicalSize failed (%u), cannot defer CacheOp",
+						__FUNCTION__, eError));
+
+				/* Signal the CacheOp thread to ensure queued items get processed */
+				(void) OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+
+				return eError;
+			}
+			else if ((puiOffset[ui32Idx]+puiSize[ui32Idx]) > uiLogicalSize)
+			{
+				PVR_DPF((CACHEOP_DPFL,
+						"%s: Invalid parameters, cannot defer CacheOp",
+						__FUNCTION__));
+
+				/* Signal the CacheOp thread to ensure queued items get processed */
+				(void) OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+
+				return PVRSRV_ERROR_INVALID_PARAMS;;
+			}
+
+			/* For now use dynamic alloc, static CCB _might_ be faster */
+			psCacheOpWorkItem = OSAllocMem(sizeof(CACHEOP_WORK_ITEM));
+			if (psCacheOpWorkItem == NULL)
+			{
+				PVR_DPF((CACHEOP_DPFL, "%s: OSAllocMem failed (%u)",
+						__FUNCTION__, eError));
+
+				/* Signal the CacheOp thread to ensure whatever was enqueued thus
+				   far (if any) gets processed even though we fail the request */
+				eError = OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+
+				return PVRSRV_ERROR_OUT_OF_MEMORY;
+			}
+
+			/* For safety, take reference here in user context; to speed
+			   up deferred cache management we drop reference as late as
+			   possible (during cleanup) */
+			eError = PMRLockSysPhysAddresses(ppsPMR[ui32Idx]);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((CACHEOP_DPFL, "%s: PMRLockSysPhysAddresses failed (%u)",
+						__FUNCTION__, eError));
+
+				OSFreeMem(psCacheOpWorkItem);
+				psCacheOpWorkItem = NULL;
+
+				/* Signal the CacheOp thread to ensure whatever was enqueued thus
+				   far (if any) gets processed even though we fail the request */
+				eError = OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+
+				return eError;
+			}
+
+			/* Prepare & enqueue CacheOp work item */
+#if defined(CACHEOP_DEBUG)
+			psCacheOpWorkItem->pid = OSGetCurrentClientProcessIDKM();
+			psCacheOpWorkItem->ui64QueuedTime = OSClockns64();
+#endif
+			psCacheOpWorkItem->bSignalEventObject = IMG_FALSE;
+			psCacheOpWorkItem->uiCacheOp = puiCacheOp[ui32Idx];
+			psCacheOpWorkItem->uiOffset = puiOffset[ui32Idx];
+			psCacheOpWorkItem->uiSize = puiSize[ui32Idx];
+			psCacheOpWorkItem->psPMR = ppsPMR[ui32Idx];
+			psCacheOpWorkItem->psTimeline = NULL;
+
+			if (ui32Idx == (ui32NumCacheOps - 1))
+			{
+				/* The idea here is to track the last CacheOp in a
+				   batch queue so that we only wake-up stalled threads
+				   waiting on fence checks when such CacheOp has been
+				   processed; this serves to reduce spurious thread
+				   wake-up */
+				psCacheOpWorkItem->bSignalEventObject = IMG_TRUE;
+			}
+
+			eError = CacheOpEnqueue(psPVRSRVData, psCacheOpWorkItem, pui32OpSeqNum);
+			PVR_LOG_IF_ERROR(eError, "CacheOpEnqueue");
+		}
+
+		if (psCacheOpWorkItem != NULL)
+		{
+			/* Signal the CacheOp thread to ensure this item gets processed */
+			eError = OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+			PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+		}
+	}
+
+	return eError;
+}
+#else /* defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED) */
+static PVRSRV_ERROR CacheOpExecQueue(PMR **ppsPMR,
+									IMG_DEVMEM_OFFSET_T *puiOffset,
+									IMG_DEVMEM_SIZE_T *puiSize,
+									PVRSRV_CACHE_OP *puiCacheOp,
+									IMG_UINT32 ui32NumCacheOps,
+									IMG_UINT32 *pui32OpSeqNum)
+{
+	IMG_UINT32 ui32Idx;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	for (ui32Idx = 0; ui32Idx < ui32NumCacheOps; ui32Idx++)
+	{
+		PVRSRV_ERROR eError2 = CacheOpExec(ppsPMR[ui32Idx],
+										   puiOffset[ui32Idx],
+										   puiSize[ui32Idx],
+										   puiCacheOp[ui32Idx]);
+		if (eError2 != PVRSRV_OK)
+		{
+			eError = eError2;
+			PVR_DPF((CACHEOP_DPFL,
+					"%s: CacheOpExec failed (%u)",
+					__FUNCTION__, eError));
+		}
+	}
+
+	/* For immediate RBF, common/completed are identical */
+	*pui32OpSeqNum = OSAtomicRead(&ghCommonCacheOpSeqNum);
+	OSAtomicWrite(&ghCompletedCacheOpSeqNum, *pui32OpSeqNum);
+
+	return eError;
+}
+#endif
+
+PVRSRV_ERROR CacheOpQueue (IMG_UINT32 ui32NumCacheOps,
+						   PMR **ppsPMR,
+						   IMG_DEVMEM_OFFSET_T *puiOffset,
+						   IMG_DEVMEM_SIZE_T *puiSize,
+						   PVRSRV_CACHE_OP *puiCacheOp,
+						   IMG_UINT32 *pui32OpSeqNum)
+{
+	return CacheOpExecQueue(ppsPMR,
+							puiOffset,
+							puiSize,
+							puiCacheOp,
+							ui32NumCacheOps,
+							pui32OpSeqNum);
+}
+
+PVRSRV_ERROR CacheOpFence (RGXFWIF_DM eFenceOpType,
+						   IMG_UINT32 ui32FenceOpSeqNum)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_UINT32 ui32CompletedOpSeqNum;
+	IMG_BOOL b1stCacheOpFenceCheckPass;
+#if defined(CACHEOP_DEBUG)
+	CACHEOP_WORK_ITEM sCacheOpWorkItem;
+	IMG_UINT64 uiTimeNow = OSClockns64();
+	IMG_UINT32 ui32RetryCount = 0;
+
+	dllist_init(&sCacheOpWorkItem.sNode);
+
+	/* No PMR/timeline for fence CacheOp */
+	sCacheOpWorkItem.psPMR = NULL;
+	sCacheOpWorkItem.psTimeline = NULL;
+	sCacheOpWorkItem.ui64QueuedTime = uiTimeNow;
+	sCacheOpWorkItem.ui32OpSeqNum = ui32FenceOpSeqNum;
+	sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
+#if defined(PVR_RI_DEBUG)
+	sCacheOpWorkItem.eFenceOpType = eFenceOpType;
+#endif
+#endif
+
+	PVR_UNREFERENCED_PARAMETER(eFenceOpType);
+
+	ui32CompletedOpSeqNum = OSAtomicRead(&ghCompletedCacheOpSeqNum);
+	b1stCacheOpFenceCheckPass = CacheOpFenceCheck(ui32CompletedOpSeqNum, ui32FenceOpSeqNum);
+
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED)
+	/* If initial fence check fails, then wait-and-retry in loop */
+	if (b1stCacheOpFenceCheckPass == IMG_FALSE)
+	{
+		IMG_HANDLE hOSEvent;
+		PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+		/* Open CacheOp update event object, if event object open fails return error */
+		eError = OSEventObjectOpen(psPVRSRVData->hCacheOpUpdateEventObject, &hOSEvent);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((CACHEOP_DPFL,
+					"%s: failed to open update event object",
+					__FUNCTION__));
+			goto e0;
+		}
+
+		/* (Re)read completed cache op sequence number before wait */
+		ui32CompletedOpSeqNum = OSAtomicRead(&ghCompletedCacheOpSeqNum);
+
+		/* Check if the CacheOp dependencies for this thread are met */
+		eError = CacheOpFenceCheck(ui32CompletedOpSeqNum, ui32FenceOpSeqNum) ?
+				PVRSRV_OK : PVRSRV_ERROR_FAILED_DEPENDENCIES;
+
+		while (eError != PVRSRV_OK)
+		{
+			/* Wait here until signalled that update has occurred by CacheOp thread */
+			eError = OSEventObjectWaitTimeout(hOSEvent, CACHEOP_FENCE_WAIT_TIMEOUT);
+			if (eError == PVRSRV_ERROR_TIMEOUT)
+			{
+				PVR_DPF((CACHEOP_DPFL, "%s: wait timeout", __FUNCTION__));
+#if defined(CACHEOP_DEBUG)
+				/* This is a more accurate notion of fence check retries */
+				ui32RetryCount += 1;
+#endif
+			}
+			else if (eError == PVRSRV_OK)
+			{
+				PVR_DPF((CACHEOP_DPFL, "%s: wait OK, signal received", __FUNCTION__));
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: wait error %d", __FUNCTION__, eError));
+			}
+
+			/* (Re)read latest completed CacheOp sequence number to fence */
+			ui32CompletedOpSeqNum = OSAtomicRead(&ghCompletedCacheOpSeqNum);
+
+			/* Check if the CacheOp dependencies for this thread are met */
+			eError = CacheOpFenceCheck(ui32CompletedOpSeqNum, ui32FenceOpSeqNum) ?
+								PVRSRV_OK : PVRSRV_ERROR_FAILED_DEPENDENCIES;
+		}
+
+#if defined(CACHEOP_DEBUG)
+		uiTimeNow = OSClockns64();
+#endif
+
+		eError = OSEventObjectClose(hOSEvent);
+		PVR_LOG_IF_ERROR(eError, "OSEventObjectClose");
+	}
+
+e0:
+#if defined(CACHEOP_DEBUG)
+	if (b1stCacheOpFenceCheckPass == IMG_FALSE)
+	{
+		/* This log gives an indication of how badly deferred
+		   cache maintenance is doing and provides data for
+		   possible dynamic spawning of multiple CacheOpThreads;
+		   currently not implemented in the framework but such
+		   an extension would require a monitoring thread to
+		   scan the gasCacheOpStatStalled table and spawn/kill a 
+		   new CacheOpThread if certain conditions are met */
+		CacheOpStatStallLogWrite(ui32FenceOpSeqNum,
+								 sCacheOpWorkItem.ui64QueuedTime,
+								 uiTimeNow,
+								 ui32RetryCount);
+	}
+#endif
+#else /* defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED) */
+#if defined(CACHEOP_DEBUG)
+	PVR_UNREFERENCED_PARAMETER(ui32RetryCount);
+#endif
+	/* Fence checks _cannot_ fail in immediate RBF */
+	PVR_UNREFERENCED_PARAMETER(b1stCacheOpFenceCheckPass);
+	PVR_ASSERT(b1stCacheOpFenceCheckPass == IMG_TRUE);
+#endif
+
+#if defined(CACHEOP_DEBUG)
+	sCacheOpWorkItem.ui64ExecuteTime = uiTimeNow;
+	sCacheOpWorkItem.uiCacheOp = PVRSRV_CACHE_OP_NONE;
+	eError = CacheOpStatExecLog(&sCacheOpWorkItem.sNode);
+#endif
+
+	return eError;
+}
+
+PVRSRV_ERROR CacheOpSetTimeline (IMG_INT32 i32Timeline)
+{
+	PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED)
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	CACHEOP_WORK_ITEM *psCacheOpWorkItem;
+	IMG_UINT32 ui32OpSeqNum;
+
+	if (i32Timeline < 0)
+	{
+		return PVRSRV_OK;
+	}
+
+	psCacheOpWorkItem = OSAllocMem(sizeof(CACHEOP_WORK_ITEM));
+	if (psCacheOpWorkItem == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Prepare & enqueue a timeline CacheOp work item */
+	psCacheOpWorkItem->psPMR = NULL;
+#if defined(CACHEOP_DEBUG)
+	psCacheOpWorkItem->ui64QueuedTime = OSClockns64();
+	psCacheOpWorkItem->pid = OSGetCurrentClientProcessIDKM();
+#endif
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && defined(CONFIG_SW_SYNC)
+	psCacheOpWorkItem->psTimeline = fget(i32Timeline);
+	if (!psCacheOpWorkItem->psTimeline || 
+		!psCacheOpWorkItem->psTimeline->private_data)
+	{
+		OSFreeMem(psCacheOpWorkItem);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Enqueue timeline work-item, notifies timeline FD when executed */
+	eError = CacheOpEnqueue(psPVRSRVData, psCacheOpWorkItem, &ui32OpSeqNum);
+	PVR_LOG_IF_ERROR(eError, "CacheOpEnqueue");
+
+	/* Signal the CacheOp thread to ensure this item gets processed */
+	eError = OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+	PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+#else
+	PVR_UNREFERENCED_PARAMETER(psPVRSRVData);
+	PVR_UNREFERENCED_PARAMETER(ui32OpSeqNum);
+	eError = PVRSRV_ERROR_NOT_SUPPORTED;
+	PVR_ASSERT(0);
+#endif
+#else /* defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED) */
+	struct file *psFile;
+
+	if (i32Timeline < 0)
+	{
+		return PVRSRV_OK;
+	}
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && defined(CONFIG_SW_SYNC)
+	psFile = fget(i32Timeline);
+	if (!psFile || !psFile->private_data)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	sw_sync_timeline_inc(psFile->private_data, 1);
+	fput(psFile);
+
+	eError = PVRSRV_OK;
+#else
+	PVR_UNREFERENCED_PARAMETER(psFile);
+	eError = PVRSRV_ERROR_NOT_SUPPORTED;
+	PVR_ASSERT(0);
+#endif
+#endif
+
+	return eError;
+}
+#else /* defined(SUPPORT_RANGEBASED_CACHEFLUSH) */
+PVRSRV_ERROR CacheOpQueue (IMG_UINT32 ui32NumCacheOps,
+						   PMR **ppsPMR,
+						   IMG_DEVMEM_OFFSET_T *puiOffset,
+						   IMG_DEVMEM_SIZE_T *puiSize,
+						   PVRSRV_CACHE_OP *puiCacheOp,
+						   IMG_UINT32 *pui32OpSeqNum)
+{
+	IMG_UINT32 ui32Idx;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_BOOL bHasInvalidate = IMG_FALSE;
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	PVRSRV_CACHE_OP uiCacheOp = PVRSRV_CACHE_OP_NONE;
+#if	defined(CACHEOP_DEBUG)
+	CACHEOP_WORK_ITEM sCacheOpWorkItem;
+	dllist_init(&sCacheOpWorkItem.sNode);
+
+	sCacheOpWorkItem.psPMR = ppsPMR[0];
+	sCacheOpWorkItem.bRBF = IMG_FALSE;
+	sCacheOpWorkItem.bUMF = IMG_FALSE;
+	sCacheOpWorkItem.psTimeline = NULL;
+	sCacheOpWorkItem.uiOffset = puiOffset[0];
+	sCacheOpWorkItem.ui64QueuedTime = (IMG_UINT64)0;
+	sCacheOpWorkItem.ui64ExecuteTime = (IMG_UINT64)0;
+	sCacheOpWorkItem.uiSize = (IMG_DEVMEM_OFFSET_T)0;
+	sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
+#endif
+
+	/* Coalesce all requests into a single superset request */
+	for (ui32Idx = 0; ui32Idx < ui32NumCacheOps; ui32Idx++)
+	{
+		uiCacheOp = SetCacheOp(uiCacheOp, puiCacheOp[ui32Idx]);
+		if (puiCacheOp[ui32Idx] & PVRSRV_CACHE_OP_INVALIDATE)
+		{
+			/* Cannot be deferred, action now */
+			bHasInvalidate = IMG_TRUE;
+#if	!defined(CACHEOP_DEBUG)
+			break;
+#endif
+		}
+#if	defined(CACHEOP_DEBUG)
+		/* For debug, we _want_ to know how many items are in batch */
+		sCacheOpWorkItem.uiSize += puiSize[ui32Idx];
+		*pui32OpSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+		*pui32OpSeqNum = !*pui32OpSeqNum ?
+			OSAtomicIncrement(&ghCommonCacheOpSeqNum) : *pui32OpSeqNum;
+#endif
+	}
+
+#if	!defined(CACHEOP_DEBUG)
+	/* For release, we don't care, so use per-batch sequencing */
+	*pui32OpSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+	*pui32OpSeqNum = !*pui32OpSeqNum ?
+			OSAtomicIncrement(&ghCommonCacheOpSeqNum) : *pui32OpSeqNum;
+#endif
+
+	if (bHasInvalidate == IMG_TRUE)
+	{
+		psPVRSRVData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+
+#if	defined(CACHEOP_DEBUG)
+		sCacheOpWorkItem.ui64QueuedTime = OSClockns64();
+#endif
+
+		/* Perform global cache maintenance operation */
+		eError = OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: OSCPUOperation failed (%u)",
+					__FUNCTION__, eError));
+			goto e0;
+		}
+
+#if	defined(CACHEOP_DEBUG)
+		sCacheOpWorkItem.ui64ExecuteTime = OSClockns64();
+#endif
+
+		/* Having completed the invalidate, note sequence number */
+		OSAtomicWrite(&ghCompletedCacheOpSeqNum, *pui32OpSeqNum);
+	}
+	else
+	{
+		/* NOTE: Possible race condition, CacheOp value set here using SetCacheOp()
+		   might be over-written during read-modify-write sequence in CacheOpFence() */
+		psPVRSRVData->uiCacheOp = SetCacheOp(psPVRSRVData->uiCacheOp, uiCacheOp);
+	}
+
+#if	defined(CACHEOP_DEBUG)
+	sCacheOpWorkItem.uiCacheOp = uiCacheOp;
+	sCacheOpWorkItem.ui32OpSeqNum = *pui32OpSeqNum;
+	eError = CacheOpStatExecLog(&sCacheOpWorkItem.sNode);
+#endif
+
+e0:
+	return eError;
+}
+
+PVRSRV_ERROR CacheOpFence (RGXFWIF_DM eFenceOpType,
+						   IMG_UINT32 ui32FenceOpSeqNum)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	IMG_BOOL b1stCacheOpFenceCheckPass;
+	IMG_UINT32 ui32CacheOpSeqNum;
+	PVRSRV_CACHE_OP uiCacheOp;
+#if defined(CACHEOP_DEBUG)
+	CACHEOP_WORK_ITEM sCacheOpWorkItem;
+	sCacheOpWorkItem.ui64QueuedTime = (IMG_UINT64)0;
+	sCacheOpWorkItem.ui64ExecuteTime = (IMG_UINT64)0;
+	sCacheOpWorkItem.uiCacheOp = PVRSRV_CACHE_OP_NONE;
+#endif
+
+	ui32CacheOpSeqNum = OSAtomicRead(&ghCompletedCacheOpSeqNum);
+	b1stCacheOpFenceCheckPass = CacheOpFenceCheck(ui32CacheOpSeqNum, ui32FenceOpSeqNum);
+
+	/* Flush if there is pending CacheOp that affects this fence */
+	if (b1stCacheOpFenceCheckPass == IMG_FALSE)
+	{
+		/* After global CacheOp, requests before this sequence are met */
+		ui32CacheOpSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+		ui32CacheOpSeqNum = !ui32CacheOpSeqNum ?
+				OSAtomicIncrement(&ghCommonCacheOpSeqNum) : ui32CacheOpSeqNum;
+
+		uiCacheOp = psPVRSRVData->uiCacheOp;
+		psPVRSRVData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+
+#if	defined(CACHEOP_DEBUG)
+		sCacheOpWorkItem.ui64QueuedTime = OSClockns64();
+#endif
+
+		/* Perform global cache maintenance operation */
+		eError = OSCPUOperation(uiCacheOp);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: OSCPUOperation failed (%u)",
+					__FUNCTION__, eError));
+			goto e0;
+		}
+
+#if	defined(CACHEOP_DEBUG)
+		sCacheOpWorkItem.ui64ExecuteTime = OSClockns64();
+		sCacheOpWorkItem.uiCacheOp = uiCacheOp;
+#endif
+
+		/* Having completed global CacheOp, note sequence number */
+		OSAtomicWrite(&ghCompletedCacheOpSeqNum, ui32CacheOpSeqNum);
+	}
+
+#if defined(CACHEOP_DEBUG)
+	dllist_init(&sCacheOpWorkItem.sNode);
+
+	sCacheOpWorkItem.psPMR = NULL;
+	sCacheOpWorkItem.psTimeline = NULL;
+	sCacheOpWorkItem.ui32OpSeqNum = ui32FenceOpSeqNum;
+	sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
+#if defined(PVR_RI_DEBUG)
+	sCacheOpWorkItem.eFenceOpType = eFenceOpType;
+#endif
+
+	eError = CacheOpStatExecLog(&sCacheOpWorkItem.sNode);
+#endif
+
+e0:
+	return eError;
+}
+
+PVRSRV_ERROR CacheOpSetTimeline (IMG_INT32 i32Timeline)
+{
+	PVRSRV_ERROR eError;
+	struct file *psFile;
+	PVRSRV_CACHE_OP uiCacheOp;
+	PVRSRV_DATA *psPVRSRVData;
+
+	if (i32Timeline < 0)
+	{
+		return PVRSRV_OK;
+	}
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && defined(CONFIG_SW_SYNC)
+	psFile = fget(i32Timeline);
+	if (!psFile || !psFile->private_data)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psPVRSRVData = PVRSRVGetPVRSRVData();
+	uiCacheOp = psPVRSRVData->uiCacheOp;
+	psPVRSRVData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+
+	/* Perform global cache maintenance operation */
+	eError = OSCPUOperation(uiCacheOp);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: OSCPUOperation failed (%u)",
+				__FUNCTION__, eError));
+		goto e0;
+	}
+
+	sw_sync_timeline_inc(psFile->private_data, 1);
+	fput(psFile);
+e0:
+#else
+	PVR_UNREFERENCED_PARAMETER(psFile);
+	PVR_UNREFERENCED_PARAMETER(uiCacheOp);
+	PVR_UNREFERENCED_PARAMETER(psPVRSRVData);
+	eError = PVRSRV_ERROR_NOT_SUPPORTED;
+	PVR_ASSERT(0);
+#endif
+
+	return eError;
+}
+#endif /* defined(SUPPORT_RANGEBASED_CACHEFLUSH) */
+
+PVRSRV_ERROR CacheOpExec (PMR *psPMR,
+						  IMG_DEVMEM_OFFSET_T uiOffset,
+						  IMG_DEVMEM_SIZE_T uiSize,
+						  PVRSRV_CACHE_OP uiCacheOp)
+{
+	PVRSRV_ERROR eError;
+	IMG_DEVMEM_SIZE_T uiLogicalSize;
+	IMG_BOOL bUsedGlobalFlush = IMG_FALSE;
+#if	defined(CACHEOP_DEBUG)
+	/* This interface is always synchronous and not deferred;
+	   during debug build, use work-item to capture debug logs */
+	CACHEOP_WORK_ITEM sCacheOpWorkItem;
+	dllist_init(&sCacheOpWorkItem.sNode);
+
+	sCacheOpWorkItem.psPMR = psPMR;
+	sCacheOpWorkItem.uiSize = uiSize;
+	sCacheOpWorkItem.psTimeline = NULL;
+	sCacheOpWorkItem.uiOffset = uiOffset;
+	sCacheOpWorkItem.uiCacheOp = uiCacheOp;
+	sCacheOpWorkItem.ui64QueuedTime = OSClockns64();
+	sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
+	sCacheOpWorkItem.ui32OpSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+	sCacheOpWorkItem.ui32OpSeqNum = !sCacheOpWorkItem.ui32OpSeqNum ?
+		OSAtomicIncrement(&ghCommonCacheOpSeqNum) : sCacheOpWorkItem.ui32OpSeqNum;
+#endif
+
+	eError = PMR_LogicalSize(psPMR, &uiLogicalSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((CACHEOP_DPFL,
+				"%s: PMR_LogicalSize failed (%u)",
+				__FUNCTION__, eError));
+		goto e0;
+	}
+	else if ((uiOffset+uiSize) > uiLogicalSize)
+	{
+		PVR_DPF((CACHEOP_DPFL,
+				"%s: Invalid parameters",
+				__FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto e0;
+	}
+
+	/* Perform range-based cache maintenance operation */
+	eError = PMRLockSysPhysAddresses(psPMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((CACHEOP_DPFL,
+				"%s: PMRLockSysPhysAddresses failed (%u)",
+				__FUNCTION__, eError));
+		goto e0;
+	}
+
+	eError = CacheOpRangeBased(psPMR, uiOffset, uiSize, uiCacheOp, &bUsedGlobalFlush);
+#if	defined(CACHEOP_DEBUG)
+	sCacheOpWorkItem.bUMF = IMG_FALSE;
+	sCacheOpWorkItem.bRBF = !bUsedGlobalFlush;
+	sCacheOpWorkItem.ui64ExecuteTime = OSClockns64();
+	eError = CacheOpStatExecLog(&sCacheOpWorkItem.sNode);
+#endif
+
+	PMRUnlockSysPhysAddresses(psPMR);
+e0:
+	return eError;
+}
+
+PVRSRV_ERROR CacheOpLog (PMR *psPMR,
+						 IMG_DEVMEM_OFFSET_T uiOffset,
+						 IMG_DEVMEM_SIZE_T uiSize,
+						 IMG_UINT64 ui64QueuedTimeUs,
+						 IMG_UINT64 ui64ExecuteTimeUs,
+						 PVRSRV_CACHE_OP uiCacheOp)
+{
+#if defined(CACHEOP_DEBUG)
+	CACHEOP_WORK_ITEM sCacheOpWorkItem;
+	dllist_init(&sCacheOpWorkItem.sNode);
+
+	sCacheOpWorkItem.psPMR = psPMR;
+	sCacheOpWorkItem.uiSize = uiSize;
+	sCacheOpWorkItem.psTimeline = NULL;
+	sCacheOpWorkItem.uiOffset = uiOffset;
+	sCacheOpWorkItem.uiCacheOp = uiCacheOp;
+	sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
+	sCacheOpWorkItem.ui32OpSeqNum = OSAtomicIncrement(&ghCommonCacheOpSeqNum);
+	sCacheOpWorkItem.ui32OpSeqNum = !sCacheOpWorkItem.ui32OpSeqNum ?
+		OSAtomicIncrement(&ghCommonCacheOpSeqNum) : sCacheOpWorkItem.ui32OpSeqNum;
+
+	/* All UM cache maintenance is range-based */
+	sCacheOpWorkItem.ui64ExecuteTime = ui64ExecuteTimeUs;
+	sCacheOpWorkItem.ui64QueuedTime = ui64QueuedTimeUs;
+	sCacheOpWorkItem.bUMF = IMG_TRUE;
+	sCacheOpWorkItem.bRBF = IMG_TRUE;
+
+	CacheOpStatExecLogWrite(&sCacheOpWorkItem.sNode);
+#else /* defined(CACHEOP_DEBUG) */
+	PVR_UNREFERENCED_PARAMETER(psPMR);
+	PVR_UNREFERENCED_PARAMETER(uiSize);
+	PVR_UNREFERENCED_PARAMETER(uiOffset);
+	PVR_UNREFERENCED_PARAMETER(ui64QueuedTimeUs);
+	PVR_UNREFERENCED_PARAMETER(ui64ExecuteTimeUs);
+	PVR_UNREFERENCED_PARAMETER(uiCacheOp);
+#endif
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR CacheOpGetLineSize (IMG_UINT32 *pui32L1DataCacheLineSize)
+{
+	*pui32L1DataCacheLineSize = guiCacheLineSize;
+	PVR_ASSERT(guiCacheLineSize != 0);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR CacheOpInit (void)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DATA *psPVRSRVData;
+
+	/* DDK initialisation is anticipated to be performed on the boot
+	   processor (little core in big/little systems) though this may
+	   not always be the case. If so, the value cached here is the 
+	   system wide safe (i.e. smallest) L1 d-cache line size value 
+	   on platforms with mismatched d-cache line sizes */
+	guiCacheLineSize = OSCPUCacheAttributeSize(PVR_DCACHE_LINE_SIZE);
+	PVR_ASSERT(guiCacheLineSize != 0);
+
+	guiOSPageSize = OSGetPageSize();
+	PVR_ASSERT(guiOSPageSize != 0);
+
+	OSAtomicWrite(&ghCommonCacheOpSeqNum, 0);
+	OSAtomicWrite(&ghCompletedCacheOpSeqNum, 0);
+
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED)
+	psPVRSRVData = PVRSRVGetPVRSRVData();
+
+	/* Create an event object for pending CacheOp work items */
+	eError = OSEventObjectCreate("PVRSRV_CACHEOP_EVENTOBJECT", &psPVRSRVData->hCacheOpThreadEventObject);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* Create an event object for updating pending fence checks on CacheOp */
+	eError = OSEventObjectCreate("PVRSRV_CACHEOP_EVENTOBJECT", &psPVRSRVData->hCacheOpUpdateEventObject);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* Create a lock to police list of pending CacheOp work items */
+	eError = OSLockCreate((POS_LOCK*)&psPVRSRVData->hCacheOpThreadWorkListLock, LOCK_TYPE_PASSIVE);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* Initialise pending CacheOp list & seq number */
+	dllist_init(&psPVRSRVData->sCacheOpThreadWorkList);
+	guiPendingDevmemSize = (IMG_DEVMEM_SIZE_T) 0;
+	gbPendingTimeline = IMG_FALSE;
+
+#if defined(CACHEOP_DEBUG)
+	gi32CacheOpStatExecWriteIdx = 0;
+	gi32CacheOpStatStallWriteIdx = 0;
+
+	OSCachedMemSet(gasCacheOpStatExecuted, 0, sizeof(gasCacheOpStatExecuted));
+	OSCachedMemSet(gasCacheOpStatStalled, 0, sizeof(gasCacheOpStatStalled));
+
+	eError = OSLockCreate((POS_LOCK*)&ghCacheOpStatExecLock, LOCK_TYPE_PASSIVE);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	eError = OSLockCreate((POS_LOCK*)&ghCacheOpStatStallLock, LOCK_TYPE_PASSIVE);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	pvCacheOpStatExecEntry = OSCreateStatisticEntry("cache_ops_exec",
+												NULL,
+												CacheOpStatExecLogRead,
+												NULL,
+												NULL,
+												NULL);
+	PVR_ASSERT(pvCacheOpStatExecEntry != NULL);
+
+	pvCacheOpStatStallEntry = OSCreateStatisticEntry("cache_ops_stall",
+												NULL,
+												CacheOpStatStallLogRead,
+												NULL,
+												NULL,
+												NULL);
+	PVR_ASSERT(pvCacheOpStatStallEntry != NULL);
+#endif
+
+	/* Create a thread which is used to do the deferred CacheOp */
+	eError = OSThreadCreatePriority(&psPVRSRVData->hCacheOpThread,
+							"pvr_cache_ops",
+							CacheOpThread, 
+							psPVRSRVData,
+							OS_THREAD_HIGHEST_PRIORITY);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"CacheOpInit: failed to create CacheOp thread"));
+		return CacheOpDeInit();
+	}
+#else /* defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED) */
+	PVR_UNREFERENCED_PARAMETER(psPVRSRVData);
+#if defined(CACHEOP_DEBUG)
+	gi32CacheOpStatExecWriteIdx = 0;
+
+	OSCachedMemSet(gasCacheOpStatExecuted, 0, sizeof(gasCacheOpStatExecuted));
+
+	eError = OSLockCreate((POS_LOCK*)&ghCacheOpStatExecLock, LOCK_TYPE_PASSIVE);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	pvCacheOpStatExecEntry = OSCreateStatisticEntry("cache_ops_exec",
+												NULL,
+												CacheOpStatExecLogRead,
+												NULL,
+												NULL,
+												NULL);
+	PVR_ASSERT(pvCacheOpStatExecEntry != NULL);
+#endif
+	eError = PVRSRV_OK;
+#endif
+
+	return eError;
+}
+
+PVRSRV_ERROR CacheOpDeInit (void)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	PVRSRV_DATA *psPVRSRVData;
+
+#if defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED)
+	psPVRSRVData = PVRSRVGetPVRSRVData();
+
+#if defined(CACHEOP_DEBUG)
+	OSLockDestroy(ghCacheOpStatExecLock);
+	OSRemoveStatisticEntry(pvCacheOpStatExecEntry);
+	OSRemoveStatisticEntry(pvCacheOpStatStallEntry);
+#endif
+
+	if (psPVRSRVData->hCacheOpThread)
+	{
+		if (psPVRSRVData->hCacheOpThreadEventObject)
+		{
+			eError = OSEventObjectSignal(psPVRSRVData->hCacheOpThreadEventObject);
+			PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+		}
+
+		if (psPVRSRVData->hCacheOpUpdateEventObject)
+		{
+			eError = OSEventObjectSignal(psPVRSRVData->hCacheOpUpdateEventObject);
+			PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+		}
+
+		LOOP_UNTIL_TIMEOUT(OS_THREAD_DESTROY_TIMEOUT_US)
+		{
+			eError = OSThreadDestroy(psPVRSRVData->hCacheOpThread);
+			if (PVRSRV_OK == eError)
+			{
+				psPVRSRVData->hCacheOpThread = NULL;
+				break;
+			}
+			OSWaitus(OS_THREAD_DESTROY_TIMEOUT_US/OS_THREAD_DESTROY_RETRY_COUNT);
+		} END_LOOP_UNTIL_TIMEOUT();
+		PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
+	}
+
+	OSLockDestroy(psPVRSRVData->hCacheOpThreadWorkListLock);
+	psPVRSRVData->hCacheOpThreadWorkListLock = NULL;
+
+	if (psPVRSRVData->hCacheOpUpdateEventObject)
+	{
+		eError = OSEventObjectDestroy(psPVRSRVData->hCacheOpUpdateEventObject);
+		PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+		psPVRSRVData->hCacheOpUpdateEventObject = NULL;
+	}
+
+	if (psPVRSRVData->hCacheOpThreadEventObject)
+	{
+		eError = OSEventObjectDestroy(psPVRSRVData->hCacheOpThreadEventObject);
+		PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+		psPVRSRVData->hCacheOpThreadEventObject = NULL;
+	}
+
+	eError = PVRSRV_OK;
+#else /* defined(SUPPORT_RANGEBASED_CACHEFLUSH_DEFERRED) */
+	PVR_UNREFERENCED_PARAMETER(psPVRSRVData);
+#if defined(CACHEOP_DEBUG)
+	OSLockDestroy(ghCacheOpStatExecLock);
+	OSRemoveStatisticEntry(pvCacheOpStatExecEntry);
+#endif
+	eError = PVRSRV_OK;
+#endif
+
+	return eError;
+}
diff --git a/drivers/staging/imgtec/rogue/cache_km.h b/drivers/staging/imgtec/rogue/cache_km.h
new file mode 100644
index 0000000..a06af5e
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/cache_km.h
@@ -0,0 +1,146 @@
+/*************************************************************************/ /*!
+@File           cache.h
+@Title          CPU cache management header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _CACHE_KM_H_
+#define _CACHE_KM_H_
+
+#if defined(LINUX)
+#include <linux/version.h>
+#endif
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "cache_ops.h"
+#include "device.h"
+#include "pmr.h"
+
+typedef IMG_UINT32 PVRSRV_CACHE_OP_ADDR_TYPE;	/*!< Type represents address required for cache op. */
+#define PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL	0x1	/*!< Operation requires virtual address only */
+#define PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL	0x2	/*!< Operation requires physical address only */
+#define PVRSRV_CACHE_OP_ADDR_TYPE_BOTH		0x3	/*!< Operation requires both virtual & physical addresses */
+
+#define CACHEFLUSH_KM_RANGEBASED_DEFERRED	0x1	/*!< Services KM using deferred (i.e asynchronous) range-based flush */
+#define CACHEFLUSH_KM_RANGEBASED			0x2	/*!< Services KM using immediate (i.e synchronous) range-based flush */
+#define CACHEFLUSH_KM_GLOBAL				0x3	/*!< Services KM using global flush */
+#ifndef CACHEFLUSH_KM_TYPE						/*!< Type represents cache maintenance operation method */
+	#if defined(__x86__)
+		/* Default for x86/x86_64 is global */
+		#define CACHEFLUSH_KM_TYPE CACHEFLUSH_KM_GLOBAL
+	#elif defined(__aarch64__)
+		#if defined(LINUX) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0))
+			/* Default here is range-based (i.e. no linux global flush) */
+			#define CACHEFLUSH_KM_TYPE CACHEFLUSH_KM_RANGEBASED
+		#else
+			/* Default here is global (i.e. OS supports global flush) */
+			#define CACHEFLUSH_KM_TYPE CACHEFLUSH_KM_GLOBAL
+		#endif
+	#else
+		/* Default for other architecture is range-based */
+		#define CACHEFLUSH_KM_TYPE CACHEFLUSH_KM_RANGEBASED
+	#endif
+#else
+	#if (CACHEFLUSH_KM_TYPE == CACHEFLUSH_KM_GLOBAL)
+		#if defined(__mips__) 
+			/* Architecture does not support global cache maintenance */
+			#error "CACHEFLUSH_KM_GLOBAL is not supported on architecture"
+		#elif defined(__aarch64__)
+			#if defined(LINUX) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0))
+				/* Linux revisions does not support global cache maintenance */
+				#error "CACHEFLUSH_KM_GLOBAL is not supported on Linux v4.2 onwards"
+			#endif
+		#endif
+	#endif
+#endif
+
+/*
+	If we get multiple cache operations before the operation which will
+	trigger the operation to happen then we need to make sure we do
+	the right thing. Used for global cache maintenance
+*/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SetCacheOp)
+#endif
+static INLINE PVRSRV_CACHE_OP SetCacheOp(PVRSRV_CACHE_OP uiCurrent, PVRSRV_CACHE_OP uiNew)
+{
+	PVRSRV_CACHE_OP uiRet;
+	uiRet = uiCurrent | uiNew;
+	return uiRet;
+}
+
+/*
+	Cache maintenance framework API
+*/
+PVRSRV_ERROR CacheOpInit(void);
+PVRSRV_ERROR CacheOpDeInit(void);
+
+/* This interface is always guaranteed to be synchronous */
+PVRSRV_ERROR CacheOpExec (PMR *psPMR,
+						IMG_DEVMEM_OFFSET_T uiOffset,
+						IMG_DEVMEM_SIZE_T uiSize,
+						PVRSRV_CACHE_OP uiCacheOp);
+
+/* This interface _may_ defer cache-ops (i.e. asynchronous) */
+PVRSRV_ERROR CacheOpQueue (IMG_UINT32 ui32OpCount,
+						PMR **ppsPMR,
+						IMG_DEVMEM_OFFSET_T *puiOffset,
+						IMG_DEVMEM_SIZE_T *puiSize,
+						PVRSRV_CACHE_OP *puiCacheOp,
+						IMG_UINT32 *pui32OpSeqNum);
+
+/* This interface is used to log user-mode cache-ops */
+PVRSRV_ERROR CacheOpLog (PMR *psPMR,
+						IMG_DEVMEM_OFFSET_T uiOffset,
+						IMG_DEVMEM_SIZE_T uiSize,
+						IMG_UINT64 ui64QueuedTimeMs,
+						IMG_UINT64 ui64ExecuteTimeMs,
+						PVRSRV_CACHE_OP uiCacheOp);
+
+/* This interface must be used to fence for pending cache-ops before kicks */
+PVRSRV_ERROR CacheOpFence (RGXFWIF_DM eOpType, IMG_UINT32 ui32OpSeqNum);
+
+/* This interface is used for notification of completed cache-ops */
+PVRSRV_ERROR CacheOpSetTimeline (IMG_INT32 i32OpTimeline);
+
+/* This interface is used for retrieving the processor d-cache line size */
+PVRSRV_ERROR CacheOpGetLineSize (IMG_UINT32 *pui32L1DataCacheLineSize);
+#endif	/* _CACHE_KM_H_ */
+
diff --git a/drivers/staging/imgtec/rogue/cache_external.h b/drivers/staging/imgtec/rogue/cache_ops.h
similarity index 67%
rename from drivers/staging/imgtec/rogue/cache_external.h
rename to drivers/staging/imgtec/rogue/cache_ops.h
index 134845b..95ca76c 100644
--- a/drivers/staging/imgtec/rogue/cache_external.h
+++ b/drivers/staging/imgtec/rogue/cache_ops.h
@@ -42,40 +42,29 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _CACHE_EXTERNAL_H_
-#define _CACHE_EXTERNAL_H_
+#ifndef _CACHE_OPS_H_
+#define _CACHE_OPS_H_
 #include "img_types.h"
 
-typedef IMG_UINT32 PVRSRV_CACHE_OP;
+typedef IMG_UINT32 PVRSRV_CACHE_OP;				/*!< Type represents cache maintenance operation */
+#define PVRSRV_CACHE_OP_NONE				0x0	/*!< No operation */
+#define PVRSRV_CACHE_OP_CLEAN				0x1	/*!< Flush w/o invalidate */
+#define PVRSRV_CACHE_OP_INVALIDATE			0x2	/*!< Invalidate w/o flush */
+#define PVRSRV_CACHE_OP_FLUSH				0x3	/*!< Flush w/ invalidate */
 
-#define PVRSRV_CACHE_OP_NONE		0x0			/*!< No operation */
-#define PVRSRV_CACHE_OP_CLEAN		0x1			/*!< Flush w/o invalidate */
-#define PVRSRV_CACHE_OP_INVALIDATE	0x2			/*!< Invalidate w/o flush */
-#define PVRSRV_CACHE_OP_FLUSH		0x3			/*!< Flush w/ invalidate */
-
-typedef IMG_UINT32 PVRSRV_CACHE_OP_ADDR_TYPE;
-
-#define PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL	0x1	/*!< Operation requires virtual address only */
-#define PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL	0x2	/*!< Operation requires physical address only */
-#define PVRSRV_CACHE_OP_ADDR_TYPE_BOTH		0x3	/*!< Operation requires both virtual & physical addresses */
-
-/*
-	If we get multiple cache operations before the operation which will
-	trigger the operation to happen then we need to make sure we do
-	the right thing.
-
-	Note: PVRSRV_CACHE_OP_INVALIDATE should never be passed into here
-*/
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(SetCacheOp)
+#define CACHEFLUSH_UM_X86					0x1	/*!< Intel x86/x64 specific UM range-based cache flush */
+#define CACHEFLUSH_UM_ARM64					0x2	/*!< ARM Aarch64 specific UM range-based cache flush */
+#define CACHEFLUSH_UM_GENERIC				0x3	/*!< Generic UM/KM cache flush (i.e. CACHEFLUSH_KM_TYPE) */
+#define CACHEFLUSH_UM_X86_ONLY				0x4	/*!< Force x86/x64 UM flush exclusively */
+#define CACHEFLUSH_UM_ARM64_ONLY			0x5	/*!< Force ARM Aarch64 UM flush exclusively */
+#ifndef CACHEFLUSH_UM_TYPE
+	#if defined(__i386__) || defined(__x86_64__)
+		#define CACHEFLUSH_UM_TYPE CACHEFLUSH_UM_X86
+	#elif defined(__aarch64__)
+		#define CACHEFLUSH_UM_TYPE CACHEFLUSH_UM_ARM64
+	#else
+		#define CACHEFLUSH_UM_TYPE CACHEFLUSH_UM_GENERIC
+	#endif
 #endif
-static INLINE PVRSRV_CACHE_OP SetCacheOp(PVRSRV_CACHE_OP uiCurrent,
-										 PVRSRV_CACHE_OP uiNew)
-{
-	PVRSRV_CACHE_OP uiRet;
 
-	uiRet = uiCurrent | uiNew;
-	return uiRet;
-}
-
-#endif	/* _CACHE_EXTERNAL_H_ */
+#endif	/* _CACHE_OPS_H_ */
diff --git a/drivers/staging/imgtec/rogue/connection_server.c b/drivers/staging/imgtec/rogue/connection_server.c
index ec0dab4..9bc8e9b 100644
--- a/drivers/staging/imgtec/rogue/connection_server.c
+++ b/drivers/staging/imgtec/rogue/connection_server.c
@@ -52,6 +52,8 @@
 #include "process_stats.h"
 #include "pdump_km.h"
 #include "lists.h"
+#include "osfunc.h"
+#include "tlstream.h"
 
 /* PID associated with Connection currently being purged by Cleanup thread */
 static IMG_PID gCurrentPurgeConnectionPid = 0;
@@ -59,6 +61,19 @@
 static PVRSRV_ERROR ConnectionDataDestroy(CONNECTION_DATA *psConnection)
 {
 	PVRSRV_ERROR eError;
+	PROCESS_HANDLE_BASE *psProcessHandleBase;
+	IMG_UINT64 ui64MaxBridgeTime;
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+	if(psPVRSRVData->bUnload)
+	{
+		/* driver is unloading so do not allow the bridge lock to be released */
+		ui64MaxBridgeTime = 0;
+	}
+	else
+	{
+		ui64MaxBridgeTime = CONNECTION_DEFERRED_CLEANUP_TIMESLICE_NS;
+	}
 
 	if (psConnection == NULL)
 	{
@@ -76,25 +91,60 @@
 	}
 #endif
 
+	/* Close HWPerfClient stream here even though we created it in
+	 * PVRSRVConnectKM(). */
+	if (psConnection->hClientTLStream)
+	{
+		TLStreamClose(psConnection->hClientTLStream);
+		psConnection->hClientTLStream = NULL;
+		PVR_DPF((PVR_DBG_MESSAGE, "Destroyed private stream."));
+	}
+
+	/* Get process handle base to decrement the refcount */
+	psProcessHandleBase = psConnection->psProcessHandleBase;
+
+	if (psProcessHandleBase != NULL)
+	{
+		/* In case the refcount becomes 0 we can remove the process handle base */
+		if (OSAtomicDecrement(&psProcessHandleBase->iRefCount) == 0)
+		{
+			uintptr_t uiHashValue;
+
+			OSLockAcquire(psPVRSRVData->hProcessHandleBase_Lock);
+			uiHashValue = HASH_Remove(psPVRSRVData->psProcessHandleBase_Table, psConnection->pid);
+			OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
+
+			if (!uiHashValue)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						"%s: Failed to remove handle base from hash table.",
+						__func__));
+				return PVRSRV_ERROR_UNABLE_TO_REMOVE_HASH_VALUE;
+			}
+
+			eError = PVRSRVFreeHandleBase(psProcessHandleBase->psHandleBase, ui64MaxBridgeTime);
+			if (eError != PVRSRV_OK)
+			{
+				if (eError != PVRSRV_ERROR_RETRY)
+				{
+					PVR_DPF((PVR_DBG_ERROR,
+						 "ConnectionDataDestroy: Couldn't free handle base for process (%d)",
+						 eError));
+				}
+
+				return eError;
+			}
+
+			OSFreeMem(psProcessHandleBase);
+		}
+
+		psConnection->psProcessHandleBase = NULL;
+	}
+
 	/* Free handle base for this connection */
 	if (psConnection->psHandleBase != NULL)
 	{
-		PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-		IMG_UINT64 ui64MaxBridgeTime;
-
-		if(psPVRSRVData->bUnload)
-		{
-			/* driver is unloading so do not allow the bridge lock to be released */
-			ui64MaxBridgeTime = 0;
-		}
-		else
-		{
-			ui64MaxBridgeTime = CONNECTION_DEFERRED_CLEANUP_TIMESLICE_NS;
-		}
-
-		PMRLock();
 		eError = PVRSRVFreeHandleBase(psConnection->psHandleBase, ui64MaxBridgeTime);
-		PMRUnlock();
 		if (eError != PVRSRV_OK)
 		{
 			if (eError != PVRSRV_ERROR_RETRY)
@@ -147,6 +197,8 @@
 {
 	CONNECTION_DATA *psConnection;
 	PVRSRV_ERROR eError;
+	PROCESS_HANDLE_BASE *psProcessHandleBase;
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
 
 	/* Allocate connection data area */
 	psConnection = OSAllocZMem(sizeof(*psConnection));
@@ -192,7 +244,8 @@
 	}
 
 	/* Allocate handle base for this connection */
-	eError = PVRSRVAllocHandleBase(&psConnection->psHandleBase);
+	eError = PVRSRVAllocHandleBase(&psConnection->psHandleBase,
+	                               PVRSRV_HANDLE_BASE_TYPE_CONNECTION);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
@@ -201,6 +254,57 @@
 		goto failure;
 	}
 
+	/* Try to get process handle base if it already exists */
+	OSLockAcquire(psPVRSRVData->hProcessHandleBase_Lock);
+	psProcessHandleBase = (PROCESS_HANDLE_BASE*) HASH_Retrieve(PVRSRVGetPVRSRVData()->psProcessHandleBase_Table,
+	                                                           psConnection->pid);
+
+	/* In case there is none we are going to allocate one */
+	if (psProcessHandleBase == NULL)
+	{
+		psProcessHandleBase = OSAllocZMem(sizeof(PROCESS_HANDLE_BASE));
+		if (psProcessHandleBase == NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"%s: Failed to allocate handle base, oom.",
+					__func__));
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto failureLock;
+		}
+
+		/* Allocate handle base for this process */
+		eError = PVRSRVAllocHandleBase(&psProcessHandleBase->psHandleBase,
+		                               PVRSRV_HANDLE_BASE_TYPE_PROCESS);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Couldn't allocate handle base for process (%d)",
+			         __func__,
+			         eError));
+			OSFreeMem(psProcessHandleBase);
+			goto failureLock;
+		}
+
+		/* Insert the handle base into the global hash table */
+		if (!HASH_Insert(PVRSRVGetPVRSRVData()->psProcessHandleBase_Table,
+		                 psConnection->pid,
+		                 (uintptr_t) psProcessHandleBase))
+		{
+
+			eError = PVRSRV_ERROR_UNABLE_TO_INSERT_HASH_VALUE;
+
+			PVRSRVFreeHandleBase(psProcessHandleBase->psHandleBase, 0);
+
+			OSFreeMem(psProcessHandleBase);
+			goto failureLock;
+		}
+	}
+	OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
+
+	psConnection->psProcessHandleBase = psProcessHandleBase;
+
+	OSAtomicIncrement(&psProcessHandleBase->iRefCount);
+
 	/* Allocate process statistics */
 #if defined(PVRSRV_ENABLE_PROCESS_STATS) && !defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
 	eError = PVRSRVStatsRegisterProcess(&psConnection->hProcessStats);
@@ -217,6 +321,8 @@
 
 	return eError;
 
+failureLock:
+	OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
 failure:
 	ConnectionDataDestroy(psConnection);
 
@@ -275,22 +381,17 @@
 	{
 		PDumpDisconnectionNotify();
 	}
-
-	/* Defer the release of the connection data */
-	psConnectionData->sCleanupThreadFn.pfnFree = _CleanupThreadPurgeConnectionData;
-	psConnectionData->sCleanupThreadFn.pvData = psConnectionData;
-	psConnectionData->sCleanupThreadFn.ui32RetryCount = CLEANUP_THREAD_RETRY_COUNT_DEFAULT;
-	PVRSRVCleanupThreadAddWork(&psConnectionData->sCleanupThreadFn);
-}
-
-PVRSRV_ERROR PVRSRVConnectionInit(void)
-{
-	return PVRSRV_OK;
-}
-
-PVRSRV_ERROR PVRSRVConnectionDeInit(void)
-{
-	return PVRSRV_OK;
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	if (PVRSRVGetPVRSRVData()->eServicesState == PVRSRV_SERVICES_STATE_OK)
+#endif
+	{
+		/* Defer the release of the connection data */
+		psConnectionData->sCleanupThreadFn.pfnFree = _CleanupThreadPurgeConnectionData;
+		psConnectionData->sCleanupThreadFn.pvData = psConnectionData;
+		psConnectionData->sCleanupThreadFn.ui32RetryCount = CLEANUP_THREAD_RETRY_COUNT_DEFAULT;
+		psConnectionData->sCleanupThreadFn.bDependsOnHW = IMG_FALSE;
+		PVRSRVCleanupThreadAddWork(&psConnectionData->sCleanupThreadFn);
+	}
 }
 
 IMG_PID PVRSRVGetPurgeConnectionPid(void)
diff --git a/drivers/staging/imgtec/rogue/connection_server.h b/drivers/staging/imgtec/rogue/connection_server.h
index 2bbc623..481a07a 100644
--- a/drivers/staging/imgtec/rogue/connection_server.h
+++ b/drivers/staging/imgtec/rogue/connection_server.h
@@ -59,6 +59,7 @@
 typedef struct _CONNECTION_DATA_
 {
 	PVRSRV_HANDLE_BASE		*psHandleBase;
+	PROCESS_HANDLE_BASE		*psProcessHandleBase;
 	struct _SYNC_CONNECTION_DATA_	*psSyncConnectionData;
 	struct _PDUMP_CONNECTION_DATA_	*psPDumpConnectionData;
 
@@ -78,6 +79,8 @@
 
 	IMG_HANDLE			hProcessStats;
 
+	IMG_HANDLE			hClientTLStream;
+
 	/* Structure which is hooked into the cleanup thread work list */
 	PVRSRV_CLEANUP_THREAD_WORK sCleanupThreadFn;
 
@@ -91,9 +94,6 @@
 PVRSRV_ERROR PVRSRVConnectionConnect(void **ppvPrivData, void *pvOSData);
 void PVRSRVConnectionDisconnect(void *pvPrivData);
 
-PVRSRV_ERROR PVRSRVConnectionInit(void);
-PVRSRV_ERROR PVRSRVConnectionDeInit(void);
-
 IMG_PID PVRSRVGetPurgeConnectionPid(void);
 
 #ifdef INLINE_IS_PRAGMA
diff --git a/drivers/staging/imgtec/rogue/dbgdriv.c b/drivers/staging/imgtec/rogue/dbgdriv.c
index 0cbe704..935efc9 100644
--- a/drivers/staging/imgtec/rogue/dbgdriv.c
+++ b/drivers/staging/imgtec/rogue/dbgdriv.c
@@ -57,7 +57,7 @@
 #include <linux/string.h>
 #endif
 
-#if defined (__QNXNTO__)
+#if defined (__QNXNTO__) || defined (INTEGRITY_OS)
 #include <string.h>
 #endif
 
@@ -78,8 +78,6 @@
  Types
 ******************************************************************************/
 
-#define DBG_STREAM_NAME_MAX		30
-
 /*
 	Per-buffer control structure.
 */
@@ -98,7 +96,7 @@
 
 	IMG_UINT32 ui32InitPhaseWOff;	/*!< snapshot offset for init phase end for follow-on pdump */
 
-	IMG_CHAR   szName[DBG_STREAM_NAME_MAX];			/* Give this a size, some compilers don't like [] */
+	IMG_CHAR   szName[DEBUG_STREAM_NAME_MAX];			/* Give this a size, some compilers don't like [] */
 } DBG_STREAM;
 
 /* Check 4xDBG_STREAM will fit in one page */
@@ -166,7 +164,7 @@
 {
 	IMG_BOOL pvRet;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	pvRet=DBGDrivCreateStream(pszName, ui32Flags, ui32Size, phInit, phMain, phDeinit);
@@ -182,7 +180,7 @@
  */
 void IMG_CALLCONV ExtDBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
 {
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	DBGDrivDestroyStream(hInit, hMain, hDeinit);
@@ -200,7 +198,7 @@
 {
 	void *	pvRet;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	pvRet=DBGDrivFindStream(pszName, bResetStream);
@@ -223,7 +221,7 @@
 {
 	IMG_UINT32 ui32Ret;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	ui32Ret=DBGDrivRead(psStream, ui32BufID, ui32OutBuffSize, pui8OutBuf);
@@ -241,7 +239,7 @@
 {
 	IMG_UINT32	ui32Ret;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize);
@@ -257,7 +255,7 @@
  */
 void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
 {
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	DBGDrivSetMarker(psStream, ui32Marker);
@@ -275,7 +273,7 @@
 {
 	IMG_UINT32	ui32Marker;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	ui32Marker = DBGDrivGetMarker(psStream);
@@ -306,7 +304,7 @@
 {
 	IMG_UINT32 ui32State = 0;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	ui32State = DBGDrivGetCtrlState(psStream, ui32StateID);
@@ -324,7 +322,7 @@
 {
 	IMG_UINT32 ui32Frame = 0;
 
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	ui32Frame = DBGDrivGetFrame();
@@ -340,7 +338,7 @@
  */
 void IMG_CALLCONV ExtDBGDrivSetFrame(IMG_UINT32 ui32Frame)
 {
-	/* Aquire API Mutex */
+	/* Acquire API Mutex */
 	HostAquireMutex(g_pvAPIMutex);
 
 	DBGDrivSetFrame(ui32Frame);
@@ -662,7 +660,7 @@
 									 IMG_CHAR* pszExt)
 {
 	IMG_CHAR* pCh = psStream->szName;
-	IMG_CHAR* pChEnd = psStream->szName+DBG_STREAM_NAME_MAX-8;
+	IMG_CHAR* pChEnd = psStream->szName+DEBUG_STREAM_NAME_MAX-8;
 	IMG_CHAR* pSrcCh;
 	IMG_CHAR* pSrcChEnd;
 
@@ -966,7 +964,7 @@
 
 		if (strlen(psThis->szName) == strlen(pszName))
 		{
-			while ((ui32Off < DBG_STREAM_NAME_MAX) && (psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && bAreSame)
+			while ((ui32Off < DEBUG_STREAM_NAME_MAX) && (psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && bAreSame)
 			{
 				if (psThis->szName[ui32Off] != pszName[ui32Off])
 				{
@@ -1310,22 +1308,6 @@
 }
 #endif
 
-/*	Use PVR_DPF() to avoid state messages in release build */
-#if defined(PVR_DISABLE_LOGGING) || !defined(DEBUG)
-#define PVR_LOG(...)
-#else
-
-extern void PVRSRVDebugPrintf(IMG_UINT32	ui32DebugLevel,
-						const IMG_CHAR*	pszFileName,
-						IMG_UINT32	ui32Line,
-						const IMG_CHAR*	pszFormat,
-						...	);
-/* Reproduce the PVR_LOG macro here but direct it to DPF */
-#define PVR_LOG(...)	PVRSRVDebugPrintf( DBGPRIV_CALLTRACE, __FILE__, __LINE__ , __VA_ARGS__);
-
-#endif
-
-
 /*!****************************************************************************
  @name		DBGDrivGetCtrlState
  @brief		Gets a state value from the debug driver or stream
@@ -1346,34 +1328,43 @@
 	{
 	case DBG_GET_STATE_FLAG_IS_READONLY:
 		return ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) != 0);
-		break;
 
 	case 0xFE: /* Dump the current stream state */
-		PVR_LOG("------ PDUMP DBGDriv: psStream( %p ) ( -- %s -- ) ui32Flags( %x )",
-				psStream, psStream->szName, psStream->ui32Flags);
-		PVR_LOG("------ PDUMP DBGDriv: psStream->pvBase( %p ) psStream->ui32Size( %u )",
-				psStream->pvBase, psStream->ui32Size);
-		PVR_LOG("------ PDUMP DBGDriv: psStream->ui32RPtr( %u ) psStream->ui32WPtr( %u )",
-				psStream->ui32RPtr, psStream->ui32WPtr);
-		PVR_LOG("------ PDUMP DBGDriv: psStream->ui32Marker( %u ) psStream->ui32InitPhaseWOff( %u )",
-				psStream->ui32Marker, psStream->ui32InitPhaseWOff);
+		PVR_DPF((PVR_DBG_CALLTRACE,
+				 "------ PDUMP DBGDriv: psStream( %p ) ( -- %s -- ) ui32Flags( %x )",
+				 psStream, psStream->szName, psStream->ui32Flags));
+		PVR_DPF((PVR_DBG_CALLTRACE,
+				 "------ PDUMP DBGDriv: psStream->pvBase( %p ) psStream->ui32Size( %u )",
+				 psStream->pvBase, psStream->ui32Size));
+		PVR_DPF((PVR_DBG_CALLTRACE,
+				 "------ PDUMP DBGDriv: psStream->ui32RPtr( %u ) psStream->ui32WPtr( %u )",
+				 psStream->ui32RPtr, psStream->ui32WPtr));
+		PVR_DPF((PVR_DBG_CALLTRACE,
+				 "------ PDUMP DBGDriv: psStream->ui32Marker( %u ) psStream->ui32InitPhaseWOff( %u )",
+				 psStream->ui32Marker, psStream->ui32InitPhaseWOff));
 		if (psStream->psInitStream)
 		{
-			PVR_LOG("-------- PDUMP DBGDriv: psInitStream( %p ) ( -- %s -- ) ui32Flags( %x )",
-					psStream->psInitStream, psStream->psInitStream->szName, psStream->ui32Flags);
-			PVR_LOG("-------- PDUMP DBGDriv: psInitStream->pvBase( %p ) psInitStream->ui32Size( %u )",
-					psStream->psInitStream->pvBase, psStream->psInitStream->ui32Size);
-			PVR_LOG("-------- PDUMP DBGDriv: psInitStream->ui32RPtr( %u ) psInitStream->ui32WPtr( %u )",
-					psStream->psInitStream->ui32RPtr, psStream->psInitStream->ui32WPtr);
-			PVR_LOG("-------- PDUMP DBGDriv: psInitStream->ui32Marker( %u ) psInitStream->ui32InitPhaseWOff( %u ) ",
-					psStream->psInitStream->ui32Marker, psStream->psInitStream->ui32InitPhaseWOff);
+			PVR_DPF((PVR_DBG_CALLTRACE,
+					 "-------- PDUMP DBGDriv: psInitStream( %p ) ( -- %s -- ) ui32Flags( %x )",
+					 psStream->psInitStream, psStream->psInitStream->szName, psStream->ui32Flags));
+			PVR_DPF((PVR_DBG_CALLTRACE,
+					 "-------- PDUMP DBGDriv: psInitStream->pvBase( %p ) psInitStream->ui32Size( %u )",
+					 psStream->psInitStream->pvBase, psStream->psInitStream->ui32Size));
+			PVR_DPF((PVR_DBG_CALLTRACE,
+					 "-------- PDUMP DBGDriv: psInitStream->ui32RPtr( %u ) psInitStream->ui32WPtr( %u )",
+					 psStream->psInitStream->ui32RPtr, psStream->psInitStream->ui32WPtr));
+			PVR_DPF((PVR_DBG_CALLTRACE,
+					 "-------- PDUMP DBGDriv: psInitStream->ui32Marker( %u ) psInitStream->ui32InitPhaseWOff( %u ) ",
+					 psStream->psInitStream->ui32Marker, psStream->psInitStream->ui32InitPhaseWOff));
 		}
 
 		break;
 
 	case 0xFF: /* Dump driver state not in a stream */
 		{
-			PVR_LOG("------ PDUMP DBGDriv: g_psStreamList( head %p ) g_pvAPIMutex( %p ) g_PDumpCurrentFrameNo( %u )", g_psStreamList, g_pvAPIMutex, g_PDumpCurrentFrameNo);
+			PVR_DPF((PVR_DBG_CALLTRACE,
+					 "------ PDUMP DBGDriv: g_psStreamList( head %p ) g_pvAPIMutex( %p ) g_PDumpCurrentFrameNo( %u )",
+					 g_psStreamList, g_pvAPIMutex, g_PDumpCurrentFrameNo));
 		}
 		break;
 
@@ -1477,7 +1468,7 @@
 					(void *)(IMG_PBYTE)psStream->pvBase,
 					psStream->ui32WPtr);
 		}
-		ui32NewROffset = 0;
+		ui32NewROffset = 0; 
 	}
 	else
 	{
diff --git a/drivers/staging/imgtec/rogue/dbgdriv.h b/drivers/staging/imgtec/rogue/dbgdriv.h
index be1da26..f310b42 100644
--- a/drivers/staging/imgtec/rogue/dbgdriv.h
+++ b/drivers/staging/imgtec/rogue/dbgdriv.h
@@ -53,8 +53,14 @@
 #define DBGDRIV_MONOBASE	0x000B0000
 
 
+/*****************************************************************************
+ * OS-specific declarations and init/cleanup functions
+*****************************************************************************/
 extern void *	g_pvAPIMutex;
 
+extern IMG_INT dbgdrv_init(void);
+extern void dbgdrv_cleanup(void);
+
 /*****************************************************************************
  Internal debug driver core functions
 *****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/dbgdrvif_srv5.h b/drivers/staging/imgtec/rogue/dbgdrvif_srv5.h
index a060d0c..87f303e 100644
--- a/drivers/staging/imgtec/rogue/dbgdrvif_srv5.h
+++ b/drivers/staging/imgtec/rogue/dbgdrvif_srv5.h
@@ -63,6 +63,8 @@
 
 #endif
 
+#include "img_defs.h"
+
 
 /*****************************************************************************
  Stream mode stuff.
@@ -76,6 +78,9 @@
 #define DEBUG_FLAGS_WRITEONLY			0x00000010UL
 #define DEBUG_FLAGS_CIRCULAR			0x00000020UL
 
+/* Stream name maximum length */
+#define DEBUG_STREAM_NAME_MAX			32
+
 /*****************************************************************************
  IOCTL values.
 *****************************************************************************/
@@ -121,12 +126,6 @@
 #define DBGDRV_WINCE_DEVICE_NAME			L"DBD1:"
 #endif
 
-#ifdef __GNUC__
-#define DBG_ALIGN(n) __attribute__ ((aligned (n)))
-#else
-#define DBG_ALIGN(n)
-#endif
-
 /* A pointer type which is at least 64 bits wide. The fixed width ensures
  * consistency in structures between 32 and 64-bit code.
  * The UM code (be it 32 or 64 bit) can simply write to the native pointer type (pvPtr).
@@ -147,7 +146,7 @@
 	IMG_UINT32 ui32Ptr;
 	/* force the union width */
 	IMG_UINT64 ui64Ptr;
-} DBG_WIDEPTR DBG_ALIGN(8);
+} DBG_WIDEPTR __aligned(8);
 
 /* Helper macro for dbgdriv (KM) to get the pointer value from the WIDEPTR type,
  * depending on whether the client is 32 or 64-bit.
@@ -197,7 +196,7 @@
 
 typedef struct _DBG_IN_FINDSTREAM_
 {
-	DBG_WIDEPTR pszName;
+	IMG_CHAR pszName[DEBUG_STREAM_NAME_MAX];
 	IMG_BOOL bResetStream;
 }DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
 
diff --git a/drivers/staging/imgtec/rogue/dc_common.h b/drivers/staging/imgtec/rogue/dc_common.h
deleted file mode 100644
index f5ef848..0000000
--- a/drivers/staging/imgtec/rogue/dc_common.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Common Display Class header
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Defines DC specific structures which are shared within services
-                only
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#include "img_types.h"
-
-#ifndef _DC_COMMON_H_
-#define _DC_COMMON_H_
-
-typedef struct _DC_FBC_CREATE_INFO_
-{
-	IMG_UINT32		ui32FBCWidth;	/*!< Pixel width that the FBC module is working on */
-	IMG_UINT32		ui32FBCHeight;	/*!< Pixel height that the FBC module is working on */
-	IMG_UINT32		ui32FBCStride;	/*!< Pixel stride that the FBC module is working on */
-	IMG_UINT32		ui32Size;		/*!< Size of the buffer to create */
-} DC_FBC_CREATE_INFO;
-
-typedef struct _DC_CREATE_INFO_
-{
-	union {
-		DC_FBC_CREATE_INFO sFBC;
-	} u;
-} DC_CREATE_INFO;
-
-typedef struct _DC_BUFFER_CREATE_INFO_
-{
-	PVRSRV_SURFACE_INFO   	sSurface;	/*!< Surface properies, specificed by user */
-	IMG_UINT32            	ui32BPP;	/*!< Bits per pixel */
-	union {
-		DC_FBC_CREATE_INFO 	sFBC;		/*!< Frame buffer compressed specific data */
-	} u;
-} DC_BUFFER_CREATE_INFO;
-
-#endif /* _DC_COMMON_H_ */
diff --git a/drivers/staging/imgtec/rogue/dc_external.h b/drivers/staging/imgtec/rogue/dc_external.h
index dd64225..ad5a69e 100644
--- a/drivers/staging/imgtec/rogue/dc_external.h
+++ b/drivers/staging/imgtec/rogue/dc_external.h
@@ -1,10 +1,10 @@
 /*************************************************************************/ /*!
 @File
-@Title          Device class external
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Title          Display class external
 @Description    Defines DC specific structures which are externally visible
                 (i.e. visible to clients of services), but are also required
                 within services.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -48,24 +48,73 @@
 
 #include "img_types.h"
 
+/*!
+ * Maximum size of the display name in DC_DISPLAY_INFO
+ */
 #define DC_NAME_SIZE	50
+
+/*!
+ * This contains information about a display.
+ * The structure can be queried by services from the display driver via a
+ * registered callback.
+ *
+ *   Structure: #_DC_DISPLAY_INFO_
+ *   Typedef: ::DC_DISPLAY_INFO
+ */
 typedef struct _DC_DISPLAY_INFO_
 {
-	IMG_CHAR		szDisplayName[DC_NAME_SIZE];
-	IMG_UINT32		ui32MinDisplayPeriod;
-	IMG_UINT32		ui32MaxDisplayPeriod;
-	IMG_UINT32		ui32MaxPipes;
-	IMG_BOOL		bUnlatchedSupported;
+	IMG_CHAR		szDisplayName[DC_NAME_SIZE];	/*!< Display identifier string */
+	IMG_UINT32		ui32MinDisplayPeriod;			/*!< Minimum number of VSync periods */
+	IMG_UINT32		ui32MaxDisplayPeriod;			/*!< Maximum number of VSync periods */
+	IMG_UINT32		ui32MaxPipes;					/*!< Maximum number of pipes for this display */
+	IMG_BOOL		bUnlatchedSupported;			/*!< Can the device be unlatched? */
 } DC_DISPLAY_INFO;
 
+/*!
+ * When services imports a buffer from the display driver it has to fill
+ * this structure to inform services about the buffer properties.
+ *
+ *   Structure: #_DC_BUFFER_IMPORT_INFO_
+ *   Typedef: ::DC_BUFFER_IMPORT_INFO
+ */
 typedef struct _DC_BUFFER_IMPORT_INFO_
 {
-	IMG_UINT32		ePixFormat;
-	IMG_UINT32		ui32BPP;
-	IMG_UINT32		ui32Width[3];
-	IMG_UINT32		ui32Height[3];
-	IMG_UINT32		ui32ByteStride[3];
-	IMG_UINT32		ui32PrivData[3];
+	IMG_UINT32		ePixFormat;			/*!< Enum value of type IMG_PIXFMT for the pixel format */
+	IMG_UINT32		ui32BPP;			/*!< Bits per pixel */
+	IMG_UINT32		ui32Width[3];		/*!< Width of the different channels (defined by ePixFormat) */
+	IMG_UINT32		ui32Height[3];		/*!< Height of the different channels (defined by ePixFormat) */
+	IMG_UINT32		ui32ByteStride[3];	/*!< Byte stride of the different channels (defined by ePixFormat) */
+	IMG_UINT32		ui32PrivData[3];	/*!< Private data of the display for each of the channels */
 } DC_BUFFER_IMPORT_INFO;
 
+
+/*!
+ * Configuration details of the frame buffer compression module
+ *
+ *   Structure: #_DC_FBC_CREATE_INFO_
+ *   Typedef: ::DC_FBC_CREATE_INFO
+ */
+typedef struct _DC_FBC_CREATE_INFO_
+{
+	IMG_UINT32		ui32FBCWidth;	/*!< Pixel width that the FBC module is working on */
+	IMG_UINT32		ui32FBCHeight;	/*!< Pixel height that the FBC module is working on */
+	IMG_UINT32		ui32FBCStride;	/*!< Pixel stride that the FBC module is working on */
+	IMG_UINT32		ui32Size;		/*!< Size of the buffer to create */
+} DC_FBC_CREATE_INFO;
+
+/*!
+ * DC buffer details like frame buffer compression and surface properties
+ *
+ *   Structure: #_DC_BUFFER_CREATE_INFO_
+ *   Typedef: ::DC_BUFFER_CREATE_INFO
+ */
+typedef struct _DC_BUFFER_CREATE_INFO_
+{
+	PVRSRV_SURFACE_INFO		sSurface;	/*!< Surface properties, specified by user */
+	IMG_UINT32				ui32BPP;	/*!< Bits per pixel */
+	union {
+		DC_FBC_CREATE_INFO 	sFBC;
+	} u;								/*!< Frame buffer compressed specific data */
+} DC_BUFFER_CREATE_INFO;
+
 #endif /* _DC_EXTERNAL_H_ */
diff --git a/drivers/staging/imgtec/rogue/dc_server.c b/drivers/staging/imgtec/rogue/dc_server.c
index de198579..aef3c95 100644
--- a/drivers/staging/imgtec/rogue/dc_server.c
+++ b/drivers/staging/imgtec/rogue/dc_server.c
@@ -50,11 +50,11 @@
 #include "dc_server.h"
 #include "kerneldisplay.h"
 #include "pvr_debug.h"
+#include "pvr_notifier.h"
 #include "pmr.h"
-#include "pdump_physmem.h"
 #include "sync_server.h"
 #include "pvrsrv.h"
-#include "debug_request_ids.h"
+#include "process_stats.h"
 
 #if defined(PVR_RI_DEBUG)
 #include "ri_server.h"
@@ -85,6 +85,7 @@
 
 struct _DC_DEVICE_
 {
+	PVRSRV_DEVICE_NODE			*psDevNode;
 	const DC_DEVICE_FUNCTIONS	*psFuncTable;
 	IMG_UINT32					ui32MaxConfigsInFlight;
 	IMG_HANDLE					hDeviceData;
@@ -161,18 +162,15 @@
 	IMG_DEVMEM_LOG2ALIGN_T	uiLog2PageSize;		/*!< Log 2 of the buffers pagesize */
 	IMG_UINT32				ui32PageCount;		/*!< Number of pages in this buffer */
 	PHYS_HEAP				*psPhysHeap;		/*!< The physical heap the memory resides on */
-	IMG_DEV_PHYADDR			*pasDevPAddr;		/*!< Pointer to an array of device physcial addresses */
+	IMG_DEV_PHYADDR			*pasDevPAddr;		/*!< Pointer to an array of device physical addresses */
 	void					*pvLinAddr;			/*!< CPU virtual pointer or NULL if the DC driver didn't have one */
-
-	IMG_HANDLE				hPDumpAllocInfo;	/*!< Handle to PDump alloc data */
-	IMG_BOOL				bPDumpMalloced;		/*!< Did we get as far as PDump alloc? */
 } DC_BUFFER_PMR_DATA;
 
-POS_LOCK g_hDCListLock;
+static POS_LOCK g_hDCListLock;
 
-DC_DEVICE *g_psDCDeviceList;
-IMG_UINT32 g_ui32DCDeviceCount;
-IMG_UINT32 g_ui32DCNextIndex;
+static DC_DEVICE *g_psDCDeviceList;
+static IMG_UINT32 g_ui32DCDeviceCount;
+static IMG_UINT32 g_ui32DCNextIndex;
 static DLLIST_NODE g_sDisplayContextsList;
 
 
@@ -234,7 +232,7 @@
 			{
 				psTmp = psTmp->psNext;
 			}
-			psTmp->psNext = g_psDCDeviceList->psNext;
+			psTmp->psNext = psDevice->psNext;
 		}
 	
 		g_ui32DCDeviceCount--;
@@ -427,12 +425,11 @@
 	IMG_UINT32 i;
 
 	/* Create an array of the DC's private Buffer handles */
-	ahDeviceBuffers = OSAllocMem(sizeof(IMG_HANDLE) * ui32BufferCount);
+	ahDeviceBuffers = OSAllocZMem(sizeof(IMG_HANDLE) * ui32BufferCount);
 	if (ahDeviceBuffers == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
-	OSMemSet(ahDeviceBuffers, 0, sizeof(IMG_HANDLE) * ui32BufferCount);
 
 	for (i=0;i<ui32BufferCount;i++)
 	{
@@ -474,7 +471,7 @@
 	DC_DISPLAY_CONTEXT *psDisplayContext = psCompleteData->psDisplayContext;
 
 	PVR_DPF((PVR_DBG_ERROR, "Timeout fired for operation %d", psCompleteData->ui32Token));
-	SCPDumpStatus(psDisplayContext->psSCPContext);
+	SCPDumpStatus(psDisplayContext->psSCPContext, NULL);
 
 	OSDisableTimer(psDisplayContext->hTimer);
 	OSRemoveTimer(psDisplayContext->hTimer);
@@ -570,21 +567,14 @@
 	As we acquire the display memory at PMR create time there is nothing
 	to do here.
 */
-static PVRSRV_ERROR _DCPMRLockPhysAddresses(PMR_IMPL_PRIVDATA pvPriv,
-											IMG_UINT32 uiLog2DevPageSize)
+static PVRSRV_ERROR _DCPMRLockPhysAddresses(PMR_IMPL_PRIVDATA pvPriv)
 {
 	DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
 	DC_BUFFER *psBuffer = psPMRPriv->psBuffer;
 	DC_DEVICE *psDevice = psBuffer->psDisplayContext->psDevice;
 	PVRSRV_ERROR eError;
 
-	if (uiLog2DevPageSize < psPMRPriv->uiLog2PageSize)
-	{
-		eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
-		goto fail_contigcheck;
-	}
-
-	psPMRPriv->pasDevPAddr = OSAllocMem(sizeof(IMG_DEV_PHYADDR) *
+	psPMRPriv->pasDevPAddr = OSAllocZMem(sizeof(IMG_DEV_PHYADDR) *
 							 psPMRPriv->ui32PageCount);
 	if (psPMRPriv->pasDevPAddr == NULL)
 	{
@@ -592,10 +582,6 @@
 		goto fail_alloc;
 	}
 
-	OSMemSet(psPMRPriv->pasDevPAddr,
-			 0,
-			 sizeof(IMG_DEV_PHYADDR) * psPMRPriv->ui32PageCount);
-
 	eError = psDevice->psFuncTable->pfnBufferAcquire(psBuffer->hBuffer,
 													 psPMRPriv->pasDevPAddr,
 													 &psPMRPriv->pvLinAddr);
@@ -604,12 +590,46 @@
 		goto fail_query;
 	}
 
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+	{
+		IMG_UINT32 i;
+		for (i = 0; i < psPMRPriv->ui32PageCount; i++)
+		{
+			IMG_CPU_PHYADDR sCPUPhysAddr;
+			PVRSRV_MEM_ALLOC_TYPE eAllocType;
+#if defined(LMA)
+			eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES;
+#else
+			eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES;
+#endif
+			sCPUPhysAddr.uiAddr = ((uintptr_t)psPMRPriv->pvLinAddr) + i * (1 << psPMRPriv->uiLog2PageSize);
+			PVRSRVStatsAddMemAllocRecord(eAllocType,
+			                             NULL,
+			                             sCPUPhysAddr,
+			                             1 << psPMRPriv->uiLog2PageSize,
+			                             NULL);
+		}
+	}
+#else
+	{
+		PVRSRV_MEM_ALLOC_TYPE eAllocType;
+#if defined(LMA)
+		eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES;
+#else
+		eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES;
+#endif
+		PVRSRVStatsIncrMemAllocStat(eAllocType,
+		                            psPMRPriv->ui32PageCount * (1 << psPMRPriv->uiLog2PageSize));
+	}
+#endif
+#endif
+
 	return PVRSRV_OK;
 
 fail_query:
 	OSFreeMem(psPMRPriv->pasDevPAddr);
 fail_alloc:
-fail_contigcheck:
 	return eError;
 }
 
@@ -619,6 +639,41 @@
 	DC_BUFFER *psBuffer = psPMRPriv->psBuffer;
 	DC_DEVICE *psDevice = psBuffer->psDisplayContext->psDevice;
 
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+	{
+		PVRSRV_MEM_ALLOC_TYPE eAllocType;
+#if defined(LMA)
+		eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES;
+#else
+		eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES;
+#endif
+		PVRSRVStatsDecrMemAllocStat(eAllocType,
+		                            psPMRPriv->ui32PageCount * (1 << psPMRPriv->uiLog2PageSize));
+	}
+#else
+	{
+		PVRSRV_MEM_ALLOC_TYPE eAllocType;
+		IMG_UINT32 i;
+
+#if defined(LMA)
+		eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES;
+#else
+		eAllocType = PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES;
+#endif
+
+		for(i = 0; i < psPMRPriv->ui32PageCount; i++)
+		{
+			IMG_CPU_PHYADDR sCPUPhysAddr;
+
+			sCPUPhysAddr.uiAddr = ((uintptr_t)psPMRPriv->pvLinAddr) + i * (1 << psPMRPriv->uiLog2PageSize);
+			PVRSRVStatsRemoveMemAllocRecord(eAllocType,
+			                                sCPUPhysAddr.uiAddr);
+		}
+	}
+#endif
+#endif
+
 	psDevice->psFuncTable->pfnBufferRelease(psBuffer->hBuffer);
 	OSFreeMem(psPMRPriv->pasDevPAddr);
 
@@ -626,6 +681,7 @@
 }
 
 static PVRSRV_ERROR _DCPMRDevPhysAddr(PMR_IMPL_PRIVDATA pvPriv,
+									  IMG_UINT32 ui32Log2PageSize,
 									  IMG_UINT32 ui32NumOfPages,
 									  IMG_DEVMEM_OFFSET_T *puiOffset,
 									  IMG_BOOL *pbValid,
@@ -633,24 +689,28 @@
 {
 	DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
     IMG_UINT32 uiNumPages = psPMRPriv->ui32PageCount;
-    IMG_UINT32 uiLog2PageSize = psPMRPriv->uiLog2PageSize;
-    IMG_UINT32 uiPageSize = 1ULL << uiLog2PageSize;
+    IMG_UINT32 uiPageSize = 1ULL << ui32Log2PageSize;
     IMG_UINT32 uiPageIndex;
     IMG_UINT32 uiInPageOffset;
     IMG_DEV_PHYADDR sDevAddr;
     IMG_UINT32 idx;
 
+	if (psPMRPriv->uiLog2PageSize != ui32Log2PageSize)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
 	for (idx=0; idx < ui32NumOfPages; idx++)
 	{
 		if (pbValid[idx])
 		{
 			/* verify the cast
 			   N.B.  Strictly... this could be triggered by an illegal uiOffset arg too. */
-			uiPageIndex = (IMG_UINT32)(puiOffset[idx] >> uiLog2PageSize);
-			PVR_ASSERT((IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize == puiOffset[idx]);
+			uiPageIndex = (IMG_UINT32)(puiOffset[idx] >> ui32Log2PageSize);
+			PVR_ASSERT((IMG_DEVMEM_OFFSET_T)uiPageIndex << ui32Log2PageSize == puiOffset[idx]);
 		
-			uiInPageOffset = (IMG_UINT32)(puiOffset[idx] - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize));		
-			PVR_ASSERT(puiOffset[idx] == ((IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize) + uiInPageOffset);
+			uiInPageOffset = (IMG_UINT32)(puiOffset[idx] - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << ui32Log2PageSize));		
+			PVR_ASSERT(puiOffset[idx] == ((IMG_DEVMEM_OFFSET_T)uiPageIndex << ui32Log2PageSize) + uiInPageOffset);
 			PVR_ASSERT(uiPageIndex < uiNumPages);
 			PVR_ASSERT(uiInPageOffset < uiPageSize);
 
@@ -665,17 +725,116 @@
     return PVRSRV_OK;
 }
 
+#if defined(INTEGRITY_OS)
+static PVRSRV_ERROR _DCPMRAcquireKernelMappingData(PMR_IMPL_PRIVDATA pvPriv,
+												   size_t uiOffset,
+												   size_t uiSize,
+												   void **ppvKernelAddressOut,
+												   IMG_HANDLE *phHandleOut,
+												   PMR_FLAGS_T ulFlags)
+{
+	DC_BUFFER_PMR_DATA *psPMRPriv = (DC_BUFFER_PMR_DATA *)pvPriv;
+	DC_BUFFER          *psBuffer = NULL;
+	DC_DEVICE          *psDevice = NULL;
+	IMG_HANDLE          hMapping = NULL;
+	void	           *pvKernelAddr = NULL;
+	PVRSRV_ERROR        eError = PVRSRV_OK;
+
+	if (psPMRPriv == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_DCPMRAcquireKernelMappingData: Invalid parameters."));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	else
+	{
+		psBuffer = psPMRPriv->psBuffer;
+		psDevice = psBuffer->psDisplayContext->psDevice;
+
+		eError = psDevice->psFuncTable->pfnAcquireKernelMappingData(psBuffer->hBuffer, &hMapping, &pvKernelAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_DCPMRAcquireKernelMappingData: AcquireKernelMappingData failed."));
+		}
+		else
+		{
+			*phHandleOut = (IMG_HANDLE)psPMRPriv;
+			*ppvKernelAddressOut = pvKernelAddr;
+		}
+	}
+
+	return eError;
+}
+
+static void _DCPMRReleaseKernelMappingData(PMR_IMPL_PRIVDATA pvPriv,
+										   IMG_HANDLE hHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pvPriv);
+	PVR_UNREFERENCED_PARAMETER(hHandle);
+}
+
+static PVRSRV_ERROR _DCPMRMapMemoryObject(PMR_IMPL_PRIVDATA pvPriv, IMG_HANDLE *phMemObj)
+{
+	DC_BUFFER_PMR_DATA *psPMRPriv = (DC_BUFFER_PMR_DATA *)pvPriv;
+	DC_BUFFER          *psBuffer = NULL;
+	DC_DEVICE          *psDevice = NULL;
+	PVRSRV_ERROR        eError = PVRSRV_OK;
+
+	if ((psPMRPriv == NULL) || (phMemObj == NULL))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_DCPMRMapMemoryObject: Invalid parameters."));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	else
+	{
+		psBuffer = psPMRPriv->psBuffer;
+		psDevice = psBuffer->psDisplayContext->psDevice;
+		eError = psDevice->psFuncTable->pfnMapMemoryObject(psBuffer->hBuffer, phMemObj);
+	}
+
+	return eError;
+}
+
+static PVRSRV_ERROR _DCPMRUnmapMemoryObject(PMR_IMPL_PRIVDATA pvPriv)
+{
+	DC_BUFFER_PMR_DATA *psPMRPriv = (DC_BUFFER_PMR_DATA *)pvPriv;
+	DC_BUFFER          *psBuffer = NULL;
+	DC_DEVICE          *psDevice = NULL;
+	PVRSRV_ERROR        eError = PVRSRV_OK;
+
+	if (psPMRPriv == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_DCPMRUnmapMemoryObject: Invalid parameters."));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	else
+	{
+		psBuffer = psPMRPriv->psBuffer;
+		psDevice = psBuffer->psDisplayContext->psDevice;
+		eError = psDevice->psFuncTable->pfnUnmapMemoryObject(psBuffer->hBuffer);
+	}
+
+	return eError;
+}
+
+#if defined(USING_HYPERVISOR)
+static IMG_HANDLE _DCPMRGetPmr(PMR_IMPL_PRIVDATA pvPriv, size_t ulOffset)
+{
+	DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
+	DC_BUFFER          *psBuffer = NULL;
+	DC_DEVICE          *psDevice = NULL;
+	
+	psBuffer = psPMRPriv->psBuffer;
+	psDevice = psBuffer->psDisplayContext->psDevice;
+	
+	return psDevice->psFuncTable->pfnGetPmr(psBuffer->hBuffer, ulOffset);
+}
+#endif
+#endif
+
 static PVRSRV_ERROR _DCPMRFinalize(PMR_IMPL_PRIVDATA pvPriv)
 {
 	DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
 
-	/* Conditionally do the PDump free, because if CreatePMR failed we
-	   won't have done the PDump MALLOC.  */
-	if (psPMRPriv->bPDumpMalloced)
-	{
-		PDumpFree(psPMRPriv->hPDumpAllocInfo);
-	}
-
 	PhysHeapRelease(psPMRPriv->psPhysHeap);
 	_DCBufferReleaseRef(psPMRPriv->psBuffer);
 	OSFreeMem(psPMRPriv);
@@ -704,7 +863,7 @@
 	if (psPMRPriv->pvLinAddr)
 	{
 		pcKernelPointer = psPMRPriv->pvLinAddr;
-		OSMemCopy(pcBuffer, &pcKernelPointer[uiOffset], uiBufSz);
+		OSDeviceMemCopy(pcBuffer, &pcKernelPointer[uiOffset], uiBufSz);
 		*puiNumBytes = uiBufSz;
 		return PVRSRV_OK;
 	}
@@ -726,11 +885,12 @@
 
         pvMapping = OSMapPhysToLin(sCpuPAddr,
 								   1 << psPMRPriv->uiLog2PageSize,
-								   0);
+								   PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
         PVR_ASSERT(pvMapping != NULL);
         pcKernelPointer = pvMapping;
-        OSMemCopy(&pcBuffer[uiBufferOffset], &pcKernelPointer[uiInPageOffset], uiBytesCopyableFromPage);
-        OSUnMapPhysToLin(pvMapping, 1 << psPMRPriv->uiLog2PageSize, 0);
+        OSDeviceMemCopy(&pcBuffer[uiBufferOffset], &pcKernelPointer[uiInPageOffset], uiBytesCopyableFromPage);
+        OSUnMapPhysToLin(pvMapping, 1 << psPMRPriv->uiLog2PageSize,
+						 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
 
         uiBufferOffset += uiBytesCopyableFromPage;
         uiBytesToCopy -= uiBytesCopyableFromPage;
@@ -746,9 +906,18 @@
 	_DCPMRLockPhysAddresses,	/* .pfnLockPhysAddresses */
 	_DCPMRUnlockPhysAddresses,	/* .pfnUnlockPhysAddresses */
 	_DCPMRDevPhysAddr,			/* .pfnDevPhysAddr */
-	NULL,					/* .pfnPDumpSymbolicAddr	*/
+#if !defined(INTEGRITY_OS)
 	NULL,					/* .pfnAcquireKernelMappingData	*/
 	NULL,					/* .pfnReleaseKernelMappingData */
+#else
+	_DCPMRAcquireKernelMappingData,	/* .pfnAcquireKernelMappingData	*/
+	_DCPMRReleaseKernelMappingData,	/* .pfnReleaseKernelMappingData */
+	_DCPMRMapMemoryObject,			/* .pfnMapMemoryObject */
+	_DCPMRUnmapMemoryObject,		/* .pfnUnmapMemoryObject */
+#if defined(USING_HYPERVISOR)
+	_DCPMRGetPmr,				/* .pfnGetPmr */
+#endif
+#endif
 	_DCPMRReadBytes,			/* .pfnReadBytes */
 	NULL,					/* .pfnWriteBytes */
 	NULL,					/* .pfnUnpinMem */
@@ -759,7 +928,8 @@
 	_DCPMRFinalize				/* .pfnFinalize */
 };
 
-static PVRSRV_ERROR _DCCreatePMR(IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+static PVRSRV_ERROR _DCCreatePMR(PVRSRV_DEVICE_NODE *psDevNode,
+								 IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
 								 IMG_UINT32 ui32PageCount,
 								 IMG_UINT32 ui32PhysHeapID,
 								 DC_BUFFER *psBuffer,
@@ -768,26 +938,23 @@
 	DC_BUFFER_PMR_DATA *psPMRPriv;
 	PHYS_HEAP *psPhysHeap;
 	IMG_DEVMEM_SIZE_T uiBufferSize;
-	IMG_HANDLE hPDumpAllocInfo;
 	PVRSRV_ERROR eError;
-	IMG_BOOL bMappingTable = IMG_TRUE;
+	IMG_UINT32 uiMappingTable = 0;
 
 	/*
 		Create the PMR for this buffer.
 
 		Note: At this stage we don't need to know the physical pages just
 		the page size and the size of the PMR. The 1st call that needs the
-		physcial pages will cause a request into the DC driver (pfnBufferQuery)
+		physical pages will cause a request into the DC driver (pfnBufferQuery)
 	*/
-	psPMRPriv = OSAllocMem(sizeof(DC_BUFFER_PMR_DATA));
+	psPMRPriv = OSAllocZMem(sizeof(DC_BUFFER_PMR_DATA));
 	if (psPMRPriv == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto fail_privalloc;
 	}
 
-	OSMemSet(psPMRPriv, 0, sizeof(DC_BUFFER_PMR_DATA));
-
 	/* Acquire the physical heap the memory is on */
 	eError = PhysHeapAcquire(ui32PhysHeapID, &psPhysHeap);
 	if (eError != PVRSRV_OK)
@@ -808,19 +975,20 @@
 	uiBufferSize = (1 << uiLog2PageSize) * ui32PageCount;
 
 	/* Create the PMR for the MM layer */
-	eError = PMRCreatePMR(psPhysHeap,
+	eError = PMRCreatePMR(psDevNode,
+						  psPhysHeap,
 						  uiBufferSize,
 						  uiBufferSize,
 						  1,
 						  1,
-						  &bMappingTable,
+						  &uiMappingTable,
 						  uiLog2PageSize,
 						  PVRSRV_MEMALLOCFLAG_WRITE_COMBINE,
-						  "DISPLAY",
+				          "DC_BUFFER",
 						  &sDCPMRFuncTab,
 						  psPMRPriv,
+						  PMR_TYPE_DC,
 						  ppsPMR,
-						  &hPDumpAllocInfo,
 						  IMG_TRUE);
 
 	if (eError != PVRSRV_OK)
@@ -828,10 +996,6 @@
 		goto fail_pmrcreate;
 	}
 
-#if defined(PDUMP)
-	psPMRPriv->hPDumpAllocInfo = hPDumpAllocInfo;
-	psPMRPriv->bPDumpMalloced = IMG_TRUE;
-#endif
 	return PVRSRV_OK;
 
 fail_pmrcreate:
@@ -882,39 +1046,38 @@
 	return PVRSRV_OK;
 }
 
-PVRSRV_ERROR DCDevicesEnumerate(IMG_UINT32 ui32DeviceArraySize,
+PVRSRV_ERROR DCDevicesEnumerate(CONNECTION_DATA *psConnection,
+								PVRSRV_DEVICE_NODE *psDevNode,
+								IMG_UINT32 ui32DeviceArraySize,
 								IMG_UINT32 *pui32DeviceCount,
 								IMG_UINT32 *paui32DeviceIndex)
 {
-	IMG_UINT32 i;
-	IMG_UINT32 ui32LoopCount;
-	DC_DEVICE *psTmp = g_psDCDeviceList;
+	DC_DEVICE *psTmp;
+	IMG_UINT32 ui32DeviceCount;
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 	OSLockAcquire(g_hDCListLock);
 
-	if (g_ui32DCDeviceCount > ui32DeviceArraySize)
+	for (psTmp = g_psDCDeviceList, ui32DeviceCount = 0;
+		 psTmp && ui32DeviceCount < ui32DeviceArraySize;
+		 psTmp = psTmp->psNext)
 	{
-		ui32LoopCount = ui32DeviceArraySize;
-	}
-	else
-	{
-		ui32LoopCount = g_ui32DCDeviceCount;
-	}
-	
-	for (i=0;i<ui32LoopCount;i++)
-	{
-		PVR_ASSERT(psTmp != NULL);
-		paui32DeviceIndex[i] = psTmp->ui32Index;
-		psTmp = psTmp->psNext;
+		if (psTmp->psDevNode == psDevNode)
+		{
+			paui32DeviceIndex[ui32DeviceCount++] = psTmp->ui32Index;
+		}
 	}
 
-	*pui32DeviceCount = ui32LoopCount;
+	*pui32DeviceCount = ui32DeviceCount;
 	OSLockRelease(g_hDCListLock);
 
 	return PVRSRV_OK;
 }
 
-PVRSRV_ERROR DCDeviceAcquire(IMG_UINT32 ui32DeviceIndex,
+PVRSRV_ERROR DCDeviceAcquire(CONNECTION_DATA *psConnection,
+							 PVRSRV_DEVICE_NODE *psDevNode,
+							 IMG_UINT32 ui32DeviceIndex,
 							 DC_DEVICE **ppsDevice)
 {
 	DC_DEVICE *psDevice = g_psDCDeviceList;
@@ -927,7 +1090,7 @@
 	while(psDevice->ui32Index != ui32DeviceIndex)
 	{
 		psDevice = psDevice->psNext;
-		if (psDevice == NULL)
+		if (psDevice == NULL || psDevice->psDevNode != psDevNode)
 		{
 			return PVRSRV_ERROR_NO_DC_DEVICES_FOUND;
 		}
@@ -1066,15 +1229,13 @@
 		goto fail_nopfn;
 	}
 
-	psNew = OSAllocMem(sizeof(DC_BUFFER));
+	psNew = OSAllocZMem(sizeof(DC_BUFFER));
 	if (psNew == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto fail_alloc;
 	}
 
-	OSMemSet(psNew, 0, sizeof(DC_BUFFER));
-
 	eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
 	if (eError != PVRSRV_OK)
 	{
@@ -1127,7 +1288,8 @@
 			PMRUnrefPMR(psDevice->psSystemBufferPMR);
 		}
 
-		eError = _DCCreatePMR(uiLog2PageSize,
+		eError = _DCCreatePMR(psDevice->psDevNode,
+							  uiLog2PageSize,
 							  ui32PageCount,
 							  ui32PhysHeapID,
 							  psNew,
@@ -1288,6 +1450,7 @@
 
 	/* Register our debug request notify callback */
 	eError = PVRSRVRegisterDbgRequestNotify(&psDisplayContext->hDebugNotify,
+											psDevice->psDevNode,
 											_DCDebugRequest,
 											DEBUG_REQUEST_DC,
 											psDisplayContext);
@@ -1409,15 +1572,15 @@
 	 * Calling SCPRun first, ensures that any call to SCPRun from the MISR
 	 * context completes before we insert any NULL flush direct to the DC.
 	 * SCPRun returns PVRSRV_OK (0) if the run command (Configure) executes OR there
-	 * is no work to do OR it consumes a padding command.
+	 * is no work to be done OR it consumes a padding command.
 	 * By counting a "good" SCPRun for each of the ui32NumConfigsInSCP we ensure
 	 * that all Configs currently in the SCP are flushed to the DC.
 	 *
 	 * In the case where we fail dependencies (PVRSRV_ERROR_FAILED_DEPENDENCIES (15))
 	 * but there are outstanding ui32ConfigsInFlight that may satisfy them,
 	 * we just loop and try again.
-	 * In the case where there is still work to do but the DC is full
-	 * (PVRSRV_ERROR_NOT_READY (254)) we just loop and try again
+	 * In the case where there is still more work but the DC is full
+	 * (PVRSRV_ERROR_NOT_READY (254)), we just loop and try again.
 	 *
 	 * During a flush, NULL flips may be inserted if waiting for the 3D (not
 	 * actually deadlocked), but this should be benign
@@ -1596,8 +1759,8 @@
 				goto FailMapBuffer;
 			}
 			ui32BuffersMapped++;
-		}
-	}
+		}    
+    }
 
 	ui32CmdRdySize = sizeof(DC_CMD_RDY_DATA) +  
 					 ((sizeof(IMG_HANDLE) + sizeof(PVRSRV_SURFACE_CONFIG_INFO))
@@ -1639,7 +1802,7 @@
 	{
 		psReadyData->pasSurfAttrib = (PVRSRV_SURFACE_CONFIG_INFO *)pui8ReadyData;
 		ui32CopySize = sizeof(PVRSRV_SURFACE_CONFIG_INFO) * ui32PipeCount;
-		OSMemCopy(psReadyData->pasSurfAttrib, pasSurfAttrib, ui32CopySize);
+		OSCachedMemCopy(psReadyData->pasSurfAttrib, pasSurfAttrib, ui32CopySize);
 		pui8ReadyData = pui8ReadyData + ui32CopySize;
 	}
 	else
@@ -1652,7 +1815,7 @@
 	{
 		psReadyData->pahBuffer = (IMG_HANDLE)pui8ReadyData;
 		ui32CopySize = sizeof(IMG_HANDLE) * ui32PipeCount;
-		OSMemCopy(psReadyData->pahBuffer, ahBuffers, ui32CopySize);
+		OSCachedMemCopy(psReadyData->pahBuffer, ahBuffers, ui32CopySize);
 	}
 	else
 	{
@@ -1788,12 +1951,11 @@
 	IMG_UINT32 ui32PageCount;
 	IMG_UINT32 ui32PhysHeapID;
 
-	psNew = OSAllocMem(sizeof(DC_BUFFER));
+	psNew = OSAllocZMem(sizeof(DC_BUFFER));
 	if (psNew == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
-	OSMemSet(psNew, 0, sizeof(DC_BUFFER));
 
 	eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
 	if (eError != PVRSRV_OK)
@@ -1828,7 +1990,8 @@
 	psNew->ui32MapCount = 0;
 	psNew->ui32RefCount = 1;
 
-	eError = _DCCreatePMR(uiLog2PageSize,
+	eError = _DCCreatePMR(psDevice->psDevNode,
+						  uiLog2PageSize,
 						  ui32PageCount,
 						  ui32PhysHeapID,
 						  psNew,
@@ -1914,13 +2077,12 @@
 		goto FailEarlyError;
 	}
 
-	psNew = OSAllocMem(sizeof(DC_BUFFER));
+	psNew = OSAllocZMem(sizeof(DC_BUFFER));
 	if (psNew == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto FailEarlyError;
 	}
-	OSMemSet(psNew, 0, sizeof(DC_BUFFER));
 
 	eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
 	if (eError != PVRSRV_OK)
@@ -2037,9 +2199,15 @@
 							  IMG_HANDLE hDeviceData,
 							  IMG_HANDLE *phSrvHandle)
 {
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
 	DC_DEVICE *psNew;
 	PVRSRV_ERROR eError;
 
+	if (!psPVRSRVData || !psPVRSRVData->psDeviceNodeList)
+	{
+		return PVRSRV_ERROR_RETRY;
+	}
+
 	psNew = OSAllocMem(sizeof(DC_DEVICE));
 	if (psNew == NULL)
 	{
@@ -2053,11 +2221,12 @@
 		goto FailLockCreate;
 	}
 
+	/* Associate display devices to the first device node */
+	psNew->psDevNode = psPVRSRVData->psDeviceNodeList;
 	psNew->psFuncTable = psFuncTable;
 	psNew->ui32MaxConfigsInFlight = ui32MaxConfigsInFlight;
 	psNew->hDeviceData = hDeviceData;
 	psNew->ui32RefCount = 1;
-	psNew->hSystemBuffer = NULL;
 	psNew->ui32Index = g_ui32DCNextIndex++;
 	eError = OSEventObjectCreate("DC_EVENT_OBJ", &psNew->psEventList);
 	if (eError != PVRSRV_OK)
@@ -2069,7 +2238,7 @@
 	psNew->hSystemBuffer = NULL;
 	psNew->psSystemBufferPMR = NULL;
 	psNew->sSystemContext.psDevice = psNew;
-	psNew->sSystemContext.hDisplayContext = hDeviceData;
+	psNew->sSystemContext.hDisplayContext = hDeviceData;	/* FIXME: Is this the correct thing to do? */
 
 	OSLockAcquire(g_hDCListLock);
 	psNew->psNext = g_psDCDeviceList;
@@ -2104,9 +2273,7 @@
 	*/
 	if (psDevice->psSystemBufferPMR)
 	{
-		PMRLock();
 		PMRUnrefPMR(psDevice->psSystemBufferPMR);
-		PMRUnlock();
 	}
 
 	/*
@@ -2210,8 +2377,11 @@
 		to ensure that we're not the last to hold the reference as
 		we can't destroy the display context from the MISR which we
 		can be called from.
+		 
+		Ignore any fence checks if doing a null flip (e.g. when trying to unblock
+		stalled applications).
 	*/
-	SCPCommandComplete(psDisplayContext->psSCPContext);
+	SCPCommandComplete(psDisplayContext->psSCPContext, psData->bDirectNullFlip);
 
 	/* Notify devices (including ourself) in case some item has been unblocked */
 	PVRSRVCheckStatus(NULL);
@@ -2268,7 +2438,7 @@
 	}
 
 	/* Lock the pages */
-	eError = PMRLockSysPhysAddresses(psPMR, uiLog2PageSize);
+	eError = PMRLockSysPhysAddresses(psPMR);
 	if (eError != PVRSRV_OK)
 	{
 		goto e2;
@@ -2317,6 +2487,51 @@
 	OSFreeMem(pasDevPAddr);
 }
 
+#if defined(INTEGRITY_OS)
+IMG_HANDLE DCDisplayContextGetHandle(DC_DISPLAY_CONTEXT *psDisplayContext)
+{
+	PVR_ASSERT(psDisplayContext);
+	return psDisplayContext->hDisplayContext;
+}
+
+IMG_UINT32 DCDeviceGetIndex(IMG_HANDLE hDeviceData)
+{
+	DC_DEVICE *psDevice = g_psDCDeviceList;
+	IMG_UINT32 ui32Index = 0;
+
+	while (psDevice != NULL)
+	{
+		if (psDevice->hDeviceData == hDeviceData)
+		{
+			ui32Index = psDevice->ui32Index;
+			break;
+		}
+		psDevice = psDevice->psNext;
+	}
+
+	return ui32Index;
+}
+
+IMG_HANDLE DCDeviceGetDeviceAtIndex(IMG_UINT32 ui32DeviceIndex)
+{
+	IMG_HANDLE hDeviceData = NULL;
+	DC_DEVICE *psDevice = g_psDCDeviceList;
+
+	while (psDevice != NULL)
+	{
+		if (psDevice->ui32Index == ui32DeviceIndex)
+		{
+			hDeviceData = psDevice->hDeviceData;
+			break;
+		}
+		psDevice = psDevice->psNext;
+	}
+
+	return hDeviceData;
+}
+
+#endif
+
 /*****************************************************************************
  *                Public interface functions for services                    *
  *****************************************************************************/
@@ -2341,3 +2556,5 @@
 
 	return PVRSRV_OK;
 }
+
+
diff --git a/drivers/staging/imgtec/rogue/dc_server.h b/drivers/staging/imgtec/rogue/dc_server.h
index 4d9892c..f27b33c 100644
--- a/drivers/staging/imgtec/rogue/dc_server.h
+++ b/drivers/staging/imgtec/rogue/dc_server.h
@@ -44,7 +44,7 @@
 
 #include "img_types.h"
 #include "pvrsrv_error.h"
-#include "sync_external.h"
+#include <powervr/sync_external.h>
 #include "pvrsrv_surface.h"
 #include "pmr.h"
 #include "kerneldisplay.h"
@@ -57,11 +57,15 @@
 
 PVRSRV_ERROR DCDevicesQueryCount(IMG_UINT32 *pui32DeviceCount);
 
-PVRSRV_ERROR DCDevicesEnumerate(IMG_UINT32 ui32DeviceArraySize,
+PVRSRV_ERROR DCDevicesEnumerate(CONNECTION_DATA *psConnection,
+								PVRSRV_DEVICE_NODE *psDevNode,
+								IMG_UINT32 ui32DeviceArraySize,
 								IMG_UINT32 *pui32DeviceCount,
 								IMG_UINT32 *paui32DeviceIndex);
 
-PVRSRV_ERROR DCDeviceAcquire(IMG_UINT32 ui32DeviceIndex,
+PVRSRV_ERROR DCDeviceAcquire(CONNECTION_DATA *psConnection,
+							 PVRSRV_DEVICE_NODE *psDevNode,
+							 IMG_UINT32 ui32DeviceIndex,
 							 DC_DEVICE **ppsDevice);
 
 PVRSRV_ERROR DCDeviceRelease(DC_DEVICE *psDevice);
@@ -153,4 +157,16 @@
 PVRSRV_ERROR DCInit(void);
 PVRSRV_ERROR DCDeInit(void);
 
+#if defined(INTEGRITY_OS)
+IMG_HANDLE DCDisplayContextGetHandle(DC_DISPLAY_CONTEXT *psDisplayContext);
+IMG_UINT32 DCDeviceGetIndex(IMG_HANDLE hDevice);
+IMG_HANDLE DCDeviceGetDeviceAtIndex(IMG_UINT32 ui32DeviceIndex);
+#endif
+
+#if defined(SUPPORT_DRM_EXT)
+/* FIXME: Temporary workaround. Awaiting buildpkg refresh. */
+#define OSMemCopy(a,b,c) memcpy(a,b,c)
+#endif
+
 #endif /*_DC_SERVER_H_  */
+
diff --git a/drivers/staging/imgtec/rogue/debugmisc_server.c b/drivers/staging/imgtec/rogue/debugmisc_server.c
index c1e54d8..aa71482 100644
--- a/drivers/staging/imgtec/rogue/debugmisc_server.c
+++ b/drivers/staging/imgtec/rogue/debugmisc_server.c
@@ -72,7 +72,8 @@
 	                            RGXFWIF_DM_GP,
 	                            &sSLCBPCtlCmd,
 	                            sizeof(sSLCBPCtlCmd),
-	                            IMG_TRUE);
+	                            0,
+	                            PDUMP_FLAGS_CONTINUOUS);
 	if(eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscSLCSetEnableStateKM: RGXScheduleCommandfailed. Error:%u", eError));
@@ -80,7 +81,7 @@
 	else
 	{
 		/* Wait for the SLC flush to complete */
-		eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+		eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"PVRSRVDebugMiscSLCSetEnableStateKM: Waiting for value aborted with error (%u)", eError));
@@ -91,9 +92,43 @@
 }
 
 IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscQueryFWLogKM(
+	const CONNECTION_DATA *psConnection,
+	const PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32 *pui32RGXFWLogType)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/* Guest drivers do not support tracebuf */
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(pui32RGXFWLogType);
+	return PVRSRV_ERROR_NOT_IMPLEMENTED;
+#else
+	if (!psDeviceNode || !pui32RGXFWLogType)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	if (!psDevInfo || !psDevInfo->psRGXFWIfTraceBuf)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	*pui32RGXFWLogType = psDevInfo->psRGXFWIfTraceBuf->ui32LogType;
+	return PVRSRV_OK;
+#endif
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
 PVRSRVRGXDebugMiscSetFWLogKM(
-	CONNECTION_DATA * psConnection,
-	PVRSRV_DEVICE_NODE *psDeviceNode,
+	const CONNECTION_DATA * psConnection,
+	const PVRSRV_DEVICE_NODE *psDeviceNode,
 	IMG_UINT32  ui32RGXFWLogType)
 {
 	RGXFWIF_KCCB_CMD sLogTypeUpdateCmd;
@@ -129,7 +164,8 @@
 	                            RGXFWIF_DM_GP,
 	                            &sLogTypeUpdateCmd,
 	                            sizeof(sLogTypeUpdateCmd),
-	                            IMG_TRUE);
+	                            0,
+	                            PDUMP_FLAGS_CONTINUOUS);
 	if(eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: RGXScheduleCommandfailed. Error:%u", __FUNCTION__, eError));
@@ -137,7 +173,7 @@
 	else
 	{
 		/* Wait for the LogType value to be updated */
-		eError = RGXWaitForFWOp(psDevInfo, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+		eError = RGXWaitForFWOp(psDevInfo, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"%s: Waiting for value aborted with error (%u)", __FUNCTION__, eError));
@@ -149,8 +185,51 @@
 }
 
 IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetHCSDeadlineKM(
+	CONNECTION_DATA *psConnection,
+	PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32  ui32HCSDeadlineMS)
+{
+	PVRSRV_RGXDEV_INFO* psDevInfo = psDeviceNode->pvDevice;
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+	
+	return RGXFWSetHCSDeadline(psDevInfo, ui32HCSDeadlineMS);
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetOSidPriorityKM(
+	CONNECTION_DATA *psConnection,
+	PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32  ui32OSid,
+	IMG_UINT32  ui32OSidPriority)
+{
+	PVRSRV_RGXDEV_INFO* psDevInfo = psDeviceNode->pvDevice;
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	return RGXFWChangeOSidPriority(psDevInfo, ui32OSid, ui32OSidPriority);
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetOSNewOnlineStateKM(
+	CONNECTION_DATA *psConnection,
+	PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32  ui32OSid,
+	IMG_UINT32  ui32OSNewState)
+{
+	PVRSRV_RGXDEV_INFO* psDevInfo = psDeviceNode->pvDevice;
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	if (ui32OSNewState)
+	{
+		return RGXFWSetVMOnlineState(psDevInfo, ui32OSid, RGXFWIF_OS_ONLINE);
+	}
+
+	return RGXFWSetVMOnlineState(psDevInfo, ui32OSid, RGXFWIF_OS_OFFLINE);
+}
+
+IMG_EXPORT PVRSRV_ERROR
 PVRSRVRGXDebugMiscDumpFreelistPageListKM(
-	CONNECTION_DATA * psConnection,	
+	CONNECTION_DATA * psConnection,
 	PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 	PVRSRV_RGXDEV_INFO* psDevInfo = psDeviceNode->pvDevice;
diff --git a/drivers/staging/imgtec/rogue/debugmisc_server.h b/drivers/staging/imgtec/rogue/debugmisc_server.h
index 0ab835a..af20f3f 100644
--- a/drivers/staging/imgtec/rogue/debugmisc_server.h
+++ b/drivers/staging/imgtec/rogue/debugmisc_server.h
@@ -69,10 +69,36 @@
 	IMG_UINT64 ui64FWSigLen);
 
 IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscQueryFWLogKM(
+	const CONNECTION_DATA *psConnection,
+	const PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32 *pui32RGXFWLogType);
+
+IMG_EXPORT PVRSRV_ERROR
 PVRSRVRGXDebugMiscSetFWLogKM(
+	const CONNECTION_DATA *psConnection,
+	const PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32  ui32RGXFWLogType);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetHCSDeadlineKM(
 	CONNECTION_DATA *psConnection,
 	PVRSRV_DEVICE_NODE *psDeviceNode,
-	IMG_UINT32  ui32RGXFWLogType);
+	IMG_UINT32  ui32HCSDeadlineMS);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetOSidPriorityKM(
+	CONNECTION_DATA *psConnection,
+	PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32  ui32OSid,
+	IMG_UINT32  ui32OSidPriority);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetOSNewOnlineStateKM(
+	CONNECTION_DATA *psConnection,
+	PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32  ui32OSid,
+	IMG_UINT32  ui32OSNewState);
 
 IMG_EXPORT PVRSRV_ERROR
 PVRSRVRGXDebugMiscDumpFreelistPageListKM(
diff --git a/drivers/staging/imgtec/rogue/device.h b/drivers/staging/imgtec/rogue/device.h
index 0c91f25..854cf6b 100644
--- a/drivers/staging/imgtec/rogue/device.h
+++ b/drivers/staging/imgtec/rogue/device.h
@@ -50,11 +50,11 @@
 #include "ra.h"  		/* RA_ARENA */
 #include "pvrsrv_device.h"
 #include "srvkm.h"
-#include "devicemem.h"
 #include "physheap.h"
-#include "sync.h"
+#include <powervr/sync_external.h>
+#include "sysinfo.h"
 #include "dllist.h"
-#include "cache_external.h"
+#include "cache_km.h"
 
 #include "lock.h"
 
@@ -62,8 +62,15 @@
 #include "virt_validation_defs.h"
 #endif
 
-/* BM context forward reference */
-typedef struct _BM_CONTEXT_ BM_CONTEXT;
+#if defined(SUPPORT_BUFFER_SYNC)
+struct pvr_buffer_sync_context;
+#endif
+
+typedef struct _PVRSRV_POWER_DEV_TAG_ PVRSRV_POWER_DEV;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+struct SYNC_RECORD;
+#endif
 
 /*********************************************************************/ /*!
  @Function      AllocUFOCallback
@@ -97,27 +104,18 @@
 typedef void (*FreeUFOBlockCallback)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
 									 DEVMEM_MEMDESC *psMemDesc);
 
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+	/* Pdump memory and register bank names */
+	IMG_CHAR				*pszPDumpDevName;
+	IMG_CHAR				*pszPDumpRegName;
+} PVRSRV_DEVICE_IDENTIFIER;
 
 typedef struct _DEVICE_MEMORY_INFO_
 {
-	/* size of address space, as log2 */
-	IMG_UINT32				ui32AddressSpaceSizeLog2;
-
-	/* 
-		flags, includes physical memory resource types available to the system.  
-		Allows for validation at heap creation, define PVRSRV_BACKINGSTORE_XXX 
-	*/
-	IMG_UINT32				ui32Flags;
-
 	/* heap count.  Doesn't include additional heaps from PVRSRVCreateDeviceMemHeap */
 	IMG_UINT32				ui32HeapCount;
 
-	/* BM kernel context for the device */
-    BM_CONTEXT				*pBMKernelContext;
-
-	/* BM context list for the device*/
-    BM_CONTEXT				*pBMContext;
-
     /* Blueprints for creating new device memory contexts */
     IMG_UINT32              uiNumHeapConfigs;
     DEVMEM_HEAP_CONFIG      *psDeviceMemoryHeapConfigArray;
@@ -158,6 +156,7 @@
 	PVRSRV_DEVICE_STATE_INIT,
 	PVRSRV_DEVICE_STATE_ACTIVE,
 	PVRSRV_DEVICE_STATE_DEINIT,
+	PVRSRV_DEVICE_STATE_BAD,
 } PVRSRV_DEVICE_STATE;
 
 typedef enum _PVRSRV_DEVICE_HEALTH_STATUS_
@@ -185,20 +184,29 @@
 										IMG_UINT32 *pui32MappingTable,
 										IMG_UINT32 uiLog2PageSize,
 										PVRSRV_MEMALLOCFLAGS_T uiFlags,
+										const IMG_CHAR *pszAnnotation,
 										PMR **ppsPMRPtr);
+
 typedef struct _PVRSRV_DEVICE_NODE_
 {
 	PVRSRV_DEVICE_IDENTIFIER	sDevId;
 
 	PVRSRV_DEVICE_STATE			eDevState;
-	PVRSRV_DEVICE_HEALTH_STATUS eHealthStatus;
-	PVRSRV_DEVICE_HEALTH_REASON eHealthReason;
+	ATOMIC_T					eHealthStatus; /* Holds values from PVRSRV_DEVICE_HEALTH_STATUS */
+	ATOMIC_T					eHealthReason; /* Holds values from PVRSRV_DEVICE_HEALTH_REASON */
+
+	IMG_HANDLE						*hDebugTable;
 
 	/* device specific MMU attributes */
    	MMU_DEVICEATTRIBS      *psMMUDevAttrs;
 	/* device specific MMU firmware atrributes, used only in some devices*/
 	MMU_DEVICEATTRIBS      *psFirmwareMMUDevAttrs;
 
+	/* lock for power state transitions */
+	POS_LOCK				hPowerLock;
+	/* current system device power state */
+	PVRSRV_SYS_POWER_STATE	eCurrentSysPowerState;
+	PVRSRV_POWER_DEV		*psPowerDev;
 
 	/*
 		callbacks the device must support:
@@ -218,20 +226,24 @@
 	void (*pfnDevPxUnMap)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
 						  PG_HANDLE *psMemHandle, void *pvPtr);
 
-	PVRSRV_ERROR (*pfnDevPxClean)(PG_HANDLE *pshMemHandle,
+	PVRSRV_ERROR (*pfnDevPxClean)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+								PG_HANDLE *pshMemHandle,
 								IMG_UINT32 uiOffset,
 								IMG_UINT32 uiLength);
 
 	IMG_UINT32 uiMMUPxLog2AllocGran;
-	IMG_CHAR				*pszMMUPxPDumpMemSpaceName;
 
 	void (*pfnMMUCacheInvalidate)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
 								  IMG_HANDLE hDeviceData,
 								  MMU_LEVEL eLevel,
 								  IMG_BOOL bUnmap);
 
-	PVRSRV_ERROR (*pfnSLCCacheInvalidateRequest)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-										PMR *psPmr);
+	PVRSRV_ERROR (*pfnMMUCacheInvalidateKick)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+	                                          IMG_UINT32 *pui32NextMMUInvalidateUpdate,
+	                                          IMG_BOOL bInterrupt);
+
+	IMG_UINT32 (*pfnMMUCacheGetInvalidateCounter)(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+
 
 	void (*pfnDumpDebugInfo)(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
 
@@ -249,30 +261,49 @@
 
 	PVRSRV_ERROR (*pfnSoftReset)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_UINT64 ui64ResetValue1, IMG_UINT64 ui64ResetValue2);
 
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(RGXFW_ALIGNCHECKS)
+	PVRSRV_ERROR (*pfnAlignmentCheck)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_UINT32 ui32FWAlignChecksSize, IMG_UINT32 aui32FWAlignChecks[]);
+#endif
+	IMG_BOOL	(*pfnCheckDeviceFeature)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_UINT64 ui64FeatureMask);
+
+	IMG_INT32	(*pfnGetDeviceFeatureValue)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_UINT64 ui64FeatureMask);
+
 	PVRSRV_DEVICE_CONFIG	*psDevConfig;
 
 	/* device post-finalise compatibility check */
-	PVRSRV_ERROR			(*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*,IMG_UINT32 ui32ClientBuildOptions);
+	PVRSRV_ERROR			(*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
 
 	/* information about the device's address space and heaps */
 	DEVICE_MEMORY_INFO		sDevMemoryInfo;
 
+	/* device's shared-virtual-memory heap max virtual address */
+	IMG_UINT64				ui64GeneralSVMHeapTopVA;
+
 	/* private device information */
 	void					*pvDevice;
 
-	IMG_CHAR				szRAName[50];
+
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 	RA_ARENA                *psOSidSubArena[GPUVIRT_VALIDATION_NUM_OS];
 #endif
 
-	RA_ARENA				*psLocalDevMemArena;
+
+#define PVRSRV_MAX_RA_NAME_LENGTH (50)
+	RA_ARENA				**apsLocalDevMemArenas;
+	IMG_CHAR				**apszRANames;
+	IMG_UINT32				ui32NumOfLocalMemArenas;
+
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
-	IMG_CHAR				szKernelFwRAName[RGXFW_NUM_OS][50];
+	IMG_CHAR				szKernelFwRAName[RGXFW_NUM_OS][PVRSRV_MAX_RA_NAME_LENGTH];
 	RA_ARENA				*psKernelFwMemArena[RGXFW_NUM_OS];
 	IMG_UINT32				uiKernelFwRAIdx;
+	RA_BASE_T				ui64RABase[RGXFW_NUM_OS];
 #endif
 
+	IMG_UINT32				ui32RegisteredPhysHeaps;
+	PHYS_HEAP				**papsRegisteredPhysHeaps;
+
 	/*
 	 * Pointers to the device's physical memory heap(s)
 	 * The first entry (apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]) will be used for allocations
@@ -299,17 +330,43 @@
 														IMG_HANDLE					*hPrivData);
 	void					(*pfnUnregisterMemoryContext)(IMG_HANDLE hPrivData);
 
-	/* Funtions for allocation/freeing of UFOs */
+	/* Functions for allocation/freeing of UFOs */
 	AllocUFOBlockCallback	pfnAllocUFOBlock;	/*!< Callback for allocation of a block of UFO memory */
 	FreeUFOBlockCallback	pfnFreeUFOBlock;	/*!< Callback for freeing of a block of UFO memory */
 
+#if defined(SUPPORT_BUFFER_SYNC)
+	struct pvr_buffer_sync_context *psBufferSyncContext;
+#endif
+
+	IMG_HANDLE				hSyncServerNotify;
+	POS_LOCK				hSyncServerListLock;
+	DLLIST_NODE				sSyncServerSyncsList;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	IMG_HANDLE				hSyncServerRecordNotify;
+	POS_LOCK				hSyncServerRecordLock;
+	DLLIST_NODE				sSyncServerRecordList;
+	struct SYNC_RECORD		*apsSyncServerRecordsFreed[PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN];
+	IMG_UINT32				uiSyncServerRecordFreeIdx;
+#endif
+
 	PSYNC_PRIM_CONTEXT		hSyncPrimContext;
 
-	PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim;
+	PVRSRV_CLIENT_SYNC_PRIM	*psSyncPrim;
+	/* With this sync-prim we make sure the MMU cache is flushed
+	 * before we free the page table memory */
+	PVRSRV_CLIENT_SYNC_PRIM	*psMMUCacheSyncPrim;
+	IMG_UINT32				ui32NextMMUInvalidateUpdate;
 
 	IMG_HANDLE				hCmdCompNotify;
 	IMG_HANDLE				hDbgReqNotify;
+	IMG_HANDLE				hHtbDbgReqNotify;
+	IMG_HANDLE				hAppHintDbgReqNotify;
+
 	PVRSRV_DUMMY_PAGE		sDummyPage;
+
+	DLLIST_NODE				sMemoryContextPageFaultNotifyListHead;
+
 #if defined(PDUMP)
 	/* 	device-level callback which is called when pdump.exe starts.
 	 *	Should be implemented in device-specific init code, e.g. rgxinit.c
@@ -320,11 +377,12 @@
 #endif
 } PVRSRV_DEVICE_NODE;
 
-PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful,
-														IMG_UINT32 ui32ClientBuildOptions);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
+											   IMG_BOOL bInitSuccessful);
 
-PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode,
-														IMG_UINT32 ui32ClientBuildOptions);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV RGXClientConnectCompatCheck_ClientAgainstFW(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32ClientBuildOptions);
 
 	
 #endif /* __DEVICE_H__ */
diff --git a/drivers/staging/imgtec/rogue/device_connection.h b/drivers/staging/imgtec/rogue/device_connection.h
index 3f000a4..715833b 100644
--- a/drivers/staging/imgtec/rogue/device_connection.h
+++ b/drivers/staging/imgtec/rogue/device_connection.h
@@ -41,16 +41,35 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#if defined(__KERNEL__)
-#include "device.h"
-#endif
+#if !defined(__DEVICE_CONNECTION_H__)
+#define __DEVICE_CONNECTION_H__
+
+#include "img_types.h"
 
 #if defined(__KERNEL__)
-typedef struct _PVRSRV_DEVICE_NODE_* SHARED_DEV_CONNECTION;
+typedef struct _PVRSRV_DEVICE_NODE_ *SHARED_DEV_CONNECTION;
 #else
 typedef IMG_HANDLE SHARED_DEV_CONNECTION;
 #endif
 
-/**************************************************************************//**
-End of file (device_connection.h)
-******************************************************************************/
+/******************************************************************************
+ * Device capability flags and masks
+ *****************************************************************************/
+
+/* Flag to be passed over the bridge during connection stating whether CPU cache coherent is available*/
+#define PVRSRV_CACHE_COHERENT_SHIFT (0)
+#define	PVRSRV_CACHE_COHERENT_DEVICE_FLAG (1U << PVRSRV_CACHE_COHERENT_SHIFT)
+#define	PVRSRV_CACHE_COHERENT_CPU_FLAG (2U << PVRSRV_CACHE_COHERENT_SHIFT)
+#define PVRSRV_CACHE_COHERENT_MASK (3U << PVRSRV_CACHE_COHERENT_SHIFT)
+
+/* Flag to be passed over the bridge during connection stating whether CPU non-mappable memory is present */
+#define PVRSRV_NONMAPPABLE_MEMORY_PRESENT_SHIFT (3)
+#define PVRSRV_NONMAPPABLE_MEMORY_PRESENT_FLAG (1U << PVRSRV_NONMAPPABLE_MEMORY_PRESENT_SHIFT)
+
+/* Flag to be passed over the bridge during connection stating SVM allocation availability */
+#define PVRSRV_DEVMEM_SVM_ALLOC_SHIFT (4)
+#define PVRSRV_DEVMEM_SVM_ALLOC_UNSUPPORTED (1U << PVRSRV_DEVMEM_SVM_ALLOC_SHIFT)
+#define PVRSRV_DEVMEM_SVM_ALLOC_SUPPORTED (2U << PVRSRV_DEVMEM_SVM_ALLOC_SHIFT)
+#define PVRSRV_DEVMEM_SVM_ALLOC_CANFAIL (4U << PVRSRV_DEVMEM_SVM_ALLOC_SHIFT)
+
+#endif /* !defined(__DEVICE_CONNECTION_H__) */
diff --git a/drivers/staging/imgtec/rogue/devicemem.c b/drivers/staging/imgtec/rogue/devicemem.c
index 40444cd..9eccef9 100644
--- a/drivers/staging/imgtec/rogue/devicemem.c
+++ b/drivers/staging/imgtec/rogue/devicemem.c
@@ -51,23 +51,32 @@
 #include "allocmem.h"
 #include "ra.h"
 #include "osfunc.h"
-#include "devicemem_mmap.h"
+#include "osmmap.h"
 #include "devicemem_utils.h"
 #include "client_mm_bridge.h"
-#include "client_cachegeneric_bridge.h"
+#include "client_cache_bridge.h"
+#include "services_km.h"
+
 #if defined(PDUMP)
+#if defined(__KERNEL__)
+#include "pdump_km.h"
+#else
+#include "client_pdump_bridge.h"
+#endif
 #include "devicemem_pdump.h"
 #endif
 #if defined(PVR_RI_DEBUG)
 #include "client_ri_bridge.h"
-#endif 
+#endif
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
 #include "client_devicememhistory_bridge.h"
 #endif
 
+#include "rgx_heaps.h"
 #if defined(__KERNEL__)
-#include "rgxdefs_km.h"
 #include "pvrsrv.h"
+#include "rgxdefs_km.h"
+#include "rgx_bvnc_defs_km.h"
 #if defined(LINUX)
 #include "linux/kernel.h"
 #endif
@@ -75,11 +84,9 @@
 #include "rgxdefs.h"
 #endif
 
-/** Page size.
- *  Should be initialised to the correct value at driver init time.
- *  Use macros from devicemem.h to access from outside this module.
- */
-IMG_UINT32 g_uiLog2PageSize = 0;
+#if defined(__KERNEL__) && defined(PVR_RI_DEBUG)
+extern PVRSRV_ERROR RIDumpAllKM(void);
+#endif
 
 /*****************************************************************************
  *                    Sub allocation internals                               *
@@ -96,6 +103,7 @@
                       IMG_DEVMEM_ALIGN_T uiAlign,
                       DEVMEM_FLAGS_T uiFlags,
                       IMG_BOOL bExportable,
+                      const IMG_CHAR *pszAnnotation,
                       DEVMEM_IMPORT **ppsImport)
 {
 	DEVMEM_IMPORT *psImport;
@@ -123,7 +131,19 @@
                                           pui32MappingTable,
                                           uiLog2Quantum,
                                           uiPMRFlags,
+#if defined(PDUMP)
+                                          OSStringLength(pszAnnotation) + 1,
+                                          pszAnnotation,
                                           &hPMR);
+#else
+                                          1,
+                                          "",
+                                          &hPMR);
+
+	PVR_UNREFERENCED_PARAMETER(pszAnnotation);
+#endif
+
+
     if (eError != PVRSRV_OK)
     {
         /* Our check above should have ensured this the "not page
@@ -158,26 +178,25 @@
 
 IMG_INTERNAL PVRSRV_ERROR
 DeviceMemChangeSparse(DEVMEM_MEMDESC *psMemDesc,
-					  IMG_UINT32 ui32AllocPageCount,
-					  IMG_UINT32 *paui32AllocPageIndices,
-					  IMG_UINT32 ui32FreePageCount,
-					  IMG_UINT32 *pauiFreePageIndices,
-					  SPARSE_MEM_RESIZE_FLAGS uiSparseFlags,
-					  IMG_UINT32 *pui32Status)
+                      IMG_UINT32 ui32AllocPageCount,
+                      IMG_UINT32 *paui32AllocPageIndices,
+                      IMG_UINT32 ui32FreePageCount,
+                      IMG_UINT32 *pauiFreePageIndices,
+                      SPARSE_MEM_RESIZE_FLAGS uiSparseFlags)
 {
-	PVRSRV_ERROR eError=-1;
-	IMG_UINT32	ui32Status;
-	DEVMEM_IMPORT *psImport=psMemDesc->psImport;
+	PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
+	DEVMEM_IMPORT *psImport = psMemDesc->psImport;
 	SHARED_DEV_CONNECTION hDevConnection;
-	IMG_HANDLE	hPMR, hSrvDevMemHeap;
+	IMG_HANDLE hPMR;
+	IMG_HANDLE hSrvDevMemHeap;
 	POS_LOCK hLock;
 	IMG_DEV_VIRTADDR sDevVAddr;
 	IMG_CPU_VIRTADDR sCpuVAddr;
 
-	if(NULL == psImport)
+	if (NULL == psImport)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Invalid Sparse memory import",__func__));
-		goto ChangeSparseError;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Sparse memory import", __func__));
+		goto e0;
 	}
 
 	hDevConnection = psImport->hDevConnection;
@@ -186,69 +205,114 @@
 	sDevVAddr = psImport->sDeviceImport.sDevVAddr;
 	sCpuVAddr = psImport->sCPUImport.pvCPUVAddr;
 
-	if(NULL == hDevConnection)
+	if (NULL == hDevConnection)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Invalid Bridge handle",__func__));
-		goto ChangeSparseError;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Bridge handle", __func__));
+		goto e0;
 	}
 
-	if(NULL == hPMR)
+	if (NULL == hPMR)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Invalid PMR handle",__func__));
-		goto ChangeSparseError;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid PMR handle", __func__));
+		goto e0;
 	}
 
-	if((uiSparseFlags & SPARSE_RESIZE_BOTH) && (0 == sDevVAddr.uiAddr))
+	if ((uiSparseFlags & SPARSE_RESIZE_BOTH) && (0 == sDevVAddr.uiAddr))
 	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Invalid Device Virtual Map",__func__));
-		goto ChangeSparseError;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Device Virtual Map", __func__));
+		goto e0;
 	}
 
-	if((uiSparseFlags & SPARSE_MAP_CPU_ADDR) && (0 == sCpuVAddr))
+	if ((uiSparseFlags & SPARSE_MAP_CPU_ADDR) && (0 == sCpuVAddr))
 	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Invalid CPU Virtual Map",__func__));
-		goto ChangeSparseError;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid CPU Virtual Map", __func__));
+		goto e0;
 	}
 
-	hSrvDevMemHeap  = psImport->sDeviceImport.psHeap->hDevMemServerHeap;
+	if (psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_SECURE)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Secure buffers currently do not support sparse changes",
+				__func__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto e0;
+	}
+
+	hSrvDevMemHeap = psImport->sDeviceImport.psHeap->hDevMemServerHeap;
 
 	OSLockAcquire(hLock);
 
 	eError = BridgeChangeSparseMem(hDevConnection,
-										hSrvDevMemHeap,
-										hPMR,
-										ui32AllocPageCount,
-										paui32AllocPageIndices,
-										ui32FreePageCount,
-										pauiFreePageIndices,
-										uiSparseFlags,
-										psImport->uiFlags,
-										sDevVAddr,
-										(IMG_UINT64)((uintptr_t)sCpuVAddr),
-										&ui32Status);
+	                               hSrvDevMemHeap,
+	                               hPMR,
+	                               ui32AllocPageCount,
+	                               paui32AllocPageIndices,
+	                               ui32FreePageCount,
+	                               pauiFreePageIndices,
+	                               uiSparseFlags,
+	                               psImport->uiFlags,
+	                               sDevVAddr,
+	                               (IMG_UINT64)((uintptr_t)sCpuVAddr));
 
 	 OSLockRelease(hLock);
-	 *pui32Status = ui32Status;
 
 #if defined(PVR_RI_DEBUG)
-	BridgeRIUpdateMEMDESCBacking(psImport->hDevConnection,
-	                             psMemDesc->hRIHandle,
-	                             ((IMG_INT32) ui32AllocPageCount - (IMG_INT32) ui32FreePageCount)
-	                              * (1 << psImport->sDeviceImport.psHeap->uiLog2Quantum));
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_RI))
+	{
+		BridgeRIUpdateMEMDESCBacking(psImport->hDevConnection,
+		                             psMemDesc->hRIHandle,
+		                             ((IMG_INT32) ui32AllocPageCount - (IMG_INT32) ui32FreePageCount)
+		                              * (1 << psImport->sDeviceImport.psHeap->uiLog2Quantum));
+	}
+#endif
+
+#if defined(SUPPORT_PAGE_FAULT_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		static IMG_BOOL bHaveNewAPI = IMG_TRUE;
+		PVRSRV_ERROR eError;
+
+		if(bHaveNewAPI)
+		{
+			eError = BridgeDevicememHistorySparseChange(psMemDesc->psImport->hDevConnection,
+								psMemDesc->psImport->hPMR,
+								psMemDesc->uiOffset,
+								psMemDesc->sDeviceMemDesc.sDevVAddr,
+								psMemDesc->uiAllocSize,
+								psMemDesc->sTraceData.szText,
+								DevmemGetHeapLog2PageSize(psImport->sDeviceImport.psHeap),
+								ui32AllocPageCount,
+								paui32AllocPageIndices,
+								ui32FreePageCount,
+								pauiFreePageIndices,
+								psMemDesc->sTraceData.ui32AllocationIndex,
+								&psMemDesc->sTraceData.ui32AllocationIndex);
+
+			 if(eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+			 {
+			 	bHaveNewAPI = IMG_FALSE;
+			 }
+		}
+
+		/* no fallback required here.
+		 * the old version of devicememhistory doesn't have entry
+		 * points for SparseChange
+		 */
+	}
 #endif
 
 #ifdef PVRSRV_UNMAP_ON_SPARSE_CHANGE
-	 if((PVRSRV_OK == eError) && (psMemDesc->sCPUMemDesc.ui32RefCount))
-	 {
-		 /*
-		  * Release the CPU Virtual mapping here
-		  * the caller is supposed to map entire range again
-		  */
-		 DevmemReleaseCpuVirtAddr(psMemDesc);
-	 }
+	if ((PVRSRV_OK == eError) && (psMemDesc->sCPUMemDesc.ui32RefCount))
+	{
+		/*
+		 * Release the CPU Virtual mapping here
+		 * the caller is supposed to map entire range again
+		 */
+		DevmemReleaseCpuVirtAddr(psMemDesc);
+	}
 #endif
 
-ChangeSparseError:
+e0:
 	return eError;
 }
 
@@ -258,40 +322,51 @@
 	_DevmemImportStructRelease(psImport);
 }
 
-static IMG_BOOL
+static PVRSRV_ERROR
 _SubAllocImportAlloc(RA_PERARENA_HANDLE hArena,
                      RA_LENGTH_T uiSize,
                      RA_FLAGS_T _flags,
+                     const IMG_CHAR *pszAnnotation,
                      /* returned data */
                      RA_BASE_T *puiBase,
                      RA_LENGTH_T *puiActualSize,
                      RA_PERISPAN_HANDLE *phImport)
 {
-    /* When suballocations need a new lump of memory, the RA calls
-       back here.  Later, in the kernel, we must construct a new PMR
-       and a pairing between the new lump of virtual memory and the
-       PMR (whether or not such PMR is backed by physical memory) */
-    DEVMEM_HEAP *psHeap;
-    DEVMEM_IMPORT *psImport;
-    IMG_DEVMEM_ALIGN_T uiAlign;
-    DEVMEM_FLAGS_T uiFlags;
-    PVRSRV_ERROR eError;
-    IMG_UINT32 ui32MappingTable = 0;
+	/* When suballocations need a new lump of memory, the RA calls
+	   back here.  Later, in the kernel, we must construct a new PMR
+	   and a pairing between the new lump of virtual memory and the
+	   PMR (whether or not such PMR is backed by physical memory) */
+	DEVMEM_HEAP *psHeap;
+	DEVMEM_IMPORT *psImport;
+	IMG_DEVMEM_ALIGN_T uiAlign;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32MappingTable = 0;
+	DEVMEM_FLAGS_T uiFlags = (DEVMEM_FLAGS_T) _flags;
+	IMG_UINT64 ui64OptionalMapAddress = DEVICEMEM_UTILS_NO_ADDRESS;
 
-    uiFlags = (DEVMEM_FLAGS_T) _flags;
+	/* Per-arena private handle is, for us, the heap */
+	psHeap = hArena;
 
-    /* Per-arena private handle is, for us, the heap */
-    psHeap = hArena;
+	/* align to the l.s.b. of the size...  e.g. 96kiB aligned to
+	   32kiB. NB: There is an argument to say that the RA should never
+	   ask us for Non-power-of-2 size anyway, but I don't want to make
+	   that restriction arbitrarily now */
+	uiAlign = uiSize & ~(uiSize-1);
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	/* Technically this is only required for guest drivers due to
+	   fw heaps being pre-allocated and pre-mapped resulting in
+	   a 1:1 (i.e. virtual : physical) offset correlation but we
+	   force this behaviour for all drivers to maintain consistency
+	   (i.e. heap->VA uiAlign <= heap->PA uiLog2Quantum) */
+	if (uiAlign > (IMG_DEVMEM_ALIGN_T)(1 << psHeap->uiLog2Quantum))
+	{
+		uiAlign = (IMG_DEVMEM_ALIGN_T)(1 << psHeap->uiLog2Quantum);
+	}
+#endif
 
-    /* align to the l.s.b. of the size...  e.g. 96kiB aligned to
-       32kiB. NB: There is an argument to say that the RA should never
-       ask us for Non-power-of-2 size anyway, but I don't want to make
-       that restriction arbitrarily now */
-    uiAlign = uiSize & ~(uiSize-1);
-
-    /* The RA should not have invoked us with a size that is not a
-       multiple of the quantum anyway */
-    PVR_ASSERT((uiSize & ((1ULL<<psHeap->uiLog2Quantum)-1)) == 0);
+	/* The RA should not have invoked us with a size that is not a
+	   multiple of the quantum anyway */
+	PVR_ASSERT((uiSize & ((1ULL<<psHeap->uiLog2Quantum)-1)) == 0);
 
 	eError = _AllocateDeviceMemory(psHeap->psCtx->hDevConnection,
 	                               psHeap->uiLog2Quantum,
@@ -303,13 +378,26 @@
 	                               uiAlign,
 	                               uiFlags,
 	                               IMG_FALSE,
+	                               pszAnnotation,
 	                               &psImport);
 	if (eError != PVRSRV_OK)
 	{
 		goto failAlloc;
 	}
 
+#if defined (PDUMP)
+	/* Keep the annotation in the Devmem layer so we know where suballocations were done from*/
+	psImport->pszAnnotation = OSAllocMem(OSStringLength(pszAnnotation)+1);
+	if (psImport->pszAnnotation == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto failAllocMem;
+	}
+	OSStringNCopy(psImport->pszAnnotation, pszAnnotation, OSStringLength(pszAnnotation)+1);
+#endif
+
 #if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 	{
 		eError = BridgeRIWritePMREntry (psImport->hDevConnection,
 										psImport->hPMR,
@@ -322,6 +410,7 @@
 		}
 	}
 #endif
+
 	/*
 		Suballocations always get mapped into the device was we need to
 		key the RA off something and as we can't export suballocations
@@ -330,30 +419,39 @@
 	eError = _DevmemImportStructDevMap(psHeap,
 									   IMG_TRUE,
 									   psImport,
-									   DEVICEMEM_UTILS_NO_ADDRESS);
+									   ui64OptionalMapAddress);
 	if (eError != PVRSRV_OK)
 	{
 		goto failMap;
 	}
 
-	/* Mark this import struct as clean so we can save some PDump LDBs
-	 * and do not have to CPU map + memset + flush*/
+	/* Mark this import struct as zeroed so we can save some PDump LDBs
+	 * and do not have to CPU map + memset()*/
+	if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+	{
+		psImport->uiProperties |= DEVMEM_PROPERTIES_IMPORT_IS_ZEROED;
+	}
 	psImport->uiProperties |= DEVMEM_PROPERTIES_IMPORT_IS_CLEAN;
 
 	*puiBase = psImport->sDeviceImport.sDevVAddr.uiAddr;
 	*puiActualSize = uiSize;
 	*phImport = psImport;
 
-    return IMG_TRUE;
+	return PVRSRV_OK;
 
-    /*
-      error exit paths follow
-    */
+	/*
+	  error exit paths follow
+	*/
 failMap:
-    _FreeDeviceMemory(psImport);
+#if defined(PDUMP)
+failAllocMem:
+	OSFreeMem(psImport->pszAnnotation);
+	psImport->pszAnnotation = NULL;
+#endif
+	_FreeDeviceMemory(psImport);
 failAlloc:
 
-    return IMG_FALSE;
+	return eError;
 }
 
 static void
@@ -361,13 +459,13 @@
                     RA_BASE_T uiBase,
                     RA_PERISPAN_HANDLE hImport)
 {
-    DEVMEM_IMPORT *psImport = hImport;
+	DEVMEM_IMPORT *psImport = hImport;
 
-    PVR_ASSERT(psImport != NULL);
-    PVR_ASSERT(hArena == psImport->sDeviceImport.psHeap);
-    PVR_ASSERT(uiBase == psImport->sDeviceImport.sDevVAddr.uiAddr);
+	PVR_ASSERT(psImport != NULL);
+	PVR_ASSERT(hArena == psImport->sDeviceImport.psHeap);
+	PVR_ASSERT(uiBase == psImport->sDeviceImport.sDevVAddr.uiAddr);
 
-    _DevmemImportStructDevUnmap(psImport);  
+	_DevmemImportStructDevUnmap(psImport);
 	_DevmemImportStructRelease(psImport);
 }
 
@@ -379,17 +477,18 @@
 _PopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx,
                               DEVMEM_HEAPCFGID uiHeapBlueprintID)
 {
-    PVRSRV_ERROR eError;
-    PVRSRV_ERROR eError2;
-    struct _DEVMEM_HEAP_ **ppsHeapArray;
-    IMG_UINT32 uiNumHeaps;
-    IMG_UINT32 uiHeapsToUnwindOnError;
-    IMG_UINT32 uiHeapIndex;
-    IMG_DEV_VIRTADDR sDevVAddrBase;
-    IMG_CHAR aszHeapName[DEVMEM_HEAPNAME_MAXLENGTH];
-    IMG_DEVMEM_SIZE_T uiHeapLength;
-    IMG_DEVMEM_LOG2ALIGN_T uiLog2DataPageSize;
-    IMG_DEVMEM_LOG2ALIGN_T uiLog2ImportAlignment;
+	PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError2;
+	struct _DEVMEM_HEAP_ **ppsHeapArray;
+	IMG_UINT32 uiNumHeaps;
+	IMG_UINT32 uiHeapsToUnwindOnError;
+	IMG_UINT32 uiHeapIndex;
+	IMG_DEV_VIRTADDR sDevVAddrBase;
+	IMG_CHAR aszHeapName[DEVMEM_HEAPNAME_MAXLENGTH];
+	IMG_DEVMEM_SIZE_T uiHeapLength;
+	IMG_DEVMEM_LOG2ALIGN_T uiLog2DataPageSize;
+	IMG_DEVMEM_LOG2ALIGN_T uiLog2ImportAlignment;
+	IMG_DEVMEM_LOG2ALIGN_T uiLog2TilingStrideFactor;
 
     eError = DevmemHeapCount(psCtx->hDevConnection,
                              uiHeapBlueprintID,
@@ -425,7 +524,8 @@
                                    &sDevVAddrBase,
                                    &uiHeapLength,
                                    &uiLog2DataPageSize,
-                                   &uiLog2ImportAlignment);
+                                   &uiLog2ImportAlignment,
+                                   &uiLog2TilingStrideFactor);
         if (eError != PVRSRV_OK)
         {
             goto e1;
@@ -436,6 +536,7 @@
                                   uiHeapLength,
                                   uiLog2DataPageSize,
                                   uiLog2ImportAlignment,
+                                  uiLog2TilingStrideFactor,
                                   aszHeapName,
                                   uiHeapBlueprintID,
                                   &ppsHeapArray[uiHeapIndex]);
@@ -475,40 +576,47 @@
     return eError;
 }
 
-static void
+static PVRSRV_ERROR
 _UnpopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx)
 {
-    PVRSRV_ERROR eError2;
-    IMG_UINT32 uiHeapIndex;
-    IMG_BOOL bDoCheck = IMG_TRUE;
+	PVRSRV_ERROR eReturn = PVRSRV_OK;
+	PVRSRV_ERROR eError2;
+	IMG_UINT32 uiHeapIndex;
+	IMG_BOOL bDoCheck = IMG_TRUE;
 #if defined(__KERNEL__)
-    PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-    if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
-    {
-    	bDoCheck = IMG_FALSE;
-    }
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+	{
+		bDoCheck = IMG_FALSE;
+	}
 #endif
 
-    PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
+	for (uiHeapIndex = 0; uiHeapIndex < psCtx->uiAutoHeapCount; uiHeapIndex++)
+	{
+		if (!psCtx->ppsAutoHeapArray[uiHeapIndex])
+		{
+			continue;
+		}
 
-    for (uiHeapIndex = 0; uiHeapIndex < psCtx->uiAutoHeapCount; uiHeapIndex++)
-    {
-        eError2 = DevmemDestroyHeap(psCtx->ppsAutoHeapArray[uiHeapIndex]);
-        if (bDoCheck)
-        {
-        	PVR_ASSERT(eError2 == PVRSRV_OK);
-        }
-    }
+		eError2 = DevmemDestroyHeap(psCtx->ppsAutoHeapArray[uiHeapIndex]);
+		if (eError2 != PVRSRV_OK)
+		{
+			eReturn = eError2;
+		}
+		else
+		{
+			psCtx->ppsAutoHeapArray[uiHeapIndex] = NULL;
+		}
+	}
 
-    if (psCtx->uiAutoHeapCount != 0)
-    {
-        OSFreeMem(psCtx->ppsAutoHeapArray);
-        psCtx->ppsAutoHeapArray = NULL;
-    }
-    psCtx->uiAutoHeapCount = 0;
+	if ((!bDoCheck || (eReturn == PVRSRV_OK)) && psCtx->ppsAutoHeapArray)
+	{
+		OSFreeMem(psCtx->ppsAutoHeapArray);
+		psCtx->ppsAutoHeapArray = NULL;
+		psCtx->uiAutoHeapCount = 0;
+	}
 
-    PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
-    PVR_ASSERT(psCtx->ppsAutoHeapArray == NULL);
+	return eReturn;
 }
 
 
@@ -547,22 +655,11 @@
     psCtx->hDevConnection = hDevConnection;
 
     /* Create (server-side) Device Memory context */
-    eError = BridgeDevmemIntCtxCreateCLS(psCtx->hDevConnection,
-                                         bHeapCfgMetaId,
-                                         &hDevMemServerContext,
-                                         &hPrivData,
-                                         &psCtx->ui32CPUCacheLineSize);
-
-    if (eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
-    {
-
-        psCtx->ui32CPUCacheLineSize = 0;
-        eError = BridgeDevmemIntCtxCreate(psCtx->hDevConnection,
-                                          bHeapCfgMetaId,
-                                          &hDevMemServerContext,
-                                          &hPrivData);
-    }
-
+    eError = BridgeDevmemIntCtxCreate(psCtx->hDevConnection,
+                                      bHeapCfgMetaId,
+                                      &hDevMemServerContext,
+                                      &hPrivData,
+                                      &psCtx->ui32CPUCacheLineSize);
     if (eError != PVRSRV_OK)
     {
         goto e1;
@@ -667,45 +764,56 @@
 IMG_INTERNAL PVRSRV_ERROR
 DevmemDestroyContext(DEVMEM_CONTEXT *psCtx)
 {
-    PVRSRV_ERROR eError;
-    IMG_BOOL bDoCheck = IMG_TRUE;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bDoCheck = IMG_TRUE;
 
 #if defined(__KERNEL__)
-    PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-    if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
-    {
-    	bDoCheck = IMG_FALSE;
-    }
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+	{
+		bDoCheck = IMG_FALSE;
+	}
 #endif
 
-    if (psCtx == NULL)
-    {
-        return PVRSRV_ERROR_INVALID_PARAMS;
-    }
+	if (psCtx == NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
 
-    /* should be only the automagically instantiated heaps left */
-    if (psCtx->uiNumHeaps != psCtx->uiAutoHeapCount)
-    {
-        return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
-    }
+	eError = _UnpopulateContextFromBlueprint(psCtx);
+	if (bDoCheck && eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: _UnpopulateContextFromBlueprint failed (%d) leaving %d heaps",
+		          __func__, eError, psCtx->uiNumHeaps));
+		goto e1;
+	}
 
-    _UnpopulateContextFromBlueprint(psCtx);
+	eError = BridgeDevmemIntCtxDestroy(psCtx->hDevConnection,
+	                                   psCtx->hDevMemServerContext);
+	if (bDoCheck && eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: BridgeDevmemIntCtxDestroy failed (%d)",
+		          __func__, eError));
+		goto e1;
+	}
 
-    if (bDoCheck)
-    {
-		PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
-		PVR_ASSERT(psCtx->uiNumHeaps == 0);
-    }
-    eError = BridgeDevmemIntCtxDestroy(psCtx->hDevConnection,
-                                       psCtx->hDevMemServerContext);
-    if (bDoCheck)
-    {
-    	PVR_ASSERT (eError == PVRSRV_OK);
-    }
+	/* should be no more heaps left */
+	if (bDoCheck && psCtx->uiNumHeaps)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Additional heaps remain in DEVMEM_CONTEXT",
+		          __func__));
+		eError = PVRSRV_ERROR_DEVICEMEM_ADDITIONAL_HEAPS_IN_CONTEXT;
+		goto e1;
+	}
 
-    OSFreeMem(psCtx);
+	OSDeviceMemSet(psCtx, 0, sizeof(*psCtx));
+	OSFreeMem(psCtx);
 
-    return PVRSRV_OK;
+e1:
+	return eError;
 }
 
 /*****************************************************************************
@@ -760,7 +868,8 @@
                   IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
                   IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
                   IMG_UINT32 *puiLog2DataPageSizeOut,
-                  IMG_UINT32 *puiLog2ImportAlignmentOut)
+                  IMG_UINT32 *puiLog2ImportAlignmentOut,
+                  IMG_UINT32 *puiLog2TilingStrideFactor)
 {
     PVRSRV_ERROR eError;
 
@@ -774,6 +883,23 @@
                                       puiLog2DataPageSizeOut,
                                       puiLog2ImportAlignmentOut);
 
+    /* REL/1.8 maintain bridge compatibility
+     *     4:0 - uiLog2ImportAlignment (13--20)
+     *   18:16 - uiLog2TilingStrideFactor (3--4)
+     */
+    *puiLog2TilingStrideFactor = (*puiLog2ImportAlignmentOut >> 16);
+    *puiLog2ImportAlignmentOut &= 0xffff;
+
+    /* NB: *puiLog2TilingStrideFactor is either 3 or 4 (tiling mode 1 or 0).
+     * If reading from an older KM, *puiLog2TilingStrideFactor will not be set.
+     * If so force to 4 (tiling mode 0), which was the original assumption
+     * before puiLog2TilingStrideFactor was queried.
+     */
+    if (!*puiLog2TilingStrideFactor)
+    {
+        *puiLog2TilingStrideFactor = 4;
+    }
+
     VG_MARK_INITIALIZED(pszHeapNameOut,uiHeapNameBufSz);
 
     return eError;
@@ -782,7 +908,19 @@
 /*****************************************************************************
  *                    Devmem heap functions                                  *
  *****************************************************************************/
- 
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetHeapInt(DEVMEM_HEAP *psHeap,
+				 IMG_HANDLE *phDevmemHeap)
+{
+	if (psHeap == NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	*phDevmemHeap  = psHeap->hDevMemServerHeap;
+	return PVRSRV_OK;
+}
+
 /* See devicemem.h for important notes regarding the arguments
    to this function */
 IMG_INTERNAL PVRSRV_ERROR
@@ -791,6 +929,7 @@
                  IMG_DEVMEM_SIZE_T uiLength,
                  IMG_UINT32 ui32Log2Quantum,
                  IMG_UINT32 ui32Log2ImportAlignment,
+                 IMG_UINT32 ui32Log2TilingStrideFactor,
                  const IMG_CHAR *pszName,
                  DEVMEM_HEAPCFGID uiHeapBlueprintID,
                  DEVMEM_HEAP **ppsHeapPtr)
@@ -830,6 +969,7 @@
     OSStringCopy(pszStr, pszName);
     psHeap->pszName = pszStr;
 
+    psHeap->uiSize = uiLength;
     psHeap->sBaseAddress = sBaseAddress;
     OSAtomicWrite(&psHeap->hImportCount,0);
 
@@ -882,45 +1022,57 @@
         goto e3;
     }
 
-    psHeap->uiLog2ImportAlignment = ui32Log2ImportAlignment;
-    psHeap->uiLog2Quantum = ui32Log2Quantum;
+	psHeap->uiLog2ImportAlignment = ui32Log2ImportAlignment;
+	psHeap->uiLog2TilingStrideFactor = ui32Log2TilingStrideFactor;
+	psHeap->uiLog2Quantum = ui32Log2Quantum;
 
-    OSSNPrintf(aszBuf, sizeof(aszBuf),
-               "NDM heap '%s' (QVM) ctx:%p",
-               pszName, psCtx);
-    pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
-    if (pszStr == NULL)
-    {
+	if (! OSStringCompare(pszName, RGX_GENERAL_SVM_HEAP_IDENT))
+	{
+		/* The SVM heap normally starts out as this type though
+		   it may transition to DEVMEM_HEAP_TYPE_USER_MANAGED
+		   on platforms with more processor virtual address
+		   bits than device virtual address bits */
+		psHeap->eHeapType = DEVMEM_HEAP_TYPE_KERNEL_MANAGED;
+	}
+	else
+	{
+		psHeap->eHeapType = DEVMEM_HEAP_TYPE_UNKNOWN;
+	}
+
+	OSSNPrintf(aszBuf, sizeof(aszBuf),
+				"NDM heap '%s' (QVM) ctx:%p",
+				pszName, psCtx);
+	pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
+	if (pszStr == NULL)
+	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-        goto e4;
-    }
-    OSStringCopy(pszStr, aszBuf);
-    psHeap->pszQuantizedVMRAName = pszStr;
+		goto e4;
+	}
+	OSStringCopy(pszStr, aszBuf);
+	psHeap->pszQuantizedVMRAName = pszStr;
 
-    psHeap->psQuantizedVMRA = RA_Create(psHeap->pszQuantizedVMRAName,
-                       /* Subsequent import: */
-                                       0, RA_LOCKCLASS_1, NULL, NULL,
-                       (RA_PERARENA_HANDLE) psHeap,
-                       IMG_FALSE);
-
-    if (psHeap->psQuantizedVMRA == NULL)
-    {
-        eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
-        goto e5;
-    }
+	psHeap->psQuantizedVMRA = RA_Create(psHeap->pszQuantizedVMRAName,
+					   /* Subsequent import: */
+									   0, RA_LOCKCLASS_1, NULL, NULL,
+					   (RA_PERARENA_HANDLE) psHeap,
+					   IMG_FALSE);
+	if (psHeap->psQuantizedVMRA == NULL)
+	{
+		eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
+		goto e5;
+	}
 
 	if (!RA_Add(psHeap->psQuantizedVMRA,
-                       (RA_BASE_T)sBaseAddress.uiAddr,
-                       (RA_LENGTH_T)uiLength,
-                       (RA_FLAGS_T)0, /* This RA doesn't use or need flags */
+					   (RA_BASE_T)sBaseAddress.uiAddr,
+					   (RA_LENGTH_T)uiLength,
+					   (RA_FLAGS_T)0, /* This RA doesn't use or need flags */
 				NULL /* per ispan handle */))
 	{
 		RA_Delete(psHeap->psQuantizedVMRA);
-        eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
-        goto e5;
+		eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
+		goto e5;
 	}
 
-
     psHeap->psCtx = psCtx;
 
 
@@ -943,8 +1095,6 @@
 		goto e7;
 	}
 
-	psHeap->eHeapType = DEVMEM_HEAP_TYPE_UNKNOWN;
-
     psHeap->psCtx->uiNumHeaps ++;
     *ppsHeapPtr = psHeap;
 
@@ -962,9 +1112,11 @@
                                        psHeap->hDevMemServerHeap);
     PVR_ASSERT (eError2 == PVRSRV_OK);
  e6:
-    RA_Delete(psHeap->psQuantizedVMRA);
+    if (psHeap->psQuantizedVMRA)
+		RA_Delete(psHeap->psQuantizedVMRA);
  e5:
-    OSFreeMem(psHeap->pszQuantizedVMRAName);
+    if (psHeap->pszQuantizedVMRAName)
+		OSFreeMem(psHeap->pszQuantizedVMRAName);
  e4:
     RA_Delete(psHeap->psSubAllocRA);
  e3:
@@ -993,20 +1145,12 @@
 }
 
 IMG_INTERNAL void
-DevmemExportalignAdjustSizeAndAlign(DEVMEM_HEAP *psHeap, IMG_DEVMEM_SIZE_T *puiSize, IMG_DEVMEM_ALIGN_T *puiAlign)
+DevmemExportalignAdjustSizeAndAlign(IMG_UINT32 uiLog2Quantum,
+                                    IMG_DEVMEM_SIZE_T *puiSize,
+                                    IMG_DEVMEM_ALIGN_T *puiAlign)
 {
 	IMG_DEVMEM_SIZE_T uiSize = *puiSize;
 	IMG_DEVMEM_ALIGN_T uiAlign = *puiAlign;
-	IMG_UINT32 uiLog2Quantum;
-
-	if (psHeap)
-	{
-		uiLog2Quantum = psHeap->uiLog2Quantum;
-	}
-	else
-	{
-		uiLog2Quantum = GET_LOG2_PAGESIZE();
-	}
 
     if ((1ULL << uiLog2Quantum) > uiAlign)
     {
@@ -1022,41 +1166,82 @@
 IMG_INTERNAL PVRSRV_ERROR
 DevmemDestroyHeap(DEVMEM_HEAP *psHeap)
 {
-    PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError;
 	IMG_INT uiImportCount;
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	IMG_BOOL bDoCheck = IMG_TRUE;
+#if defined(__KERNEL__)
+	if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+	{
+		bDoCheck = IMG_FALSE;
+	}
+#endif
+#endif
 
-    if (psHeap == NULL)
-    {
-        return PVRSRV_ERROR_INVALID_PARAMS;
-    }
+	if (psHeap == NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
 
 	uiImportCount = OSAtomicRead(&psHeap->hImportCount);
-    if (uiImportCount > 0)
-    {
-        PVR_DPF((PVR_DBG_ERROR, "%d(%s) leaks remain", uiImportCount, psHeap->pszName));
-        return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
-    }
+	if (uiImportCount > 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%d(%s) leaks remain", uiImportCount, psHeap->pszName));
+#if defined(__KERNEL__)
+#if defined(PVR_RI_DEBUG)
+		PVR_DPF((PVR_DBG_ERROR, "Details of remaining allocated device memory (for all processes):"));
+		RIDumpAllKM();
+#else
+		PVR_DPF((PVR_DBG_ERROR, "Compile with PVR_RI_DEBUG=1 to get a full "
+				"list of all driver allocations."));
+#endif
+#endif
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+		if (bDoCheck)
+#endif
+		{
+			return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
+		}
+	}
+
+	eError = BridgeDevmemIntHeapDestroy(psHeap->psCtx->hDevConnection,
+	                                    psHeap->hDevMemServerHeap);
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	if (bDoCheck)
+#endif
+	{
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: BridgeDevmemIntHeapDestroy failed (%d)",
+			          __func__, eError));
+			return eError;
+		}
+	}
+
+	PVR_ASSERT(psHeap->psCtx->uiNumHeaps > 0);
+	psHeap->psCtx->uiNumHeaps--;
 
 	OSLockDestroy(psHeap->hLock);
 
-    PVR_ASSERT(psHeap->psCtx->uiNumHeaps > 0);
-    psHeap->psCtx->uiNumHeaps --;
+	if (psHeap->psQuantizedVMRA)
+	{
+		RA_Delete(psHeap->psQuantizedVMRA);
+	}
+	if (psHeap->pszQuantizedVMRAName)
+	{
+		OSFreeMem(psHeap->pszQuantizedVMRAName);
+	}
 
-    eError = BridgeDevmemIntHeapDestroy(psHeap->psCtx->hDevConnection,
-                                        psHeap->hDevMemServerHeap);
-    PVR_ASSERT (eError == PVRSRV_OK);
+	RA_Delete(psHeap->psSubAllocRA);
+	OSFreeMem(psHeap->pszSubAllocRAName);
 
-    RA_Delete(psHeap->psQuantizedVMRA);
-    OSFreeMem(psHeap->pszQuantizedVMRAName);
+	OSFreeMem(psHeap->pszName);
 
-    RA_Delete(psHeap->psSubAllocRA);
-    OSFreeMem(psHeap->pszSubAllocRAName);
+	OSDeviceMemSet(psHeap, 0, sizeof(*psHeap));
+	OSFreeMem(psHeap);
 
-    OSFreeMem(psHeap->pszName);
-
-    OSFreeMem(psHeap);
-
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 }
 
 /*****************************************************************************
@@ -1069,21 +1254,29 @@
                   IMG_DEVMEM_SIZE_T uiSize,
                   IMG_DEVMEM_ALIGN_T uiAlign,
                   DEVMEM_FLAGS_T uiFlags,
-                  const IMG_PCHAR pszText,
+                  const IMG_CHAR *pszText,
                   DEVMEM_MEMDESC **ppsMemDescPtr)
 {
-    IMG_BOOL bStatus; /* eError for RA */
-    RA_BASE_T uiAllocatedAddr;
-    RA_LENGTH_T uiAllocatedSize;
-    RA_PERISPAN_HANDLE hImport; /* the "import" from which this sub-allocation came */
-    RA_FLAGS_T uiFlagsForRA;
-    PVRSRV_ERROR eError;
-    DEVMEM_MEMDESC *psMemDesc = NULL;
+	RA_BASE_T uiAllocatedAddr;
+	RA_LENGTH_T uiAllocatedSize;
+	RA_PERISPAN_HANDLE hImport; /* the "import" from which this sub-allocation came */
+	PVRSRV_ERROR eError;
+	DEVMEM_MEMDESC *psMemDesc = NULL;
 	IMG_DEVMEM_OFFSET_T uiOffset = 0;
 	DEVMEM_IMPORT *psImport;
 	IMG_UINT32 ui32CPUCacheLineSize;
 	void *pvAddr;
 
+	IMG_BOOL bImportClean;
+	IMG_BOOL bCPUCleanFlag = PVRSRV_CHECK_CPU_CACHE_CLEAN(uiFlags);
+	IMG_BOOL bZero = PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags);
+	IMG_BOOL bCPUCached = (PVRSRV_CHECK_CPU_CACHE_COHERENT(uiFlags)   ||
+	                       PVRSRV_CHECK_CPU_CACHE_INCOHERENT(uiFlags));
+	IMG_BOOL bGPUCached = (PVRSRV_CHECK_GPU_CACHE_COHERENT(uiFlags)   ||
+	                       PVRSRV_CHECK_GPU_CACHE_INCOHERENT(uiFlags));
+	PVRSRV_CACHE_OP eOp = PVRSRV_CACHE_OP_INVALIDATE;
+	IMG_UINT32	ui32CacheLineSize;
+
 	if (uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
 	{
 		/* Deferred Allocation not supported on SubAllocs*/
@@ -1091,12 +1284,24 @@
 		goto failParams;
 	}
 
-    if (psHeap == NULL || psHeap->psCtx == NULL || ppsMemDescPtr == NULL)
-    {
-        eError = PVRSRV_ERROR_INVALID_PARAMS;
-        goto failParams;
-    }
+	if (psHeap == NULL || psHeap->psCtx == NULL ||ppsMemDescPtr == NULL)
+	{
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto failParams;
+	}
 
+#if defined(__KERNEL__)
+	{
+		/* The hDevConnection holds two different types of pointers depending on the
+		 * address space in which it is used.
+		 * In this instance the variable points to the device node in server */
+		PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)psHeap->psCtx->hDevConnection;
+		ui32CacheLineSize = GET_ROGUE_CACHE_LINE_SIZE(psDevNode->pfnGetDeviceFeatureValue(psDevNode, \
+				RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_BIT_MASK));
+	}
+#else
+	ui32CacheLineSize = ROGUE_CACHE_LINE_SIZE;
+#endif
 
 	/* The following logic makes sure that any cached memory is aligned to both the CPU and GPU.
 	 * To be aligned on both you have to take the Lowest Common Multiple (LCM) of the cache line sizes of each.
@@ -1104,12 +1309,12 @@
 	 * Therefore this algorithm just picks the highest from the CPU, GPU and given alignments.
 	 */
 	ui32CPUCacheLineSize = psHeap->psCtx->ui32CPUCacheLineSize;
-	 /* If the CPU cache line size is larger than the alignment given then it is the lowest common multiple
+	/* If the CPU cache line size is larger than the alignment given then it is the lowest common multiple
 	 * Also checking if the allocation is going to be cached on the CPU
 	 * Currently there is no check for the validity of the cache coherent option.
 	 * In this case, the alignment could be applied but the mode could still fall back to uncached.
 	 */
-	if(ui32CPUCacheLineSize > uiAlign && (((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) || ((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT) || ((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK) == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT)))
+	if (ui32CPUCacheLineSize > uiAlign && bCPUCached)
 	{
 		uiAlign = ui32CPUCacheLineSize;
 	}
@@ -1119,55 +1324,37 @@
 	 * Currently there is no check for the validity of the cache coherent option.
 	 * In this case, the alignment could be applied but the mode could still fall back to uncached.
 	 */
-	if(ROGUE_CACHE_LINE_SIZE > uiAlign && (((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT) || ((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT) || ((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK) == PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT)))
+	if (ui32CacheLineSize > uiAlign && bGPUCached)
 	{
-		uiAlign = ROGUE_CACHE_LINE_SIZE;
+		uiAlign = ui32CacheLineSize;
 	}
 
 	eError = _DevmemValidateParams(uiSize,
-								   uiAlign,
-								   uiFlags);
+	                               uiAlign,
+	                               &uiFlags);
 	if (eError != PVRSRV_OK)
 	{
 		goto failParams;
 	}
 
 	eError =_DevmemMemDescAlloc(&psMemDesc);
-    if (eError != PVRSRV_OK)
-    {
-        goto failMemDescAlloc;
-    }
-
-    /*
-        If zero flag is set we have to have write access to the page.
-    */
-    uiFlags |= (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) ? PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE : 0;
-
-	/*
-		No request for exportable memory so use the RA
-	*/
-    uiFlagsForRA = (RA_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK);
-    /* Check that the cast didn't lose any flags due to different integer widths */
-    PVR_ASSERT(uiFlagsForRA == (uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK));
-
-	/* 
-	   When the RA suballocates memory from a Span it does not zero it. It only zeroes the
-	   memory if it allocates a new Span; but we don't know what is going to happen for this
-	   RA_Alloc call. Therefore, we zero the mem after the allocation below.
-	*/
-	uiFlagsForRA &= ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
-	
-	bStatus = RA_Alloc(psHeap->psSubAllocRA,
-					   uiSize,
-					   uiPreAllocMultiplier,
-					   uiFlagsForRA,
-					   uiAlign,
-					   &uiAllocatedAddr,
-					   &uiAllocatedSize,
-					   &hImport);
-	if (!bStatus)
+	if (eError != PVRSRV_OK)
 	{
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto failMemDescAlloc;
+	}
+
+	/* No request for exportable memory so use the RA */
+	eError = RA_Alloc(psHeap->psSubAllocRA,
+	                  uiSize,
+	                  uiPreAllocMultiplier,
+	                  uiFlags,
+	                  uiAlign,
+	                  pszText,
+	                  &uiAllocatedAddr,
+	                  &uiAllocatedSize,
+	                  &hImport);
+	if (PVRSRV_OK != eError)
+	{
 		goto failDeviceMemAlloc;
 	}
 
@@ -1176,84 +1363,118 @@
 	/* This assignment is assuming the RA returns an hImport where suballocations
 	 * can be made from if uiSize is NOT a page multiple of the passed heap.
 	 *
-	 * So we check if uiSize is a page multiple and mark it as suballocatable
+	 * So we check if uiSize is a page multiple and mark it as exportable
 	 * if it is not.
 	 * */
-	if (uiSize & ((1 << psHeap->uiLog2Quantum) - 1) )
+	if (!(uiSize & ((1 << psHeap->uiLog2Quantum) - 1)) &&
+	     (uiPreAllocMultiplier == RA_NO_IMPORT_MULTIPLIER) )
 	{
-		psImport->uiProperties |= DEVMEM_PROPERTIES_SUBALLOCATABLE;
+		psImport->uiProperties |= DEVMEM_PROPERTIES_EXPORTABLE;
 	}
+	psImport->uiProperties |= DEVMEM_PROPERTIES_SUBALLOCATABLE;
 
 	uiOffset = uiAllocatedAddr - psImport->sDeviceImport.sDevVAddr.uiAddr;
 
-	_DevmemMemDescInit(psMemDesc,
-					   uiOffset,
-					   psImport,
-					   uiSize);
-
-	/* zero the memory */
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
-
+#if defined(PDUMP)
+#if defined(__KERNEL__)
+	PDumpCommentWithFlags(PDUMP_NONE,
+	                      "Suballocated %u Byte for \"%s\" from physical allocation \"%s\"",
+	                      (IMG_UINT32) uiSize, pszText, psImport->pszAnnotation);
+#else
 	{
-		eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvAddr);
-		if (eError != PVRSRV_OK)
-		{
-			goto failZero;
-		}
+		IMG_CHAR pszComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+		OSSNPrintf(pszComment,
+	                   PVRSRV_PDUMP_MAX_COMMENT_SIZE,
+	                   "Suballocated %u Byte for \"%s\" from physical allocation \"%s\"",
+	                   (IMG_UINT32) uiSize,
+	                   pszText,
+	                   psImport->pszAnnotation);
 
-#if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
-		PVR_ASSERT(uiSize<IMG_UINT32_MAX);
+		BridgePVRSRVPDumpComment(psHeap->psCtx->hDevConnection, pszComment, IMG_FALSE);
+	}
+#endif
 #endif
 
-		OSDeviceMemSet(pvAddr, 0x0, (size_t) uiSize);
-	    
-		DevmemReleaseCpuVirtAddr(psMemDesc);
+	_DevmemMemDescInit(psMemDesc,
+	                   uiOffset,
+	                   psImport,
+	                   uiSize);
+
+	bImportClean = ((psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_IMPORT_IS_CLEAN) != 0);
+
+	/* Zero the memory */
+	if (bZero)
+	{
+		/* Has the import been zeroed on allocation and were no suballocations returned to it so far? */
+		bImportClean = bImportClean && ((psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_IMPORT_IS_ZEROED) != 0);
+
+		if(!bImportClean)
+		{
+			eOp = PVRSRV_CACHE_OP_FLUSH;
+
+			eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvAddr);
+			if (eError != PVRSRV_OK)
+			{
+				goto failMaintenance;
+			}
+
+			/* uiSize is a 64-bit quantity whereas the 3rd argument
+			 * to OSDeviceMemSet is a 32-bit quantity on 32-bit systems
+			 * hence a compiler warning of implicit cast and loss of data.
+			 * Added explicit cast and assert to remove warning.
+			 */
+			PVR_ASSERT(uiSize < IMG_UINT32_MAX);
+
+			OSDeviceMemSet(pvAddr, 0x0, (size_t) uiSize);
+
+			DevmemReleaseCpuVirtAddr(psMemDesc);
 
 #if defined(PDUMP)
-		DevmemPDumpLoadZeroMem(psMemDesc, 0, uiSize, PDUMP_FLAGS_CONTINUOUS);
+			DevmemPDumpLoadZeroMem(psMemDesc, 0, uiSize, PDUMP_FLAGS_CONTINUOUS);
 #endif
+		}
 	}
 
-	/* Flush if (cached && (!clean || zeroed) */
-	if (PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT)
+	/* Flush or invalidate */
+	if (bCPUCached && !bImportClean && (bZero || bCPUCleanFlag))
 	{
-		PVRSRV_CACHE_OP eOp = PVRSRV_CACHE_OP_NONE;
-
-		if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
-			eOp = PVRSRV_CACHE_OP_FLUSH;
-		else if (!(psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_IMPORT_IS_CLEAN))
-			eOp = PVRSRV_CACHE_OP_INVALIDATE;
-
-		if (eOp != PVRSRV_CACHE_OP_NONE)
+		/* BridgeCacheOpQueue _may_ be deferred so use BridgeCacheOpExec
+		   to ensure this cache maintenance is actioned immediately */
+		eError = BridgeCacheOpExec (psMemDesc->psImport->hDevConnection,
+		                            psMemDesc->psImport->hPMR,
+		                            psMemDesc->uiOffset,
+		                            psMemDesc->uiAllocSize,
+		                            eOp);
+		if (eError != PVRSRV_OK)
 		{
-			BridgeCacheOpQueue (psMemDesc->psImport->hDevConnection,
-								psMemDesc->psImport->hPMR,
-								psMemDesc->uiOffset,
-								psMemDesc->uiAllocSize,
-								eOp);
+			goto failMaintenance;
 		}
 	}
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
-	 * the allocation gets mapped/unmapped
-	 */
-	OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
+		 * the allocation gets mapped/unmapped
+		 */
+		OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
+	}
 #endif
 
 #if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 	{
 		/* Attach RI information */
 		eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hDevConnection,
-											psMemDesc->psImport->hPMR,
-											OSStringNLength(pszText, RI_MAX_TEXT_LEN),
-											pszText,
-											psMemDesc->uiOffset,
-											uiAllocatedSize,
-											uiAllocatedSize,
-											IMG_FALSE,
-											IMG_FALSE,
-											&(psMemDesc->hRIHandle));
+		                                    psMemDesc->psImport->hPMR,
+		                                    OSStringNLength(pszText, RI_MAX_TEXT_LEN),
+		                                    pszText,
+		                                    psMemDesc->uiOffset,
+		                                    uiAllocatedSize,
+		                                    uiAllocatedSize,
+		                                    IMG_FALSE,
+		                                    IMG_FALSE,
+		                                    &(psMemDesc->hRIHandle));
 		if( eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
@@ -1265,105 +1486,107 @@
 
 	*ppsMemDescPtr = psMemDesc;
 
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 
-    /*
-      error exit paths follow
-    */
+	/*
+	  error exit paths follow
+	 */
 
-failZero:
+failMaintenance:
 	_DevmemMemDescRelease(psMemDesc);
 	psMemDesc = NULL;	/* Make sure we don't do a discard after the release */
 failDeviceMemAlloc:
 	if (psMemDesc)
+	{
 		_DevmemMemDescDiscard(psMemDesc);
+	}
 failMemDescAlloc:
 failParams:
-    PVR_ASSERT(eError != PVRSRV_OK);
+	PVR_ASSERT(eError != PVRSRV_OK);
 	PVR_DPF((PVR_DBG_ERROR,
 			"%s: Failed! Error is %s. Allocation size: %#llX",
 			__func__,
 			PVRSRVGETERRORSTRING(eError),
 			(unsigned long long) uiSize));
-    return eError;
+	return eError;
 }
 
 
 
 IMG_INTERNAL PVRSRV_ERROR
 DevmemAllocateExportable(SHARED_DEV_CONNECTION hDevConnection,
-						 IMG_DEVMEM_SIZE_T uiSize,
-						 IMG_DEVMEM_ALIGN_T uiAlign,
-						 DEVMEM_FLAGS_T uiFlags,
-						 const IMG_PCHAR pszText,
-						 DEVMEM_MEMDESC **ppsMemDescPtr)
+                         IMG_DEVMEM_SIZE_T uiSize,
+                         IMG_DEVMEM_ALIGN_T uiAlign,
+                         IMG_UINT32 uiLog2HeapPageSize,
+                         DEVMEM_FLAGS_T uiFlags,
+                         const IMG_CHAR *pszText,
+                         DEVMEM_MEMDESC **ppsMemDescPtr)
 {
-    PVRSRV_ERROR eError;
-    DEVMEM_MEMDESC *psMemDesc = NULL;
+	PVRSRV_ERROR eError;
+	DEVMEM_MEMDESC *psMemDesc = NULL;
 	DEVMEM_IMPORT *psImport;
-    IMG_UINT32 ui32MappingTable = 0;
+	IMG_UINT32 ui32MappingTable = 0;
 
-	DevmemExportalignAdjustSizeAndAlign(NULL,
-										&uiSize,
-										&uiAlign);
+	DevmemExportalignAdjustSizeAndAlign(uiLog2HeapPageSize,
+	                                    &uiSize,
+	                                    &uiAlign);
 
 	eError = _DevmemValidateParams(uiSize,
-								   uiAlign,
-								   uiFlags);
+	                               uiAlign,
+	                               &uiFlags);
 	if (eError != PVRSRV_OK)
 	{
 		goto failParams;
 	}
 
-
 	eError =_DevmemMemDescAlloc(&psMemDesc);
-    if (eError != PVRSRV_OK)
-    {
-        goto failMemDescAlloc;
-    }
+	if (eError != PVRSRV_OK)
+	{
+		goto failMemDescAlloc;
+	}
 
-	/*
-		Note:
-		In the case of exportable memory we have no heap to
-		query the pagesize from, so we assume host pagesize.
-	*/
 	eError = _AllocateDeviceMemory(hDevConnection,
-								   GET_LOG2_PAGESIZE(),
-								   uiSize,
-								   uiSize,
-								   1,
-								   1,
-								   &ui32MappingTable,
-								   uiAlign,
-								   uiFlags,
-								   IMG_TRUE,
-								   &psImport);
+	                               uiLog2HeapPageSize,
+	                               uiSize,
+	                               uiSize,
+	                               1,
+	                               1,
+	                               &ui32MappingTable,
+	                               uiAlign,
+	                               uiFlags,
+	                               IMG_TRUE,
+	                               pszText,
+	                               &psImport);
 	if (eError != PVRSRV_OK)
 	{
 		goto failDeviceMemAlloc;
 	}
 
 	_DevmemMemDescInit(psMemDesc,
-					   0,
-					   psImport,
-					   uiSize);
+	                   0,
+	                   psImport,
+	                   uiSize);
 
     *ppsMemDescPtr = psMemDesc;
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
-	 * the allocation gets mapped/unmapped
-	 */
-	OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
+		 * the allocation gets mapped/unmapped
+		 */
+		OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
+	}
 #endif
 
 #if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 	{
 		eError = BridgeRIWritePMREntry (psImport->hDevConnection,
-										psImport->hPMR,
-										OSStringNLength(pszText, RI_MAX_TEXT_LEN),
-										(IMG_CHAR *)pszText,
-										psImport->uiSize);
+		                                psImport->hPMR,
+		                                OSStringNLength(pszText, RI_MAX_TEXT_LEN),
+		                                (IMG_CHAR *)pszText,
+		                                psImport->uiSize);
 		if( eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
@@ -1371,15 +1594,15 @@
 
 		 /* Attach RI information */
 		eError = BridgeRIWriteMEMDESCEntry (psImport->hDevConnection,
-											psImport->hPMR,
-											sizeof("^"),
-											"^",
-											psMemDesc->uiOffset,
-											uiSize,
-											uiSize,
-											IMG_FALSE,
-											IMG_TRUE,
-											&psMemDesc->hRIHandle);
+		                                    psImport->hPMR,
+		                                    sizeof("^"),
+		                                    "^",
+		                                    psMemDesc->uiOffset,
+		                                    uiSize,
+		                                    uiSize,
+		                                    IMG_FALSE,
+		                                    IMG_TRUE,
+		                                    &psMemDesc->hRIHandle);
 		if( eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
@@ -1389,116 +1612,133 @@
 	PVR_UNREFERENCED_PARAMETER (pszText);
 #endif /* if defined(PVR_RI_DEBUG) */
 
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 
-    /*
-      error exit paths follow
-    */
+	/*
+	  error exit paths follow
+	 */
 
 failDeviceMemAlloc:
-    _DevmemMemDescDiscard(psMemDesc);
+	_DevmemMemDescDiscard(psMemDesc);
 
 failMemDescAlloc:
 failParams:
-    PVR_ASSERT(eError != PVRSRV_OK);
+	PVR_ASSERT(eError != PVRSRV_OK);
 	PVR_DPF((PVR_DBG_ERROR,
-		"%s: Failed! Error is %s. Allocation size: %#llX",
-		__func__,
-		PVRSRVGETERRORSTRING(eError),
-		(unsigned long long) uiSize));
-    return eError;
+			"%s: Failed! Error is %s. Allocation size: %#llX",
+			__func__,
+			PVRSRVGETERRORSTRING(eError),
+			(unsigned long long) uiSize));
+	return eError;
 }
 
 IMG_INTERNAL PVRSRV_ERROR
 DevmemAllocateSparse(SHARED_DEV_CONNECTION hDevConnection,
-					 IMG_DEVMEM_SIZE_T uiSize,
-					 IMG_DEVMEM_SIZE_T uiChunkSize,
-					 IMG_UINT32 ui32NumPhysChunks,
-					 IMG_UINT32 ui32NumVirtChunks,
-					 IMG_UINT32 *pui32MappingTable,
-					 IMG_DEVMEM_ALIGN_T uiAlign,
-					 DEVMEM_FLAGS_T uiFlags,
-					 const IMG_PCHAR pszText,
-					 DEVMEM_MEMDESC **ppsMemDescPtr)
+                     IMG_DEVMEM_SIZE_T uiSize,
+                     IMG_DEVMEM_SIZE_T uiChunkSize,
+                     IMG_UINT32 ui32NumPhysChunks,
+                     IMG_UINT32 ui32NumVirtChunks,
+                     IMG_UINT32 *pui32MappingTable,
+                     IMG_DEVMEM_ALIGN_T uiAlign,
+                     IMG_UINT32 uiLog2HeapPageSize,
+                     DEVMEM_FLAGS_T uiFlags,
+                     const IMG_CHAR *pszText,
+                     DEVMEM_MEMDESC **ppsMemDescPtr)
 {
-    PVRSRV_ERROR eError;
-    DEVMEM_MEMDESC *psMemDesc = NULL;
+	PVRSRV_ERROR eError;
+	DEVMEM_MEMDESC *psMemDesc = NULL;
 	DEVMEM_IMPORT *psImport;
+	IMG_UINT32 i;
 
-	DevmemExportalignAdjustSizeAndAlign(NULL,
-										&uiSize,
-										&uiAlign);
+	for (i = 0; i < ui32NumPhysChunks; i++)
+	{
+		if (!(pui32MappingTable[i] < ui32NumVirtChunks))
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"A mapping table index exceeds the size of the allocation:"
+					" pui32MappingTable[%u] %u, ui32NumVirtChunks %u ",
+					i,
+					pui32MappingTable[i],
+					ui32NumVirtChunks));
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto failMemDescAlloc;
+		}
+	}
+
+	DevmemExportalignAdjustSizeAndAlign(uiLog2HeapPageSize,
+	                                    &uiSize,
+	                                    &uiAlign);
 
 	eError = _DevmemValidateParams(uiSize,
-								   uiAlign,
-								   uiFlags);
+	                               uiAlign,
+	                               &uiFlags);
 	if (eError != PVRSRV_OK)
 	{
 		goto failParams;
 	}
 
 	eError =_DevmemMemDescAlloc(&psMemDesc);
-    if (eError != PVRSRV_OK)
-    {
-        goto failMemDescAlloc;
-    }
+	if (eError != PVRSRV_OK)
+	{
+		goto failMemDescAlloc;
+	}
 
-	/*
-		Note:
-		In the case of sparse memory we have no heap to
-		query the pagesize from, so we assume host pagesize.
-	*/
-    eError = _AllocateDeviceMemory(hDevConnection,
-								   GET_LOG2_PAGESIZE(),
-								   uiSize,
-								   uiChunkSize,
-								   ui32NumPhysChunks,
-								   ui32NumVirtChunks,
-								   pui32MappingTable,
-								   uiAlign,
-								   uiFlags,
-								   IMG_TRUE,
-								   &psImport);
+	eError = _AllocateDeviceMemory(hDevConnection,
+	                               uiLog2HeapPageSize,
+	                               uiSize,
+	                               uiChunkSize,
+	                               ui32NumPhysChunks,
+	                               ui32NumVirtChunks,
+	                               pui32MappingTable,
+	                               uiAlign,
+	                               uiFlags,
+	                               IMG_TRUE,
+	                               pszText,
+	                               &psImport);
 	if (eError != PVRSRV_OK)
 	{
 		goto failDeviceMemAlloc;
 	}
 
 	_DevmemMemDescInit(psMemDesc,
-					   0,
-					   psImport,
-					   uiSize);
+	                   0,
+	                   psImport,
+	                   uiSize);
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
-	 * the allocation gets mapped/unmapped
-	 */
-	OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
+		 * the allocation gets mapped/unmapped
+		 */
+		OSStringNCopy(psMemDesc->sTraceData.szText, pszText, sizeof(psMemDesc->sTraceData.szText) - 1);
+	}
 #endif
 
 #if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 	{
 		eError = BridgeRIWritePMREntry (psImport->hDevConnection,
-										psImport->hPMR,
-										OSStringNLength(pszText, RI_MAX_TEXT_LEN),
-										(IMG_CHAR *)pszText,
-										psImport->uiSize);
+		                                psImport->hPMR,
+		                                OSStringNLength(pszText, RI_MAX_TEXT_LEN),
+		                                (IMG_CHAR *)pszText,
+		                                psImport->uiSize);
 		if( eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
 		}
 
 		/* Attach RI information */
-    	eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hDevConnection,
-											psMemDesc->psImport->hPMR,
-											sizeof("^"),
-											"^",
-											psMemDesc->uiOffset,
-											uiSize,
-											ui32NumPhysChunks * uiChunkSize,
-											IMG_FALSE,
-											IMG_TRUE,
-											&psMemDesc->hRIHandle);
+		eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hDevConnection,
+		                                    psMemDesc->psImport->hPMR,
+		                                    sizeof("^"),
+		                                    "^",
+		                                    psMemDesc->uiOffset,
+		                                    uiSize,
+		                                    ui32NumPhysChunks * uiChunkSize,
+		                                    IMG_FALSE,
+		                                    IMG_TRUE,
+		                                    &psMemDesc->hRIHandle);
 		if( eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
@@ -1510,24 +1750,24 @@
 
 	*ppsMemDescPtr = psMemDesc;
 
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 
-    /*
-      error exit paths follow
-    */
+	/*
+	  error exit paths follow
+	 */
 
 failDeviceMemAlloc:
-    _DevmemMemDescDiscard(psMemDesc);
+	_DevmemMemDescDiscard(psMemDesc);
 
 failMemDescAlloc:
 failParams:
-    PVR_ASSERT(eError != PVRSRV_OK);
+	PVR_ASSERT(eError != PVRSRV_OK);
 	PVR_DPF((PVR_DBG_ERROR,
 		"%s: Failed! Error is %s. Allocation size: %#llX",
 		__func__,
 		PVRSRVGETERRORSTRING(eError),
 		(unsigned long long) uiSize));
-    return eError;
+	return eError;
 }
 
 IMG_INTERNAL PVRSRV_ERROR
@@ -1705,23 +1945,23 @@
 
 	eError = _DevmemImportStructAlloc(hDevConnection,
 									  &psImport);
-    if (eError != PVRSRV_OK)
-    {
-        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-        goto failImportAlloc;
-    }
+	if (eError != PVRSRV_OK)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto failImportAlloc;
+	}
 
-    /* Get a handle to the PMR (inc refcount) */
+	/* Get a handle to the PMR (inc refcount) */
     eError = BridgePMRImportPMR(hDevConnection,
                                 psCookie->hPMRExportHandle,
                                 psCookie->uiPMRExportPassword,
                                 psCookie->uiSize, /* not trusted - just for sanity checks */
                                 psCookie->uiLog2ContiguityGuarantee, /* not trusted - just for sanity checks */
                                 &hPMR);
-    if (eError != PVRSRV_OK)
-    {
-        goto failImport;
-    }
+	if (eError != PVRSRV_OK)
+	{
+		goto failImport;
+	}
 
 	_DevmemImportStructInit(psImport,
 							psCookie->uiSize,
@@ -1739,6 +1979,7 @@
     *ppsMemDescPtr = psMemDesc;
 
 #if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 	{
 		/* Attach RI information */
 		eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hDevConnection,
@@ -1787,7 +2028,7 @@
 	DEVMEM_IMPORT *psImport = psMemDesc->psImport;
 
 	/* Stop if the allocation might have suballocations. */
-	if (psImport->uiProperties & DEVMEM_PROPERTIES_SUBALLOCATABLE)
+	if (!(psImport->uiProperties & DEVMEM_PROPERTIES_EXPORTABLE))
 	{
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		PVR_DPF((PVR_DBG_ERROR,
@@ -1838,19 +2079,22 @@
 	{
 		psImport->uiProperties |= DEVMEM_PROPERTIES_UNPINNED;
 #if defined(PVR_RI_DEBUG)
-		if (psMemDesc->hRIHandle)
+		if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 		{
-			PVRSRV_ERROR eError2;
-
-			eError2 = BridgeRIUpdateMEMDESCPinning(psMemDesc->psImport->hDevConnection,
-			                                       psMemDesc->hRIHandle,
-			                                       IMG_FALSE);
-
-			if( eError2 != PVRSRV_OK)
+			if (psMemDesc->hRIHandle)
 			{
-				PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCPinningKM failed (eError=%d)",
-				         __func__,
-				         eError));
+				PVRSRV_ERROR eError2;
+
+				eError2 = BridgeRIUpdateMEMDESCPinning(psMemDesc->psImport->hDevConnection,
+				                                       psMemDesc->hRIHandle,
+				                                       IMG_FALSE);
+
+				if( eError2 != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCPinningKM failed (eError=%d)",
+					         __func__,
+					         eError));
+				}
 			}
 		}
 #endif
@@ -1898,19 +2142,22 @@
 	{
 		psImport->uiProperties &= ~DEVMEM_PROPERTIES_UNPINNED;
 #if defined(PVR_RI_DEBUG)
-		if (psMemDesc->hRIHandle)
+		if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 		{
-			PVRSRV_ERROR eError2;
-
-			eError2 = BridgeRIUpdateMEMDESCPinning(psMemDesc->psImport->hDevConnection,
-			                                       psMemDesc->hRIHandle,
-			                                       IMG_TRUE);
-
-			if( eError2 != PVRSRV_OK)
+			if (psMemDesc->hRIHandle)
 			{
-				PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCPinningKM failed (eError=%d)",
-				         __func__,
-				         eError));
+				PVRSRV_ERROR eError2;
+
+				eError2 = BridgeRIUpdateMEMDESCPinning(psMemDesc->psImport->hDevConnection,
+								       psMemDesc->hRIHandle,
+								       IMG_TRUE);
+
+				if( eError2 != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCPinningKM failed (eError=%d)",
+						 __func__,
+						 eError));
+				}
 			}
 		}
 #endif
@@ -1927,22 +2174,44 @@
 	return eError;
 }
 
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetSize(DEVMEM_MEMDESC *psMemDesc, IMG_DEVMEM_SIZE_T* puiSize)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	*puiSize = psMemDesc->uiAllocSize;
+
+	return eError;
+}
+
 /*
 	This function is called for freeing any class of memory
 */
 IMG_INTERNAL void
 DevmemFree(DEVMEM_MEMDESC *psMemDesc)
 {
-#if defined(PVR_RI_DEBUG)
-	if (psMemDesc->hRIHandle)
+	if (psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_SECURE)
 	{
-	    PVRSRV_ERROR eError;
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Please use methods dedicated to secure buffers.",
+				__func__));
+		return;
+	}
 
-	    eError = BridgeRIDeleteMEMDESCEntry(psMemDesc->psImport->hDevConnection,
-					   	   	   	   psMemDesc->hRIHandle);
-		if( eError != PVRSRV_OK)
+#if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_RI))
+	{
+		if (psMemDesc->hRIHandle)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIDeleteMEMDESCEntry failed (eError=%d)", __func__, eError));
+		    PVRSRV_ERROR eError;
+
+		    eError = BridgeRIDeleteMEMDESCEntry(psMemDesc->psImport->hDevConnection,
+									   psMemDesc->hRIHandle);
+			if( eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIDeleteMEMDESCEntry failed (eError=%d)", __func__, eError));
+			}
 		}
 	}
 #endif  /* if defined(PVR_RI_DEBUG) */
@@ -2014,21 +2283,51 @@
     OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	BridgeDevicememHistoryMap(psMemDesc->psImport->hDevConnection,
-						psMemDesc->sDeviceMemDesc.sDevVAddr,
-						psMemDesc->uiAllocSize,
-						psMemDesc->sTraceData.szText);
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		static IMG_BOOL bHaveNewAPI = IMG_TRUE;
+		PVRSRV_ERROR eError;
+
+		if(bHaveNewAPI)
+		{
+			eError = BridgeDevicememHistoryMapNew(psMemDesc->psImport->hDevConnection,
+								psMemDesc->psImport->hPMR,
+								psMemDesc->uiOffset,
+								psMemDesc->sDeviceMemDesc.sDevVAddr,
+								psMemDesc->uiAllocSize,
+								psMemDesc->sTraceData.szText,
+								DevmemGetHeapLog2PageSize(psHeap),
+								psMemDesc->sTraceData.ui32AllocationIndex,
+								&psMemDesc->sTraceData.ui32AllocationIndex);
+
+			if(eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+			{
+				bHaveNewAPI = IMG_FALSE;
+			}
+		}
+
+		if(!bHaveNewAPI)
+		{
+			BridgeDevicememHistoryMap(psMemDesc->psImport->hDevConnection,
+								psMemDesc->sDeviceMemDesc.sDevVAddr,
+								psMemDesc->uiAllocSize,
+								psMemDesc->sTraceData.szText);
+		}
+	}
 #endif
 
 #if defined(PVR_RI_DEBUG)
-	if (psMemDesc->hRIHandle)
-    {
-		 eError = BridgeRIUpdateMEMDESCAddr(psImport->hDevConnection,
-    									   psMemDesc->hRIHandle,
-    									   psImport->sDeviceImport.sDevVAddr);
-		if( eError != PVRSRV_OK)
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_RI))
+	{
+		if (psMemDesc->hRIHandle)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
+			 eError = BridgeRIUpdateMEMDESCAddr(psImport->hDevConnection,
+											   psMemDesc->hRIHandle,
+											   psImport->sDeviceImport.sDevVAddr);
+			if( eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
+			}
 		}
 	}
 #endif
@@ -2109,21 +2408,51 @@
     OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	BridgeDevicememHistoryMap(psMemDesc->psImport->hDevConnection,
-						psMemDesc->sDeviceMemDesc.sDevVAddr,
-						psMemDesc->uiAllocSize,
-						psMemDesc->sTraceData.szText);
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		static IMG_BOOL bHaveNewAPI = IMG_TRUE;
+		PVRSRV_ERROR eError;
+
+		if(bHaveNewAPI)
+		{
+			eError = BridgeDevicememHistoryMapNew(psMemDesc->psImport->hDevConnection,
+								psMemDesc->psImport->hPMR,
+								psMemDesc->uiOffset,
+								psMemDesc->sDeviceMemDesc.sDevVAddr,
+								psMemDesc->uiAllocSize,
+								psMemDesc->sTraceData.szText,
+								DevmemGetHeapLog2PageSize(psHeap),
+								psMemDesc->sTraceData.ui32AllocationIndex,
+								&psMemDesc->sTraceData.ui32AllocationIndex);
+
+			if(eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+			{
+				bHaveNewAPI = IMG_FALSE;
+			}
+		}
+
+		if(!bHaveNewAPI)
+		{
+			BridgeDevicememHistoryMap(psMemDesc->psImport->hDevConnection,
+								psMemDesc->sDeviceMemDesc.sDevVAddr,
+								psMemDesc->uiAllocSize,
+								psMemDesc->sTraceData.szText);
+		}
+	}
 #endif
 
 #if defined(PVR_RI_DEBUG)
-	if (psMemDesc->hRIHandle)
-    {
-		 eError = BridgeRIUpdateMEMDESCAddr(psImport->hDevConnection,
-    									   psMemDesc->hRIHandle,
-    									   psImport->sDeviceImport.sDevVAddr);
-		if( eError != PVRSRV_OK)
+	if(PVRSRVIsBridgeEnabled(psImport->hDevConnection, PVRSRV_BRIDGE_RI))
+	{
+		if (psMemDesc->hRIHandle)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
+			 eError = BridgeRIUpdateMEMDESCAddr(psImport->hDevConnection,
+											   psMemDesc->hRIHandle,
+											   psImport->sDeviceImport.sDevVAddr);
+			if( eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
+			}
 		}
 	}
 #endif
@@ -2197,10 +2526,37 @@
 	if (--psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
 	{
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-		BridgeDevicememHistoryUnmap(psMemDesc->psImport->hDevConnection,
-							psMemDesc->sDeviceMemDesc.sDevVAddr,
-							psMemDesc->uiAllocSize,
-							psMemDesc->sTraceData.szText);
+		if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+		{
+			static IMG_BOOL bHaveNewAPI = IMG_TRUE;
+			PVRSRV_ERROR eError;
+
+			if(bHaveNewAPI)
+			{
+				eError = BridgeDevicememHistoryUnmapNew(psMemDesc->psImport->hDevConnection,
+									psMemDesc->psImport->hPMR,
+									psMemDesc->uiOffset,
+									psMemDesc->sDeviceMemDesc.sDevVAddr,
+									psMemDesc->uiAllocSize,
+									psMemDesc->sTraceData.szText,
+									DevmemGetHeapLog2PageSize(psMemDesc->psImport->sDeviceImport.psHeap),
+									psMemDesc->sTraceData.ui32AllocationIndex,
+									&psMemDesc->sTraceData.ui32AllocationIndex);
+
+				if(eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+				{
+					bHaveNewAPI = IMG_FALSE;
+				}
+			}
+
+			if(!bHaveNewAPI)
+			{
+				BridgeDevicememHistoryUnmap(psMemDesc->psImport->hDevConnection,
+									psMemDesc->sDeviceMemDesc.sDevVAddr,
+									psMemDesc->uiAllocSize,
+									psMemDesc->sTraceData.szText);
+			}
+		}
 #endif
 		_DevmemImportStructDevUnmap(psMemDesc->psImport);
 		OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
@@ -2219,9 +2575,13 @@
 {
 	PVRSRV_ERROR eError;
 
-	/* Do not try to map unpinned memory */
-	if (psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_UNPINNED)
+	if ( psMemDesc->psImport->uiProperties &
+	    (DEVMEM_PROPERTIES_UNPINNED | DEVMEM_PROPERTIES_SECURE) )
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Allocation is currently unpinned or a secure buffer. "
+				"Not possible to map to CPU!",
+				__func__));
 		eError = PVRSRV_ERROR_INVALID_MAP_REQUEST;
 		goto failFlags;
 	}
@@ -2367,12 +2727,19 @@
 	return PVRSRV_OK;
 }
 
+IMG_INTERNAL IMG_HANDLE
+DevmemGetConnection(DEVMEM_MEMDESC *psMemDesc)
+{
+	return psMemDesc->psImport->hDevConnection;
+}
+
 IMG_INTERNAL PVRSRV_ERROR
 DevmemLocalImport(IMG_HANDLE hBridge,
 				  IMG_HANDLE hExtHandle,
 				  DEVMEM_FLAGS_T uiFlags,
 				  DEVMEM_MEMDESC **ppsMemDescPtr,
-				  IMG_DEVMEM_SIZE_T *puiSizePtr)
+				  IMG_DEVMEM_SIZE_T *puiSizePtr,
+				  const IMG_CHAR *pszAnnotation)
 {
     DEVMEM_MEMDESC *psMemDesc = NULL;
     DEVMEM_IMPORT *psImport;
@@ -2385,7 +2752,7 @@
     {
         eError = PVRSRV_ERROR_INVALID_PARAMS;
         goto failParams;
-    }	
+    }
 
 	eError =_DevmemMemDescAlloc(&psMemDesc);
     if (eError != PVRSRV_OK)
@@ -2401,7 +2768,7 @@
         goto failImportAlloc;
     }
 
-	/* Get the PMR handle and it's size from the server */
+	/* Get the PMR handle and its size from the server */
 	eError = BridgePMRLocalImportPMR(hBridge,
 									 hExtHandle,
 									 &hPMR,
@@ -2430,15 +2797,18 @@
 		*puiSizePtr = uiSize;
 
 #if defined(PVR_RI_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_RI))
 	{
-		/* Attach RI information */
+		/* Attach RI information.
+		 * Set backed size to 0 since this allocation has been allocated
+		 * by the same process and has been accounted for. */
 		eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hDevConnection,
 											psMemDesc->psImport->hPMR,
 											sizeof("^"),
 											"^",
 											psMemDesc->uiOffset,
 											psMemDesc->psImport->uiSize,
-											psMemDesc->psImport->uiSize,
+											0,
 											IMG_TRUE,
 											IMG_FALSE,
 											&(psMemDesc->hRIHandle));
@@ -2448,6 +2818,19 @@
 		}
 	}
 #endif /* if defined(PVR_RI_DEBUG) */
+
+#if defined(SUPPORT_PAGE_FAULT_DEBUG)
+	if(PVRSRVIsBridgeEnabled(psMemDesc->psImport->hDevConnection, PVRSRV_BRIDGE_DEVICEMEMHISTORY))
+	{
+		/* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
+		* the allocation gets mapped/unmapped
+		*/
+		OSStringNCopy(psMemDesc->sTraceData.szText, pszAnnotation, sizeof(psMemDesc->sTraceData.szText) - 1);
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(pszAnnotation);
+#endif
+
 	return PVRSRV_OK;
 
 failImport:
@@ -2477,8 +2860,45 @@
 }
 
 IMG_INTERNAL IMG_UINT32
-DevmemGetHeapLog2ImportAlignment(DEVMEM_HEAP *psHeap)
+DevmemGetHeapTilingProperties(DEVMEM_HEAP *psHeap,
+                              IMG_UINT32 *puiLog2ImportAlignment,
+                              IMG_UINT32 *puiLog2TilingStrideFactor)
 {
-	return psHeap->uiLog2ImportAlignment;
+	*puiLog2ImportAlignment = psHeap->uiLog2ImportAlignment;
+	*puiLog2TilingStrideFactor = psHeap->uiLog2TilingStrideFactor;
+	return PVRSRV_OK;
 }
 
+/**************************************************************************/ /*!
+@Function       RegisterDevMemPFNotify
+@Description    Registers that the application wants to be signaled when a page
+                fault occurs.
+
+@Input          psContext      Memory context the process that would like to
+                               be notified about.
+@Input          ui32PID        The PID  of the calling process.
+@Input          bRegister      If true, register. If false, de-register.
+@Return         PVRSRV_ERROR:  PVRSRV_OK on success. Otherwise, a PVRSRV_
+                               error code
+*/ /***************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR
+RegisterDevmemPFNotify(DEVMEM_CONTEXT *psContext,
+                       IMG_UINT32     ui32PID,
+                       IMG_BOOL       bRegister)
+{
+	PVRSRV_ERROR eError;
+
+	eError = BridgeDevmemIntRegisterPFNotifyKM(psContext->hDevConnection,
+	                                           psContext->hDevMemServerContext,
+	                                           ui32PID,
+	                                           bRegister);
+	if (eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Bridge Call Failed: This could suggest a UM/KM miss-match (%d)",
+		         __func__,
+		         (IMG_INT)(eError)));
+	}
+
+	return eError;
+}
diff --git a/drivers/staging/imgtec/rogue/devicemem.h b/drivers/staging/imgtec/rogue/devicemem.h
index 9fbf918..bcbf5a6 100644
--- a/drivers/staging/imgtec/rogue/devicemem.h
+++ b/drivers/staging/imgtec/rogue/devicemem.h
@@ -112,16 +112,6 @@
 #include "device_connection.h"
 
 
-/* Use GET and SET function to access this */
-IMG_INTERNAL extern IMG_UINT32  g_uiLog2PageSize;
-
-#define GET_LOG2_PAGESIZE() ( (const IMG_UINT32) g_uiLog2PageSize )
-#define SET_LOG2_PAGESIZE(ui32Log2PageSize) \
-	{ \
-		PVR_ASSERT( (ui32Log2PageSize > 11) && (ui32Log2PageSize < 22) ); \
-		g_uiLog2PageSize = (IMG_UINT32) ui32Log2PageSize; \
-	}
-
 typedef IMG_UINT32 DEVMEM_HEAPCFGID;
 #define DEVMEM_HEAPCFG_FORCLIENTS 0
 #define DEVMEM_HEAPCFG_META 1
@@ -173,6 +163,13 @@
 IMG_INTERNAL PVRSRV_ERROR
 DevmemPin(DEVMEM_MEMDESC *psMemDesc);
 
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetHeapInt(DEVMEM_HEAP *psHeap,
+				 IMG_HANDLE *phDevmemHeap);
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetSize(DEVMEM_MEMDESC *psMemDesc,
+			  IMG_DEVMEM_SIZE_T* puiSize);
 
 /*
  * DevmemCreateContext()
@@ -275,6 +272,9 @@
                  IMG_UINT32 ui32Log2Quantum,
                  /* The minimum import alignment for this heap */
                  IMG_UINT32 ui32Log2ImportAlignment,
+                 /* (For tiling heaps) the factor to use to convert
+                    alignment to optimum buffer stride */
+                 IMG_UINT32 ui32Log2TilingStrideFactor,
                  /* Name of heap for debug */
                  /* N.B.  Okay to exist on caller's stack - this
                     func takes a copy if it needs it. */
@@ -297,7 +297,9 @@
  * Compute the Size and Align passed to avoid suballocations (used when allocation with PVRSRV_MEMALLOCFLAG_EXPORTALIGN)
  */
 IMG_INTERNAL void
-DevmemExportalignAdjustSizeAndAlign(DEVMEM_HEAP *psHeap, IMG_DEVMEM_SIZE_T *puiSize, IMG_DEVMEM_ALIGN_T *puiAlign);
+DevmemExportalignAdjustSizeAndAlign(IMG_UINT32 uiLog2Quantum,
+                                    IMG_DEVMEM_SIZE_T *puiSize,
+                                    IMG_DEVMEM_ALIGN_T *puiAlign);
 
 /*
  * DevmemSubAllocate()
@@ -332,7 +334,7 @@
                   IMG_DEVMEM_SIZE_T uiSize,
                   IMG_DEVMEM_ALIGN_T uiAlign,
                   DEVMEM_FLAGS_T uiFlags,
-                  const IMG_PCHAR pszText,
+                  const IMG_CHAR *pszText,
                   DEVMEM_MEMDESC **ppsMemDescPtr);
 
 #define DevmemAllocate(...) \
@@ -340,32 +342,33 @@
 
 PVRSRV_ERROR
 DevmemAllocateExportable(SHARED_DEV_CONNECTION hDevConnection,
-						 IMG_DEVMEM_SIZE_T uiSize,
-						 IMG_DEVMEM_ALIGN_T uiAlign,
-						 DEVMEM_FLAGS_T uiFlags,
-						 const IMG_PCHAR pszText,
-						 DEVMEM_MEMDESC **ppsMemDescPtr);
+                         IMG_DEVMEM_SIZE_T uiSize,
+                         IMG_DEVMEM_ALIGN_T uiAlign,
+                         IMG_UINT32 uiLog2HeapPageSize,
+                         DEVMEM_FLAGS_T uiFlags,
+                         const IMG_CHAR *pszText,
+                         DEVMEM_MEMDESC **ppsMemDescPtr);
 
 PVRSRV_ERROR
 DeviceMemChangeSparse(DEVMEM_MEMDESC *psMemDesc,
-					  IMG_UINT32 ui32AllocPageCount,
-					  IMG_UINT32 *paui32AllocPageIndices,
-					  IMG_UINT32 ui32FreePageCount,
-					  IMG_UINT32 *pauiFreePageIndices,
-					  SPARSE_MEM_RESIZE_FLAGS uiFlags,
-					  IMG_UINT32 *pui32Status);
+                      IMG_UINT32 ui32AllocPageCount,
+                      IMG_UINT32 *paui32AllocPageIndices,
+                      IMG_UINT32 ui32FreePageCount,
+                      IMG_UINT32 *pauiFreePageIndices,
+                      SPARSE_MEM_RESIZE_FLAGS uiFlags);
 
 PVRSRV_ERROR
 DevmemAllocateSparse(SHARED_DEV_CONNECTION hDevConnection,
-					 IMG_DEVMEM_SIZE_T uiSize,
-					 IMG_DEVMEM_SIZE_T uiChunkSize,
-					 IMG_UINT32 ui32NumPhysChunks,
-					 IMG_UINT32 ui32NumVirtChunks,
-					 IMG_UINT32 *pui32MappingTable,
-					 IMG_DEVMEM_ALIGN_T uiAlign,
-					 DEVMEM_FLAGS_T uiFlags,
-					 const IMG_PCHAR pszText,
-					 DEVMEM_MEMDESC **ppsMemDescPtr);
+                     IMG_DEVMEM_SIZE_T uiSize,
+                     IMG_DEVMEM_SIZE_T uiChunkSize,
+                     IMG_UINT32 ui32NumPhysChunks,
+                     IMG_UINT32 ui32NumVirtChunks,
+                     IMG_UINT32 *pui32MappingTable,
+                     IMG_DEVMEM_ALIGN_T uiAlign,
+                     IMG_UINT32 uiLog2HeapPageSize,
+                     DEVMEM_FLAGS_T uiFlags,
+                     const IMG_CHAR *pszText,
+                     DEVMEM_MEMDESC **ppsMemDescPtr);
 
 /*
  * DevmemFree()
@@ -551,7 +554,8 @@
                   IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
                   IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
                   IMG_UINT32 *puiLog2DataPageSize,
-                  IMG_UINT32 *puiLog2ImportAlignmentOut);
+                  IMG_UINT32 *puiLog2ImportAlignmentOut,
+                  IMG_UINT32 *puiLog2TilingStrideFactor);
 
 /*
  * Devmem_FindHeapByName()
@@ -596,12 +600,16 @@
 DevmemGetFlags(DEVMEM_MEMDESC *psMemDesc,
 				DEVMEM_FLAGS_T *puiFlags);
 
+IMG_INTERNAL IMG_HANDLE
+DevmemGetConnection(DEVMEM_MEMDESC *psMemDesc);
+
 PVRSRV_ERROR
 DevmemLocalImport(IMG_HANDLE hBridge,
 				  IMG_HANDLE hExtHandle,
 				  DEVMEM_FLAGS_T uiFlags,
 				  DEVMEM_MEMDESC **ppsMemDescPtr,
-				  IMG_DEVMEM_SIZE_T *puiSizePtr);
+				  IMG_DEVMEM_SIZE_T *puiSizePtr,
+				  const IMG_CHAR *pszAnnotation);
 
 IMG_INTERNAL PVRSRV_ERROR
 DevmemIsDevVirtAddrValid(DEVMEM_CONTEXT *psContext,
@@ -614,11 +622,30 @@
 IMG_UINT32
 DevmemGetHeapLog2PageSize(DEVMEM_HEAP *psHeap);
 
-/* DevmemGetHeapLog2ImportAlignment()
+/* DevmemGetHeapTilingProperties()
  *
- * Get the import alignment used for a certain heap.
+ * Get the import alignment and tiling stride factor used for a certain heap.
  */
 IMG_UINT32
-DevmemGetHeapLog2ImportAlignment(DEVMEM_HEAP *psHeap);
+DevmemGetHeapTilingProperties(DEVMEM_HEAP *psHeap,
+                              IMG_UINT32 *puiLog2ImportAlignment,
+                              IMG_UINT32 *puiLog2TilingStrideFactor);
+
+/**************************************************************************/ /*!
+@Function       RegisterDevMemPFNotify
+@Description    Registers that the application wants to be signaled when a page
+                fault occurs.
+
+@Input          psContext      Memory context the process that would like to
+                               be notified about.
+@Input          ui32PID        The PID  of the calling process.
+@Input          bRegister      If true, register. If false, de-register.
+@Return         PVRSRV_ERROR:  PVRSRV_OK on success. Otherwise, a PVRSRV_
+                               error code
+*/ /***************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR
+RegisterDevmemPFNotify(DEVMEM_CONTEXT *psContext,
+                       IMG_UINT32     ui32PID,
+                       IMG_BOOL       bRegister);
 
 #endif /* #ifndef SRVCLIENT_DEVICEMEM_CLIENT_H */
diff --git a/drivers/staging/imgtec/rogue/devicemem_heapcfg.c b/drivers/staging/imgtec/rogue/devicemem_heapcfg.c
index d14be4d..bb5f566 100644
--- a/drivers/staging/imgtec/rogue/devicemem_heapcfg.c
+++ b/drivers/staging/imgtec/rogue/devicemem_heapcfg.c
@@ -134,5 +134,11 @@
     *puiLog2DataPageSizeOut = psHeapBlueprint->uiLog2DataPageSize;
     *puiLog2ImportAlignmentOut = psHeapBlueprint->uiLog2ImportAlignment;
 
-    return PVRSRV_OK;    
+    /* REL/1.8 maintain bridge compatibility
+     *   4:0 - uiLog2ImportAlignment (13--20)
+     * 18:16 - uiLog2TilingStrideFactor (3--4)
+     */
+    *puiLog2ImportAlignmentOut |= (psHeapBlueprint->uiLog2TilingStrideFactor << 16);
+
+    return PVRSRV_OK;
 }
diff --git a/drivers/staging/imgtec/rogue/devicemem_heapcfg.h b/drivers/staging/imgtec/rogue/devicemem_heapcfg.h
index c74ddd8..f8a42bf 100644
--- a/drivers/staging/imgtec/rogue/devicemem_heapcfg.h
+++ b/drivers/staging/imgtec/rogue/devicemem_heapcfg.h
@@ -44,12 +44,16 @@
 #ifndef __DEVICEMEMHEAPCFG_H__
 #define __DEVICEMEMHEAPCFG_H__
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 
 
+/* FIXME: Find a better way of defining _PVRSRV_DEVICE_NODE_ */
 struct _PVRSRV_DEVICE_NODE_;
+/* FIXME: Find a better way of defining _CONNECTION_DATA_ */
 struct _CONNECTION_DATA_;
 
 
@@ -66,40 +70,45 @@
 /* blueprint for a single heap */
 typedef struct _DEVMEM_HEAP_BLUEPRINT_
 {
-    /* Name of this heap - for debug purposes, and perhaps for lookup
-       by name? */
-    const IMG_CHAR *pszName;
+	/* Name of this heap - for debug purposes, and perhaps for lookup
+	by name? */
+	const IMG_CHAR *pszName;
 
-    /* Virtual address of the beginning of the heap.  This _must_ be a
-       multiple of the data page size for the heap.  It is
-       _recommended_ that it be coarser than that - especially, it
-       should begin on a boundary appropriate to the MMU for the
-       device.  For Rogue, this is a Page Directory boundary, or 1GB
-       (virtual address a multiple of 0x0040000000). */
-    IMG_DEV_VIRTADDR sHeapBaseAddr;
+	/* Virtual address of the beginning of the heap.  This _must_ be a
+	multiple of the data page size for the heap.  It is
+	_recommended_ that it be coarser than that - especially, it
+	should begin on a boundary appropriate to the MMU for the
+	device.  For Rogue, this is a Page Directory boundary, or 1GB
+	(virtual address a multiple of 0x0040000000). */
+	IMG_DEV_VIRTADDR sHeapBaseAddr;
 
-    /* Length of the heap.  Given that the END address of the heap has
-       a similar restriction to that of the _beginning_ of the heap.
-       That is the heap length _must_ be a whole number of data pages.
-       Again, the recommendation is that it ends on a 1GB boundary.
-       Again, this is not essential, but we do know that (at the time
-       of writing) the current implementation of mmu_common.c is such
-       that no two heaps may share a page directory, thus the
-       remaining virtual space would be wasted if the length were not
-       a multiple of 1GB */
-    IMG_DEVMEM_SIZE_T uiHeapLength;
+	/* Length of the heap.  Given that the END address of the heap has
+	a similar restriction to that of the _beginning_ of the heap.
+	That is the heap length _must_ be a whole number of data pages.
+	Again, the recommendation is that it ends on a 1GB boundary.
+	Again, this is not essential, but we do know that (at the time
+	of writing) the current implementation of mmu_common.c is such
+	that no two heaps may share a page directory, thus the
+	remaining virtual space would be wasted if the length were not
+	a multiple of 1GB */
+	IMG_DEVMEM_SIZE_T uiHeapLength;
 
-    /* Data page size.  This is the page size that is going to get
-       programmed into the MMU, so it needs to be a valid one for the
-       device.  Importantly, the start address and length _must_ be
-       multiples of this page size.  Note that the page size is
-       specified as the log 2 relative to 1 byte (e.g. 12 indicates
-       4kB) */
-    IMG_UINT32 uiLog2DataPageSize;
+	/* Data page size.  This is the page size that is going to get
+	programmed into the MMU, so it needs to be a valid one for the
+	device.  Importantly, the start address and length _must_ be
+	multiples of this page size.  Note that the page size is
+	specified as the log 2 relative to 1 byte (e.g. 12 indicates
+	4kB) */
+	IMG_UINT32 uiLog2DataPageSize;
 
-    /* Import alignment.  Force imports to this heap to be
-       aligned to at least this value */
-    IMG_UINT32 uiLog2ImportAlignment;
+	/* Import alignment.  Force imports to this heap to be
+	aligned to at least this value */
+	IMG_UINT32 uiLog2ImportAlignment;
+
+	/* Tiled heaps have an optimum byte-stride, this can be derived from
+	the heap alignment and tiling mode. This is abstracted here such that
+	Log2ByteStride = Log2Alignment - Log2TilingStrideFactor */
+	IMG_UINT32 uiLog2TilingStrideFactor;
 } DEVMEM_HEAP_BLUEPRINT;
 
 /* entire named heap config */
diff --git a/drivers/staging/imgtec/rogue/devicemem_history_server.c b/drivers/staging/imgtec/rogue/devicemem_history_server.c
index 60c8b5b..e6d1d35 100644
--- a/drivers/staging/imgtec/rogue/devicemem_history_server.c
+++ b/drivers/staging/imgtec/rogue/devicemem_history_server.c
@@ -46,35 +46,156 @@
 #include "pvrsrv.h"
 #include "pvrsrv_device.h"
 #include "pvr_debug.h"
-#include "dllist.h"
-#include "syscommon.h"
 #include "devicemem_server.h"
 #include "lock.h"
 #include "devicemem_history_server.h"
+#include "pdump_km.h"
 
-/* a device memory allocation */
-typedef struct _DEVICEMEM_HISTORY_ALLOCATION_
+#define ALLOCATION_LIST_NUM_ENTRIES 10000
+
+/* data type to hold an allocation index.
+ * we make it 16 bits wide if possible
+ */
+#if ALLOCATION_LIST_NUM_ENTRIES <= 0xFFFF
+typedef uint16_t ALLOC_INDEX_T;
+#else
+typedef uint32_t ALLOC_INDEX_T;
+#endif
+
+/* a record describing a single allocation known to DeviceMemHistory.
+ * this is an element in a doubly linked list of allocations
+ */
+typedef struct _RECORD_ALLOCATION_
 {
+	/* time when this RECORD_ALLOCATION was created/initialised */
+	IMG_UINT64 ui64CreationTime;
+	/* serial number of the PMR relating to this allocation */
+	IMG_UINT64 ui64Serial;
+	/* base DevVAddr of this allocation */
 	IMG_DEV_VIRTADDR sDevVAddr;
+	/* size in bytes of this allocation */
 	IMG_DEVMEM_SIZE_T uiSize;
-	IMG_CHAR szString[DEVICEMEM_HISTORY_TEXT_BUFSZ];
-	IMG_UINT64 ui64Time;
-	/* FALSE if this allocation has been freed */
-	IMG_BOOL bAllocated;
+	/* Log2 page size of this allocation's GPU pages */
+	IMG_UINT32 ui32Log2PageSize;
+	/* Process ID (PID) this allocation belongs to */
 	IMG_PID uiPID;
-} DEVICEMEM_HISTORY_ALLOCATION;
+	/* index of previous allocation in the list */
+	ALLOC_INDEX_T ui32Prev;
+	/* index of next allocation in the list */
+	ALLOC_INDEX_T ui32Next;
+	/* annotation/name of this allocation */
+	IMG_CHAR szName[DEVICEMEM_HISTORY_TEXT_BUFSZ];
+} RECORD_ALLOCATION;
 
-/* this number of entries makes the history buffer allocation just under 2MB */
-#define DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN 29127
+/* each command in the circular buffer is prefixed with an 8-bit value
+ * denoting the command type
+ */
+typedef enum _COMMAND_TYPE_
+{
+	COMMAND_TYPE_NONE,
+	COMMAND_TYPE_TIMESTAMP,
+	COMMAND_TYPE_MAP_ALL,
+	COMMAND_TYPE_UNMAP_ALL,
+	COMMAND_TYPE_MAP_RANGE,
+	COMMAND_TYPE_UNMAP_RANGE,
+	/* sentinel value */
+	COMMAND_TYPE_COUNT,
+} COMMAND_TYPE;
 
-#define DECREMENT_WITH_WRAP(value, sz) ((value) ? ((value) - 1) : ((sz) - 1))
+/* Timestamp command:
+ * This command is inserted into the circular buffer to provide an updated
+ * timestamp.
+ * The nanosecond-accuracy timestamp is packed into a 56-bit integer, in order
+ * for the whole command to fit into 8 bytes.
+ */
+typedef struct _COMMAND_TIMESTAMP_
+{
+	IMG_UINT8 aui8TimeNs[7];
+} COMMAND_TIMESTAMP;
+
+/* MAP_ALL command:
+ * This command denotes the allocation at the given index was wholly mapped
+ * in to the GPU MMU
+ */
+typedef struct _COMMAND_MAP_ALL_
+{
+	ALLOC_INDEX_T uiAllocIndex;
+} COMMAND_MAP_ALL;
+
+/* UNMAP_ALL command:
+ * This command denotes the allocation at the given index was wholly unmapped
+ * from the GPU MMU
+ * Note: COMMAND_MAP_ALL and COMMAND_UNMAP_ALL commands have the same layout.
+ */
+typedef COMMAND_MAP_ALL COMMAND_UNMAP_ALL;
+
+/* packing attributes for the MAP_RANGE command */
+#define MAP_RANGE_MAX_START ((1 << 18) - 1)
+#define MAP_RANGE_MAX_RANGE ((1 << 12) - 1)
+
+/* MAP_RANGE command:
+ * Denotes a range of pages within the given allocation being mapped.
+ * The range is expressed as [Page Index] + [Page Count]
+ * This information is packed into a 40-bit integer, in order to make
+ * the command size 8 bytes.
+ */
+
+typedef struct _COMMAND_MAP_RANGE_
+{
+	IMG_UINT8 aui8Data[5];
+	ALLOC_INDEX_T uiAllocIndex;
+} COMMAND_MAP_RANGE;
+
+/* UNMAP_RANGE command:
+ * Denotes a range of pages within the given allocation being mapped.
+ * The range is expressed as [Page Index] + [Page Count]
+ * This information is packed into a 40-bit integer, in order to make
+ * the command size 8 bytes.
+ * Note: COMMAND_MAP_RANGE and COMMAND_UNMAP_RANGE commands have the same layout.
+ */
+typedef COMMAND_MAP_RANGE COMMAND_UNMAP_RANGE;
+
+/* wrapper structure for a command */
+typedef struct _COMMAND_WRAPPER_
+{
+	IMG_UINT8 ui8Type;
+	union {
+		COMMAND_TIMESTAMP sTimeStamp;
+		COMMAND_MAP_ALL sMapAll;
+		COMMAND_UNMAP_ALL sUnmapAll;
+		COMMAND_MAP_RANGE sMapRange;
+		COMMAND_UNMAP_RANGE sUnmapRange;
+	} u;
+} COMMAND_WRAPPER;
+
+/* target size for the circular buffer of commands */
+#define CIRCULAR_BUFFER_SIZE_KB 2048
+/* turn the circular buffer target size into a number of commands */
+#define CIRCULAR_BUFFER_NUM_COMMANDS ((CIRCULAR_BUFFER_SIZE_KB * 1024) / sizeof(COMMAND_WRAPPER))
+
+/* index value denoting the end of a list */
+#define END_OF_LIST 0xFFFFFFFF
+#define ALLOC_INDEX_TO_PTR(idx) (&(gsDevicememHistoryData.sRecords.pasAllocations[idx]))
+#define CHECK_ALLOC_INDEX(idx) (idx < ALLOCATION_LIST_NUM_ENTRIES)
+
+/* wrapper structure for the allocation records and the commands circular buffer */
+typedef struct _RECORDS_
+{
+	RECORD_ALLOCATION *pasAllocations;
+	IMG_UINT32 ui32AllocationsListHead;
+
+	IMG_UINT32 ui32Head;
+	IMG_UINT32 ui32Tail;
+	COMMAND_WRAPPER *pasCircularBuffer;;
+} RECORDS;
 
 typedef struct _DEVICEMEM_HISTORY_DATA_
 {
-	IMG_UINT32 ui32Head;
-	DEVICEMEM_HISTORY_ALLOCATION *psAllocations;
-	POS_LOCK hLock;
+	/* debugfs entry */
 	void *pvStatsEntry;
+
+	RECORDS sRecords;
+	POS_LOCK hLock;
 } DEVICEMEM_HISTORY_DATA;
 
 static DEVICEMEM_HISTORY_DATA gsDevicememHistoryData = { 0 };
@@ -89,13 +210,11 @@
 	OSLockRelease(gsDevicememHistoryData.hLock);
 }
 
-/* given a time stamp, calculate the age in nanoseconds (relative to now) */
-static IMG_UINT64 _CalculateAge(IMG_UINT64 ui64Then)
+/* given a time stamp, calculate the age in nanoseconds */
+static IMG_UINT64 _CalculateAge(IMG_UINT64 ui64Now,
+						IMG_UINT64 ui64Then,
+						IMG_UINT64 ui64Max)
 {
-	IMG_UINT64 ui64Now;
-
-	ui64Now = OSClockns64();
-
 	if(ui64Now >= ui64Then)
 	{
 		/* no clock wrap */
@@ -104,30 +223,1544 @@
 	else
 	{
 		/* clock has wrapped */
-		return ((~(IMG_UINT64) 0) - ui64Then) + ui64Now + 1;
+		return (ui64Max - ui64Then) + ui64Now + 1;
 	}
 }
 
-static void DeviceMemHistoryFmt(IMG_UINT32 ui32Off, IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN])
+/* AcquireCBSlot:
+ * Acquire the next slot in the circular buffer and
+ * move the circular buffer head along by one
+ * Returns a pointer to the acquired slot.
+ */
+static COMMAND_WRAPPER *AcquireCBSlot(void)
 {
-	DEVICEMEM_HISTORY_ALLOCATION *psAlloc;
+	COMMAND_WRAPPER *psSlot;
 
-	psAlloc = &gsDevicememHistoryData.psAllocations[ui32Off % DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN];
+	psSlot = &gsDevicememHistoryData.sRecords.pasCircularBuffer[gsDevicememHistoryData.sRecords.ui32Head];
+
+	gsDevicememHistoryData.sRecords.ui32Head =
+		(gsDevicememHistoryData.sRecords.ui32Head + 1)
+				% CIRCULAR_BUFFER_NUM_COMMANDS;
+
+	return psSlot;
+}
+
+/* TimeStampPack:
+ * Packs the given timestamp value into the COMMAND_TIMESTAMP structure.
+ * This takes a 64-bit nanosecond timestamp and packs it in to a 56-bit
+ * integer in the COMMAND_TIMESTAMP command.
+ */
+static void TimeStampPack(COMMAND_TIMESTAMP *psTimeStamp, IMG_UINT64 ui64Now)
+{
+	IMG_UINT32 i;
+
+	for(i = 0; i < IMG_ARR_NUM_ELEMS(psTimeStamp->aui8TimeNs); i++)
+	{
+		psTimeStamp->aui8TimeNs[i] = ui64Now & 0xFF;
+		ui64Now >>= 8;
+	}
+}
+
+/* packing a 64-bit nanosecond into a 7-byte integer loses the
+ * top 8 bits of data. This must be taken into account when
+ * comparing a full timestamp against an unpacked timestamp
+ */
+#define TIME_STAMP_MASK ((1LLU << 56) - 1)
+#define DO_TIME_STAMP_MASK(ns64) (ns64 & TIME_STAMP_MASK)
+
+/* TimeStampUnpack:
+ * Unpack the timestamp value from the given COMMAND_TIMESTAMP command
+ */
+static IMG_UINT64 TimeStampUnpack(COMMAND_TIMESTAMP *psTimeStamp)
+{
+	IMG_UINT64 ui64TimeNs = 0;
+	IMG_UINT32 i;
+
+	for(i = IMG_ARR_NUM_ELEMS(psTimeStamp->aui8TimeNs); i > 0; i--)
+	{
+		ui64TimeNs <<= 8;
+		ui64TimeNs |= psTimeStamp->aui8TimeNs[i - 1];
+	}
+
+	return ui64TimeNs;
+}
+
+#if defined(PDUMP)
+
+static void EmitPDumpAllocation(IMG_UINT32 ui32AllocationIndex,
+					RECORD_ALLOCATION *psAlloc)
+{
+	PDUMPCOMMENT("[SrvPFD] Allocation: %u"
+			" Addr: " IMG_DEV_VIRTADDR_FMTSPEC
+			" Size: " IMG_DEVMEM_SIZE_FMTSPEC
+			" Page size: %u"
+			" PID: %u"
+			" Process: %s"
+			" Name: %s",
+			ui32AllocationIndex,
+			psAlloc->sDevVAddr.uiAddr,
+			psAlloc->uiSize,
+			1U << psAlloc->ui32Log2PageSize,
+			psAlloc->uiPID,
+			OSGetCurrentClientProcessNameKM(),
+			psAlloc->szName);
+}
+
+static void EmitPDumpMapUnmapAll(COMMAND_TYPE eType,
+					IMG_UINT32 ui32AllocationIndex)
+{
+	const IMG_CHAR *pszOpName;
+
+	switch(eType)
+	{
+		case COMMAND_TYPE_MAP_ALL:
+			pszOpName = "MAP_ALL";
+			break;
+		case COMMAND_TYPE_UNMAP_ALL:
+			pszOpName = "UNMAP_ALL";
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR, "EmitPDumpMapUnmapAll: Invalid type: %u",
+										eType));
+			return;
+
+	}
+
+	PDUMPCOMMENT("[SrvPFD] Op: %s Allocation: %u",
+								pszOpName,
+								ui32AllocationIndex);
+}
+
+static void EmitPDumpMapUnmapRange(COMMAND_TYPE eType,
+					IMG_UINT32 ui32AllocationIndex,
+					IMG_UINT32 ui32StartPage,
+					IMG_UINT32 ui32Count)
+{
+	const IMG_CHAR *pszOpName;
+
+	switch(eType)
+	{
+		case COMMAND_TYPE_MAP_RANGE:
+			pszOpName = "MAP_RANGE";
+			break;
+		case COMMAND_TYPE_UNMAP_RANGE:
+			pszOpName = "UNMAP_RANGE";
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR, "EmitPDumpMapUnmapRange: Invalid type: %u",
+										eType));
+			return;
+	}
+
+	PDUMPCOMMENT("[SrvPFD] Op: %s Allocation: %u Start Page: %u Count: %u",
+									pszOpName,
+									ui32AllocationIndex,
+									ui32StartPage,
+									ui32Count);
+}
+
+#endif
+
+/* InsertTimeStampCommand:
+ * Insert a timestamp command into the circular buffer.
+ */
+static void InsertTimeStampCommand(IMG_UINT64 ui64Now)
+{
+	COMMAND_WRAPPER *psCommand;
+
+	psCommand = AcquireCBSlot();
+
+	psCommand->ui8Type = COMMAND_TYPE_TIMESTAMP;
+
+	TimeStampPack(&psCommand->u.sTimeStamp, ui64Now);
+}
+
+/* InsertMapAllCommand:
+ * Insert a "MAP_ALL" command for the given allocation into the circular buffer
+ */
+static void InsertMapAllCommand(IMG_UINT32 ui32AllocIndex)
+{
+	COMMAND_WRAPPER *psCommand;
+
+	psCommand = AcquireCBSlot();
+
+	psCommand->ui8Type = COMMAND_TYPE_MAP_ALL;
+	psCommand->u.sMapAll.uiAllocIndex = ui32AllocIndex;
+
+#if defined(PDUMP)
+	EmitPDumpMapUnmapAll(COMMAND_TYPE_MAP_ALL, ui32AllocIndex);
+#endif
+}
+
+/* InsertUnmapAllCommand:
+ * Insert a "UNMAP_ALL" command for the given allocation into the circular buffer
+ */
+static void InsertUnmapAllCommand(IMG_UINT32 ui32AllocIndex)
+{
+	COMMAND_WRAPPER *psCommand;
+
+	psCommand = AcquireCBSlot();
+
+	psCommand->ui8Type = COMMAND_TYPE_UNMAP_ALL;
+	psCommand->u.sUnmapAll.uiAllocIndex = ui32AllocIndex;
+
+#if defined(PDUMP)
+	EmitPDumpMapUnmapAll(COMMAND_TYPE_UNMAP_ALL, ui32AllocIndex);
+#endif
+}
+
+/* MapRangePack:
+ * Pack the given StartPage and Count values into the 40-bit representation
+ * in the MAP_RANGE command.
+ */
+static void MapRangePack(COMMAND_MAP_RANGE *psMapRange,
+						IMG_UINT32 ui32StartPage,
+						IMG_UINT32 ui32Count)
+{
+	IMG_UINT64 ui64Data;
+	IMG_UINT32 i;
+
+	/* we must encode the data into 40 bits:
+	 *   18 bits for the start page index
+	 *   12 bits for the range
+	*/
+
+	PVR_ASSERT(ui32StartPage <= MAP_RANGE_MAX_START);
+	PVR_ASSERT(ui32Count <= MAP_RANGE_MAX_RANGE);
+
+	ui64Data = (((IMG_UINT64) ui32StartPage) << 12) | ui32Count;
+
+	for(i = 0; i < IMG_ARR_NUM_ELEMS(psMapRange->aui8Data); i++)
+	{
+		psMapRange->aui8Data[i] = ui64Data & 0xFF;
+		ui64Data >>= 8;
+	}
+}
+
+/* MapRangePack:
+ * Unpack the StartPage and Count values from the 40-bit representation
+ * in the MAP_RANGE command.
+ */
+static void MapRangeUnpack(COMMAND_MAP_RANGE *psMapRange,
+						IMG_UINT32 *pui32StartPage,
+						IMG_UINT32 *pui32Count)
+{
+	IMG_UINT64 ui64Data = 0;
+	IMG_UINT32 i;
+
+	for(i = IMG_ARR_NUM_ELEMS(psMapRange->aui8Data); i > 0; i--)
+	{
+		ui64Data <<= 8;
+		ui64Data |= psMapRange->aui8Data[i - 1];
+	}
+
+	*pui32StartPage = (ui64Data >> 12);
+	*pui32Count = ui64Data & ((1 << 12) - 1);
+}
+
+/* InsertMapRangeCommand:
+ * Insert a MAP_RANGE command into the circular buffer with the given
+ * StartPage and Count values.
+ */
+static void InsertMapRangeCommand(IMG_UINT32 ui32AllocIndex,
+						IMG_UINT32 ui32StartPage,
+						IMG_UINT32 ui32Count)
+{
+	COMMAND_WRAPPER *psCommand;
+
+	psCommand = AcquireCBSlot();
+
+	psCommand->ui8Type = COMMAND_TYPE_MAP_RANGE;
+	psCommand->u.sMapRange.uiAllocIndex = ui32AllocIndex;
+
+	MapRangePack(&psCommand->u.sMapRange, ui32StartPage, ui32Count);
+
+#if defined(PDUMP)
+	EmitPDumpMapUnmapRange(COMMAND_TYPE_MAP_RANGE,
+							ui32AllocIndex,
+							ui32StartPage,
+							ui32Count);
+#endif
+}
+
+/* InsertUnmapRangeCommand:
+ * Insert a UNMAP_RANGE command into the circular buffer with the given
+ * StartPage and Count values.
+ */
+static void InsertUnmapRangeCommand(IMG_UINT32 ui32AllocIndex,
+						IMG_UINT32 ui32StartPage,
+						IMG_UINT32 ui32Count)
+{
+	COMMAND_WRAPPER *psCommand;
+
+	psCommand = AcquireCBSlot();
+
+	psCommand->ui8Type = COMMAND_TYPE_UNMAP_RANGE;
+	psCommand->u.sMapRange.uiAllocIndex = ui32AllocIndex;
+
+	MapRangePack(&psCommand->u.sMapRange, ui32StartPage, ui32Count);
+
+#if defined(PDUMP)
+	EmitPDumpMapUnmapRange(COMMAND_TYPE_UNMAP_RANGE,
+							ui32AllocIndex,
+							ui32StartPage,
+							ui32Count);
+#endif
+}
+
+/* InsertAllocationToList:
+ * Helper function for the allocation list.
+ * Inserts the given allocation at the head of the list, whose current head is
+ * pointed to by pui32ListHead
+ */
+static void InsertAllocationToList(IMG_UINT32 *pui32ListHead, IMG_UINT32 ui32Alloc)
+{
+	RECORD_ALLOCATION *psAlloc;
+
+	psAlloc = ALLOC_INDEX_TO_PTR(ui32Alloc);
+
+	if(*pui32ListHead == END_OF_LIST)
+	{
+		/* list is currently empty, so just replace it */
+		*pui32ListHead = ui32Alloc;
+		psAlloc->ui32Next = psAlloc->ui32Prev = *pui32ListHead;
+	}
+	else
+	{
+		RECORD_ALLOCATION *psHeadAlloc;
+		RECORD_ALLOCATION *psTailAlloc;
+
+		psHeadAlloc = ALLOC_INDEX_TO_PTR(*pui32ListHead);
+		psTailAlloc = ALLOC_INDEX_TO_PTR(psHeadAlloc->ui32Prev);
+
+		/* make the new alloc point forwards to the previous head */
+		psAlloc->ui32Next = *pui32ListHead;
+		/* make the new alloc point backwards to the previous tail */
+		psAlloc->ui32Prev = psHeadAlloc->ui32Prev;
+
+		/* the head is now our new alloc */
+		*pui32ListHead = ui32Alloc;
+
+		/* the old head now points back to the new head */
+		psHeadAlloc->ui32Prev = *pui32ListHead;
+
+		/* the tail now points forward to the new head */
+		psTailAlloc->ui32Next = ui32Alloc;
+	}
+}
+
+static void InsertAllocationToBusyList(IMG_UINT32 ui32Alloc)
+{
+	InsertAllocationToList(&gsDevicememHistoryData.sRecords.ui32AllocationsListHead, ui32Alloc);
+}
+
+/* RemoveAllocationFromList:
+ * Helper function for the allocation list.
+ * Removes the given allocation from the list, whose head is
+ * pointed to by pui32ListHead
+ */
+static void RemoveAllocationFromList(IMG_UINT32 *pui32ListHead, IMG_UINT32 ui32Alloc)
+{
+	RECORD_ALLOCATION *psAlloc;
+
+	psAlloc = ALLOC_INDEX_TO_PTR(ui32Alloc);
+
+	/* if this is the only element in the list then just make the list empty */
+	if((*pui32ListHead == ui32Alloc) && (psAlloc->ui32Next == ui32Alloc))
+	{
+		*pui32ListHead = END_OF_LIST;
+	}
+	else
+	{
+		RECORD_ALLOCATION *psPrev, *psNext;
+
+		psPrev = ALLOC_INDEX_TO_PTR(psAlloc->ui32Prev);
+		psNext = ALLOC_INDEX_TO_PTR(psAlloc->ui32Next);
+
+		/* remove the allocation from the list */
+		psPrev->ui32Next = psAlloc->ui32Next;
+		psNext->ui32Prev = psAlloc->ui32Prev;
+
+		/* if this allocation is the head then update the head */
+		if(*pui32ListHead == ui32Alloc)
+		{
+			*pui32ListHead = psAlloc->ui32Prev;
+		}
+	}
+}
+
+static void RemoveAllocationFromBusyList(IMG_UINT32 ui32Alloc)
+{
+	RemoveAllocationFromList(&gsDevicememHistoryData.sRecords.ui32AllocationsListHead, ui32Alloc);
+}
+
+/* TouchBusyAllocation:
+ * Move the given allocation to the head of the list
+ */
+static void TouchBusyAllocation(IMG_UINT32 ui32Alloc)
+{
+	RemoveAllocationFromBusyList(ui32Alloc);
+	InsertAllocationToBusyList(ui32Alloc);
+}
+
+static INLINE IMG_BOOL IsAllocationListEmpty(IMG_UINT32 ui32ListHead)
+{
+	return ui32ListHead == END_OF_LIST;
+}
+
+/* GetOldestBusyAllocation:
+ * Returns the index of the oldest allocation in the MRU list
+ */
+static IMG_UINT32 GetOldestBusyAllocation(void)
+{
+	IMG_UINT32 ui32Alloc;
+	RECORD_ALLOCATION *psAlloc;
+
+	ui32Alloc = gsDevicememHistoryData.sRecords.ui32AllocationsListHead;
+
+	if(ui32Alloc == END_OF_LIST)
+	{
+		return END_OF_LIST;
+	}
+
+	psAlloc = ALLOC_INDEX_TO_PTR(ui32Alloc);
+
+	return psAlloc->ui32Prev;
+}
+
+static IMG_UINT32 GetFreeAllocation(void)
+{
+	IMG_UINT32 ui32Alloc;
+
+	ui32Alloc = GetOldestBusyAllocation();
+
+	return ui32Alloc;
+}
+
+/* FindAllocation:
+ * Searches the list of allocations and returns the index if an allocation
+ * is found which matches the given properties
+ */
+static IMG_UINT32 FindAllocation(const IMG_CHAR *pszName,
+							IMG_UINT64 ui64Serial,
+							IMG_PID uiPID,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize)
+{
+	IMG_UINT32 ui32Head, ui32Index;
+	RECORD_ALLOCATION *psAlloc;
+
+	ui32Head = ui32Index = gsDevicememHistoryData.sRecords.ui32AllocationsListHead;
+
+	if(IsAllocationListEmpty(ui32Index))
+	{
+		goto not_found;
+	}
+
+	do
+	{
+		psAlloc = &gsDevicememHistoryData.sRecords.pasAllocations[ui32Index];
+
+		if(	(psAlloc->ui64Serial == ui64Serial) &&
+			(psAlloc->sDevVAddr.uiAddr == sDevVAddr.uiAddr) &&
+			(psAlloc->uiSize == uiSize) &&
+			(strcmp(psAlloc->szName, pszName) == 0))
+		{
+			goto found;
+		}
+
+		ui32Index = psAlloc->ui32Next;
+	} while(ui32Index != ui32Head);
+
+not_found:
+	/* not found */
+	ui32Index = END_OF_LIST;
+
+found:
+	/* if the allocation was not found then we return END_OF_LIST.
+	 * otherwise, we return the index of the allocation
+	 */
+
+	return ui32Index;
+}
+
+/* InitialiseAllocation:
+ * Initialise the given allocation structure with the given properties
+ */
+static void InitialiseAllocation(RECORD_ALLOCATION *psAlloc,
+							const IMG_CHAR *pszName,
+							IMG_UINT64 ui64Serial,
+							IMG_PID uiPID,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							IMG_UINT32 ui32Log2PageSize)
+{
+	OSStringNCopy(psAlloc->szName, pszName, sizeof(psAlloc->szName));
+	psAlloc->szName[sizeof(psAlloc->szName) - 1] = '\0';
+	psAlloc->ui64Serial = ui64Serial;
+	psAlloc->uiPID = uiPID;
+	psAlloc->sDevVAddr = sDevVAddr;
+	psAlloc->uiSize = uiSize;
+	psAlloc->ui32Log2PageSize = ui32Log2PageSize;
+	psAlloc->ui64CreationTime = OSClockns64();
+}
+
+/* CreateAllocation:
+ * Creates a new allocation with the given properties then outputs the
+ * index of the allocation
+ */
+static PVRSRV_ERROR CreateAllocation(const IMG_CHAR *pszName,
+							IMG_UINT64 ui64Serial,
+							IMG_PID uiPID,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_BOOL bAutoPurge,
+							IMG_UINT32 *puiAllocationIndex)
+{
+	IMG_UINT32 ui32Alloc;
+	RECORD_ALLOCATION *psAlloc;
+
+	ui32Alloc = GetFreeAllocation();
+
+	psAlloc = ALLOC_INDEX_TO_PTR(ui32Alloc);
+
+	InitialiseAllocation(ALLOC_INDEX_TO_PTR(ui32Alloc),
+						pszName,
+						ui64Serial,
+						uiPID,
+						sDevVAddr,
+						uiSize,
+						ui32Log2PageSize);
+
+	/* put the newly initialised allocation at the front of the MRU list */
+	TouchBusyAllocation(ui32Alloc);
+
+	*puiAllocationIndex = ui32Alloc;
+
+#if defined(PDUMP)
+	EmitPDumpAllocation(ui32Alloc, psAlloc);
+#endif
+
+	return PVRSRV_OK;
+}
+
+/* MatchAllocation:
+ * Tests if the allocation at the given index matches the supplied properties.
+ * Returns IMG_TRUE if it is a match, otherwise IMG_FALSE.
+ */
+static IMG_BOOL MatchAllocation(IMG_UINT32 ui32AllocationIndex,
+						IMG_UINT64 ui64Serial,
+						IMG_DEV_VIRTADDR sDevVAddr,
+						IMG_DEVMEM_SIZE_T uiSize,
+						const IMG_CHAR *pszName,
+						IMG_UINT32 ui32Log2PageSize,
+						IMG_PID uiPID)
+{
+	RECORD_ALLOCATION *psAlloc;
+
+	psAlloc = ALLOC_INDEX_TO_PTR(ui32AllocationIndex);
+
+	return 	(psAlloc->ui64Serial == ui64Serial) &&
+			(psAlloc->sDevVAddr.uiAddr == sDevVAddr.uiAddr) &&
+			(psAlloc->uiSize == uiSize) &&
+			(psAlloc->ui32Log2PageSize == ui32Log2PageSize) &&
+			(strcmp(psAlloc->szName, pszName) == 0);
+}
+
+/* FindOrCreateAllocation:
+ * Convenience function.
+ * Given a set of allocation properties (serial, DevVAddr, size, name, etc),
+ * this function will look for an existing record of this allocation and
+ * create the allocation if there is no existing record
+ */
+static PVRSRV_ERROR FindOrCreateAllocation(IMG_UINT32 ui32AllocationIndexHint,
+							IMG_UINT64 ui64Serial,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char *pszName,
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_PID uiPID,
+							IMG_BOOL bSparse,
+							IMG_UINT32 *pui32AllocationIndexOut,
+							IMG_BOOL *pbCreated)
+{
+	IMG_UINT32 ui32AllocationIndex;
+
+	if(ui32AllocationIndexHint != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE)
+	{
+		IMG_BOOL bHaveAllocation;
+
+		/* first, try to match against the index given by the client */
+		bHaveAllocation = MatchAllocation(ui32AllocationIndexHint,
+								ui64Serial,
+								sDevVAddr,
+								uiSize,
+								pszName,
+								ui32Log2PageSize,
+								uiPID);
+		if(bHaveAllocation)
+		{
+			*pbCreated = IMG_FALSE;
+			*pui32AllocationIndexOut = ui32AllocationIndexHint;
+			return PVRSRV_OK;
+		}
+	}
+
+	/* if matching against the client-supplied index fails then check
+	 * if the allocation exists in the list
+	 */
+	ui32AllocationIndex = FindAllocation(pszName,
+						ui64Serial,
+						uiPID,
+						sDevVAddr,
+						uiSize);
+
+	/* if there is no record of the allocation then we
+	 * create it now
+	 */
+	if(ui32AllocationIndex == END_OF_LIST)
+	{
+		PVRSRV_ERROR eError;
+		eError = CreateAllocation(pszName,
+						ui64Serial,
+						uiPID,
+						sDevVAddr,
+						uiSize,
+						ui32Log2PageSize,
+						IMG_TRUE,
+						&ui32AllocationIndex);
+
+		if(eError == PVRSRV_OK)
+		{
+			*pui32AllocationIndexOut = ui32AllocationIndex;
+			*pbCreated = IMG_TRUE;
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+				"%s: Failed to create record for allocation %s",
+									__func__,
+									pszName));
+		}
+
+		return eError;
+	}
+	else
+	{
+		/* found existing record */
+		*pui32AllocationIndexOut = ui32AllocationIndex;
+		*pbCreated = IMG_FALSE;
+		return PVRSRV_OK;
+	}
+
+}
+
+/* GenerateMapUnmapCommandsForSparsePMR:
+ * Generate the MAP_RANGE or UNMAP_RANGE commands for the sparse PMR, using the PMR's
+ * current mapping table
+ *
+ * PMR: The PMR whose mapping table to read.
+ * ui32AllocIndex: The allocation to attribute the MAP_RANGE/UNMAP range commands to.
+ * bMap: Set to TRUE for mapping or IMG_FALSE for unmapping
+ *
+ * This function goes through every page in the PMR's mapping table and looks for
+ * virtually contiguous ranges to record as being mapped or unmapped.
+ */
+static void GenerateMapUnmapCommandsForSparsePMR(PMR *psPMR,
+							IMG_UINT32 ui32AllocIndex,
+							IMG_BOOL bMap)
+{
+	PMR_MAPPING_TABLE *psMappingTable;
+	IMG_UINT32 ui32DonePages = 0;
+	IMG_UINT32 ui32NumPages;
+	IMG_UINT32 i;
+	IMG_BOOL bInARun = IMG_FALSE;
+	IMG_UINT32 ui32CurrentStart = 0;
+	IMG_UINT32 ui32RunCount = 0;
+
+	psMappingTable = PMR_GetMappigTable(psPMR);
+	ui32NumPages = psMappingTable->ui32NumPhysChunks;
+
+	if(ui32NumPages == 0)
+	{
+		/* nothing to do */
+		return;
+	}
+
+	for(i = 0; i < psMappingTable->ui32NumVirtChunks; i++)
+	{
+		if(psMappingTable->aui32Translation[i] != TRANSLATION_INVALID)
+		{
+			if(!bInARun)
+			{
+				bInARun = IMG_TRUE;
+				ui32CurrentStart = i;
+				ui32RunCount = 1;
+			}
+			else
+			{
+				ui32RunCount++;
+			}
+		}
+
+		if(bInARun)
+		{
+			/* test if we need to end this current run and generate the command,
+			 * either because the next page is not virtually contiguous
+			 * to the current page, we have reached the maximum range,
+			 * or this is the last page in the mapping table
+			 */
+			if((psMappingTable->aui32Translation[i] == TRANSLATION_INVALID) ||
+						(ui32RunCount == MAP_RANGE_MAX_RANGE) ||
+						(i == (psMappingTable->ui32NumVirtChunks - 1)))
+			{
+				if(bMap)
+				{
+					InsertMapRangeCommand(ui32AllocIndex,
+										ui32CurrentStart,
+										ui32RunCount);
+				}
+				else
+				{
+					InsertUnmapRangeCommand(ui32AllocIndex,
+										ui32CurrentStart,
+										ui32RunCount);
+				}
+
+				ui32DonePages += ui32RunCount;
+
+				if(ui32DonePages == ui32NumPages)
+				{
+					 break;
+				}
+
+				bInARun = IMG_FALSE;
+			}
+		}
+	}
+
+}
+
+/* GenerateMapUnmapCommandsForChangeList:
+ * Generate the MAP_RANGE or UNMAP_RANGE commands for the sparse PMR, using the
+ * list of page change (page map or page unmap) indices given.
+ *
+ * ui32NumPages: Number of pages which have changed.
+ * pui32PageList: List of indices of the pages which have changed.
+ * ui32AllocIndex: The allocation to attribute the MAP_RANGE/UNMAP range commands to.
+ * bMap: Set to TRUE for mapping or IMG_FALSE for unmapping
+ *
+ * This function goes through every page in the list and looks for
+ * virtually contiguous ranges to record as being mapped or unmapped.
+ */
+static void GenerateMapUnmapCommandsForChangeList(IMG_UINT32 ui32NumPages,
+							IMG_UINT32 *pui32PageList,
+							IMG_UINT32 ui32AllocIndex,
+							IMG_BOOL bMap)
+{
+	IMG_UINT32 i;
+	IMG_BOOL bInARun = IMG_FALSE;
+	IMG_UINT32 ui32CurrentStart = 0;
+	IMG_UINT32 ui32RunCount = 0;
+
+	for(i = 0; i < ui32NumPages; i++)
+	{
+		if(!bInARun)
+		{
+			bInARun = IMG_TRUE;
+			ui32CurrentStart = pui32PageList[i];
+		}
+
+		ui32RunCount++;
+
+		 /* we flush if:
+		 * - the next page in the list is not one greater than the current page
+		 * - this is the last page in the list
+		 * - we have reached the maximum range size
+		 */
+		if((i == (ui32NumPages - 1)) ||
+			((pui32PageList[i] + 1) != pui32PageList[i + 1]) ||
+			(ui32RunCount == MAP_RANGE_MAX_RANGE))
+		{
+			if(bMap)
+			{
+				InsertMapRangeCommand(ui32AllocIndex,
+									ui32CurrentStart,
+									ui32RunCount);
+			}
+			else
+			{
+				InsertUnmapRangeCommand(ui32AllocIndex,
+									ui32CurrentStart,
+									ui32RunCount);
+			}
+
+			bInARun = IMG_FALSE;
+			ui32RunCount = 0;
+		}
+	}
+}
+
+/* DevicememHistoryMapKM:
+ * Entry point for when an allocation is mapped into the MMU GPU
+ *
+ * psPMR: The PMR to which the allocation belongs.
+ * ui32Offset: The offset within the PMR at which the allocation begins.
+ * sDevVAddr: The DevVAddr at which the allocation begins.
+ * szName: Annotation/name for the allocation.
+ * ui32Log2PageSize: Page size of the allocation, expressed in log2 form.
+ * ui32AllocationIndex: Allocation index as provided by the client.
+ *                      We will use this as a short-cut to find the allocation
+ *                      in our records.
+ * pui32AllocationIndexOut: An updated allocation index for the client.
+ *                          This may be a new value if we just created the
+ *                          allocation record.
+ */
+PVRSRV_ERROR DevicememHistoryMapNewKM(PMR *psPMR,
+							IMG_UINT32 ui32Offset,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *pui32AllocationIndexOut)
+{
+	IMG_BOOL bSparse = PMR_IsSparse(psPMR);
+	IMG_UINT64 ui64Serial;
+	IMG_PID uiPID = OSGetCurrentProcessID();
+	PVRSRV_ERROR eError;
+	IMG_BOOL bCreated;
+
+	if((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
+				!CHECK_ALLOC_INDEX(ui32AllocationIndex))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid allocation index: %u",
+								__func__,
+								ui32AllocationIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	PMRGetUID(psPMR, &ui64Serial);
+
+	DevicememHistoryLock();
+
+	eError = FindOrCreateAllocation(ui32AllocationIndex,
+						ui64Serial,
+						sDevVAddr,
+						uiSize,
+						szName,
+						ui32Log2PageSize,
+						uiPID,
+						bSparse,
+						&ui32AllocationIndex,
+						&bCreated);
+
+	if((eError == PVRSRV_OK) && !bCreated)
+	{
+		/* touch the allocation so it goes to the head of our MRU list */
+		TouchBusyAllocation(ui32AllocationIndex);
+	}
+	else if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to Find or Create allocation %s (%s)",
+									__func__,
+									szName,
+									PVRSRVGETERRORSTRING(eError)));
+		goto out_unlock;
+	}
+
+	if(!bSparse)
+	{
+		InsertMapAllCommand(ui32AllocationIndex);
+	}
+	else
+	{
+		GenerateMapUnmapCommandsForSparsePMR(psPMR,
+								ui32AllocationIndex,
+								IMG_TRUE);
+	}
+
+	InsertTimeStampCommand(OSClockns64());
+
+	*pui32AllocationIndexOut = ui32AllocationIndex;
+
+out_unlock:
+	DevicememHistoryUnlock();
+
+	return eError;
+}
+
+static void VRangeInsertMapUnmapCommands(IMG_BOOL bMap,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_DEV_VIRTADDR sBaseDevVAddr,
+							IMG_UINT32 ui32StartPage,
+							IMG_UINT32 ui32NumPages,
+							const IMG_CHAR *pszName)
+{
+	while(ui32NumPages > 0)
+	{
+		IMG_UINT32 ui32PagesToAdd;
+
+		ui32PagesToAdd = MIN(ui32NumPages, MAP_RANGE_MAX_RANGE);
+
+		if(ui32StartPage > MAP_RANGE_MAX_START)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "Cannot record %s range beginning at page "
+									"%u on allocation %s",
+									bMap ? "map" : "unmap",
+									ui32StartPage,
+									pszName));
+			return;
+		}
+
+		if(bMap)
+		{
+			InsertMapRangeCommand(ui32AllocationIndex,
+								ui32StartPage,
+								ui32PagesToAdd);
+		}
+		else
+		{
+			InsertUnmapRangeCommand(ui32AllocationIndex,
+								ui32StartPage,
+								ui32PagesToAdd);
+		}
+
+		ui32StartPage += ui32PagesToAdd;
+		ui32NumPages -= ui32PagesToAdd;
+	}
+}
+
+PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+						IMG_UINT32 ui32StartPage,
+						IMG_UINT32 ui32NumPages,
+						IMG_DEVMEM_SIZE_T uiAllocSize,
+						const IMG_CHAR szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+						IMG_UINT32 ui32Log2PageSize,
+						IMG_UINT32 ui32AllocationIndex,
+						IMG_UINT32 *pui32AllocationIndexOut)
+{
+	IMG_PID uiPID = OSGetCurrentProcessID();
+	PVRSRV_ERROR eError;
+	IMG_BOOL bCreated;
+
+	if((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
+				!CHECK_ALLOC_INDEX(ui32AllocationIndex))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid allocation index: %u",
+								__func__,
+							ui32AllocationIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	DevicememHistoryLock();
+
+	eError = FindOrCreateAllocation(ui32AllocationIndex,
+						0,
+						sBaseDevVAddr,
+						uiAllocSize,
+						szName,
+						ui32Log2PageSize,
+						uiPID,
+						IMG_FALSE,
+						&ui32AllocationIndex,
+						&bCreated);
+
+	if((eError == PVRSRV_OK) && !bCreated)
+	{
+		/* touch the allocation so it goes to the head of our MRU list */
+		TouchBusyAllocation(ui32AllocationIndex);
+	}
+	else if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to Find or Create allocation %s (%s)",
+									__func__,
+									szName,
+									PVRSRVGETERRORSTRING(eError)));
+		goto out_unlock;
+	}
+
+	VRangeInsertMapUnmapCommands(IMG_TRUE,
+						ui32AllocationIndex,
+						sBaseDevVAddr,
+						ui32StartPage,
+						ui32NumPages,
+						szName);
+
+	*pui32AllocationIndexOut = ui32AllocationIndex;
+
+out_unlock:
+	DevicememHistoryUnlock();
+
+	return eError;
+
+}
+
+PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+						IMG_UINT32 ui32StartPage,
+						IMG_UINT32 ui32NumPages,
+						IMG_DEVMEM_SIZE_T uiAllocSize,
+						const IMG_CHAR szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+						IMG_UINT32 ui32Log2PageSize,
+						IMG_UINT32 ui32AllocationIndex,
+						IMG_UINT32 *pui32AllocationIndexOut)
+{
+	IMG_PID uiPID = OSGetCurrentProcessID();
+	PVRSRV_ERROR eError;
+	IMG_BOOL bCreated;
+
+	if((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
+				!CHECK_ALLOC_INDEX(ui32AllocationIndex))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid allocation index: %u",
+								__func__,
+							ui32AllocationIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	DevicememHistoryLock();
+
+	eError = FindOrCreateAllocation(ui32AllocationIndex,
+						0,
+						sBaseDevVAddr,
+						uiAllocSize,
+						szName,
+						ui32Log2PageSize,
+						uiPID,
+						IMG_FALSE,
+						&ui32AllocationIndex,
+						&bCreated);
+
+	if((eError == PVRSRV_OK) && !bCreated)
+	{
+		/* touch the allocation so it goes to the head of our MRU list */
+		TouchBusyAllocation(ui32AllocationIndex);
+	}
+	else if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to Find or Create allocation %s (%s)",
+									__func__,
+									szName,
+									PVRSRVGETERRORSTRING(eError)));
+		goto out_unlock;
+	}
+
+	VRangeInsertMapUnmapCommands(IMG_FALSE,
+						ui32AllocationIndex,
+						sBaseDevVAddr,
+						ui32StartPage,
+						ui32NumPages,
+						szName);
+
+	*pui32AllocationIndexOut = ui32AllocationIndex;
+
+out_unlock:
+	DevicememHistoryUnlock();
+
+	return eError;
+}
+
+
+
+/* DevicememHistoryUnmapKM:
+ * Entry point for when an allocation is unmapped from the MMU GPU
+ *
+ * psPMR: The PMR to which the allocation belongs.
+ * ui32Offset: The offset within the PMR at which the allocation begins.
+ * sDevVAddr: The DevVAddr at which the allocation begins.
+ * szName: Annotation/name for the allocation.
+ * ui32Log2PageSize: Page size of the allocation, expressed in log2 form.
+ * ui32AllocationIndex: Allocation index as provided by the client.
+ *                      We will use this as a short-cut to find the allocation
+ *                      in our records.
+ * pui32AllocationIndexOut: An updated allocation index for the client.
+ *                          This may be a new value if we just created the
+ *                          allocation record.
+ */
+PVRSRV_ERROR DevicememHistoryUnmapNewKM(PMR *psPMR,
+							IMG_UINT32 ui32Offset,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *pui32AllocationIndexOut)
+{
+	IMG_BOOL bSparse = PMR_IsSparse(psPMR);
+	IMG_UINT64 ui64Serial;
+	IMG_PID uiPID = OSGetCurrentProcessID();
+	PVRSRV_ERROR eError;
+	IMG_BOOL bCreated;
+
+	if((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
+				!CHECK_ALLOC_INDEX(ui32AllocationIndex))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid allocation index: %u",
+								__func__,
+								ui32AllocationIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	PMRGetUID(psPMR, &ui64Serial);
+
+	DevicememHistoryLock();
+
+	eError = FindOrCreateAllocation(ui32AllocationIndex,
+						ui64Serial,
+						sDevVAddr,
+						uiSize,
+						szName,
+						ui32Log2PageSize,
+						uiPID,
+						bSparse,
+						&ui32AllocationIndex,
+						&bCreated);
+
+	if((eError == PVRSRV_OK) && !bCreated)
+	{
+		/* touch the allocation so it goes to the head of our MRU list */
+		TouchBusyAllocation(ui32AllocationIndex);
+	}
+	else if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to Find or Create allocation %s (%s)",
+									__func__,
+									szName,
+									PVRSRVGETERRORSTRING(eError)));
+		goto out_unlock;
+	}
+
+	if(!bSparse)
+	{
+		InsertUnmapAllCommand(ui32AllocationIndex);
+	}
+	else
+	{
+		GenerateMapUnmapCommandsForSparsePMR(psPMR,
+								ui32AllocationIndex,
+								IMG_FALSE);
+	}
+
+	InsertTimeStampCommand(OSClockns64());
+
+	*pui32AllocationIndexOut = ui32AllocationIndex;
+
+out_unlock:
+	DevicememHistoryUnlock();
+
+	return eError;
+}
+
+/* DevicememHistorySparseChangeKM:
+ * Entry point for when a sparse allocation is changed, such that some of the
+ * pages within the sparse allocation are mapped or unmapped.
+ *
+ * psPMR: The PMR to which the allocation belongs.
+ * ui32Offset: The offset within the PMR at which the allocation begins.
+ * sDevVAddr: The DevVAddr at which the allocation begins.
+ * szName: Annotation/name for the allocation.
+ * ui32Log2PageSize: Page size of the allocation, expressed in log2 form.
+ * ui32AllocPageCount: Number of pages which have been mapped.
+ * paui32AllocPageIndices: Indices of pages which have been mapped.
+ * ui32FreePageCount: Number of pages which have been unmapped.
+ * paui32FreePageIndices: Indices of pages which have been unmapped.
+ * ui32AllocationIndex: Allocation index as provided by the client.
+ *                      We will use this as a short-cut to find the allocation
+ *                      in our records.
+ * pui32AllocationIndexOut: An updated allocation index for the client.
+ *                          This may be a new value if we just created the
+ *                          allocation record.
+ */
+PVRSRV_ERROR DevicememHistorySparseChangeKM(PMR *psPMR,
+							IMG_UINT32 ui32Offset,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_UINT32 ui32AllocPageCount,
+							IMG_UINT32 *paui32AllocPageIndices,
+							IMG_UINT32 ui32FreePageCount,
+							IMG_UINT32 *paui32FreePageIndices,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *pui32AllocationIndexOut)
+{
+	IMG_UINT64 ui64Serial;
+	IMG_PID uiPID = OSGetCurrentProcessID();
+	PVRSRV_ERROR eError;
+	IMG_BOOL bCreated;
+
+	if((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
+				!CHECK_ALLOC_INDEX(ui32AllocationIndex))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid allocation index: %u",
+								__func__,
+								ui32AllocationIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	PMRGetUID(psPMR, &ui64Serial);
+
+	DevicememHistoryLock();
+
+	eError = FindOrCreateAllocation(ui32AllocationIndex,
+						ui64Serial,
+						sDevVAddr,
+						uiSize,
+						szName,
+						ui32Log2PageSize,
+						uiPID,
+						IMG_TRUE /* bSparse */,
+						&ui32AllocationIndex,
+						&bCreated);
+
+	if((eError == PVRSRV_OK) && !bCreated)
+	{
+		/* touch the allocation so it goes to the head of our MRU list */
+		TouchBusyAllocation(ui32AllocationIndex);
+	}
+	else if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to Find or Create allocation %s (%s)",
+									__func__,
+									szName,
+									PVRSRVGETERRORSTRING(eError)));
+		goto out_unlock;
+	}
+
+	GenerateMapUnmapCommandsForChangeList(ui32AllocPageCount,
+							paui32AllocPageIndices,
+							ui32AllocationIndex,
+							IMG_TRUE);
+
+	GenerateMapUnmapCommandsForChangeList(ui32FreePageCount,
+							paui32FreePageIndices,
+							ui32AllocationIndex,
+							IMG_FALSE);
+
+	InsertTimeStampCommand(OSClockns64());
+
+	*pui32AllocationIndexOut = ui32AllocationIndex;
+
+out_unlock:
+	DevicememHistoryUnlock();
+
+	return eError;
+
+}
+
+/* CircularBufferIterateStart:
+ * Initialise local state for iterating over the circular buffer
+ */
+static void CircularBufferIterateStart(IMG_UINT32 *pui32Head, IMG_UINT32 *pui32Iter)
+{
+	*pui32Head = gsDevicememHistoryData.sRecords.ui32Head;
+
+	if(*pui32Head != 0)
+	{
+		*pui32Iter = *pui32Head - 1;
+	}
+	else
+	{
+		*pui32Iter = CIRCULAR_BUFFER_NUM_COMMANDS - 1;
+	}
+}
+
+/* CircularBufferIteratePrevious:
+ * Iterate to the previous item in the circular buffer.
+ * This is called repeatedly to iterate over the whole circular buffer.
+ */
+static COMMAND_WRAPPER *CircularBufferIteratePrevious(IMG_UINT32 ui32Head,
+							IMG_UINT32 *pui32Iter,
+							COMMAND_TYPE *peType,
+							IMG_BOOL *pbLast)
+{
+	IMG_UINT8 *pui8Header;
+	COMMAND_WRAPPER *psOut = NULL;
+
+	psOut = gsDevicememHistoryData.sRecords.pasCircularBuffer + *pui32Iter;
+
+	pui8Header = (IMG_UINT8 *) psOut;
+
+	/* sanity check the command looks valid.
+	 * this condition should never happen, but check for it anyway
+	 * and try to handle it
+	 */
+	if(*pui8Header >= COMMAND_TYPE_COUNT)
+	{
+		/* invalid header detected. Circular buffer corrupted? */
+		PVR_DPF((PVR_DBG_ERROR, "CircularBufferIteratePrevious: "
+							"Invalid header: %u",
+							*pui8Header));
+		*pbLast = IMG_TRUE;
+		return NULL;
+	}
+
+	*peType = *pui8Header;
+
+	if(*pui32Iter != 0)
+	{
+		(*pui32Iter)--;
+	}
+	else
+	{
+		*pui32Iter = CIRCULAR_BUFFER_NUM_COMMANDS - 1;
+	}
+
+
+	/* inform the caller this is the last command if either we have reached
+	 * the head (where we started) or if we have reached an empty command,
+	 * which means we have covered all populated entries
+	 */
+	if((*pui32Iter == ui32Head) || (*peType == COMMAND_TYPE_NONE))
+	{
+		/* this is the final iteration */
+		*pbLast = IMG_TRUE;
+	}
+
+	return psOut;
+}
+
+/* MapUnmapCommandGetInfo:
+ * Helper function to get the address and mapping information from a MAP_ALL, UNMAP_ALL,
+ * MAP_RANGE or UNMAP_RANGE command
+ */
+static void MapUnmapCommandGetInfo(COMMAND_WRAPPER *psCommand,
+					COMMAND_TYPE eType,
+					IMG_DEV_VIRTADDR *psDevVAddrStart,
+					IMG_DEV_VIRTADDR *psDevVAddrEnd,
+					IMG_BOOL *pbMap,
+					IMG_UINT32 *pui32AllocIndex)
+{
+	if((eType == COMMAND_TYPE_MAP_ALL) || ((eType == COMMAND_TYPE_UNMAP_ALL)))
+	{
+		COMMAND_MAP_ALL *psMapAll = &psCommand->u.sMapAll;
+		RECORD_ALLOCATION *psAlloc;
+
+		*pbMap = (eType == COMMAND_TYPE_MAP_ALL);
+		*pui32AllocIndex = psMapAll->uiAllocIndex;
+
+		psAlloc = ALLOC_INDEX_TO_PTR(psMapAll->uiAllocIndex);
+
+		*psDevVAddrStart = psAlloc->sDevVAddr;
+		psDevVAddrEnd->uiAddr = psDevVAddrStart->uiAddr + psAlloc->uiSize - 1;
+	}
+	else if((eType == COMMAND_TYPE_MAP_RANGE) || ((eType == COMMAND_TYPE_UNMAP_RANGE)))
+	{
+		COMMAND_MAP_RANGE *psMapRange = &psCommand->u.sMapRange;
+		RECORD_ALLOCATION *psAlloc;
+		IMG_UINT32 ui32StartPage, ui32Count;
+
+		*pbMap = (eType == COMMAND_TYPE_MAP_RANGE);
+		*pui32AllocIndex = psMapRange->uiAllocIndex;
+
+		psAlloc = ALLOC_INDEX_TO_PTR(psMapRange->uiAllocIndex);
+
+		MapRangeUnpack(psMapRange, &ui32StartPage, &ui32Count);
+
+		psDevVAddrStart->uiAddr = psAlloc->sDevVAddr.uiAddr +
+				((1U << psAlloc->ui32Log2PageSize) * ui32StartPage);
+
+		psDevVAddrEnd->uiAddr = psDevVAddrStart->uiAddr +
+				((1U << psAlloc->ui32Log2PageSize) * ui32Count) - 1;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid command type: %u",
+								__func__,
+								eType));
+	}
+}
+
+/* DevicememHistoryQuery:
+ * Entry point for rgxdebug to look up addresses relating to a page fault
+ */
+IMG_BOOL DevicememHistoryQuery(DEVICEMEM_HISTORY_QUERY_IN *psQueryIn,
+                               DEVICEMEM_HISTORY_QUERY_OUT *psQueryOut,
+                               IMG_UINT32 ui32PageSizeBytes,
+                               IMG_BOOL bMatchAnyAllocInPage)
+{
+	IMG_UINT32 ui32Head, ui32Iter;
+	COMMAND_TYPE eType = COMMAND_TYPE_NONE;
+	COMMAND_WRAPPER *psCommand = NULL;
+	IMG_BOOL bLast = IMG_FALSE;
+	IMG_UINT64 ui64StartTime = OSClockns64();
+	IMG_UINT64 ui64TimeNs = 0;
+
+	/* initialise the results count for the caller */
+	psQueryOut->ui32NumResults = 0;
+
+	DevicememHistoryLock();
+
+	/* if the search is constrained to a particular PID then we
+	 * first search the list of allocations to see if this
+	 * PID is known to us
+	 */
+	if(psQueryIn->uiPID != DEVICEMEM_HISTORY_PID_ANY)
+	{
+		IMG_UINT32 ui32Alloc;
+		ui32Alloc = gsDevicememHistoryData.sRecords.ui32AllocationsListHead;
+
+		while(ui32Alloc != END_OF_LIST)
+		{
+			RECORD_ALLOCATION *psAlloc;
+
+			psAlloc = ALLOC_INDEX_TO_PTR(ui32Alloc);
+
+			if(psAlloc->uiPID == psQueryIn->uiPID)
+			{
+				goto found_pid;
+			}
+
+			if(ui32Alloc == gsDevicememHistoryData.sRecords.ui32AllocationsListHead)
+			{
+				/* gone through whole list */
+				break;
+			}
+		}
+
+		/* PID not found, so we do not have any suitable data for this
+		 * page fault
+		 */
+		 goto out_unlock;
+	}
+
+found_pid:
+
+	CircularBufferIterateStart(&ui32Head, &ui32Iter);
+
+	while(!bLast)
+	{
+		psCommand = CircularBufferIteratePrevious(ui32Head, &ui32Iter, &eType, &bLast);
+
+		if(eType == COMMAND_TYPE_TIMESTAMP)
+		{
+			ui64TimeNs = TimeStampUnpack(&psCommand->u.sTimeStamp);
+			continue;
+		}
+
+		if((eType == COMMAND_TYPE_MAP_ALL) ||
+			(eType == COMMAND_TYPE_UNMAP_ALL) ||
+			(eType == COMMAND_TYPE_MAP_RANGE) ||
+			(eType == COMMAND_TYPE_UNMAP_RANGE))
+		{
+			RECORD_ALLOCATION *psAlloc;
+			IMG_DEV_VIRTADDR sAllocStartAddrOrig, sAllocEndAddrOrig;
+			IMG_DEV_VIRTADDR sAllocStartAddr, sAllocEndAddr;
+			IMG_BOOL bMap;
+			IMG_UINT32 ui32AllocIndex;
+
+			MapUnmapCommandGetInfo(psCommand,
+							eType,
+							&sAllocStartAddrOrig,
+							&sAllocEndAddrOrig,
+							&bMap,
+							&ui32AllocIndex);
+
+			sAllocStartAddr = sAllocStartAddrOrig;
+			sAllocEndAddr = sAllocEndAddrOrig;
+
+			psAlloc = ALLOC_INDEX_TO_PTR(ui32AllocIndex);
+
+			/* skip this command if we need to search within
+			 * a particular PID, and this allocation is not from
+			 * that PID
+			 */
+			if((psQueryIn->uiPID != DEVICEMEM_HISTORY_PID_ANY) &&
+				(psAlloc->uiPID != psQueryIn->uiPID))
+			{
+				continue;
+			}
+
+			/* if the allocation was created after this event, then this
+			 * event must be for an old/removed allocation, so skip it
+			 */
+			if(DO_TIME_STAMP_MASK(psAlloc->ui64CreationTime) > ui64TimeNs)
+			{
+				continue;
+			}
+
+			/* if the caller wants us to match any allocation in the
+			 * same page as the allocation then tweak the real start/end
+			 * addresses of the allocation here
+			 */
+			if(bMatchAnyAllocInPage)
+			{
+				sAllocStartAddr.uiAddr = sAllocStartAddr.uiAddr & ~(IMG_UINT64) (ui32PageSizeBytes - 1);
+				sAllocEndAddr.uiAddr = (sAllocEndAddr.uiAddr + ui32PageSizeBytes - 1) & ~(IMG_UINT64) (ui32PageSizeBytes - 1);
+			}
+
+			if((psQueryIn->sDevVAddr.uiAddr >= sAllocStartAddr.uiAddr) &&
+				(psQueryIn->sDevVAddr.uiAddr <  sAllocEndAddr.uiAddr))
+			{
+				DEVICEMEM_HISTORY_QUERY_OUT_RESULT *psResult = &psQueryOut->sResults[psQueryOut->ui32NumResults];
+
+				OSStringNCopy(psResult->szString, psAlloc->szName, sizeof(psResult->szString));
+				psResult->szString[DEVICEMEM_HISTORY_TEXT_BUFSZ - 1] = '\0';
+				psResult->sBaseDevVAddr = psAlloc->sDevVAddr;
+				psResult->uiSize = psAlloc->uiSize;
+				psResult->bMap = bMap;
+				psResult->ui64Age = _CalculateAge(ui64StartTime, ui64TimeNs, TIME_STAMP_MASK);
+				psResult->ui64When = ui64TimeNs;
+				/* write the responsible PID in the placeholder */
+				psResult->sProcessInfo.uiPID = psAlloc->uiPID;
+
+				if((eType == COMMAND_TYPE_MAP_ALL) || (eType == COMMAND_TYPE_UNMAP_ALL))
+				{
+					psResult->bRange = IMG_FALSE;
+					psResult->bAll = IMG_TRUE;
+				}
+				else
+				{
+					psResult->bRange = IMG_TRUE;
+					MapRangeUnpack(&psCommand->u.sMapRange,
+										&psResult->ui32StartPage,
+										&psResult->ui32PageCount);
+					psResult->bAll = (psResult->ui32PageCount * (1U << psAlloc->ui32Log2PageSize))
+											== psAlloc->uiSize;
+					psResult->sMapStartAddr = sAllocStartAddrOrig;
+					psResult->sMapEndAddr = sAllocEndAddrOrig;
+				}
+
+				psQueryOut->ui32NumResults++;
+
+				if(psQueryOut->ui32NumResults == DEVICEMEM_HISTORY_QUERY_OUT_MAX_RESULTS)
+				{
+					break;
+				}
+			}
+		}
+	}
+
+out_unlock:
+	DevicememHistoryUnlock();
+
+	return psQueryOut->ui32NumResults > 0;
+}
+
+static void DeviceMemHistoryFmt(IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN],
+							IMG_PID uiPID,
+							const IMG_CHAR *pszName,
+							const IMG_CHAR *pszAction,
+							IMG_DEV_VIRTADDR sDevVAddrStart,
+							IMG_DEV_VIRTADDR sDevVAddrEnd,
+							IMG_UINT64 ui64TimeNs)
+{
 
 	szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN - 1] = '\0';
 	OSSNPrintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN,
 				/* PID NAME MAP/UNMAP MIN-MAX SIZE AbsUS AgeUS*/
-				"%04u %-40s %-6s "
-				IMG_DEV_VIRTADDR_FMTSPEC "-" IMG_DEV_VIRTADDR_FMTSPEC" "
+				"%04u %-40s %-10s "
+				IMG_DEV_VIRTADDR_FMTSPEC "-" IMG_DEV_VIRTADDR_FMTSPEC " "
 				"0x%08llX "
 				"%013llu", /* 13 digits is over 2 hours of ns */
-				psAlloc->uiPID,
-				psAlloc->szString,
-				psAlloc->bAllocated ? "MAP" : "UNMAP",
-				psAlloc->sDevVAddr.uiAddr,
-				psAlloc->sDevVAddr.uiAddr + psAlloc->uiSize - 1,
-				psAlloc->uiSize,
-				psAlloc->ui64Time);
+				uiPID,
+				pszName,
+				pszAction,
+				sDevVAddrStart.uiAddr,
+				sDevVAddrEnd.uiAddr,
+				sDevVAddrEnd.uiAddr - sDevVAddrStart.uiAddr,
+				ui64TimeNs);
 }
 
 static void DeviceMemHistoryFmtHeader(IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN])
@@ -143,37 +1776,93 @@
 				"ABS NS");
 }
 
+static const char *CommandTypeToString(COMMAND_TYPE eType)
+{
+	switch(eType)
+	{
+		case COMMAND_TYPE_MAP_ALL:
+			return "MapAll";
+		case COMMAND_TYPE_UNMAP_ALL:
+			return "UnmapAll";
+		case COMMAND_TYPE_MAP_RANGE:
+			return "MapRange";
+		case COMMAND_TYPE_UNMAP_RANGE:
+			return "UnmapRange";
+		case COMMAND_TYPE_TIMESTAMP:
+			return "TimeStamp";
+		default:
+			return "???";
+	}
+}
+
 static void DevicememHistoryPrintAll(void *pvFilePtr, OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
 {
 	IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
 	IMG_UINT32 ui32Iter;
+	IMG_UINT32 ui32Head;
+	IMG_BOOL bLast = IMG_FALSE;
+	IMG_UINT64 ui64TimeNs = 0;
+	IMG_UINT64 ui64StartTime = OSClockns64();
 
 	DeviceMemHistoryFmtHeader(szBuffer);
 	pfnOSStatsPrintf(pvFilePtr, "%s\n", szBuffer);
 
-	for(ui32Iter = DECREMENT_WITH_WRAP(gsDevicememHistoryData.ui32Head, DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN);
-			;
-			ui32Iter = DECREMENT_WITH_WRAP(ui32Iter, DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN))
+	CircularBufferIterateStart(&ui32Head, &ui32Iter);
+
+	while(!bLast)
 	{
-		DEVICEMEM_HISTORY_ALLOCATION *psAlloc;
+		COMMAND_WRAPPER *psCommand;
+		COMMAND_TYPE eType = COMMAND_TYPE_NONE;
 
-		psAlloc = &gsDevicememHistoryData.psAllocations[ui32Iter];
+		psCommand = CircularBufferIteratePrevious(ui32Head, &ui32Iter, &eType, &bLast);
 
-		/* no more written elements */
-		if(psAlloc->sDevVAddr.uiAddr == 0)
+		if(eType == COMMAND_TYPE_TIMESTAMP)
 		{
-			break;
+			ui64TimeNs = TimeStampUnpack(&psCommand->u.sTimeStamp);
+			continue;
 		}
 
-		DeviceMemHistoryFmt(ui32Iter, szBuffer);
-pfnOSStatsPrintf(pvFilePtr, "%s\n", szBuffer);
 
-		if(ui32Iter == gsDevicememHistoryData.ui32Head)
+		if((eType == COMMAND_TYPE_MAP_ALL) ||
+			(eType == COMMAND_TYPE_UNMAP_ALL) ||
+			(eType == COMMAND_TYPE_MAP_RANGE) ||
+			(eType == COMMAND_TYPE_UNMAP_RANGE))
 		{
-			break;
+			RECORD_ALLOCATION *psAlloc;
+			IMG_DEV_VIRTADDR sDevVAddrStart, sDevVAddrEnd;
+			IMG_BOOL bMap;
+			IMG_UINT32 ui32AllocIndex;
+
+			MapUnmapCommandGetInfo(psCommand,
+								eType,
+								&sDevVAddrStart,
+								&sDevVAddrEnd,
+								&bMap,
+								&ui32AllocIndex);
+
+			psAlloc = ALLOC_INDEX_TO_PTR(ui32AllocIndex);
+
+			if(DO_TIME_STAMP_MASK(psAlloc->ui64CreationTime) > ui64TimeNs)
+			{
+				/* if this event relates to an allocation we
+				 * are no longer tracking then do not print it
+				 */
+				continue;
+			}
+
+			DeviceMemHistoryFmt(szBuffer,
+								psAlloc->uiPID,
+								psAlloc->szName,
+								CommandTypeToString(eType),
+								sDevVAddrStart,
+								sDevVAddrEnd,
+								ui64TimeNs);
+
+			pfnOSStatsPrintf(pvFilePtr, "%s\n", szBuffer);
 		}
 	}
-	pfnOSStatsPrintf(pvFilePtr, "\nTimestamp reference: %013llu\n", OSClockns64());
+
+	pfnOSStatsPrintf(pvFilePtr, "\nTimestamp reference: %013llu\n", ui64StartTime);
 }
 
 static void DevicememHistoryPrintAllWrapper(void *pvFilePtr, void *pvData, OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
@@ -184,6 +1873,61 @@
 	DevicememHistoryUnlock();
 }
 
+static PVRSRV_ERROR CreateRecords(void)
+{
+	gsDevicememHistoryData.sRecords.pasAllocations =
+			OSAllocMem(sizeof(RECORD_ALLOCATION) * ALLOCATION_LIST_NUM_ENTRIES);
+
+	if(gsDevicememHistoryData.sRecords.pasAllocations == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	gsDevicememHistoryData.sRecords.pasCircularBuffer =
+			OSAllocMem(sizeof(COMMAND_WRAPPER) * CIRCULAR_BUFFER_NUM_COMMANDS);
+
+	if(gsDevicememHistoryData.sRecords.pasCircularBuffer == NULL)
+	{
+		OSFreeMem(gsDevicememHistoryData.sRecords.pasAllocations);
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	return PVRSRV_OK;
+}
+
+static void DestroyRecords(void)
+{
+	OSFreeMem(gsDevicememHistoryData.sRecords.pasCircularBuffer);
+	OSFreeMem(gsDevicememHistoryData.sRecords.pasAllocations);
+}
+
+static void InitialiseRecords(void)
+{
+	IMG_UINT32 i;
+
+	/* initialise the allocations list */
+
+	gsDevicememHistoryData.sRecords.pasAllocations[0].ui32Prev = ALLOCATION_LIST_NUM_ENTRIES - 1;
+	gsDevicememHistoryData.sRecords.pasAllocations[0].ui32Next = 1;
+
+	for(i = 1; i < ALLOCATION_LIST_NUM_ENTRIES; i++)
+	{
+		gsDevicememHistoryData.sRecords.pasAllocations[i].ui32Prev = i - 1;
+		gsDevicememHistoryData.sRecords.pasAllocations[i].ui32Next = i + 1;
+	}
+
+	gsDevicememHistoryData.sRecords.pasAllocations[ALLOCATION_LIST_NUM_ENTRIES - 1].ui32Next = 0;
+
+	gsDevicememHistoryData.sRecords.ui32AllocationsListHead = 0;
+
+	/* initialise the circular buffer with zeros so every command
+	 * is initialised as a command of type COMMAND_TYPE_NONE
+	 */
+	OSCachedMemSet(gsDevicememHistoryData.sRecords.pasCircularBuffer,
+								COMMAND_TYPE_NONE,
+			sizeof(gsDevicememHistoryData.sRecords.pasCircularBuffer[0]) * CIRCULAR_BUFFER_NUM_COMMANDS);
+}
+
 PVRSRV_ERROR DevicememHistoryInitKM(void)
 {
 	PVRSRV_ERROR eError;
@@ -196,14 +1940,16 @@
 		goto err_lock;
 	}
 
-	gsDevicememHistoryData.psAllocations = OSAllocZMem(sizeof(DEVICEMEM_HISTORY_ALLOCATION) * DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN);
+	eError = CreateRecords();
 
-	if(gsDevicememHistoryData.psAllocations == NULL)
+	if(eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "DevicememHistoryInitKM: Failed to allocate space for allocations list"));
+		PVR_DPF((PVR_DBG_ERROR, "DevicememHistoryInitKM: Failed to create records"));
 		goto err_allocations;
 	}
 
+	InitialiseRecords();
+
 	gsDevicememHistoryData.pvStatsEntry = OSCreateStatisticEntry("devicemem_history",
 						NULL,
 						DevicememHistoryPrintAllWrapper,
@@ -225,93 +1971,54 @@
 	{
 		OSRemoveStatisticEntry(gsDevicememHistoryData.pvStatsEntry);
 	}
-	OSFREEMEM(gsDevicememHistoryData.psAllocations);
+
+	DestroyRecords();
+
 	OSLockDestroy(gsDevicememHistoryData.hLock);
 }
 
-static PVRSRV_ERROR DevicememHistoryWrite(IMG_DEV_VIRTADDR sDevVAddr, size_t uiSize,
-						const char szString[DEVICEMEM_HISTORY_TEXT_BUFSZ],
-						IMG_BOOL bAlloc)
-{
-	DEVICEMEM_HISTORY_ALLOCATION *psAlloc;
-
-	PVR_ASSERT(gsDevicememHistoryData.psAllocations != NULL);
-
-	DevicememHistoryLock();
-
-	psAlloc = &gsDevicememHistoryData.psAllocations[gsDevicememHistoryData.ui32Head];
-	PVR_ASSERT(gsDevicememHistoryData.ui32Head < DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN);
-
-	gsDevicememHistoryData.ui32Head = (gsDevicememHistoryData.ui32Head + 1) % DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN;
-
-	psAlloc->sDevVAddr = sDevVAddr;
-	psAlloc->uiSize = uiSize;
-	psAlloc->uiPID = OSGetCurrentProcessID();
-	OSStringNCopy(psAlloc->szString, szString, sizeof(psAlloc->szString));
-	psAlloc->szString[sizeof(psAlloc->szString) - 1] = '\0';
-	psAlloc->bAllocated = bAlloc;
-	psAlloc->ui64Time = OSClockns64();
-
-	DevicememHistoryUnlock();
-
-	return PVRSRV_OK;
-}
-
 PVRSRV_ERROR DevicememHistoryMapKM(IMG_DEV_VIRTADDR sDevVAddr, size_t uiSize, const char szString[DEVICEMEM_HISTORY_TEXT_BUFSZ])
 {
-	return DevicememHistoryWrite(sDevVAddr, uiSize, szString, IMG_TRUE);
+	IMG_UINT32 ui32AllocationIndex = DEVICEMEM_HISTORY_ALLOC_INDEX_NONE;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32StartPage;
+	IMG_UINT32 ui32NumPages;
+
+	/* assume 4K page size */
+	ui32Log2PageSize = 12;
+
+	ui32StartPage = 0;
+	ui32NumPages = (uiSize + 4095) / 4096;
+
+	return DevicememHistoryMapVRangeKM(sDevVAddr,
+								ui32StartPage,
+								ui32NumPages,
+								uiSize,
+								szString,
+								ui32Log2PageSize,
+								ui32AllocationIndex,
+								&ui32AllocationIndex);
 }
 
 PVRSRV_ERROR DevicememHistoryUnmapKM(IMG_DEV_VIRTADDR sDevVAddr, size_t uiSize, const char szString[DEVICEMEM_HISTORY_TEXT_BUFSZ])
 {
-	return DevicememHistoryWrite(sDevVAddr, uiSize, szString, IMG_FALSE);
-}
+	IMG_UINT32 ui32AllocationIndex = DEVICEMEM_HISTORY_ALLOC_INDEX_NONE;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32StartPage;
+	IMG_UINT32 ui32NumPages;
 
-IMG_BOOL DevicememHistoryQuery(DEVICEMEM_HISTORY_QUERY_IN *psQueryIn, DEVICEMEM_HISTORY_QUERY_OUT *psQueryOut)
-{
-	IMG_UINT32 ui32Entry;
+	/* assume 4K page size */
+	ui32Log2PageSize = 12;
 
-	/* initialise the results count for the caller */
-	psQueryOut->ui32NumResults = 0;
+	ui32StartPage = 0;
+	ui32NumPages = (uiSize + 4095) / 4096;
 
-	DevicememHistoryLock();
-
-	/* search from newest to oldest */
-
-	ui32Entry = gsDevicememHistoryData.ui32Head;
-
-	do
-	{
-		DEVICEMEM_HISTORY_ALLOCATION *psAlloc;
-
-		/* searching backwards (from newest to oldest)
-		 * wrap around backwards when going past zero
-		 */
-		ui32Entry = (ui32Entry != 0) ? ui32Entry - 1 : DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN - 1;
-		psAlloc = &gsDevicememHistoryData.psAllocations[ui32Entry];
-
-		if(((psAlloc->uiPID == psQueryIn->uiPID) || (psQueryIn->uiPID == DEVICEMEM_HISTORY_PID_ANY)) &&
-			(psQueryIn->sDevVAddr.uiAddr >= psAlloc->sDevVAddr.uiAddr) &&
-			(psQueryIn->sDevVAddr.uiAddr < psAlloc->sDevVAddr.uiAddr + psAlloc->uiSize))
-		{
-				DEVICEMEM_HISTORY_QUERY_OUT_RESULT *psResult = &psQueryOut->sResults[psQueryOut->ui32NumResults];
-
-				OSStringNCopy(psResult->szString, psAlloc->szString, sizeof(psResult->szString));
-				psResult->szString[DEVICEMEM_HISTORY_TEXT_BUFSZ - 1] = '\0';
-				psResult->sBaseDevVAddr = psAlloc->sDevVAddr;
-				psResult->uiSize = psAlloc->uiSize;
-				psResult->bAllocated = psAlloc->bAllocated;
-				psResult->ui64Age = _CalculateAge(psAlloc->ui64Time);
-				psResult->ui64When = psAlloc->ui64Time;
-				/* write the responsible PID in the placeholder */
-				psResult->sProcessInfo.uiPID = psAlloc->uiPID;
-
-				psQueryOut->ui32NumResults++;
-		}
-	} while((psQueryOut->ui32NumResults < DEVICEMEM_HISTORY_QUERY_OUT_MAX_RESULTS) &&
-						(ui32Entry != gsDevicememHistoryData.ui32Head));
-
-	DevicememHistoryUnlock();
-
-	return psQueryOut->ui32NumResults > 0;
+	return DevicememHistoryUnmapVRangeKM(sDevVAddr,
+								ui32StartPage,
+								ui32NumPages,
+								uiSize,
+								szString,
+								ui32Log2PageSize,
+								ui32AllocationIndex,
+								&ui32AllocationIndex);
 }
diff --git a/drivers/staging/imgtec/rogue/devicemem_history_server.h b/drivers/staging/imgtec/rogue/devicemem_history_server.h
index 9341567..a0e4dc5 100644
--- a/drivers/staging/imgtec/rogue/devicemem_history_server.h
+++ b/drivers/staging/imgtec/rogue/devicemem_history_server.h
@@ -61,6 +61,56 @@
 extern PVRSRV_ERROR
 DevicememHistoryUnmapKM(IMG_DEV_VIRTADDR sDevVAddr, size_t uiSize, const char szText[DEVICEMEM_HISTORY_TEXT_BUFSZ]);
 
+
+PVRSRV_ERROR DevicememHistoryMapNewKM(PMR *psPMR,
+							IMG_UINT32 ui32Offset,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32PageSize,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *pui32AllocationIndexOut);
+
+PVRSRV_ERROR DevicememHistoryUnmapNewKM(PMR *psPMR,
+							IMG_UINT32 ui32Offset,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32PageSize,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *pui32AllocationIndexOut);
+
+PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+							IMG_UINT32 ui32StartPage,
+							IMG_UINT32 ui32NumPages,
+							IMG_DEVMEM_SIZE_T uiAllocSize,
+							const IMG_CHAR szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *ui32AllocationIndexOut);
+
+PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+							IMG_UINT32 ui32StartPage,
+							IMG_UINT32 ui32NumPages,
+							IMG_DEVMEM_SIZE_T uiAllocSize,
+							const IMG_CHAR szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32Log2PageSize,
+							IMG_UINT32 ui32AllocationIndex,
+							IMG_UINT32 *ui32AllocationIndexOut);
+
+PVRSRV_ERROR DevicememHistorySparseChangeKM(PMR *psPMR,
+							IMG_UINT32 ui32Offset,
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_DEVMEM_SIZE_T uiSize,
+							const char szName[DEVICEMEM_HISTORY_TEXT_BUFSZ],
+							IMG_UINT32 ui32PageSize,
+							IMG_UINT32 ui32AllocPageCount,
+							IMG_UINT32 *paui32AllocPageIndices,
+							IMG_UINT32 ui32FreePageCount,
+							IMG_UINT32 *pauiFreePageIndices,
+							IMG_UINT32 AllocationIndex,
+							IMG_UINT32 *pui32AllocationIndexOut);
+
 /* used when the PID does not matter */
 #define DEVICEMEM_HISTORY_PID_ANY 0xFFFFFFFE
 
@@ -70,20 +120,28 @@
 	IMG_DEV_VIRTADDR sDevVAddr;
 } DEVICEMEM_HISTORY_QUERY_IN;
 
-/* store up to 2 results for a lookup. in the case of the faulting page being
+/* Store up to 4 results for a lookup. In the case of the faulting page being
  * re-mapped between the page fault occurring on HW and the page fault analysis
- * being done, the second result entry will show the allocation being unmapped
+ * being done, the second result entry will show the allocation being unmapped.
+ * A further 2 entries are added to cater for multiple buffers in the same page.
  */
-#define DEVICEMEM_HISTORY_QUERY_OUT_MAX_RESULTS 2
+#define DEVICEMEM_HISTORY_QUERY_OUT_MAX_RESULTS 4
 
 typedef struct _DEVICEMEM_HISTORY_QUERY_OUT_RESULT_
 {
 	IMG_CHAR szString[DEVICEMEM_HISTORY_TEXT_BUFSZ];
 	IMG_DEV_VIRTADDR sBaseDevVAddr;
 	size_t uiSize;
-	IMG_BOOL bAllocated;
+	IMG_BOOL bMap;
+	IMG_BOOL bRange;
+	IMG_BOOL bAll;
 	IMG_UINT64 ui64When;
 	IMG_UINT64 ui64Age;
+	/* info for sparse map/unmap operations (i.e. bRange=IMG_TRUE) */
+	IMG_UINT32 ui32StartPage;
+	IMG_UINT32 ui32PageCount;
+	IMG_DEV_VIRTADDR sMapStartAddr;
+	IMG_DEV_VIRTADDR sMapEndAddr;
 	RGXMEM_PROCESS_INFO sProcessInfo;
 } DEVICEMEM_HISTORY_QUERY_OUT_RESULT;
 
@@ -95,6 +153,9 @@
 } DEVICEMEM_HISTORY_QUERY_OUT;
 
 extern IMG_BOOL
-DevicememHistoryQuery(DEVICEMEM_HISTORY_QUERY_IN *psQueryIn, DEVICEMEM_HISTORY_QUERY_OUT *psQueryOut);
+DevicememHistoryQuery(DEVICEMEM_HISTORY_QUERY_IN *psQueryIn,
+                      DEVICEMEM_HISTORY_QUERY_OUT *psQueryOut,
+                      IMG_UINT32 ui32PageSizeBytes,
+                      IMG_BOOL bMatchAnyAllocInPage);
 
 #endif
diff --git a/drivers/staging/imgtec/rogue/devicemem_history_shared.h b/drivers/staging/imgtec/rogue/devicemem_history_shared.h
index 2ad35db..03f1765 100644
--- a/drivers/staging/imgtec/rogue/devicemem_history_shared.h
+++ b/drivers/staging/imgtec/rogue/devicemem_history_shared.h
@@ -51,6 +51,7 @@
 typedef struct _DEVICEMEM_HISTORY_MEMDESC_DATA_
 {
 	IMG_CHAR szText[DEVICEMEM_HISTORY_TEXT_BUFSZ];
+	IMG_UINT32 ui32AllocationIndex;
 } DEVICEMEM_HISTORY_MEMDESC_DATA;
 
 #endif
diff --git a/drivers/staging/imgtec/rogue/devicemem_mmap.h b/drivers/staging/imgtec/rogue/devicemem_mmap.h
deleted file mode 100644
index 2b88b6a..0000000
--- a/drivers/staging/imgtec/rogue/devicemem_mmap.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Device Memory Management
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    OS abstraction for the mmap2 interface for mapping PMRs into
-                User Mode memory
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#ifndef _DEVICEMEM_MMAP_H_
-#define _DEVICEMEM_MMAP_H_
-
-#include "img_types.h"
-#include "pvrsrv_error.h"
-
-/*
- *
- * OSMMapPMR
- *
- * Causes this PMR to be mapped into CPU memory that the user process
- * may access.
- *
- * Whether the memory is mapped readonly, readwrite, or not at all, is
- * dependent on the PMR itself.
- *
- * The PMR handle is opaque to the user, and lower levels of this
- * stack ensure that the handle is private to this process, such that
- * this API cannot be abused to gain access to other people's PMRs.
- *
- * The OS implementation of this function should return the virtual
- * address and length for the User to use.  The "PrivData" is to be
- * stored opaquely by the caller (N.B. he should make no assumptions,
- * in particular, NULL is a valid handle) and given back to the
- * call to OSMunmapPMR.
- *
- * The OS implementation is free to use the PrivData handle for any
- * purpose it sees fit.
- */
-
-extern PVRSRV_ERROR
-OSMMapPMR(IMG_HANDLE hBridge,
-          IMG_HANDLE hPMR,
-          IMG_DEVMEM_SIZE_T uiPMRLength,
-          IMG_UINT32 uiFlags,
-          IMG_HANDLE *phOSMMapPrivDataOut,
-          void **ppvMappingAddressOut,
-          size_t *puiMappingLengthOut);
-
-/*
- *
- * OSMUnmapPMR
- *
- * The reverse of OSMMapPMR
- *
- * The caller is required to pass the PMR handle back in along with
- * the same 3-tuple of information as was returned by the call to
- * OSMMapPMR
- *
- */
-extern void
-OSMUnmapPMR(IMG_HANDLE hBridge,
-            IMG_HANDLE hPMR,
-            IMG_HANDLE hOSMMapPrivData,
-            void *pvMappingAddress,
-            size_t uiMappingLength);
-
-#endif
diff --git a/drivers/staging/imgtec/rogue/devicemem_pdump.c b/drivers/staging/imgtec/rogue/devicemem_pdump.c
index e9a6d1f..acbc53d 100644
--- a/drivers/staging/imgtec/rogue/devicemem_pdump.c
+++ b/drivers/staging/imgtec/rogue/devicemem_pdump.c
@@ -48,9 +48,16 @@
 #include "img_types.h"
 #include "pvrsrv_error.h"
 #include "pdump.h"
+#include "devicemem.h"
 #include "devicemem_utils.h"
 #include "devicemem_pdump.h"
 #include "client_pdumpmm_bridge.h"
+#if defined(LINUX) && !defined(__KERNEL__)
+#include <stdio.h>
+#if defined(SUPPORT_ANDROID_PLATFORM)
+#include "android_utils.h"
+#endif
+#endif
 
 IMG_INTERNAL void
 DevmemPDumpLoadMem(DEVMEM_MEMDESC *psMemDesc,
@@ -149,6 +156,7 @@
     PVR_ASSERT(eError == PVRSRV_OK);
 }
 
+/* FIXME: This should be server side only */
 IMG_INTERNAL PVRSRV_ERROR
 DevmemPDumpPageCatBaseToSAddr(DEVMEM_MEMDESC		*psMemDesc,
 							  IMG_DEVMEM_OFFSET_T	*puiMemOffset,
@@ -212,6 +220,7 @@
 
 
 
+/* FIXME: Remove? */
 IMG_INTERNAL void
 DevmemPDumpSaveToFileVirtual(DEVMEM_MEMDESC *psMemDesc,
                              IMG_DEVMEM_OFFSET_T uiOffset,
diff --git a/drivers/staging/imgtec/rogue/devicemem_server.c b/drivers/staging/imgtec/rogue/devicemem_server.c
index 9b6bb00..b455b11 100644
--- a/drivers/staging/imgtec/rogue/devicemem_server.c
+++ b/drivers/staging/imgtec/rogue/devicemem_server.c
@@ -59,6 +59,8 @@
 #include "osfunc.h"
 #include "lock.h"
 
+#include "rgx_bvnc_defs_km.h"
+
 #if defined(SUPPORT_BUFFER_SYNC)
 #include <linux/sched.h>
 #include "pvr_buffer_sync.h"
@@ -81,6 +83,12 @@
        memory context is created and they need to store private data that
        is associated with the context. */
     IMG_HANDLE hPrivData;
+
+	/* The following tracks UM applications that need to be notified of a
+	 * page fault */
+	DLLIST_NODE sProcessNotifyListHead;
+	/* The following is a node for the list of registered devmem contexts */
+	DLLIST_NODE sPageFaultNotifyListElem;
 };
 
 struct _DEVMEMINT_CTX_EXPORT_ 
@@ -112,6 +120,12 @@
     IMG_UINT32 uiNumPages;
 };
 
+struct _DEVMEMINT_PF_NOTIFY_
+{
+	IMG_UINT32  ui32PID;
+	DLLIST_NODE sProcessNotifyListElem;
+};
+
 /*************************************************************************/ /*!
 @Function       _DevmemIntCtxAcquire
 @Description    Acquire a reference to the provided device memory context.
@@ -135,7 +149,25 @@
 	{
 		/* The last reference has gone, destroy the context */
 		PVRSRV_DEVICE_NODE *psDevNode = psDevmemCtx->psDevNode;
-	
+		DLLIST_NODE *psNode, *psNodeNext;
+
+		/* If there are any PIDs registered for page fault notification.
+		 * Loop through the registered PIDs and free each one */
+		dllist_foreach_node(&(psDevmemCtx->sProcessNotifyListHead), psNode, psNodeNext)
+		{
+			DEVMEMINT_PF_NOTIFY *psNotifyNode =
+				IMG_CONTAINER_OF(psNode, DEVMEMINT_PF_NOTIFY, sProcessNotifyListElem);
+			dllist_remove_node(psNode);
+			OSFreeMem(psNotifyNode);
+		}
+
+		/* If this context is in the list registered for a debugger, remove
+		 * from that list */
+		if (dllist_node_is_in_list(&psDevmemCtx->sPageFaultNotifyListElem))
+		{
+			dllist_remove_node(&psDevmemCtx->sPageFaultNotifyListElem);
+		}
+
 		if (psDevNode->pfnUnregisterMemoryContext)
 		{
 			psDevNode->pfnUnregisterMemoryContext(psDevmemCtx->hPrivData);
@@ -312,20 +344,25 @@
                    PVRSRV_DEVICE_NODE *psDeviceNode,
                    IMG_BOOL bKernelMemoryCtx,
                    DEVMEMINT_CTX **ppsDevmemCtxPtr,
-                   IMG_HANDLE *hPrivData)
+                   IMG_HANDLE *hPrivData,
+                   IMG_UINT32 *pui32CPUCacheLineSize
+                   )
 {
 	PVRSRV_ERROR eError;
 	DEVMEMINT_CTX *psDevmemCtx;
 	IMG_HANDLE hPrivDataInt = NULL;
 	MMU_DEVICEATTRIBS      *psMMUDevAttrs;
 
-#if defined(RGX_FEATURE_META)
-	psMMUDevAttrs = psDeviceNode->psMMUDevAttrs;
-	PVR_UNREFERENCED_PARAMETER(bKernelMemoryCtx);
-#else
-	psMMUDevAttrs = bKernelMemoryCtx ? psDeviceNode->psFirmwareMMUDevAttrs:
-									   psDeviceNode->psMMUDevAttrs;
-#endif
+	if((psDeviceNode->pfnCheckDeviceFeature) && \
+			psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		psMMUDevAttrs = bKernelMemoryCtx ? psDeviceNode->psFirmwareMMUDevAttrs:
+											psDeviceNode->psMMUDevAttrs;
+	}else
+	{
+		psMMUDevAttrs = psDeviceNode->psMMUDevAttrs;
+		PVR_UNREFERENCED_PARAMETER(bKernelMemoryCtx);
+	}
 
 
 	PVR_DPF((PVR_DBG_MESSAGE, "%s", __FUNCTION__));
@@ -337,17 +374,17 @@
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		PVR_DPF ((PVR_DBG_ERROR, "%s: Alloc failed", __FUNCTION__));
-        	goto fail_alloc;
+		goto fail_alloc;
 	}
 
 	OSAtomicWrite(&psDevmemCtx->hRefCount, 1);
-   	psDevmemCtx->psDevNode = psDeviceNode;
+	psDevmemCtx->psDevNode = psDeviceNode;
 
 	/* Call down to MMU context creation */
 
-   	eError = MMU_ContextCreate(psDeviceNode,
-                                   &psDevmemCtx->psMMUContext,
-                                   psMMUDevAttrs);
+	eError = MMU_ContextCreate(psDeviceNode,
+	                           &psDevmemCtx->psMMUContext,
+	                           psMMUDevAttrs);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: MMU_ContextCreate failed", __FUNCTION__));
@@ -370,39 +407,23 @@
 	*hPrivData = hPrivDataInt;
 	*ppsDevmemCtxPtr = psDevmemCtx;
 
-	return PVRSRV_OK;
-
-fail_register:
-    MMU_ContextDestroy(psDevmemCtx->psMMUContext);
-fail_mmucontext:
-	OSFREEMEM(psDevmemCtx);
-fail_alloc:
-    PVR_ASSERT(eError != PVRSRV_OK);
-    return eError;
-}
-
-/*************************************************************************/ /*!
-@Function       DevmemIntCtxCreateCLS
-@Description    Creates and initialises a device memory context.
-@Return         valid Device Memory context handle - Success
-                PVRSRV_ERROR failure code
-*/ /**************************************************************************/
-PVRSRV_ERROR
-DevmemIntCtxCreateCLS(CONNECTION_DATA *psConnection,
-                      PVRSRV_DEVICE_NODE *psDeviceNode,
-                      IMG_BOOL bKernelMemoryCtx,
-                      DEVMEMINT_CTX **ppsDevmemCtxPtr,
-                      IMG_HANDLE *hPrivData,
-                      IMG_UINT32 *pui32CPUCacheLineSize)
-{
 	/* Pass the CPU cache line size through the bridge to the user mode as it can't be queried in user mode.*/
 	*pui32CPUCacheLineSize = OSCPUCacheAttributeSize(PVR_DCACHE_LINE_SIZE);
 
-	return DevmemIntCtxCreate(psConnection,
-	                          psDeviceNode,
-	                          bKernelMemoryCtx,
-	                          ppsDevmemCtxPtr,
-	                          hPrivData);
+	/* Initialise the PID notify list */
+	dllist_init(&(psDevmemCtx->sProcessNotifyListHead));
+	psDevmemCtx->sPageFaultNotifyListElem.psNextNode = NULL;
+	psDevmemCtx->sPageFaultNotifyListElem.psPrevNode = NULL;
+
+	return PVRSRV_OK;
+
+fail_register:
+	MMU_ContextDestroy(psDevmemCtx->psMMUContext);
+fail_mmucontext:
+	OSFreeMem(psDevmemCtx);
+fail_alloc:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
 }
 
 /*************************************************************************/ /*!
@@ -488,7 +509,7 @@
 				u8Value,
 				bInitPage,
 #if	defined(PDUMP)
-				psDevNode->pszMMUPxPDumpMemSpaceName,
+				psDevNode->psMMUDevAttrs->pszMMUPxPDumpMemSpaceName,
 				DUMMY_PAGE,
 				&psDevNode->sDummyPage.hPdumpDummyPg,
 #endif
@@ -558,6 +579,18 @@
 {
 	PVRSRV_ERROR eError;
 
+	if (psReservation->psDevmemHeap->uiLog2PageSize > PMR_GetLog2Contiguity(psPMR))
+	{
+		PVR_DPF ((PVR_DBG_ERROR,
+				"%s: Device heap and PMR have incompatible Log2Contiguity (%u - %u). "
+				"PMR contiguity must be a multiple of the heap contiguity!",
+				__func__,
+				psReservation->psDevmemHeap->uiLog2PageSize,
+				PMR_GetLog2Contiguity(psPMR) ));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto e0;
+	}
+
 	eError = MMU_MapPages(psReservation->psDevmemHeap->psDevmemCtx->psMMUContext,
 	                      uiFlags,
 	                      sDevVAddrBase,
@@ -567,6 +600,7 @@
 	                      NULL,
 	                      psReservation->psDevmemHeap->uiLog2PageSize);
 
+e0:
 	return eError;
 }
 
@@ -607,6 +641,17 @@
 	PVRSRV_DEVICE_NODE *psDevNode;
 	 PMR_FLAGS_T uiPMRFlags;
 
+	if (uiLog2Contiguity > PMR_GetLog2Contiguity(psPMR))
+	{
+		PVR_DPF ((PVR_DBG_ERROR,
+				"%s: Device heap and PMR have incompatible contiguity (%u - %u). "
+				"Heap contiguity must be a multiple of the heap contiguity!",
+				__func__,
+				uiLog2Contiguity,
+				PMR_GetLog2Contiguity(psPMR) ));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto e0;
+	}
 	psDevNode = psDevmemHeap->psDevmemCtx->psDevNode;
 
 	/* allocate memory to record the mapping info */
@@ -624,8 +669,7 @@
     ui32NumDevPages = 0xffffffffU & ( ( (uiAllocationSize - 1) >> uiLog2Contiguity) + 1);
     PVR_ASSERT(ui32NumDevPages << uiLog2Contiguity == uiAllocationSize);
 
-    eError = PMRLockSysPhysAddresses(psPMR,
-                                     uiLog2Contiguity);
+    eError = PMRLockSysPhysAddresses(psPMR);
     if (eError != PVRSRV_OK)
 	{
         goto e2;
@@ -647,11 +691,11 @@
 			 * As the allocation fails we need to fail the map request and
 			 * return appropriate error
 			 *
-			 * Wondering if we do dummy allocation first and then physically lock pages later.
-			 * But on further thought failure of dummy allocation has lesser chance than
-			 * failing of physically locking down of the pages.
-			 * Hence we unlock the locked pages if dummy allocation fails. yes this is 
-			 * time consuming but very unlikely to occur */
+			 * Allocation of dummy page is done after locking the pages for PMR physically
+			 * By implementing this way, the best case path of dummy page being most likely to be
+			 * allocated after physically locking down pages, is considered.
+			 * If the dummy page allocation fails, we do unlock the physical address and the impact
+			 * is a bit more in on demand mode of operation */
 			eError = DevmemIntAllocDummyPage(psDevmemHeap);
 			if(PVRSRV_OK != eError)
 			{
@@ -729,21 +773,22 @@
 DevmemIntUnmapPMR(DEVMEMINT_MAPPING *psMapping)
 {
     PVRSRV_ERROR eError;
-    DEVMEMINT_HEAP *psDevmemHeap;
+    DEVMEMINT_HEAP *psDevmemHeap = psMapping->psReservation->psDevmemHeap;
     /* device virtual address of start of allocation */
     IMG_DEV_VIRTADDR sAllocationDevVAddr;
     /* number of pages (device pages) that allocation spans */
     IMG_UINT32 ui32NumDevPages;
     IMG_BOOL bIsSparse = IMG_FALSE, bNeedBacking = IMG_FALSE;
-	PVRSRV_DEVICE_NODE *psDevNode;
 	PMR_FLAGS_T uiPMRFlags;
 #if defined(SUPPORT_BUFFER_SYNC)
+	PVRSRV_DEVICE_NODE *psDevNode = psDevmemHeap->psDevmemCtx->psDevNode;
 	bool bInterruptible = true;
 	unsigned long ulTimeout = MAX_SCHEDULE_TIMEOUT;
 	IMG_INT iErr;
 
 retry:
-	iErr = pvr_buffer_sync_wait(psMapping->psPMR, bInterruptible, ulTimeout);
+	iErr = pvr_buffer_sync_wait(psDevNode->psBufferSyncContext,
+								psMapping->psPMR, bInterruptible, ulTimeout);
 	if (iErr)
 	{
 		if (iErr == -ERESTARTSYS)
@@ -761,9 +806,6 @@
 	}
 #endif
 
-    psDevmemHeap = psMapping->psReservation->psDevmemHeap;
-	psDevNode = psDevmemHeap->psDevmemCtx->psDevNode;
-
     ui32NumDevPages = psMapping->uiNumPages;
     sAllocationDevVAddr = psMapping->psReservation->sBase;
 
@@ -925,26 +967,25 @@
 }
 
 PVRSRV_ERROR
-DeviceMemChangeSparseServer(DEVMEMINT_HEAP *psDevmemHeap,
-					PMR *psPMR,
-					IMG_UINT32 ui32AllocPageCount,
-					IMG_UINT32 *pai32AllocIndices,
-					IMG_UINT32 ui32FreePageCount,
-					IMG_UINT32 *pai32FreeIndices,
-					SPARSE_MEM_RESIZE_FLAGS uiSparseFlags,
-					PVRSRV_MEMALLOCFLAGS_T uiFlags,
-					IMG_DEV_VIRTADDR sDevVAddrBase,
-					IMG_UINT64 sCpuVAddrBase,
-					IMG_UINT32 *pui32Status)
+DevmemIntChangeSparse(DEVMEMINT_HEAP *psDevmemHeap,
+                      PMR *psPMR,
+                      IMG_UINT32 ui32AllocPageCount,
+                      IMG_UINT32 *pai32AllocIndices,
+                      IMG_UINT32 ui32FreePageCount,
+                      IMG_UINT32 *pai32FreeIndices,
+                      SPARSE_MEM_RESIZE_FLAGS uiSparseFlags,
+                      PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                      IMG_DEV_VIRTADDR sDevVAddrBase,
+                      IMG_UINT64 sCpuVAddrBase)
 {
-	PVRSRV_ERROR eError = ~PVRSRV_OK;
+	PVRSRV_ERROR eError;
 
-	IMG_UINT32 uiLog2PageSize = GET_LOG2_PAGESIZE(),uiPageSize=0;
+	IMG_UINT32 uiLog2PageSize = PMR_GetLog2Contiguity(psPMR);
 
-	uiPageSize = (1 << uiLog2PageSize);
 	/*
 	 * The order of steps in which this request is done is given below. The order of
-	 * operations is very important in this case
+	 * operations is very important in this case:
+	 *
 	 * 1. The parameters are validated in function PMR_ChangeSparseMem below.
 	 * 	   A successful response indicates all the parameters are correct.
 	 * 	   In failure case we bail out from here with out processing further.
@@ -952,125 +993,125 @@
 	 *    and the corresponding PMR status changes.
 	 *    when this call fails, it is ensured that the state of the PMR before is
 	 *    not disturbed. If it succeeds, then we can go ahead with the subsequent steps.
-	 * 3. Dewire the GPU page table entries for the pages to be freed.
+	 * 3. Invalidate the GPU page table entries for the pages to be freed.
 	 * 4. Write the GPU page table entries for the pages that got allocated.
 	 * 5. Change the corresponding CPU space map.
 	 *
 	 * The above steps can be selectively controlled using flags.
 	 */
-	*pui32Status = PVRSRV_OK;
 
 	{
-		if(uiSparseFlags & (SPARSE_REMAP_MEM | SPARSE_RESIZE_BOTH))
+		if (uiSparseFlags & (SPARSE_REMAP_MEM | SPARSE_RESIZE_BOTH))
 		{
-			/*
-			 * Do the PMR specific changes first
-			 */
+			/* Do the PMR specific changes first */
 			eError = PMR_ChangeSparseMem(psPMR,
-					ui32AllocPageCount,
-					pai32AllocIndices,
-					ui32FreePageCount,
-					pai32FreeIndices,
-					uiSparseFlags,
-					pui32Status);
-			if(PVRSRV_OK != eError)
+			                             ui32AllocPageCount,
+			                             pai32AllocIndices,
+			                             ui32FreePageCount,
+			                             pai32FreeIndices,
+			                             uiSparseFlags);
+			if (PVRSRV_OK != eError)
 			{
-				PVR_DPF((PVR_DBG_MESSAGE,"%s: Failed to do PMR specific changes......",__func__));
-				goto SparseChangeError;
+				PVR_DPF((PVR_DBG_MESSAGE,
+				        "%s: Failed to do PMR specific changes.",
+				        __func__));
+				goto e0;
 			}
 
-			/*
-			 * Dewire the page table entries for the free pages
-			 * Optimization later would be not to touch the ones that gets re-mapped
-			 */
-			if((0 != ui32FreePageCount) && (uiSparseFlags & SPARSE_RESIZE_FREE))
+			/* Invalidate the page table entries for the free pages.
+			 * Optimisation later would be not to touch the ones that gets re-mapped */
+			if ((0 != ui32FreePageCount) && (uiSparseFlags & SPARSE_RESIZE_FREE))
 			{
 				PMR_FLAGS_T uiPMRFlags;
 				IMG_BOOL bNeedBacking = IMG_FALSE;
+
 				/*Get the flags*/
 				uiPMRFlags = PMR_Flags(psPMR);
 				bNeedBacking = PVRSRV_IS_SPARSE_DUMMY_BACKING_REQUIRED(uiPMRFlags);
 
-				if(SPARSE_REMAP_MEM != (uiSparseFlags & SPARSE_REMAP_MEM))
+				if (SPARSE_REMAP_MEM != (uiSparseFlags & SPARSE_REMAP_MEM))
 				{
-					/*Unmap the pages and mark them invalid in the MMU PTE */
+					/* Unmap the pages and mark them invalid in the MMU PTE */
 					MMU_UnmapPages (psDevmemHeap->psDevmemCtx->psMMUContext,
-							uiFlags,
-							sDevVAddrBase,
-							ui32FreePageCount,
-							pai32FreeIndices,
-							uiLog2PageSize,
-							bNeedBacking);
+					                uiFlags,
+					                sDevVAddrBase,
+					                ui32FreePageCount,
+					                pai32FreeIndices,
+					                uiLog2PageSize,
+					                bNeedBacking);
 				}
 			}
 
-			/*
-			 *  Wire the pages tables that got allocated
-			 */
-			if((0 != ui32AllocPageCount) && (uiSparseFlags & SPARSE_RESIZE_ALLOC))
+			/* Wire the pages tables that got allocated */
+			if ((0 != ui32AllocPageCount) && (uiSparseFlags & SPARSE_RESIZE_ALLOC))
 			{
-				/*Map the pages and mark them Valid in the MMU PTE */
+				/* Map the pages and mark them Valid in the MMU PTE */
 				eError = MMU_MapPages (psDevmemHeap->psDevmemCtx->psMMUContext,
-						uiFlags,
-						sDevVAddrBase,
-						psPMR,
-						0,
-						ui32AllocPageCount,
-						pai32AllocIndices,
-						uiLog2PageSize);
+				                       uiFlags,
+				                       sDevVAddrBase,
+				                       psPMR,
+				                       0,
+				                       ui32AllocPageCount,
+				                       pai32AllocIndices,
+				                       uiLog2PageSize);
 
-				if(PVRSRV_OK != eError)
+				if (PVRSRV_OK != eError)
 				{
-					PVR_DPF((PVR_DBG_MESSAGE,"%s: Failed to map alloc indices......",__func__));
-					goto SparseChangeError;
+					PVR_DPF((PVR_DBG_MESSAGE,
+					        "%s: Failed to map alloc indices.",
+					        __func__));
+					goto e0;
 				}
 			}
 			
-			/*Should this be a debug feature or ever used in real scenario */
-			if(SPARSE_REMAP_MEM == (uiSparseFlags & SPARSE_REMAP_MEM))
+			/* Currently only used for debug */
+			if (SPARSE_REMAP_MEM == (uiSparseFlags & SPARSE_REMAP_MEM))
 			{
 				eError = MMU_MapPages (psDevmemHeap->psDevmemCtx->psMMUContext,
-						uiFlags,
-						sDevVAddrBase,
-						psPMR,
-						0,
-						ui32AllocPageCount,
-						pai32FreeIndices,
-						uiLog2PageSize);
-				if(PVRSRV_OK != eError)
+				                       uiFlags,
+				                       sDevVAddrBase,
+				                       psPMR,
+				                       0,
+				                       ui32AllocPageCount,
+				                       pai32FreeIndices,
+				                       uiLog2PageSize);
+				if (PVRSRV_OK != eError)
 				{
-					PVR_DPF((PVR_DBG_MESSAGE,"%s: Failed to map Free indices......",__func__));
-					goto SparseChangeError;
+					PVR_DPF((PVR_DBG_MESSAGE,
+					        "%s: Failed to map Free indices.",
+					        __func__));
+					goto e0;
 				}
 			}
 		}
 
 	}
 #ifndef PVRSRV_UNMAP_ON_SPARSE_CHANGE
-	/*
-	 * Do the changes in sparse on to the CPU virtual map accordingly
-	 */
-
-	if(uiSparseFlags & SPARSE_MAP_CPU_ADDR)
+	/* Do the changes in sparse on to the CPU virtual map accordingly */
+	if (uiSparseFlags & SPARSE_MAP_CPU_ADDR)
 	{
-		if(sCpuVAddrBase != 0)
+		if (sCpuVAddrBase != 0)
 		{
 			eError = PMR_ChangeSparseMemCPUMap(psPMR,
-												sCpuVAddrBase,
-												ui32AllocPageCount,
-												pai32AllocIndices,
-												ui32FreePageCount,
-												pai32FreeIndices,
-												pui32Status);
-			if(PVRSRV_OK != eError)
+			                                   sCpuVAddrBase,
+			                                   ui32AllocPageCount,
+			                                   pai32AllocIndices,
+			                                   ui32FreePageCount,
+			                                   pai32FreeIndices);
+			if (PVRSRV_OK != eError)
 			{
-				PVR_DPF((PVR_DBG_MESSAGE,"%s: Failed to map to CPU addr space......",__func__));
-				goto SparseChangeError;
+				PVR_DPF((PVR_DBG_MESSAGE,
+				        "%s: Failed to map to CPU addr space.",
+				        __func__));
+				goto e0;
 			}
 		}
 	}
 #endif
-	SparseChangeError:
+
+	return PVRSRV_OK;
+
+e0:
 	return eError;	
 }
 
@@ -1099,12 +1140,48 @@
 	return PVRSRV_OK;
 }
 
-PVRSRV_ERROR DevmemIntIsVDevAddrValid(DEVMEMINT_CTX *psDevMemContext,
+PVRSRV_ERROR DevmemIntIsVDevAddrValid(CONNECTION_DATA * psConnection,
+                                      PVRSRV_DEVICE_NODE *psDevNode,
+                                      DEVMEMINT_CTX *psDevMemContext,
                                       IMG_DEV_VIRTADDR sDevAddr)
 {
-    return MMU_IsVDevAddrValid(psDevMemContext->psMMUContext,
-                               GET_LOG2_PAGESIZE(),
-                               sDevAddr) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_GPU_ADDR;
+	IMG_UINT32 i, j, uiLog2HeapPageSize = 0;
+	DEVICE_MEMORY_INFO *psDinfo = &psDevNode->sDevMemoryInfo;
+	DEVMEM_HEAP_CONFIG *psConfig = psDinfo->psDeviceMemoryHeapConfigArray;
+
+	IMG_BOOL bFound = IMG_FALSE;
+
+	for (i = 0;
+	     i < psDinfo->uiNumHeapConfigs && !bFound;
+	     i++)
+	{
+		for (j = 0;
+		     j < psConfig[i].uiNumHeaps  && !bFound;
+		     j++)
+		{
+			IMG_DEV_VIRTADDR uiBase =
+					psConfig[i].psHeapBlueprintArray[j].sHeapBaseAddr;
+			IMG_DEVMEM_SIZE_T uiSize =
+					psConfig[i].psHeapBlueprintArray[j].uiHeapLength;
+
+			if ( (sDevAddr.uiAddr >= uiBase.uiAddr) &&
+			     (sDevAddr.uiAddr < (uiBase.uiAddr + uiSize)))
+			{
+				uiLog2HeapPageSize =
+						psConfig[i].psHeapBlueprintArray[j].uiLog2DataPageSize;
+				bFound = IMG_TRUE;
+			}
+		}
+	}
+
+	if (uiLog2HeapPageSize == 0)
+	{
+		return PVRSRV_ERROR_INVALID_GPU_ADDR;
+	}
+
+	return MMU_IsVDevAddrValid(psDevMemContext->psMMUContext,
+	                           uiLog2HeapPageSize,
+	                           sDevAddr) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_GPU_ADDR;
 }
 
 
@@ -1195,19 +1272,179 @@
 }
 
 /*************************************************************************/ /*!
-@Function       DevmemSLCFlushInvalRequest
-@Description    Requests a SLC Flush and Invalidate
-@Input          psDeviceNode    Device node
-@Input          psPmr           PMR
-@Return         PVRSRV_OK
+@Function       DevmemIntRegisterPFNotify
+@Description    Registers a PID to be notified when a page fault occurs on a
+                specific device memory context.
+@Input          psDevmemCtx    The context to be notified about.
+@Input          ui32PID        The PID of the process that would like to be
+                               notified.
+@Input          bRegister      If true, register. If false, de-register.
+@Return         PVRSRV_ERROR.
 */ /**************************************************************************/
-PVRSRV_ERROR
-DevmemSLCFlushInvalRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
-							PMR *psPmr)
+PVRSRV_ERROR DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
+                                         IMG_INT32     ui32PID,
+                                         IMG_BOOL      bRegister)
 {
+	PVRSRV_DEVICE_NODE *psDevNode;
+	DLLIST_NODE         *psNode, *psNodeNext;
+	DEVMEMINT_PF_NOTIFY *psNotifyNode;
+	IMG_BOOL            bPresent = IMG_FALSE;
 
-	/* invoke SLC flush and invalidate request */
-	psDeviceNode->pfnSLCCacheInvalidateRequest(psDeviceNode, psPmr);
+	if (psDevmemCtx == NULL)
+	{
+		PVR_ASSERT(!"Devmem Context Missing");
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevNode = psDevmemCtx->psDevNode;
+
+	if (bRegister)
+	{
+		/* If this is the first PID in the list, the device memory context
+		 * needs to be registered for notification */
+		if (dllist_is_empty(&psDevmemCtx->sProcessNotifyListHead))
+		{
+			dllist_add_to_tail(&psDevNode->sMemoryContextPageFaultNotifyListHead,
+			                   &psDevmemCtx->sPageFaultNotifyListElem);
+		}
+	}
+
+	/* Loop through the registered PIDs and check whether this one is
+	 * present */
+	dllist_foreach_node(&(psDevmemCtx->sProcessNotifyListHead), psNode, psNodeNext)
+	{
+		psNotifyNode = IMG_CONTAINER_OF(psNode, DEVMEMINT_PF_NOTIFY, sProcessNotifyListElem);
+
+		if (psNotifyNode->ui32PID == ui32PID)
+		{
+			bPresent = IMG_TRUE;
+			break;
+		}
+	}
+
+	if (bRegister == IMG_TRUE)
+	{
+		if (bPresent)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Trying to register a PID that is already registered",
+			         __func__));
+			return PVRSRV_ERROR_PID_ALREADY_REGISTERED;
+		}
+
+		psNotifyNode = OSAllocMem(sizeof(*psNotifyNode));
+		if (psNotifyNode == NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Unable to allocate memory for the notify list",
+			          __func__));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+		psNotifyNode->ui32PID = ui32PID;
+		dllist_add_to_tail(&(psDevmemCtx->sProcessNotifyListHead), &(psNotifyNode->sProcessNotifyListElem));
+	}
+	else
+	{
+		if (!bPresent)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Trying to unregister a PID that is not registered",
+			         __func__));
+			return PVRSRV_ERROR_PID_NOT_REGISTERED;
+		}
+		dllist_remove_node(psNode);
+		psNotifyNode = IMG_CONTAINER_OF(psNode, DEVMEMINT_PF_NOTIFY, sProcessNotifyListElem);
+		OSFreeMem(psNotifyNode);
+	}
+
+	if (!bRegister)
+	{
+		/* If the last process in the list is being unregistered, then also
+		 * unregister the device memory context from the notify list. */
+		if (dllist_is_empty(&psDevmemCtx->sProcessNotifyListHead))
+		{
+			dllist_remove_node(&psDevmemCtx->sPageFaultNotifyListElem);
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function       DevmemIntPFNotify
+@Description    Notifies any processes that have registered themselves to be
+                notified when a page fault happens on a specific device memory
+                context.
+@Input          *psDevNode           The device node.
+@Input          ui64FaultedPCAddress The page catalogue address that faulted.
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR DevmemIntPFNotify(PVRSRV_DEVICE_NODE *psDevNode,
+                               IMG_UINT64         ui64FaultedPCAddress)
+{
+	DLLIST_NODE         *psNode, *psNodeNext;
+	DEVMEMINT_PF_NOTIFY *psNotifyNode;
+	PVRSRV_ERROR        eError;
+	DEVMEMINT_CTX       *psDevmemCtx = NULL;
+	IMG_BOOL            bFailed = IMG_FALSE;
+
+	if (dllist_is_empty(&(psDevNode->sMemoryContextPageFaultNotifyListHead)))
+	{
+		return PVRSRV_OK;
+	}
+
+	dllist_foreach_node(&(psDevNode->sMemoryContextPageFaultNotifyListHead), psNode, psNodeNext)
+	{
+		DEVMEMINT_CTX *psThisContext =
+			IMG_CONTAINER_OF(psNode, DEVMEMINT_CTX, sPageFaultNotifyListElem);
+		IMG_DEV_PHYADDR sPCDevPAddr;
+
+		eError = MMU_AcquireBaseAddr(psThisContext->psMMUContext, &sPCDevPAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Failed to Acquire Base Address (%s)",
+			         __func__,
+			         PVRSRVGetErrorStringKM(eError)));
+			return eError;
+		}
+
+		if (sPCDevPAddr.uiAddr == ui64FaultedPCAddress)
+		{
+			psDevmemCtx = psThisContext;
+			break;
+		}
+	}
+
+	if (psDevmemCtx == NULL)
+	{
+		/* Not found, just return */
+		return PVRSRV_OK;
+	}
+
+	/* Loop through each registered PID and send a signal to the process */
+	dllist_foreach_node(&(psDevmemCtx->sProcessNotifyListHead), psNode, psNodeNext)
+	{
+		psNotifyNode = IMG_CONTAINER_OF(psNode, DEVMEMINT_PF_NOTIFY, sProcessNotifyListElem);
+
+		eError = OSDebugSignalPID(psNotifyNode->ui32PID);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Unable to signal process for PID: %u",
+			         __func__,
+			         psNotifyNode->ui32PID));
+
+			PVR_ASSERT(!"Unable to signal process");
+
+			bFailed = IMG_TRUE;
+		}
+	}
+
+	if (bFailed)
+	{
+		return PVRSRV_ERROR_SIGNAL_FAILED;
+	}
 
 	return PVRSRV_OK;
 }
diff --git a/drivers/staging/imgtec/rogue/devicemem_server.h b/drivers/staging/imgtec/rogue/devicemem_server.h
index 2ed0677..9025a01 100644
--- a/drivers/staging/imgtec/rogue/devicemem_server.h
+++ b/drivers/staging/imgtec/rogue/devicemem_server.h
@@ -60,6 +60,7 @@
 
 typedef struct _DEVMEMINT_RESERVATION_ DEVMEMINT_RESERVATION;
 typedef struct _DEVMEMINT_MAPPING_ DEVMEMINT_MAPPING;
+typedef struct _DEVMEMINT_PF_NOTIFY_ DEVMEMINT_PF_NOTIFY;
 
 
 /**************************************************************************/ /*!
@@ -175,18 +176,8 @@
                    /* devnode / perproc etc */
                    IMG_BOOL bKernelMemoryCtx,
                    DEVMEMINT_CTX **ppsDevmemCtxPtr,
-                   IMG_HANDLE *hPrivData);
-
-/* Same as DevmemIntCtxCreate but additionally carries the
- * CPU cache line size back to the user */
-extern PVRSRV_ERROR
-DevmemIntCtxCreateCLS(CONNECTION_DATA *psConnection,
-                      PVRSRV_DEVICE_NODE *psDeviceNode,
-                      IMG_BOOL bKernelMemoryCtx,
-                      DEVMEMINT_CTX **ppsDevmemCtxPtr,
-                      IMG_HANDLE *hPrivData,
-                      IMG_UINT32 *pui32CPUCacheLineSize);
-
+                   IMG_HANDLE *hPrivData,
+                   IMG_UINT32 *pui32CPUCacheLineSize);
 /*
  * DevmemIntCtxDestroy()
  *
@@ -337,9 +328,9 @@
 DevmemIntUnreserveRange(DEVMEMINT_RESERVATION *psDevmemReservation);
 
 /*************************************************************************/ /*!
-@Function       DeviceMemChangeSparseServer
+@Function       DevmemIntChangeSparse
 @Description    Changes the sparse allocations of a PMR by allocating and freeing
-				pages and changing their corresponding CPU and GPU mappings.
+                pages and changing their corresponding CPU and GPU mappings.
 
 @input          psDevmemHeap          Pointer to the heap we map on
 @input          psPMR                 The PMR we want to map
@@ -360,32 +351,50 @@
 @Return         PVRSRV_ERROR failure code
 */ /**************************************************************************/
 extern PVRSRV_ERROR
-DeviceMemChangeSparseServer(DEVMEMINT_HEAP *psDevmemHeap,
-					PMR *psPMR,
-					IMG_UINT32 ui32AllocPageCount,
-					IMG_UINT32 *pai32AllocIndices,
-					IMG_UINT32 ui32FreePageCount,
-					IMG_UINT32 *pai32FreeIndices,
-					SPARSE_MEM_RESIZE_FLAGS uiSparseFlags,
-					PVRSRV_MEMALLOCFLAGS_T uiFlags,
-					IMG_DEV_VIRTADDR sDevVAddrBase,
-					IMG_UINT64 sCpuVAddrBase,
-					IMG_UINT32 *pui32Status);
-
-/*
- * SLCFlushInvalRequest()
- *
- * Schedules an SLC Flush & Invalidate on the firmware if required.
- * If the request is performed depends on the caching attributes
- * of the allocation and hence depends on the underlying PMR
- */
-extern PVRSRV_ERROR
-DevmemSLCFlushInvalRequest(PVRSRV_DEVICE_NODE *psDeviceNode, PMR *psPmr);
+DevmemIntChangeSparse(DEVMEMINT_HEAP *psDevmemHeap,
+                      PMR *psPMR,
+                      IMG_UINT32 ui32AllocPageCount,
+                      IMG_UINT32 *pai32AllocIndices,
+                      IMG_UINT32 ui32FreePageCount,
+                      IMG_UINT32 *pai32FreeIndices,
+                      SPARSE_MEM_RESIZE_FLAGS uiSparseFlags,
+                      PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                      IMG_DEV_VIRTADDR sDevVAddrBase,
+                      IMG_UINT64 sCpuVAddrBase);
 
 extern PVRSRV_ERROR
-DevmemIntIsVDevAddrValid(DEVMEMINT_CTX *psDevMemContext,
+DevmemIntIsVDevAddrValid(CONNECTION_DATA * psConnection,
+                         PVRSRV_DEVICE_NODE *psDevNode,
+                         DEVMEMINT_CTX *psDevMemContext,
                          IMG_DEV_VIRTADDR sDevAddr);
 
+/*************************************************************************/ /*!
+@Function       DevmemIntRegisterPFNotify
+@Description    Registers a PID to be notified when a page fault occurs on a
+                specific device memory context.
+@Input          psDevmemCtx    The context to be notified about.
+@Input          ui32PID        The PID of the process that would like to be
+                               notified.
+@Input          bRegister      If true, register. If false, de-register.
+@Return         PVRSRV_ERROR.
+*/ /**************************************************************************/
+IMG_EXPORT PVRSRV_ERROR
+DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
+                            IMG_INT32     ui32PID,
+                            IMG_BOOL      bRegister);
+
+/*************************************************************************/ /*!
+@Function       DevmemIntPFNotify
+@Description    Notifies any processes that have registered themselves to be
+                notified when a page fault happens on a specific device memory
+                context.
+@Input          *psDevNode           The device node.
+@Input          ui64FaultedPCAddress The page catalogue address that faulted.
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR DevmemIntPFNotify(PVRSRV_DEVICE_NODE *psDevNode,
+                               IMG_UINT64         ui64FaultedPCAddress);
+
 #if defined(PDUMP)
 /*
  * DevmemIntPDumpSaveToFileVirtual()
@@ -393,14 +402,16 @@
  * Writes out PDump "SAB" commands with the data found in memory at
  * the given virtual address.
  */
+/* FIXME: uiArraySize shouldn't be here, and is an
+   artefact of the bridging */
 extern PVRSRV_ERROR
 DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
                                 IMG_DEV_VIRTADDR sDevAddrStart,
                                 IMG_DEVMEM_SIZE_T uiSize,
                                 IMG_UINT32 uiArraySize,
                                 const IMG_CHAR *pszFilename,
-								IMG_UINT32 ui32FileOffset,
-								IMG_UINT32 ui32PDumpFlags);
+                                IMG_UINT32 ui32FileOffset,
+                                IMG_UINT32 ui32PDumpFlags);
 
 extern IMG_UINT32
 DevmemIntMMUContextID(DEVMEMINT_CTX *psDevMemContext);
diff --git a/drivers/staging/imgtec/rogue/devicemem_server_utils.h b/drivers/staging/imgtec/rogue/devicemem_server_utils.h
index f492040..632eba1 100644
--- a/drivers/staging/imgtec/rogue/devicemem_server_utils.h
+++ b/drivers/staging/imgtec/rogue/devicemem_server_utils.h
@@ -43,15 +43,17 @@
 
 #include "img_defs.h"
 #include "img_types.h"
+#include "device.h"
 #include "pvrsrv_memallocflags.h"
 #include "pvrsrv.h"
 
-static INLINE IMG_UINT32 DevmemCPUCacheMode(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+static INLINE IMG_UINT32 DevmemCPUCacheMode(PVRSRV_DEVICE_NODE *psDeviceNode,
+											PVRSRV_MEMALLOCFLAGS_T ulFlags)
 {
-	IMG_UINT32 ui32CPUCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK;
+	IMG_UINT32 ui32CPUCacheMode = PVRSRV_CPU_CACHE_MODE(ulFlags);
 	IMG_UINT32 ui32Ret;
 
-	PVR_ASSERT(ui32CPUCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
+	PVR_ASSERT(ui32CPUCacheMode == PVRSRV_CPU_CACHE_MODE(ulFlags));
 
 	switch (ui32CPUCacheMode)
 	{
@@ -68,25 +70,26 @@
 			break;
 
 		case PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT:
-			/* Fall through */
-		case PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT:
+
 			/*
-				If the allocation needs to be coherent what we end up doing
-				depends on the snooping features of the system
+			 * If system has no coherency but coherency has been requested for CPU
+			 * and GPU we currently have to fall back to uncached.
+			 *
+			 * Usually the first case here should return an error but as long as a lot
+			 * of services allocations using both CPU/GPU coherency flags and rely on
+			 * the UNCACHED fallback we have to leave it here.
 			*/
-			if (PVRSRVSystemSnoopingOfCPUCache())
+			if ( (PVRSRV_GPU_CACHE_MODE(ulFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT) &&
+				!(PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig) && PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig)) )
 			{
-				/*
-					If the system has CPU cache snooping (tested above)
-					then the allocation should be cached ...
-				*/
-				ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_CACHED;
+				ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED;
 			}
 			else
 			{
-				/* ... otherwise it should be uncached */
-				ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED;
+				ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_CACHED;
 			}
+
+			break;
 			break;
 
 		default:
@@ -103,12 +106,13 @@
 	return ui32Ret;
 }
 
-static INLINE IMG_UINT32 DevmemDeviceCacheMode(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+static INLINE IMG_UINT32 DevmemDeviceCacheMode(PVRSRV_DEVICE_NODE *psDeviceNode,
+											   PVRSRV_MEMALLOCFLAGS_T ulFlags)
 {
-	IMG_UINT32 ui32DeviceCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK;
+	IMG_UINT32 ui32DeviceCacheMode = PVRSRV_GPU_CACHE_MODE(ulFlags);
 	IMG_UINT32 ui32Ret;
 
-	PVR_ASSERT(ui32DeviceCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK));
+	PVR_ASSERT(ui32DeviceCacheMode == PVRSRV_GPU_CACHE_MODE(ulFlags));
 
 	switch (ui32DeviceCacheMode)
 	{
@@ -125,25 +129,25 @@
 			break;
 
 		case PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT:
-			/* Fall through */
-		case PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT:
+
 			/*
-				If the allocation needs to be coherent what we end up doing
-				depends on the snooping features of the system
+			 * If system has no coherency but coherency has been requested for CPU
+			 * and GPU we currently have to fall back to uncached.
+			 *
+			 * Usually the first case here should return an error but as long as a lot
+			 * of services allocations using both CPU/GPU coherency flags and rely on
+			 * the UNCACHED fallback we have to leave it here.
 			*/
-			if (PVRSRVSystemSnoopingOfDeviceCache())
+			if ( (PVRSRV_CPU_CACHE_MODE(ulFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) &&
+				!(PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig) && PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig)) )
 			{
-				/*
-					If the system has GPU cache snooping (tested above)
-					then the allocation should be cached ...
-				*/
-				ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_CACHED;
+				ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED;
 			}
 			else
 			{
-				/* ... otherwise it should be uncached */
-				ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED;
+				ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_CACHED;
 			}
+
 			break;
 
 		default:
@@ -160,32 +164,32 @@
 	return ui32Ret;
 }
 
-static INLINE IMG_BOOL DevmemCPUCacheCoherency(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+static INLINE IMG_BOOL DevmemCPUCacheCoherency(PVRSRV_DEVICE_NODE *psDeviceNode,
+											   PVRSRV_MEMALLOCFLAGS_T ulFlags)
 {
-	IMG_UINT32 ui32CPUCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK;
+	IMG_UINT32 ui32CPUCacheMode = PVRSRV_CPU_CACHE_MODE(ulFlags);
 	IMG_BOOL bRet = IMG_FALSE;
 
-	PVR_ASSERT(ui32CPUCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
+	PVR_ASSERT(ui32CPUCacheMode == PVRSRV_CPU_CACHE_MODE(ulFlags));
 
-	if ((ui32CPUCacheMode == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) ||
-		(ui32CPUCacheMode == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT))
+	if (ui32CPUCacheMode == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT)
 	{
-		bRet = PVRSRVSystemSnoopingOfDeviceCache();
+		bRet = PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig);
 	}
 	return bRet;
 }
 
-static INLINE IMG_BOOL DevmemDeviceCacheCoherency(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+static INLINE IMG_BOOL DevmemDeviceCacheCoherency(PVRSRV_DEVICE_NODE *psDeviceNode,
+												  PVRSRV_MEMALLOCFLAGS_T ulFlags)
 {
-	IMG_UINT32 ui32DeviceCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK;
+	IMG_UINT32 ui32DeviceCacheMode = PVRSRV_GPU_CACHE_MODE(ulFlags);
 	IMG_BOOL bRet = IMG_FALSE;
 
-	PVR_ASSERT(ui32DeviceCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK));
+	PVR_ASSERT(ui32DeviceCacheMode == PVRSRV_GPU_CACHE_MODE(ulFlags));
 
-	if ((ui32DeviceCacheMode == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT) ||
-		(ui32DeviceCacheMode == PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT))
+	if (ui32DeviceCacheMode == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT)
 	{
-		bRet = PVRSRVSystemSnoopingOfCPUCache();
+		bRet = PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig);
 	}
 	return bRet;
 }
diff --git a/drivers/staging/imgtec/rogue/devicemem_typedefs.h b/drivers/staging/imgtec/rogue/devicemem_typedefs.h
index 9e4d974..e4611b1 100644
--- a/drivers/staging/imgtec/rogue/devicemem_typedefs.h
+++ b/drivers/staging/imgtec/rogue/devicemem_typedefs.h
@@ -47,19 +47,20 @@
 #ifndef DEVICEMEM_TYPEDEFS_H
 #define DEVICEMEM_TYPEDEFS_H
 
+#include <powervr/mem_types.h>
 #include "img_types.h"
 #include "pvrsrv_memallocflags.h"
 
-typedef struct _DEVMEM_CONTEXT_ DEVMEM_CONTEXT;     /*!< Convenience typedef for struct _DEVMEM_CONTEXT_ */
-typedef struct _DEVMEM_HEAP_ DEVMEM_HEAP;           /*!< Convenience typedef for struct _DEVMEM_HEAP_ */
-typedef struct _DEVMEM_MEMDESC_ DEVMEM_MEMDESC;     /*!< Convenience typedef for struct _DEVMEM_MEMDESC_ */
+typedef struct _DEVMEM_CONTEXT_ DEVMEM_CONTEXT;		/*!< Convenience typedef for struct _DEVMEM_CONTEXT_ */
+typedef struct _DEVMEM_HEAP_ DEVMEM_HEAP;			/*!< Convenience typedef for struct _DEVMEM_HEAP_ */
+typedef struct _DEVMEM_MEMDESC_ DEVMEM_MEMDESC;		/*!< Convenience typedef for struct _DEVMEM_MEMDESC_ */
 typedef struct _DEVMEM_PAGELIST_ DEVMEM_PAGELIST;	/*!< Convenience typedef for struct _DEVMEM_PAGELIST_ */
-typedef PVRSRV_MEMALLOCFLAGS_T DEVMEM_FLAGS_T;      /*!< Conveneince typedef for PVRSRV_MEMALLOCFLAGS_T */
+typedef PVRSRV_MEMALLOCFLAGS_T DEVMEM_FLAGS_T;		/*!< Conveneince typedef for PVRSRV_MEMALLOCFLAGS_T */
 
-typedef IMG_HANDLE DEVMEM_EXPORTHANDLE;                             /*!< Typedef for DeviceMem Export Handle */
+typedef IMG_HANDLE /* FIXME: should be a SID */ DEVMEM_EXPORTHANDLE; /*!< Typedef for DeviceMem Export Handle */
 typedef IMG_UINT64 DEVMEM_EXPORTKEY;                                /*!< Typedef for DeviceMem Export Key */
 typedef IMG_DEVMEM_SIZE_T DEVMEM_SIZE_T;                            /*!< Typedef for DeviceMem SIZE_T */
-typedef IMG_DEVMEM_LOG2ALIGN_T DEVMEM_LOG2ALIGN_T;                  /*!< Typdef for DeviceMem LOG2 Alignment */
+typedef IMG_DEVMEM_LOG2ALIGN_T DEVMEM_LOG2ALIGN_T;                  /*!< Typedef for DeviceMem LOG2 Alignment */
 
 typedef struct _DEVMEMX_PHYS_MEMDESC_ DEVMEMX_PHYSDESC;    /*!< Convenience typedef for DevmemX physical */
 typedef struct _DEVMEMX_VIRT_MEMDESC_ DEVMEMX_VIRTDESC;    /*!< Convenience typedef for DevmemX virtual */
@@ -67,7 +68,9 @@
 /*! calling code needs all the info in this struct, to be able to pass it around */
 typedef struct
 {
-    /*! A handle to the PMR. */
+    /*! A handle to the PMR.  Should be a SID.  FIXME: decide whether
+       this is right... as the PMR would have to be a cross-process
+       handle */
     IMG_HANDLE hPMRExportHandle;
     /*! The "key" to prove we have authorization to use this PMR */
     IMG_UINT64 uiPMRExportPassword;
@@ -100,23 +103,31 @@
     IMG_DEVMEM_LOG2ALIGN_T uiLog2ContiguityGuarantee;
 } DEVMEM_EXPORTCOOKIE;
 
-/*enum that describes the operation associated with changing sparse memory*/
+/* Enum that describes the operation associated with changing sparse memory*/
 typedef enum Resize {
-	SPARSE_RESIZE_NONE=0,
-	SPARSE_RESIZE_ALLOC=1, /*This is should be set to indicate, the change needs allocation */
-	SPARSE_RESIZE_FREE=2, /*This is should be set to indicate, the change needs free */
-	SPARSE_RESIZE_BOTH=(SPARSE_RESIZE_ALLOC | SPARSE_RESIZE_FREE),
-	SPARSE_REMAP_MEM=4, /*  This is should be set to silently swap underlying physical memory
-	                     *  with out disturbing its device or cpu virtual maps
-	                     *  This flag is not supported in the case of PDUMP and could lead to
-	                     *  PDUMP panic when used
-	                     */
-	SPARSE_MAP_CPU_ADDR=8 /*should be set to get the sparse changes appear in cpu virtual map */
+	SPARSE_RESIZE_NONE = 0,
+
+	/* This should be set to indicate the change needs allocation */
+	SPARSE_RESIZE_ALLOC = 1,
+
+	/* This should be set to indicate the change needs free */
+	SPARSE_RESIZE_FREE = 2,
+
+	SPARSE_RESIZE_BOTH = (SPARSE_RESIZE_ALLOC | SPARSE_RESIZE_FREE),
+
+	/* This should be set to silently swap underlying physical memory
+	 * without disturbing its device or cpu virtual maps
+	 * This flag is not supported in the case of PDUMP and could lead to
+	 * PDUMP panic when used */
+	SPARSE_REMAP_MEM = 4,
+
+	/* Should be set to get the sparse changes appear in cpu virtual map */
+	SPARSE_MAP_CPU_ADDR = 8
 }SPARSE_MEM_RESIZE_FLAGS;
 
 /* To use with DevmemSubAllocate() as the default factor if no
  * over-allocation is desired. */
 #define DEVMEM_NO_PRE_ALLOCATE_MULTIPLIER 1
 
-#endif /* #ifndef SRVCLIENT_NEW_DEVMEM_ALLOCATION_TYPEDEFS_H */
+#endif /* #ifndef DEVICEMEM_TYPEDEFS_H */
 
diff --git a/drivers/staging/imgtec/rogue/devicemem_utils.c b/drivers/staging/imgtec/rogue/devicemem_utils.c
index 285caed..8cb94fa 100644
--- a/drivers/staging/imgtec/rogue/devicemem_utils.c
+++ b/drivers/staging/imgtec/rogue/devicemem_utils.c
@@ -50,6 +50,267 @@
 #include "client_mm_bridge.h"
 
 /*
+	SVM heap management support functions for CPU (un)mapping
+*/
+#define DEVMEM_MAP_SVM_USER_MANAGED_RETRY				2
+
+static inline PVRSRV_ERROR 
+_DevmemCPUMapSVMKernelManaged(DEVMEM_HEAP *psHeap,
+							  DEVMEM_IMPORT *psImport,
+							  IMG_UINT64 *ui64MapAddress)
+{
+	PVRSRV_ERROR eError;
+	IMG_UINT64 ui64SvmMapAddr;
+	IMG_UINT64 ui64SvmMapAddrEnd;
+	IMG_UINT64 ui64SvmHeapAddrEnd;
+
+	/* SVM heap management is always XXX_KERNEL_MANAGED unless we
+	   have triggered the fall back code-path in which case we
+	   should not be calling into this code-path */
+	PVR_ASSERT(psHeap->eHeapType == DEVMEM_HEAP_TYPE_KERNEL_MANAGED);
+
+	/* By acquiring the CPU virtual address here, it essentially
+	   means we lock-down the virtual address for the duration
+	   of the life-cycle of the allocation until a de-allocation
+	   request comes in. Thus the allocation is guaranteed not to
+	   change its virtual address on the CPU during its life-time. 
+	   NOTE: Import might have already been CPU Mapped before now,
+	   normally this is not a problem, see fall back */
+	eError = _DevmemImportStructCPUMap(psImport);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Unable to CPU map (lock-down) device memory for SVM use",
+				__func__));
+		eError = PVRSRV_ERROR_DEVICEMEM_MAP_FAILED;
+		goto failSVM;
+	}
+
+	/* Supplied kernel mmap virtual address is also device virtual address;
+	   calculate the heap & kernel supplied mmap virtual address limits */
+	ui64SvmMapAddr = (IMG_UINT64)(uintptr_t)psImport->sCPUImport.pvCPUVAddr;
+	ui64SvmHeapAddrEnd = psHeap->sBaseAddress.uiAddr + psHeap->uiSize;
+	ui64SvmMapAddrEnd = ui64SvmMapAddr + psImport->uiSize;
+	PVR_ASSERT(ui64SvmMapAddr != (IMG_UINT64)0);
+
+	/* SVM limit test may fail if processor has more virtual address bits than device */
+	if (ui64SvmMapAddr >= ui64SvmHeapAddrEnd || ui64SvmMapAddrEnd > ui64SvmHeapAddrEnd)
+	{
+		/* Unmap incompatible SVM virtual address, this
+		   may not release address if it was elsewhere
+		   CPU Mapped before call into this function */
+		_DevmemImportStructCPUUnmap(psImport);
+
+		/* Flag incompatible SVM mapping */
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto failSVM;
+	}
+
+	*ui64MapAddress = ui64SvmMapAddr;
+failSVM:
+	/* either OK, MAP_FAILED or BAD_MAPPING */
+	return eError;
+}
+
+static inline void 
+_DevmemCPUUnmapSVMKernelManaged(DEVMEM_HEAP *psHeap, DEVMEM_IMPORT *psImport)
+{
+	PVR_UNREFERENCED_PARAMETER(psHeap);
+	_DevmemImportStructCPUUnmap(psImport);
+}
+
+static inline PVRSRV_ERROR 
+_DevmemCPUMapSVMUserManaged(DEVMEM_HEAP *psHeap,
+							DEVMEM_IMPORT *psImport,
+							IMG_UINT uiAlign,
+							IMG_UINT64 *ui64MapAddress)
+{
+	RA_LENGTH_T uiAllocatedSize;
+	RA_BASE_T uiAllocatedAddr;
+	IMG_UINT64 ui64SvmMapAddr;
+	IMG_UINT uiRetry = 0;
+	PVRSRV_ERROR eError;
+
+	/* If SVM heap management has transitioned to XXX_USER_MANAGED,
+	   this is essentially a fall back approach that ensures we
+	   continue to satisfy SVM alloc. This approach is not without
+	   hazards in that we may specify a virtual address that is
+	   already in use by the user process */
+	PVR_ASSERT(psHeap->eHeapType == DEVMEM_HEAP_TYPE_USER_MANAGED);
+
+	/* Normally, for SVM heap allocations, CPUMap _must_  be done
+	   before DevMap; ideally the initial CPUMap should be done by
+	   SVM functions though this is not a hard requirement as long
+	   as the prior elsewhere obtained CPUMap virtual address meets
+	   SVM address requirements. This is a fall-back code-pathway
+	   so we have to test that this assumption holds before we 
+	   progress any further */
+	OSLockAcquire(psImport->sCPUImport.hLock);
+
+	if (psImport->sCPUImport.ui32RefCount)
+	{
+		/* Already CPU Mapped SVM heap allocation, this prior elsewhere
+		   obtained virtual address is  responsible for the above 
+		   XXX_KERNEL_MANAGED failure. As we are not responsible for 
+		   this, we cannot progress any further so need to fail */
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Previously obtained CPU map address not SVM compatible"
+				, __func__));
+
+		/* Revert SVM heap to DEVMEM_HEAP_TYPE_KERNEL_MANAGED */
+		psHeap->eHeapType = DEVMEM_HEAP_TYPE_KERNEL_MANAGED;
+		PVR_DPF((PVR_DBG_MESSAGE,
+				"%s: Reverting SVM heap back to kernel managed",
+				__func__));
+
+		OSLockRelease(psImport->sCPUImport.hLock);
+
+		/* Do we need a more specific error code here */
+		eError = PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED;
+		goto failSVM;
+	}
+
+	OSLockRelease(psImport->sCPUImport.hLock);
+
+	do
+	{
+		/* Next we proceed to instruct the kernel to use the RA_Alloc supplied
+		   virtual address to map-in this SVM import suballocation; there is no
+		   guarantee that this RA_Alloc virtual address may not collide with an
+		   already in-use VMA range in the process */
+		eError = RA_Alloc(psHeap->psQuantizedVMRA,
+						psImport->uiSize,
+						RA_NO_IMPORT_MULTIPLIER,
+						0, /* flags: this RA doesn't use flags*/
+						uiAlign,
+						"SVM_Virtual_Alloc",
+						&uiAllocatedAddr,
+						&uiAllocatedSize,
+						NULL /* don't care about per-import priv data */);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"%s: Cannot RA allocate SVM compatible address",
+					__func__));
+			goto failSVM;
+		}
+
+		/* No reason for allocated virtual size to be different from
+		   the PMR's size */
+		psImport->sCPUImport.pvCPUVAddr = (void*)(uintptr_t)uiAllocatedAddr;
+		PVR_ASSERT(uiAllocatedSize == psImport->uiSize);
+			
+		/* Map the import or allocation using the RA_Alloc virtual address;
+		   the kernel may fail the request if the supplied virtual address
+		   is already in-use in which case we re-try using another virtual
+		   address obtained from the RA_Alloc */
+		eError = _DevmemImportStructCPUMap(psImport);
+		if (eError != PVRSRV_OK)
+		{
+			/* For now we simply discard failed RA_Alloc() obtained virtual 
+			   address (i.e. plenty of virtual space), this prevents us from
+			   re-using these and furthermore essentially blacklists these
+			   addresses from future SVM consideration; We exit fall-back
+			   attempt if retry exceeds the fall-back retry limit */
+			if (uiRetry++ > DEVMEM_MAP_SVM_USER_MANAGED_RETRY)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						"%s: Cannot find SVM compatible address, bad mapping",
+						__func__));
+				eError = PVRSRV_ERROR_BAD_MAPPING;
+				goto failSVM;
+			}
+		}
+		else
+		{
+			/* Found compatible SVM virtual address, set as device virtual address */
+			ui64SvmMapAddr = (IMG_UINT64)(uintptr_t)psImport->sCPUImport.pvCPUVAddr;
+		}
+	} while (eError != PVRSRV_OK);
+
+	*ui64MapAddress = ui64SvmMapAddr;
+failSVM:	
+	return eError;
+}
+
+static inline void 
+_DevmemCPUUnmapSVMUserManaged(DEVMEM_HEAP *psHeap, DEVMEM_IMPORT *psImport)
+{
+	RA_BASE_T uiAllocatedAddr;
+
+	/* We only free SVM compatible addresses, all addresses in
+	   the blacklist are essentially excluded from future RA_Alloc */
+	uiAllocatedAddr = psImport->sDeviceImport.sDevVAddr.uiAddr;
+	RA_Free(psHeap->psQuantizedVMRA, uiAllocatedAddr);
+
+	_DevmemImportStructCPUUnmap(psImport);
+}
+
+static inline PVRSRV_ERROR 
+_DevmemImportStructDevMapSVM(DEVMEM_HEAP *psHeap,
+							 DEVMEM_IMPORT *psImport,
+							 IMG_UINT uiAlign,
+							 IMG_UINT64 *ui64MapAddress)
+{
+	PVRSRV_ERROR eError;
+
+	switch(psHeap->eHeapType)
+	{
+		case DEVMEM_HEAP_TYPE_KERNEL_MANAGED:
+			eError = _DevmemCPUMapSVMKernelManaged(psHeap,
+												   psImport,
+												   ui64MapAddress);
+			if (eError == PVRSRV_ERROR_BAD_MAPPING)
+			{
+				/* If the SVM map address is outside of SVM heap limits,
+				   change heap type to DEVMEM_HEAP_TYPE_USER_MANAGED */
+				psHeap->eHeapType = DEVMEM_HEAP_TYPE_USER_MANAGED;
+				PVR_DPF((PVR_DBG_MESSAGE,
+					"%s: Kernel managed SVM heap is now user managed",
+					__func__));
+
+				/* Retry using user managed fall-back approach */
+				eError = _DevmemCPUMapSVMUserManaged(psHeap,
+													 psImport,
+													 uiAlign,
+													 ui64MapAddress);
+			}
+			break;
+
+		case DEVMEM_HEAP_TYPE_USER_MANAGED:
+			eError = _DevmemCPUMapSVMUserManaged(psHeap,
+												 psImport,
+												 uiAlign,
+												 ui64MapAddress);
+			break;
+
+		default:
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			break;
+	}
+
+	return eError;
+}
+
+static inline void 
+_DevmemImportStructDevUnmapSVM(DEVMEM_HEAP *psHeap, DEVMEM_IMPORT *psImport)
+{
+	switch(psHeap->eHeapType)
+	{
+		case DEVMEM_HEAP_TYPE_KERNEL_MANAGED:
+			_DevmemCPUUnmapSVMKernelManaged(psHeap, psImport);
+			break;
+
+		case DEVMEM_HEAP_TYPE_USER_MANAGED:
+			_DevmemCPUUnmapSVMUserManaged(psHeap, psImport);
+			break;
+
+		default:
+			break;
+	}
+}
+
+/*
 	The Devmem import structure is the structure we use
 	to manage memory that is "imported" (which is page
 	granular) from the server into our process, this
@@ -94,6 +355,9 @@
 		OSLockDestroy(psImport->sCPUImport.hLock);
 		OSLockDestroy(psImport->sDeviceImport.hLock);
 		OSLockDestroy(psImport->hLock);
+#if defined(PDUMP)
+		OSFreeMem(psImport->pszAnnotation);
+#endif
 		OSFreeMem(psImport);
 	}
 }
@@ -180,6 +444,11 @@
 	psMemDesc->sDeviceMemDesc.ui32RefCount = 0;
 	psMemDesc->sCPUMemDesc.ui32RefCount = 0;
 	psMemDesc->uiAllocSize = uiSize;
+	psMemDesc->hPrivData = NULL;
+
+#if defined(SUPPORT_PAGE_FAULT_DEBUG)
+	psMemDesc->sTraceData.ui32AllocationIndex = DEVICEMEM_HISTORY_ALLOC_INDEX_NONE;
+#endif
 
 	OSAtomicWrite(&psMemDesc->hRefCount, 1);
 }
@@ -187,8 +456,7 @@
 IMG_INTERNAL
 void _DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc)
 {
-	IMG_INT iRefCount;
-	PVR_UNREFERENCED_PARAMETER(iRefCount);
+	IMG_INT iRefCount = 0;
 
 	iRefCount = OSAtomicIncrement(&psMemDesc->hRefCount);
 	DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
@@ -215,21 +483,23 @@
 
 	if (iRefCount == 0)
 	{
-		if (psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_EXPORTABLE)
-		{
-			_DevmemImportStructRelease(psMemDesc->psImport);
-		}
-		else
+		if (psMemDesc->psImport->uiProperties & DEVMEM_PROPERTIES_SUBALLOCATABLE)
 		{
 			/* As soon as the first sub-allocation on the psImport is freed
 			 * we might get dirty memory when reusing it.
-			 * We have to delete the CLEAN flag */
+			 * We have to delete the ZEROED & CLEAN flag */
+
+			psMemDesc->psImport->uiProperties &= ~DEVMEM_PROPERTIES_IMPORT_IS_ZEROED;
 			psMemDesc->psImport->uiProperties &= ~DEVMEM_PROPERTIES_IMPORT_IS_CLEAN;
 
 			RA_Free(psMemDesc->psImport->sDeviceImport.psHeap->psSubAllocRA,
 					psMemDesc->psImport->sDeviceImport.sDevVAddr.uiAddr +
 					psMemDesc->uiOffset);
 		}
+		else
+		{
+			_DevmemImportStructRelease(psMemDesc->psImport);
+		}
 
 		OSLockDestroy(psMemDesc->sCPUMemDesc.hLock);
 		OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
@@ -252,35 +522,42 @@
 
 IMG_INTERNAL
 PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
-								   IMG_DEVMEM_ALIGN_T uiAlign,
-								   DEVMEM_FLAGS_T uiFlags)
+                                   IMG_DEVMEM_ALIGN_T uiAlign,
+                                   DEVMEM_FLAGS_T *puiFlags)
 {
-    if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
-        (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
-    {
+	if ((*puiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
+	    (*puiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
+	{
 		PVR_DPF((PVR_DBG_ERROR,
 		         "%s: Zero on Alloc and Poison on Alloc are mutually exclusive.",
 		         __FUNCTION__));
-        return PVRSRV_ERROR_INVALID_PARAMS;
-    }
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
 
-    if (uiAlign & (uiAlign-1))
-    {
+	if (uiAlign & (uiAlign-1))
+	{
 		PVR_DPF((PVR_DBG_ERROR,
 		         "%s: The requested alignment is not a power of two.",
 		         __FUNCTION__));
-        return PVRSRV_ERROR_INVALID_PARAMS;
-    }
+		return PVRSRV_ERROR_INVALID_PARAMS;
+ 	}
 
-    if (uiSize == 0)
-    {
+	if (uiSize == 0)
+	{
 		PVR_DPF((PVR_DBG_ERROR,
 		         "%s: Please request a non-zero size value.",
 		         __FUNCTION__));
-        return PVRSRV_ERROR_INVALID_PARAMS;
-    }
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
 
-    return PVRSRV_OK;
+	/* If zero flag is set we have to have write access to the page. */
+	if (PVRSRV_CHECK_ZERO_ON_ALLOC(*puiFlags) || PVRSRV_CHECK_CPU_WRITEABLE(*puiFlags))
+	{
+		(*puiFlags) |= PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+		             PVRSRV_MEMALLOCFLAG_CPU_READABLE;
+	}
+
+	return PVRSRV_OK;
 }
 
 /*
@@ -299,6 +576,11 @@
         return PVRSRV_ERROR_OUT_OF_MEMORY;
     }
 
+#if defined (PDUMP)
+	/* Make sure this points nowhere as long as we don't need it */
+	psImport->pszAnnotation = NULL;
+#endif
+
 	/* Setup some known bad values for things we don't have yet */
 	psImport->sDeviceImport.hReservation = LACK_OF_RESERVATION_POISON;
     psImport->sDeviceImport.hMapping = LACK_OF_MAPPING_POISON;
@@ -383,17 +665,16 @@
 */
 IMG_INTERNAL
 PVRSRV_ERROR _DevmemImportStructDevMap(DEVMEM_HEAP *psHeap,
-									   IMG_BOOL bMap,
-									   DEVMEM_IMPORT *psImport,
-									   IMG_UINT64 uiOptionalMapAddress)
+                                       IMG_BOOL bMap,
+                                       DEVMEM_IMPORT *psImport,
+                                       IMG_UINT64 ui64OptionalMapAddress)
 {
 	DEVMEM_DEVICE_IMPORT *psDeviceImport;
-	IMG_BOOL bStatus;
-    RA_BASE_T uiAllocatedAddr;
-    RA_LENGTH_T uiAllocatedSize;
-    IMG_DEV_VIRTADDR sBase;
-    IMG_HANDLE hReservation;
-    PVRSRV_ERROR eError;
+	RA_BASE_T uiAllocatedAddr;
+	RA_LENGTH_T uiAllocatedSize;
+	IMG_DEV_VIRTADDR sBase;
+	IMG_HANDLE hReservation;
+	PVRSRV_ERROR eError;
 	IMG_UINT uiAlign;
 
 	/* Round the provided import alignment to the configured heap alignment */
@@ -415,30 +696,50 @@
 
 		OSAtomicIncrement(&psHeap->hImportCount);
 
-		if (uiOptionalMapAddress == 0)
+		if (PVRSRV_CHECK_SVM_ALLOC(psImport->uiFlags))
 		{
-			if (psHeap->eHeapType == DEVMEM_HEAP_TYPE_USER_MANAGED)
+			/*  SVM (shared virtual memory) imports or allocations always
+				need to acquire CPU virtual address first as address is
+				used to map the allocation into the device virtual address
+				space; i.e. the virtual address of the allocation for both
+				the CPU/GPU must be identical. */
+			eError = _DevmemImportStructDevMapSVM(psHeap,
+												  psImport,
+												  uiAlign,
+												  &ui64OptionalMapAddress);
+			if (eError != PVRSRV_OK)
+			{
+				goto failVMRAAlloc;
+			}
+		}
+
+		if (ui64OptionalMapAddress == 0)
+		{
+			if (psHeap->eHeapType == DEVMEM_HEAP_TYPE_USER_MANAGED ||
+				psHeap->eHeapType == DEVMEM_HEAP_TYPE_KERNEL_MANAGED)
 			{
 				PVR_DPF((PVR_DBG_ERROR,
-						"%s: This heap is managed by the user application itself, "
-						"please continue to use PVRSRVMapToDeviceAddress()."
-						, __func__));
+						psHeap->eHeapType == DEVMEM_HEAP_TYPE_USER_MANAGED ?
+						"%s: Heap is user managed, please use PVRSRVMapToDeviceAddress().":
+						"%s: Heap is kernel managed, use right allocation flags (e.g. SVM).",
+						__func__));
 				eError = PVRSRV_ERROR_INVALID_PARAMS;
 				goto failVMRAAlloc;
 			}
 			psHeap->eHeapType = DEVMEM_HEAP_TYPE_RA_MANAGED;
 
 			/* Allocate space in the VM */
-			bStatus = RA_Alloc(psHeap->psQuantizedVMRA,
-							   psImport->uiSize,
-							   RA_NO_IMPORT_MULTIPLIER,
-							   0, /* flags: this RA doesn't use flags*/
-							   uiAlign,
-							   &uiAllocatedAddr,
-							   &uiAllocatedSize,
-							   NULL /* don't care about per-import priv data */
-							   );
-			if (!bStatus)
+			eError = RA_Alloc(psHeap->psQuantizedVMRA,
+			                  psImport->uiSize,
+			                  RA_NO_IMPORT_MULTIPLIER,
+			                  0, /* flags: this RA doesn't use flags*/
+			                  uiAlign,
+			                  "Virtual_Alloc",
+			                  &uiAllocatedAddr,
+			                  &uiAllocatedSize,
+			                  NULL /* don't care about per-import priv data */
+			                  );
+			if (PVRSRV_OK != eError)
 			{
 				eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_DEVICE_VM;
 				goto failVMRAAlloc;
@@ -453,18 +754,60 @@
 		}
 		else
 		{
-			if (psHeap->eHeapType == DEVMEM_HEAP_TYPE_RA_MANAGED)
+			IMG_UINT64 uiHeapAddrEnd;
+
+			switch (psHeap->eHeapType)
+			{
+				case DEVMEM_HEAP_TYPE_UNKNOWN:
+					/* DEVMEM_HEAP_TYPE_USER_MANAGED can apply to _any_
+					   heap and can only be determined here. This heap
+					   type transitions from DEVMEM_HEAP_TYPE_UNKNOWN
+					   to DEVMEM_HEAP_TYPE_USER_MANAGED on 1st alloc */
+					psHeap->eHeapType = DEVMEM_HEAP_TYPE_USER_MANAGED;
+					break;
+
+				case DEVMEM_HEAP_TYPE_USER_MANAGED:
+				case DEVMEM_HEAP_TYPE_KERNEL_MANAGED:
+					if (! psHeap->uiSize)
+					{
+						PVR_DPF((PVR_DBG_ERROR,
+							psHeap->eHeapType == DEVMEM_HEAP_TYPE_USER_MANAGED ?
+							"%s: Heap DEVMEM_HEAP_TYPE_USER_MANAGED is disabled.":
+							"%s: Heap DEVMEM_HEAP_TYPE_KERNEL_MANAGED is disabled."
+							, __func__));
+						eError = PVRSRV_ERROR_INVALID_HEAP;
+						goto failVMRAAlloc;
+					}
+					break;
+
+				case DEVMEM_HEAP_TYPE_RA_MANAGED:
+					PVR_DPF((PVR_DBG_ERROR,
+						"%s: This heap is managed by an RA, please use PVRSRVMapToDevice()"
+						" and don't use allocation flags that assume differently (e.g. SVM)."
+						, __func__));
+					eError = PVRSRV_ERROR_INVALID_PARAMS;
+					goto failVMRAAlloc;
+
+				default:
+					break;
+			}
+
+			/* Ensure supplied ui64OptionalMapAddress is within heap range */
+			uiHeapAddrEnd = psHeap->sBaseAddress.uiAddr + psHeap->uiSize;
+			if (ui64OptionalMapAddress >= uiHeapAddrEnd ||
+				ui64OptionalMapAddress + psImport->uiSize > uiHeapAddrEnd)
 			{
 				PVR_DPF((PVR_DBG_ERROR,
-						"%s: This heap is managed by an RA, please use PVRSRVMapToDevice()."
-						, __func__));
+						"%s: ui64OptionalMapAddress %p is outside of heap limits <%p:%p>."
+						, __func__
+						, (void*)(uintptr_t)ui64OptionalMapAddress
+						, (void*)(uintptr_t)psHeap->sBaseAddress.uiAddr
+						, (void*)(uintptr_t)uiHeapAddrEnd));
 				eError = PVRSRV_ERROR_INVALID_PARAMS;
 				goto failVMRAAlloc;
 			}
-			psHeap->eHeapType = DEVMEM_HEAP_TYPE_USER_MANAGED;
 
-
-			if (uiOptionalMapAddress & ((1 << psHeap->uiLog2Quantum) - 1))
+			if (ui64OptionalMapAddress & ((1 << psHeap->uiLog2Quantum) - 1))
 			{
 				PVR_DPF((PVR_DBG_ERROR,
 						"%s: Invalid address to map to. Please prove an address aligned to"
@@ -473,7 +816,8 @@
 				eError = PVRSRV_ERROR_INVALID_PARAMS;
 				goto failVMRAAlloc;
 			}
-			uiAllocatedAddr = uiOptionalMapAddress;
+
+			uiAllocatedAddr = ui64OptionalMapAddress;
 
 			if (psImport->uiSize & ((1 << psHeap->uiLog2Quantum) - 1))
 			{
@@ -489,15 +833,15 @@
 		}
 	
 		/* Setup page tables for the allocated VM space */
-	    eError = BridgeDevmemIntReserveRange(psHeap->psCtx->hDevConnection,
+		eError = BridgeDevmemIntReserveRange(psHeap->psCtx->hDevConnection,
 											 psHeap->hDevMemServerHeap,
 											 sBase,
 											 uiAllocatedSize,
 											 &hReservation);
-	    if (eError != PVRSRV_OK)
-	    {
-	        goto failReserve;
-	    }
+		if (eError != PVRSRV_OK)
+		{
+			goto failReserve;
+		}
 
 		if (bMap)
 		{
@@ -544,7 +888,7 @@
 	BridgeDevmemIntUnreserveRange(psHeap->psCtx->hDevConnection,
 								  hReservation);
 failReserve:
-	if (uiOptionalMapAddress == 0)
+	if (ui64OptionalMapAddress == 0)
 	{
 		RA_Free(psHeap->psQuantizedVMRA,
 				uiAllocatedAddr);
@@ -596,8 +940,16 @@
 	    psDeviceImport->hMapping = LACK_OF_MAPPING_POISON;
 	    psDeviceImport->hReservation = LACK_OF_RESERVATION_POISON;
 
-	    RA_Free(psHeap->psQuantizedVMRA,
-	            psDeviceImport->sDevVAddr.uiAddr);
+		if (psHeap->eHeapType == DEVMEM_HEAP_TYPE_RA_MANAGED)
+		{
+			RA_Free(psHeap->psQuantizedVMRA,
+					psDeviceImport->sDevVAddr.uiAddr);
+		}
+
+		if (PVRSRV_CHECK_SVM_ALLOC(psImport->uiFlags))
+		{
+			_DevmemImportStructDevUnmapSVM(psHeap, psImport);
+		}
 
 	    OSLockRelease(psDeviceImport->hLock);
 
@@ -680,15 +1032,19 @@
 
 	if (--psCPUImport->ui32RefCount == 0)
 	{
+		/* FIXME: psImport->uiSize is a 64-bit quantity where as the 5th
+		 * argument to OSUnmapPMR is a 32-bit quantity on 32-bit systems
+		 * hence a compiler warning of implicit cast and loss of data.
+		 * Added explicit cast and assert to remove warning.
+		 */
 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
 		PVR_ASSERT(psImport->uiSize<IMG_UINT32_MAX);
 #endif
-
 		OSMUnmapPMR(psImport->hDevConnection,
-		            psImport->hPMR,
-		            psCPUImport->hOSMMapData,
-		            psCPUImport->pvCPUVAddr,
-		            (size_t)psImport->uiSize);
+					psImport->hPMR,
+					psCPUImport->hOSMMapData,
+					psCPUImport->pvCPUVAddr,
+					psImport->uiSize);
 
 		OSLockRelease(psCPUImport->hLock);
 
diff --git a/drivers/staging/imgtec/rogue/devicemem_utils.h b/drivers/staging/imgtec/rogue/devicemem_utils.h
index fa10867..884ab49 100644
--- a/drivers/staging/imgtec/rogue/devicemem_utils.h
+++ b/drivers/staging/imgtec/rogue/devicemem_utils.h
@@ -53,7 +53,7 @@
 #include "ra.h"
 #include "osfunc.h"
 #include "lock.h"
-#include "devicemem_mmap.h"
+#include "osmmap.h"
 #include "devicemem_utils.h"
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
 #include "mm_common.h"
@@ -106,8 +106,8 @@
     /* The cache line size for use when allocating memory, as it is not queryable on the client side */
     IMG_UINT32 ui32CPUCacheLineSize;
 
-    /* Private data handle for device specific data */
-    IMG_HANDLE hPrivData;
+	/* Private data handle for device specific data */
+	IMG_HANDLE hPrivData;
 };
 
 
@@ -115,55 +115,62 @@
 {
 	DEVMEM_HEAP_TYPE_UNKNOWN = 0,
 	DEVMEM_HEAP_TYPE_USER_MANAGED,
-	DEVMEM_HEAP_TYPE_RA_MANAGED
+	DEVMEM_HEAP_TYPE_KERNEL_MANAGED,
+	DEVMEM_HEAP_TYPE_RA_MANAGED,
 }DEVMEM_HEAP_TYPE;
 
 struct _DEVMEM_HEAP_ {
-    /* Name of heap - for debug and lookup purposes. */
-    IMG_CHAR *pszName;
+	/* Name of heap - for debug and lookup purposes. */
+	IMG_CHAR *pszName;
 
-    /* Number of live imports in the heap */
-    ATOMIC_T hImportCount;
+	/* Number of live imports in the heap */
+	ATOMIC_T hImportCount;
 
-    /*
-     * Base address of heap, required by clients due to some requesters
-     * not being full range 
-     */
-    IMG_DEV_VIRTADDR sBaseAddress;
+	/*
+	* Base address and size of heap, required by clients due to some requesters
+	* not being full range
+	*/
+	IMG_DEV_VIRTADDR sBaseAddress;
+	DEVMEM_SIZE_T uiSize;
 
-    /* The heap type, describing if the space is managed by the user or an RA*/
-    DEVMEM_HEAP_TYPE eHeapType;
+	/* The heap type, describing if the space is managed by the user or an RA*/
+	DEVMEM_HEAP_TYPE eHeapType;
 
-    /* This RA is for managing sub-allocations in virtual space.  Two
-       more RA's will be used under the Hood for managing the coarser
-       allocation of virtual space from the heap, and also for
-       managing the physical backing storage. */
-    RA_ARENA *psSubAllocRA;
-    IMG_CHAR *pszSubAllocRAName;
-    /*
-      This RA is for the coarse allocation of virtual space from the heap
-    */
-    RA_ARENA *psQuantizedVMRA;
-    IMG_CHAR *pszQuantizedVMRAName;
+	/* This RA is for managing sub-allocations in virtual space.  Two
+	more RA's will be used under the Hood for managing the coarser
+	allocation of virtual space from the heap, and also for
+	managing the physical backing storage. */
+	RA_ARENA *psSubAllocRA;
+	IMG_CHAR *pszSubAllocRAName;
+	/*
+	This RA is for the coarse allocation of virtual space from the heap
+	*/
+	RA_ARENA *psQuantizedVMRA;
+	IMG_CHAR *pszQuantizedVMRAName;
 
-    /* We also need to store a copy of the quantum size in order to
-       feed this down to the server */
-    IMG_UINT32 uiLog2Quantum;
+	/* We also need to store a copy of the quantum size in order to
+	feed this down to the server */
+	IMG_UINT32 uiLog2Quantum;
 
-    /* Store a copy of the minimum import alignment */
-    IMG_UINT32 uiLog2ImportAlignment;
+	/* Store a copy of the minimum import alignment */
+	IMG_UINT32 uiLog2ImportAlignment;
 
-    /* The parent memory context for this heap */
-    struct _DEVMEM_CONTEXT_ *psCtx;
+	/* The relationship between tiled heap alignment and heap byte-stride
+	 * (dependent on tiling mode, abstracted here) */
+	IMG_UINT32 uiLog2TilingStrideFactor;
 
-	POS_LOCK hLock;							/*!< Lock to protect this structure */
+	/* The parent memory context for this heap */
+	struct _DEVMEM_CONTEXT_ *psCtx;
 
-    /*
-      Each "DEVMEM_HEAP" has a counterpart in the server,
-      which is responsible for handling the mapping into device MMU.
-      We have a handle to that here.
-    */
-    IMG_HANDLE hDevMemServerHeap;
+	/* Lock to protect this structure */
+	POS_LOCK hLock;
+
+	/*
+	Each "DEVMEM_HEAP" has a counterpart in the server,
+	which is responsible for handling the mapping into device MMU.
+	We have a handle to that here.
+	*/
+	IMG_HANDLE hDevMemServerHeap;
 };
 
 typedef IMG_UINT32 DEVMEM_PROPERTIES_T;                 /*!< Typedef for Devicemem properties */
@@ -171,7 +178,10 @@
 #define DEVMEM_PROPERTIES_IMPORTED          (1UL<<1)    /*!< Is it imported from another process? */
 #define DEVMEM_PROPERTIES_SUBALLOCATABLE    (1UL<<2)    /*!< Is it suballocatable? */
 #define DEVMEM_PROPERTIES_UNPINNED          (1UL<<3)    /*!< Is it currently pinned? */
-#define DEVMEM_PROPERTIES_IMPORT_IS_CLEAN   (1UL<<4)    /*!< Is the import clean, e.g. properly zeroed and cache clean? */
+#define DEVMEM_PROPERTIES_IMPORT_IS_ZEROED  (1UL<<4)	/*!< Is the memory fully zeroed? */
+#define DEVMEM_PROPERTIES_IMPORT_IS_CLEAN   (1UL<<5)	/*!< Is the memory clean, i.e. not been used before? */
+#define DEVMEM_PROPERTIES_SECURE            (1UL<<6)    /*!< Is it a special secure buffer? No CPU maps allowed! */
+
 
 typedef struct _DEVMEM_DEVICE_IMPORT_ {
 	DEVMEM_HEAP *psHeap;			/*!< Heap this import is bound to */
@@ -203,6 +213,9 @@
 
 	DEVMEM_DEVICE_IMPORT sDeviceImport;	/*!< Device specifics of the import */
 	DEVMEM_CPU_IMPORT sCPUImport;		/*!< CPU specifics of the import */
+#if defined(PDUMP)
+	IMG_CHAR *pszAnnotation;
+#endif
 } DEVMEM_IMPORT;
 
 typedef struct _DEVMEM_DEVICE_MEMDESC_ {
@@ -223,6 +236,7 @@
 	IMG_DEVMEM_SIZE_T uiAllocSize;          /*!< Size of the allocation */
     ATOMIC_T hRefCount;						/*!< Refcount of the memdesc */
     POS_LOCK hLock;							/*!< Lock to protect memdesc */
+    IMG_HANDLE hPrivData;
 
 	DEVMEM_DEVICE_MEMDESC sDeviceMemDesc;	/*!< Device specifics of the memdesc */
 	DEVMEM_CPU_MEMDESC sCPUMemDesc;		/*!< CPU specifics of the memdesc */
@@ -272,12 +286,12 @@
 
 @Input          uiSize      Size of the import.
 @Input          uiAlign     Alignment of the import.
-@Input          uiFlags     Flags for the import.
+@Input          puiFlags    Pointer to the flags for the import.
 @return         PVRSRV_ERROR
 ******************************************************************************/
 PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
-								   IMG_DEVMEM_ALIGN_T uiAlign,
-								   DEVMEM_FLAGS_T uiFlags);
+                                   IMG_DEVMEM_ALIGN_T uiAlign,
+                                   DEVMEM_FLAGS_T *puiFlags);
 
 /******************************************************************************
 @Function       _DevmemImportStructAlloc
diff --git a/drivers/staging/imgtec/rogue/devicememx.h b/drivers/staging/imgtec/rogue/devicememx.h
index b25f5bf..75d58a6 100644
--- a/drivers/staging/imgtec/rogue/devicememx.h
+++ b/drivers/staging/imgtec/rogue/devicememx.h
@@ -62,7 +62,7 @@
                     IMG_UINT32 uiNumPages,
                     IMG_UINT32 uiLog2PageSize,
                     DEVMEM_FLAGS_T uiFlags,
-                    const IMG_PCHAR pszText,
+                    const IMG_CHAR *pszText,
                     DEVMEMX_PHYSDESC **ppsPhysDesc);
 
 /* DevmemXReleasePhysical()
@@ -82,7 +82,7 @@
 DevmemXAllocVirtual(DEVMEM_HEAP* hHeap,
                    IMG_UINT32 uiNumPages,
                    DEVMEM_FLAGS_T uiFlags,
-                   const IMG_PCHAR pszText,
+                   const IMG_CHAR *pszText,
                    DEVMEMX_VIRTDESC **ppsVirtDesc,
                    IMG_DEV_VIRTADDR *psVirtAddr);
 
@@ -141,8 +141,7 @@
  */
 
 PVRSRV_ERROR
-DevmemXCreateDevmemMemDesc(DEVMEMX_PHYSDESC *psPhysDesc,
-                            DEVMEMX_VIRTDESC *psVirtDesc,
+DevmemXCreateDevmemMemDesc(DEVMEMX_VIRTDESC *psVirtDesc,
                             DEVMEM_MEMDESC **ppsMemDesc);
 
 /* DevmemXFreeDevmemMemDesc()
@@ -156,4 +155,22 @@
 PVRSRV_ERROR
 DevmemXFreeDevmemMemDesc(DEVMEM_MEMDESC *psMemDesc);
 
+PVRSRV_ERROR
+_DevmemXFlagCompatibilityCheck(IMG_UINT32 uiPhysFlags,
+                              IMG_UINT32 uiVirtFlags);
+
+PVRSRV_ERROR
+_DevmemXPhysDescAlloc(DEVMEMX_PHYSDESC **ppsPhysDesc);
+
+void
+_DevmemXPhysDescInit(DEVMEMX_PHYSDESC *psPhysDesc,
+                    IMG_HANDLE hPMR,
+                    IMG_UINT32 uiNumPages,
+                    IMG_UINT32 uiLog2PageSize,
+                    PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                    IMG_HANDLE hBridge);
+
+void
+_DevmemXPhysDescFree(DEVMEMX_PHYSDESC *psPhysDesc);
+
 #endif /* DEVICEMEMX_H */
diff --git a/drivers/staging/imgtec/rogue/dllist.h b/drivers/staging/imgtec/rogue/dllist.h
index 13d5805..f1ab383 100644
--- a/drivers/staging/imgtec/rogue/dllist.h
+++ b/drivers/staging/imgtec/rogue/dllist.h
@@ -91,7 +91,6 @@
 	psListHead->psNextNode = psListHead;
 }
 
-
 /*************************************************************************/ /*!
 @Function       dllist_is_empty
 
@@ -104,11 +103,10 @@
 static INLINE
 IMG_BOOL dllist_is_empty(PDLLIST_NODE psListHead)
 {
-	return ((psListHead->psPrevNode == psListHead) 
-				&& (psListHead->psNextNode == psListHead));
+	return (IMG_BOOL) ((psListHead->psPrevNode == psListHead)
+	                   && (psListHead->psNextNode == psListHead));
 }
 
-
 /*************************************************************************/ /*!
 @Function       dllist_add_to_head
 
@@ -158,7 +156,6 @@
 	psNewNode->psNextNode = psListHead;
 }
 
-
 /*************************************************************************/ /*!
 @Function       dllist_node_is_in_list
 
@@ -171,10 +168,9 @@
 static INLINE
 IMG_BOOL dllist_node_is_in_list(PDLLIST_NODE psNode)
 {
-	return (psNode->psNextNode != 0);
+	return (IMG_BOOL) (psNode->psNextNode != 0);
 }
 
-
 /*************************************************************************/ /*!
 @Function       dllist_get_next_node
 
@@ -219,6 +215,43 @@
 	psListNode->psNextNode = 0;
 }
 
+/*************************************************************************/ /*!
+@Function       dllist_replace_head
+
+@Description    Moves the list from psOldHead to psNewHead
+
+@Input          psOldHead       List node to be replaced. Will become a head
+                                node of an empty list.
+@Input          psNewHead       List node to be inserted. Must be an empty list
+                                head.
+
+*/
+/*****************************************************************************/
+static INLINE
+void dllist_replace_head(PDLLIST_NODE psOldHead, PDLLIST_NODE psNewHead)
+{
+	if (dllist_is_empty(psOldHead))
+	{
+		psNewHead->psNextNode = psNewHead;
+		psNewHead->psPrevNode = psNewHead;
+	}
+	else
+	{
+		/* Change the neighbouring nodes */
+		psOldHead->psNextNode->psPrevNode = psNewHead;
+		psOldHead->psPrevNode->psNextNode = psNewHead;
+
+		/* Copy the old data to the new node */
+		psNewHead->psNextNode = psOldHead->psNextNode;
+		psNewHead->psPrevNode = psOldHead->psPrevNode;
+
+		/* Remove links to the previous list */
+		psOldHead->psNextNode = psOldHead;
+		psOldHead->psPrevNode = psOldHead;
+	}
+
+
+}
 
 /*************************************************************************/ /*!
 @Function       dllist_foreach_node
diff --git a/drivers/staging/imgtec/rogue/driverlock.h b/drivers/staging/imgtec/rogue/driverlock.h
deleted file mode 100644
index 1c3db37..0000000
--- a/drivers/staging/imgtec/rogue/driverlock.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*************************************************************************/ /*!
-@File           driverlock.h
-@Title          Main driver lock
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    The main driver lock, held in most places in
-                the driver.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#ifndef __DRIVERLOCK_H__
-#define __DRIVERLOCK_H__
-
-/*
- * Main driver lock, used to ensure driver code is single threaded.
- * There are some places where this lock must not be taken, such as
- * in the mmap related deriver entry points.
- */
-extern struct mutex gPVRSRVLock;
-
-/*
- * This Lock is used to protect the sequence of operation used in MMapPMR and in
- * the memory management bridge. This makes it possible avoid the use of the bridge
- * lock in mmap.c
- * The global bridge lock can not be taken in the mmap entry point due to a
- * AB-BA deadlock risk with the Linux mmap semaphore.
- */
-extern struct mutex gGlobalLookupPMRLock;
-
-#endif /* __DRIVERLOCK_H__ */
-/*****************************************************************************
- End of file (driverlock.h)
-*****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/drm_pci_module.c b/drivers/staging/imgtec/rogue/drm_pci_module.c
deleted file mode 100644
index d777d1a..0000000
--- a/drivers/staging/imgtec/rogue/drm_pci_module.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Linux module setup
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <drm/drmP.h>
-#include "pvr_debug.h"
-#include "srvkm.h"
-#include "pvrmodule.h"
-#include "linkage.h"
-#include "sysinfo.h"
-#include "module_common.h"
-#include "syscommon.h"
-
-#if defined(SUPPORT_DRM_EXT)
-#include "pvr_drm_ext.h"
-#endif
-
-#include "pvr_drm.h"
-
-#if defined(SUPPORT_SHARED_SLC)
-#include "rgxapi_km.h"
-#endif
-
-/*
- * DRVNAME is the name we use to register our driver.
- * DEVNAME is the name we use to register actual device nodes.
- */
-#define	DRVNAME		PVR_LDM_DRIVER_REGISTRATION_NAME
-#define DEVNAME		PVRSRV_MODNAME
-
-/*
- * This is all module configuration stuff required by the linux kernel.
- */
-MODULE_SUPPORTED_DEVICE(DEVNAME);
-
-#if defined(SUPPORT_SHARED_SLC)
-EXPORT_SYMBOL(RGXInitSLC);
-#endif
-
-#define	LDM_DRV	struct pci_driver
-
-static void PVRSRVDriverRemove(struct pci_dev *device);
-static int PVRSRVDriverProbe(struct pci_dev *device, const struct pci_device_id *id);
-
-/* This structure is used by the Linux module code */
-struct pci_device_id powervr_id_table[] __devinitdata = {
-	{PCI_DEVICE(SYS_RGX_DEV_VENDOR_ID, SYS_RGX_DEV_DEVICE_ID)},
-#if defined (SYS_RGX_DEV1_DEVICE_ID)
-	{PCI_DEVICE(SYS_RGX_DEV_VENDOR_ID, SYS_RGX_DEV1_DEVICE_ID)},
-#endif
-	{0}
-};
-#if !defined(SUPPORT_DRM_EXT)
-MODULE_DEVICE_TABLE(pci, powervr_id_table);
-#endif
-
-static struct dev_pm_ops powervr_dev_pm_ops = {
-	.suspend	= PVRSRVDriverSuspend,
-	.resume		= PVRSRVDriverResume,
-};
-
-static LDM_DRV powervr_driver = {
-	.name		= DRVNAME,
-	.driver.pm	= &powervr_dev_pm_ops,
-	.id_table	= powervr_id_table,
-	.probe		= PVRSRVDriverProbe,
-	.remove		= __devexit_p(PVRSRVDriverRemove),
-	.shutdown	= PVRSRVDriverShutdown,
-};
-
-static IMG_BOOL bCalledSysInit = IMG_FALSE;
-static IMG_BOOL	bDriverProbeSucceeded = IMG_FALSE;
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVSystemInit
-
- @Description
-
- Wrapper for PVRSRVInit.
-
- @input pDevice - the device for which a probe is requested
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-int PVRSRVSystemInit(struct drm_device *pDrmDevice)
-{
-	struct pci_dev *pDevice = pDrmDevice->pdev;
-
-	PVR_TRACE(("PVRSRVSystemInit (pDevice=%p)", pDevice));
-
-	/* PVRSRVInit is only designed to be called once */
-	if (bCalledSysInit == IMG_FALSE)
-	{
-		gpsPVRLDMDev = pDevice;
-		bCalledSysInit = IMG_TRUE;
-
-		if (PVRSRVInit(pDevice) != PVRSRV_OK)
-		{
-			return -ENODEV;
-		}
-	}
-
-	return 0;
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVSystemDeInit
-
- @Description
-
- Wrapper for PVRSRVDeInit.
-
- @input pDevice - the device for which driver detachment is happening
- @Return nothing.
-
-*****************************************************************************/
-void PVRSRVSystemDeInit(struct pci_dev *pDevice)
-{
-	PVR_TRACE(("PVRSRVSystemDeInit"));
-
-	PVRSRVDeInit(pDevice);
-
-	gpsPVRLDMDev = NULL;
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVDriverProbe
-
- @Description
-
- See whether a given device is really one we can drive.
-
- @input pDevice - the device for which a probe is requested
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-static int __devinit PVRSRVDriverProbe(struct pci_dev *pDevice, const struct pci_device_id *pID)
-{
-	int result = 0;
-
-	PVR_TRACE(("PVRSRVDriverProbe (pDevice=%p)", pDevice));
-
-#if !defined(SUPPORT_DRM_EXT)
-	result = drm_get_pci_dev(pDevice, pID, &sPVRDRMDriver);
-#endif
-
-	bDriverProbeSucceeded = (result == 0);
-	return result;
-}
-
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVDriverRemove
-
- @Description
-
- This call is the opposite of the probe call; it is called when the device is
- being removed from the driver's control.
-
- @input pDevice - the device for which driver detachment is happening
-
- @Return 0, or no return value at all, depending on the device type.
-
-*****************************************************************************/
-static void __devexit PVRSRVDriverRemove(struct pci_dev *pDevice)
-{
-	PVR_TRACE(("PVRSRVDriverRemove (pDevice=%p)", pDevice));
-
-#if !defined(SUPPORT_DRM_EXT)
-	drm_put_dev(pci_get_drvdata(pDevice));
-#else	/* !defined(SUPPORT_DRM_EXT) */
-	PVRSRVSystemDeInit(pDevice);
-#endif	/* !defined(SUPPORT_DRM_EXT) */
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVOpen
-
- @Description
-
- Open the PVR services node.
-
- @input pInode - the inode for the file being openeded.
- @input dev    - the DRM device corresponding to this driver.
-
- @input pFile - the file handle data for the actual file being opened
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pDRMFile)
-{
-	int err;
-
-	struct file *pFile = PVR_FILE_FROM_DRM_FILE(pDRMFile);
-
-	if (!try_module_get(THIS_MODULE))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "Failed to get module"));
-		return -ENOENT;
-	}
-
-	if ((err = PVRSRVCommonOpen(pFile)) != 0)
-	{
-		module_put(THIS_MODULE);
-	}
-
-	return err;
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVRelease
-
- @Description
-
- Release access the PVR services node - called when a file is closed, whether
- at exit or using close(2) system call.
-
- @input pInode - the inode for the file being released
- @input pvPrivData - driver private data
-
- @input pFile - the file handle data for the actual file being released
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-void PVRSRVRelease(struct drm_device unref__ *dev, struct drm_file *pDRMFile)
-{
-	struct file *pFile = PVR_FILE_FROM_DRM_FILE(pDRMFile);
-
-	PVRSRVCommonRelease(pFile);
-
-	module_put(THIS_MODULE);
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRCore_Init
-
- @Description
-
- Insert the driver into the kernel.
-
- Readable and/or writable debugfs entries under /sys/kernel/debug/pvr are
- created with PVRDebugFSCreateEntry().  These can be read at runtime to get
- information about the device (eg. 'cat /sys/kernel/debug/pvr/nodes')
-
- __init places the function in a special memory section that the kernel frees
- once the function has been run.  Refer also to module_init() macro call below.
-
- @input none
-
- @Return none
-
-*****************************************************************************/
-#if defined(SUPPORT_DRM_EXT)
-int PVRCore_Init(void)
-#else
-static int __init PVRCore_Init(void)
-#endif
-{
-	int error = 0;
-
-	PVR_TRACE(("PVRCore_Init"));
-
-#if defined(PDUMP)
-	error = dbgdrv_init();
-	if (error != 0)
-	{
-		return error;
-	}
-#endif
-
-	if ((error = PVRSRVDriverInit()) != 0)
-	{
-		return error;
-	}
-
-#if !defined(SUPPORT_DRM_EXT)
-	error = drm_pci_init(&sPVRDRMDriver, &powervr_driver);
-	if (error != 0)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
-		return error;
-	}
-#else
-	if (!bDriverProbeSucceeded)
-	{
-		error = PVRSRVInit(gpsPVRLDMDev);
-		if (error != 0)
-		{
-			PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemInit: unable to init PVR service (%d)", error));
-			return error;
-		}
-		bDriverProbeSucceeded = IMG_TRUE;
-	}
-#endif /* defined(SUPPORT_DRM_EXT) */
-
-	if (!bDriverProbeSucceeded)
-	{
-		PVR_TRACE(("PVRCore_Init: PVRSRVDriverProbe has not been called or did not succeed - check that hardware is detected"));
-		return error;
-	}
-
-	return PVRSRVDeviceInit();
-}
-
-
-/*!
-*****************************************************************************
-
- @Function		PVRCore_Cleanup
-
- @Description	
-
- Remove the driver from the kernel.
-
- There's no way we can get out of being unloaded other than panicking; we
- just do everything and plough on regardless of error.
-
- __exit places the function in a special memory section that the kernel frees
- once the function has been run.  Refer also to module_exit() macro call below.
-
- @input none
-
- @Return none
-
-*****************************************************************************/
-#if defined(SUPPORT_DRM_EXT)
-void PVRCore_Cleanup(void)
-#else
-static void __exit PVRCore_Cleanup(void)
-#endif
-{
-	PVR_TRACE(("PVRCore_Cleanup"));
-
-	PVRSRVDeviceDeinit();
-	
-#if !defined(SUPPORT_DRM_EXT)
-	drm_pci_exit(&sPVRDRMDriver, &powervr_driver);
-#else
-	pci_unregister_driver(&powervr_driver);
-#endif
-
-	PVRSRVDriverDeinit();
-
-#if defined(PDUMP)
-	dbgdrv_cleanup();
-#endif
-	PVR_TRACE(("PVRCore_Cleanup: unloading"));
-}
-
-/*
- * These macro calls define the initialisation and removal functions of the
- * driver.  Although they are prefixed `module_', they apply when compiling
- * statically as well; in both cases they define the function the kernel will
- * run to start/stop the driver.
-*/
-#if !defined(SUPPORT_DRM_EXT)
-module_init(PVRCore_Init);
-module_exit(PVRCore_Cleanup);
-#endif
diff --git a/drivers/staging/imgtec/rogue/env_connection.h b/drivers/staging/imgtec/rogue/env_connection.h
index 5bf9948..46b98e2 100644
--- a/drivers/staging/imgtec/rogue/env_connection.h
+++ b/drivers/staging/imgtec/rogue/env_connection.h
@@ -45,6 +45,7 @@
 #define _ENV_CONNECTION_H_
 
 #include <linux/list.h>
+#include <linux/types.h>
 
 #include "handle.h"
 #include "pvr_debug.h"
@@ -76,6 +77,8 @@
 
 typedef struct _ENV_CONNECTION_DATA_
 {
+	pid_t owner;
+
 	struct file *psFile;
 	PVRSRV_DEVICE_NODE *psDevNode;
 
diff --git a/drivers/staging/imgtec/rogue/env_data.h b/drivers/staging/imgtec/rogue/env_data.h
deleted file mode 100644
index 7e5eb03..0000000
--- a/drivers/staging/imgtec/rogue/env_data.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Environmental Data header file
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Linux-specific part of system data.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#ifndef _ENV_DATA_
-#define _ENV_DATA_
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-
-#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
-#include <linux/workqueue.h>
-#endif
-
-#endif /* _ENV_DATA_ */
-/*****************************************************************************
- End of file (env_data.h)
-*****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/event.c b/drivers/staging/imgtec/rogue/event.c
index d2c0002..86fc2eb 100644
--- a/drivers/staging/imgtec/rogue/event.c
+++ b/drivers/staging/imgtec/rogue/event.c
@@ -40,12 +40,8 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include <linux/version.h>
 #include <asm/io.h>
 #include <asm/page.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) )
-#include <asm/system.h>
-#endif
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -62,9 +58,6 @@
 #include "img_types.h"
 #include "pvrsrv_error.h"
 #include "allocmem.h"
-#include "mm.h"
-#include "env_data.h"
-#include "driverlock.h"
 #include "event.h"
 #include "pvr_debug.h"
 #include "pvrsrv.h"
@@ -73,7 +66,9 @@
 
 /* Returns pointer to task_struct that belongs to thread which acquired
  * bridge lock. */
-extern struct task_struct *OSGetBridgeLockOwner(void);
+extern struct task_struct *BridgeLockGetOwner(void);
+extern IMG_BOOL BridgeLockIsLocked(void);
+
 
 typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
 {
@@ -113,7 +108,7 @@
 {
 	PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
 
-	psEvenObjectList = OSAllocMem(sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST));
+	psEvenObjectList = OSAllocMem(sizeof(*psEvenObjectList));
 	if (psEvenObjectList == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
@@ -220,7 +215,7 @@
 	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
 
 	/* allocate completion variable */
-	psLinuxEventObject = OSAllocMem(sizeof(PVRSRV_LINUX_EVENT_OBJECT));
+	psLinuxEventObject = OSAllocMem(sizeof(*psLinuxEventObject));
 	if (psLinuxEventObject == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
@@ -295,28 +290,36 @@
 
  @Input    hOSEventObject : Event object handle
 
- @Input   ui32MSTimeout : Time out value in msec
+ @Input   ui64Timeoutus : Time out value in usec
 
  @Return   PVRSRV_ERROR  :  Error code
 
 ******************************************************************************/
-PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout, IMG_BOOL bHoldBridgeLock)
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT64 ui64Timeoutus, IMG_BOOL bHoldBridgeLock)
 {
 	IMG_UINT32 ui32TimeStamp;
 	IMG_BOOL bReleasePVRLock;
 	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	IMG_UINT32 ui32Remainder;
+	long timeOutJiffies;
 	DEFINE_WAIT(sWait);
 
 	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
 
-	IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
-
 	/* Check if the driver is good shape */
 	if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
 	{
 		return PVRSRV_ERROR_TIMEOUT;
 	}
 
+	/* usecs_to_jiffies only takes an uint. So if our timeout is bigger than an
+	 * uint use the msec version. With such a long timeout we really don't need
+	 * the high resolution of usecs. */
+	if (ui64Timeoutus > 0xffffffffULL)
+		timeOutJiffies = msecs_to_jiffies(OSDivide64(ui64Timeoutus, 1000, &ui32Remainder));
+	else
+		timeOutJiffies = usecs_to_jiffies(ui64Timeoutus);
+
 	do
 	{
 		prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
@@ -331,13 +334,13 @@
 		 * 'release before deschedule' behaviour. Some threads choose not to
 		 * hold the bridge lock in their implementation.
 		 */
-		bReleasePVRLock = (!bHoldBridgeLock && mutex_is_locked(&gPVRSRVLock) && current == OSGetBridgeLockOwner());
+		bReleasePVRLock = (!bHoldBridgeLock && BridgeLockIsLocked() && current == BridgeLockGetOwner());
 		if (bReleasePVRLock == IMG_TRUE)
 		{
 			OSReleaseBridgeLock();
 		}
 
-		ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+		timeOutJiffies = schedule_timeout(timeOutJiffies);
 
 		if (bReleasePVRLock == IMG_TRUE)
 		{
@@ -349,12 +352,12 @@
 #endif
 
 
-	} while (ui32TimeOutJiffies);
+	} while (timeOutJiffies);
 
 	finish_wait(&psLinuxEventObject->sWait, &sWait);
 
 	psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
 
-	return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+	return timeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
 
 }
diff --git a/drivers/staging/imgtec/rogue/event.h b/drivers/staging/imgtec/rogue/event.h
index 9063f88..5b14cec 100644
--- a/drivers/staging/imgtec/rogue/event.h
+++ b/drivers/staging/imgtec/rogue/event.h
@@ -45,4 +45,4 @@
 PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
 PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObject);
 PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
-PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout, IMG_BOOL bHoldBridgeLock);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT64 ui64Timeoutus, IMG_BOOL bHoldBridgeLock);
diff --git a/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h b/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h
index 75d7dd0..28d3fd2 100644
--- a/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for breakpoint
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for breakpoint
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for breakpoint
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_BREAKPOINT_BRIDGE_H
 #define COMMON_BREAKPOINT_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c b/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c
index a316661f..a6de6ae 100644
--- a/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c
@@ -63,6 +63,9 @@
 
 
 
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
+
+
 
 /* ***************************************************************************
  * Server-side bridge entry points
@@ -74,6 +77,7 @@
 					  PVRSRV_BRIDGE_OUT_RGXSETBREAKPOINT *psRGXSetBreakpointOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPrivData = psRGXSetBreakpointIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 
 
@@ -82,19 +86,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXSetBreakpointOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXSetBreakpointIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXSetBreakpointOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXSetBreakpoint_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXSetBreakpointOUT->eError =
 		PVRSRVRGXSetBreakpointKM(psConnection, OSGetDevData(psConnection),
@@ -109,15 +123,38 @@
 
 RGXSetBreakpoint_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXClearBreakpoint(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCLEARBREAKPOINT *psRGXClearBreakpointIN,
 					  PVRSRV_BRIDGE_OUT_RGXCLEARBREAKPOINT *psRGXClearBreakpointOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPrivData = psRGXClearBreakpointIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 
 
@@ -126,19 +163,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXClearBreakpointOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXClearBreakpointIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXClearBreakpointOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXClearBreakpoint_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXClearBreakpointOUT->eError =
 		PVRSRVRGXClearBreakpointKM(psConnection, OSGetDevData(psConnection),
@@ -149,15 +196,38 @@
 
 RGXClearBreakpoint_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXEnableBreakpoint(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXENABLEBREAKPOINT *psRGXEnableBreakpointIN,
 					  PVRSRV_BRIDGE_OUT_RGXENABLEBREAKPOINT *psRGXEnableBreakpointOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPrivData = psRGXEnableBreakpointIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 
 
@@ -166,19 +236,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXEnableBreakpointOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXEnableBreakpointIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXEnableBreakpointOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXEnableBreakpoint_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXEnableBreakpointOUT->eError =
 		PVRSRVRGXEnableBreakpointKM(psConnection, OSGetDevData(psConnection),
@@ -189,15 +269,38 @@
 
 RGXEnableBreakpoint_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDisableBreakpoint(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDISABLEBREAKPOINT *psRGXDisableBreakpointIN,
 					  PVRSRV_BRIDGE_OUT_RGXDISABLEBREAKPOINT *psRGXDisableBreakpointOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPrivData = psRGXDisableBreakpointIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 
 
@@ -206,19 +309,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXDisableBreakpointOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXDisableBreakpointIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXDisableBreakpointOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXDisableBreakpoint_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXDisableBreakpointOUT->eError =
 		PVRSRVRGXDisableBreakpointKM(psConnection, OSGetDevData(psConnection),
@@ -229,9 +342,31 @@
 
 RGXDisableBreakpoint_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXOverallocateBPRegisters(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXOVERALLOCATEBPREGISTERS *psRGXOverallocateBPRegistersIN,
@@ -245,6 +380,7 @@
 
 
 
+
 	psRGXOverallocateBPRegistersOUT->eError =
 		PVRSRVRGXOverallocateBPRegistersKM(psConnection, OSGetDevData(psConnection),
 					psRGXOverallocateBPRegistersIN->ui32TempRegs,
@@ -254,17 +390,23 @@
 
 
 
+
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
 
 static IMG_BOOL bUseLock = IMG_TRUE;
+#endif /* EXCLUDE_BREAKPOINT_BRIDGE */
 
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
 PVRSRV_ERROR InitBREAKPOINTBridge(void);
 PVRSRV_ERROR DeinitBREAKPOINTBridge(void);
 
@@ -300,4 +442,14 @@
 {
 	return PVRSRV_OK;
 }
+#else /* EXCLUDE_BREAKPOINT_BRIDGE */
+/* This bridge is conditional on EXCLUDE_BREAKPOINT_BRIDGE - when defined,
+ * do not populate the dispatch table with its functions
+ */
+#define InitBREAKPOINTBridge() \
+	PVRSRV_OK
 
+#define DeinitBREAKPOINTBridge() \
+	PVRSRV_OK
+
+#endif /* EXCLUDE_BREAKPOINT_BRIDGE */
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h b/drivers/staging/imgtec/rogue/generated/cache_bridge/client_cache_bridge.h
similarity index 67%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
copy to drivers/staging/imgtec/rogue/generated/cache_bridge/client_cache_bridge.h
index 839a17a..815c0b8 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/cache_bridge/client_cache_bridge.h
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          Client bridge header for cachegeneric
+@Title          Client bridge header for cache
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Exports the client bridge functions for cachegeneric
+@Description    Exports the client bridge functions for cache
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,8 +41,8 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef CLIENT_CACHEGENERIC_BRIDGE_H
-#define CLIENT_CACHEGENERIC_BRIDGE_H
+#ifndef CLIENT_CACHE_BRIDGE_H
+#define CLIENT_CACHE_BRIDGE_H
 
 #include "img_defs.h"
 #include "pvrsrv_error.h"
@@ -52,13 +52,35 @@
 #include "pvr_bridge.h"
 #endif
 
-#include "common_cachegeneric_bridge.h"
+#include "common_cache_bridge.h"
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp);
+							  IMG_UINT32 ui32NumCacheOps,
+							  IMG_HANDLE *phPMR,
+							  IMG_DEVMEM_OFFSET_T *puiOffset,
+							  IMG_DEVMEM_SIZE_T *puiSize,
+							  PVRSRV_CACHE_OP *piuCacheOp,
+							  IMG_UINT32 *pui32CacheOpSeqNum);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpExec(IMG_HANDLE hBridge,
+							 IMG_HANDLE hPMR,
+							 IMG_DEVMEM_OFFSET_T uiOffset,
+							 IMG_DEVMEM_SIZE_T uiSize,
+							 PVRSRV_CACHE_OP iuCacheOp);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpSetTimeline(IMG_HANDLE hBridge,
+								IMG_INT32 i32OpTimeline);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpLog(IMG_HANDLE hBridge,
+							IMG_HANDLE hPMR,
+							IMG_DEVMEM_OFFSET_T uiOffset,
+							IMG_DEVMEM_SIZE_T uiSize,
+							IMG_INT64 i64QueuedTimeUs,
+							IMG_INT64 i64ExecuteTimeUs,
+							PVRSRV_CACHE_OP iuCacheOp);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpGetLineSize(IMG_HANDLE hBridge,
+								IMG_UINT32 *pui32L1DataCacheLineSize);
 
 
-#endif /* CLIENT_CACHEGENERIC_BRIDGE_H */
+#endif /* CLIENT_CACHE_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/cache_bridge/client_cache_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/cache_bridge/client_cache_direct_bridge.c
new file mode 100644
index 0000000..69837fc
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/cache_bridge/client_cache_direct_bridge.c
@@ -0,0 +1,153 @@
+/*************************************************************************/ /*!
+@Title          Direct client bridge for cache
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "client_cache_bridge.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+
+/* Module specific includes */
+#include "cache_ops.h"
+
+#include "cache_km.h"
+
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
+							  IMG_UINT32 ui32NumCacheOps,
+							  IMG_HANDLE *phPMR,
+							  IMG_DEVMEM_OFFSET_T *puiOffset,
+							  IMG_DEVMEM_SIZE_T *puiSize,
+							  PVRSRV_CACHE_OP *piuCacheOp,
+							  IMG_UINT32 *pui32CacheOpSeqNum)
+{
+	PVRSRV_ERROR eError;
+	PMR * *psPMRInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psPMRInt = (PMR **) phPMR;
+
+	eError =
+		CacheOpQueue(
+					ui32NumCacheOps,
+					psPMRInt,
+					puiOffset,
+					puiSize,
+					piuCacheOp,
+					pui32CacheOpSeqNum);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpExec(IMG_HANDLE hBridge,
+							 IMG_HANDLE hPMR,
+							 IMG_DEVMEM_OFFSET_T uiOffset,
+							 IMG_DEVMEM_SIZE_T uiSize,
+							 PVRSRV_CACHE_OP iuCacheOp)
+{
+	PVRSRV_ERROR eError;
+	PMR * psPMRInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psPMRInt = (PMR *) hPMR;
+
+	eError =
+		CacheOpExec(
+					psPMRInt,
+					uiOffset,
+					uiSize,
+					iuCacheOp);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpSetTimeline(IMG_HANDLE hBridge,
+								IMG_INT32 i32OpTimeline)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		CacheOpSetTimeline(
+					i32OpTimeline);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpLog(IMG_HANDLE hBridge,
+							IMG_HANDLE hPMR,
+							IMG_DEVMEM_OFFSET_T uiOffset,
+							IMG_DEVMEM_SIZE_T uiSize,
+							IMG_INT64 i64QueuedTimeUs,
+							IMG_INT64 i64ExecuteTimeUs,
+							PVRSRV_CACHE_OP iuCacheOp)
+{
+	PVRSRV_ERROR eError;
+	PMR * psPMRInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psPMRInt = (PMR *) hPMR;
+
+	eError =
+		CacheOpLog(
+					psPMRInt,
+					uiOffset,
+					uiSize,
+					i64QueuedTimeUs,
+					i64ExecuteTimeUs,
+					iuCacheOp);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpGetLineSize(IMG_HANDLE hBridge,
+								IMG_UINT32 *pui32L1DataCacheLineSize)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		CacheOpGetLineSize(
+					pui32L1DataCacheLineSize);
+
+	return eError;
+}
+
diff --git a/drivers/staging/imgtec/rogue/generated/cache_bridge/common_cache_bridge.h b/drivers/staging/imgtec/rogue/generated/cache_bridge/common_cache_bridge.h
new file mode 100644
index 0000000..e5c6e9c
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/cache_bridge/common_cache_bridge.h
@@ -0,0 +1,164 @@
+/*************************************************************************/ /*!
+@File
+@Title          Common bridge header for cache
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for cache
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef COMMON_CACHE_BRIDGE_H
+#define COMMON_CACHE_BRIDGE_H
+
+#include <powervr/mem_types.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+#include "cache_ops.h"
+
+
+#define PVRSRV_BRIDGE_CACHE_CMD_FIRST			0
+#define PVRSRV_BRIDGE_CACHE_CACHEOPQUEUE			PVRSRV_BRIDGE_CACHE_CMD_FIRST+0
+#define PVRSRV_BRIDGE_CACHE_CACHEOPEXEC			PVRSRV_BRIDGE_CACHE_CMD_FIRST+1
+#define PVRSRV_BRIDGE_CACHE_CACHEOPSETTIMELINE			PVRSRV_BRIDGE_CACHE_CMD_FIRST+2
+#define PVRSRV_BRIDGE_CACHE_CACHEOPLOG			PVRSRV_BRIDGE_CACHE_CMD_FIRST+3
+#define PVRSRV_BRIDGE_CACHE_CACHEOPGETLINESIZE			PVRSRV_BRIDGE_CACHE_CMD_FIRST+4
+#define PVRSRV_BRIDGE_CACHE_CMD_LAST			(PVRSRV_BRIDGE_CACHE_CMD_FIRST+4)
+
+
+/*******************************************
+            CacheOpQueue          
+ *******************************************/
+
+/* Bridge in structure for CacheOpQueue */
+typedef struct PVRSRV_BRIDGE_IN_CACHEOPQUEUE_TAG
+{
+	IMG_UINT32 ui32NumCacheOps;
+	IMG_HANDLE * phPMR;
+	IMG_DEVMEM_OFFSET_T * puiOffset;
+	IMG_DEVMEM_SIZE_T * puiSize;
+	PVRSRV_CACHE_OP * piuCacheOp;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_CACHEOPQUEUE;
+
+/* Bridge out structure for CacheOpQueue */
+typedef struct PVRSRV_BRIDGE_OUT_CACHEOPQUEUE_TAG
+{
+	IMG_UINT32 ui32CacheOpSeqNum;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CACHEOPQUEUE;
+
+
+/*******************************************
+            CacheOpExec          
+ *******************************************/
+
+/* Bridge in structure for CacheOpExec */
+typedef struct PVRSRV_BRIDGE_IN_CACHEOPEXEC_TAG
+{
+	IMG_HANDLE hPMR;
+	IMG_DEVMEM_OFFSET_T uiOffset;
+	IMG_DEVMEM_SIZE_T uiSize;
+	PVRSRV_CACHE_OP iuCacheOp;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_CACHEOPEXEC;
+
+/* Bridge out structure for CacheOpExec */
+typedef struct PVRSRV_BRIDGE_OUT_CACHEOPEXEC_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CACHEOPEXEC;
+
+
+/*******************************************
+            CacheOpSetTimeline          
+ *******************************************/
+
+/* Bridge in structure for CacheOpSetTimeline */
+typedef struct PVRSRV_BRIDGE_IN_CACHEOPSETTIMELINE_TAG
+{
+	IMG_INT32 i32OpTimeline;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_CACHEOPSETTIMELINE;
+
+/* Bridge out structure for CacheOpSetTimeline */
+typedef struct PVRSRV_BRIDGE_OUT_CACHEOPSETTIMELINE_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CACHEOPSETTIMELINE;
+
+
+/*******************************************
+            CacheOpLog          
+ *******************************************/
+
+/* Bridge in structure for CacheOpLog */
+typedef struct PVRSRV_BRIDGE_IN_CACHEOPLOG_TAG
+{
+	IMG_HANDLE hPMR;
+	IMG_DEVMEM_OFFSET_T uiOffset;
+	IMG_DEVMEM_SIZE_T uiSize;
+	IMG_INT64 i64QueuedTimeUs;
+	IMG_INT64 i64ExecuteTimeUs;
+	PVRSRV_CACHE_OP iuCacheOp;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_CACHEOPLOG;
+
+/* Bridge out structure for CacheOpLog */
+typedef struct PVRSRV_BRIDGE_OUT_CACHEOPLOG_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CACHEOPLOG;
+
+
+/*******************************************
+            CacheOpGetLineSize          
+ *******************************************/
+
+/* Bridge in structure for CacheOpGetLineSize */
+typedef struct PVRSRV_BRIDGE_IN_CACHEOPGETLINESIZE_TAG
+{
+	 IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_CACHEOPGETLINESIZE;
+
+/* Bridge out structure for CacheOpGetLineSize */
+typedef struct PVRSRV_BRIDGE_OUT_CACHEOPGETLINESIZE_TAG
+{
+	IMG_UINT32 ui32L1DataCacheLineSize;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CACHEOPGETLINESIZE;
+
+
+#endif /* COMMON_CACHE_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/cache_bridge/server_cache_bridge.c b/drivers/staging/imgtec/rogue/generated/cache_bridge/server_cache_bridge.c
new file mode 100644
index 0000000..cfb98fb
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/cache_bridge/server_cache_bridge.c
@@ -0,0 +1,543 @@
+/*************************************************************************/ /*!
+@File
+@Title          Server bridge for cache
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements the server side of the bridge for cache
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "cache_km.h"
+
+
+#include "common_cache_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#include <linux/slab.h>
+
+
+
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+ 
+static IMG_INT
+PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_CACHEOPQUEUE *psCacheOpQueueIN,
+					  PVRSRV_BRIDGE_OUT_CACHEOPQUEUE *psCacheOpQueueOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	PMR * *psPMRInt = NULL;
+	IMG_HANDLE *hPMRInt2 = NULL;
+	IMG_DEVMEM_OFFSET_T *uiOffsetInt = NULL;
+	IMG_DEVMEM_SIZE_T *uiSizeInt = NULL;
+	PVRSRV_CACHE_OP *iuCacheOpInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psCacheOpQueueIN->ui32NumCacheOps * sizeof(PMR *)) +
+			(psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE)) +
+			(psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_OFFSET_T)) +
+			(psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_SIZE_T)) +
+			(psCacheOpQueueIN->ui32NumCacheOps * sizeof(PVRSRV_CACHE_OP)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psCacheOpQueueIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psCacheOpQueueIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psCacheOpQueueOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto CacheOpQueue_exit;
+			}
+		}
+	}
+
+	if (psCacheOpQueueIN->ui32NumCacheOps != 0)
+	{
+		psPMRInt = (PMR **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(PMR *);
+		hPMRInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hPMRInt2, psCacheOpQueueIN->phPMR, psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psCacheOpQueueOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto CacheOpQueue_exit;
+				}
+			}
+	if (psCacheOpQueueIN->ui32NumCacheOps != 0)
+	{
+		uiOffsetInt = (IMG_DEVMEM_OFFSET_T*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_OFFSET_T);
+	}
+
+			/* Copy the data over */
+			if (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_OFFSET_T) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiOffsetInt, psCacheOpQueueIN->puiOffset, psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_OFFSET_T)) != PVRSRV_OK )
+				{
+					psCacheOpQueueOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto CacheOpQueue_exit;
+				}
+			}
+	if (psCacheOpQueueIN->ui32NumCacheOps != 0)
+	{
+		uiSizeInt = (IMG_DEVMEM_SIZE_T*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_SIZE_T);
+	}
+
+			/* Copy the data over */
+			if (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_SIZE_T) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiSizeInt, psCacheOpQueueIN->puiSize, psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_SIZE_T)) != PVRSRV_OK )
+				{
+					psCacheOpQueueOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto CacheOpQueue_exit;
+				}
+			}
+	if (psCacheOpQueueIN->ui32NumCacheOps != 0)
+	{
+		iuCacheOpInt = (PVRSRV_CACHE_OP*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(PVRSRV_CACHE_OP);
+	}
+
+			/* Copy the data over */
+			if (psCacheOpQueueIN->ui32NumCacheOps * sizeof(PVRSRV_CACHE_OP) > 0)
+			{
+				if ( OSCopyFromUser(NULL, iuCacheOpInt, psCacheOpQueueIN->piuCacheOp, psCacheOpQueueIN->ui32NumCacheOps * sizeof(PVRSRV_CACHE_OP)) != PVRSRV_OK )
+				{
+					psCacheOpQueueOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto CacheOpQueue_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psCacheOpQueueIN->ui32NumCacheOps;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psCacheOpQueueOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psPMRInt[i],
+											hPMRInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psCacheOpQueueOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto CacheOpQueue_exit;
+					}
+				}
+		}
+	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psCacheOpQueueOUT->eError =
+		CacheOpQueue(
+					psCacheOpQueueIN->ui32NumCacheOps,
+					psPMRInt,
+					uiOffsetInt,
+					uiSizeInt,
+					iuCacheOpInt,
+					&psCacheOpQueueOUT->ui32CacheOpSeqNum);
+
+
+
+
+CacheOpQueue_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+
+	if (hPMRInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psCacheOpQueueIN->ui32NumCacheOps;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMRInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeCacheOpExec(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_CACHEOPEXEC *psCacheOpExecIN,
+					  PVRSRV_BRIDGE_OUT_CACHEOPEXEC *psCacheOpExecOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hPMR = psCacheOpExecIN->hPMR;
+	PMR * psPMRInt = NULL;
+
+
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psCacheOpExecOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psPMRInt,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psCacheOpExecOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto CacheOpExec_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psCacheOpExecOUT->eError =
+		CacheOpExec(
+					psPMRInt,
+					psCacheOpExecIN->uiOffset,
+					psCacheOpExecIN->uiSize,
+					psCacheOpExecIN->iuCacheOp);
+
+
+
+
+CacheOpExec_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeCacheOpSetTimeline(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_CACHEOPSETTIMELINE *psCacheOpSetTimelineIN,
+					  PVRSRV_BRIDGE_OUT_CACHEOPSETTIMELINE *psCacheOpSetTimelineOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+
+	psCacheOpSetTimelineOUT->eError =
+		CacheOpSetTimeline(
+					psCacheOpSetTimelineIN->i32OpTimeline);
+
+
+
+
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeCacheOpLog(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_CACHEOPLOG *psCacheOpLogIN,
+					  PVRSRV_BRIDGE_OUT_CACHEOPLOG *psCacheOpLogOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hPMR = psCacheOpLogIN->hPMR;
+	PMR * psPMRInt = NULL;
+
+
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psCacheOpLogOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psPMRInt,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psCacheOpLogOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto CacheOpLog_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psCacheOpLogOUT->eError =
+		CacheOpLog(
+					psPMRInt,
+					psCacheOpLogIN->uiOffset,
+					psCacheOpLogIN->uiSize,
+					psCacheOpLogIN->i64QueuedTimeUs,
+					psCacheOpLogIN->i64ExecuteTimeUs,
+					psCacheOpLogIN->iuCacheOp);
+
+
+
+
+CacheOpLog_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeCacheOpGetLineSize(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_CACHEOPGETLINESIZE *psCacheOpGetLineSizeIN,
+					  PVRSRV_BRIDGE_OUT_CACHEOPGETLINESIZE *psCacheOpGetLineSizeOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(psCacheOpGetLineSizeIN);
+
+
+
+
+
+	psCacheOpGetLineSizeOUT->eError =
+		CacheOpGetLineSize(
+					&psCacheOpGetLineSizeOUT->ui32L1DataCacheLineSize);
+
+
+
+
+
+
+
+
+	return 0;
+}
+
+
+
+
+/* *************************************************************************** 
+ * Server bridge dispatch related glue 
+ */
+
+static IMG_BOOL bUseLock = IMG_TRUE;
+
+PVRSRV_ERROR InitCACHEBridge(void);
+PVRSRV_ERROR DeinitCACHEBridge(void);
+
+/*
+ * Register all CACHE functions with services
+ */
+PVRSRV_ERROR InitCACHEBridge(void)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPQUEUE, PVRSRVBridgeCacheOpQueue,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPEXEC, PVRSRVBridgeCacheOpExec,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPSETTIMELINE, PVRSRVBridgeCacheOpSetTimeline,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPLOG, PVRSRVBridgeCacheOpLog,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPGETLINESIZE, PVRSRVBridgeCacheOpGetLineSize,
+					NULL, bUseLock);
+
+
+	return PVRSRV_OK;
+}
+
+/*
+ * Unregister all cache functions with services
+ */
+PVRSRV_ERROR DeinitCACHEBridge(void)
+{
+	return PVRSRV_OK;
+}
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c b/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c
deleted file mode 100644
index 69f13b2..0000000
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Server bridge for cachegeneric
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Implements the server side of the bridge for cachegeneric
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include <stddef.h>
-#include <asm/uaccess.h>
-
-#include "img_defs.h"
-
-#include "cache_generic.h"
-
-
-#include "common_cachegeneric_bridge.h"
-
-#include "allocmem.h"
-#include "pvr_debug.h"
-#include "connection_server.h"
-#include "pvr_bridge.h"
-#include "rgx_bridge.h"
-#include "srvcore.h"
-#include "handle.h"
-
-#include <linux/slab.h>
-
-
-
-
-/* ***************************************************************************
- * Server-side bridge entry points
- */
- 
-static IMG_INT
-PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_CACHEOPQUEUE *psCacheOpQueueIN,
-					  PVRSRV_BRIDGE_OUT_CACHEOPQUEUE *psCacheOpQueueOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	PMR * psPMRInt = NULL;
-
-
-
-
-
-
-
-				{
-					/* Look up the address from the handle */
-					psCacheOpQueueOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psPMRInt,
-											psCacheOpQueueIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
-					if(psCacheOpQueueOUT->eError != PVRSRV_OK)
-					{
-						goto CacheOpQueue_exit;
-					}
-				}
-
-
-	psCacheOpQueueOUT->eError =
-		CacheOpQueue(
-					psPMRInt,
-					psCacheOpQueueIN->uiOffset,
-					psCacheOpQueueIN->uiSize,
-					psCacheOpQueueIN->iuCacheOp);
-
-
-
-
-CacheOpQueue_exit:
-
-	return 0;
-}
-
-
-
-/* *************************************************************************** 
- * Server bridge dispatch related glue 
- */
-
-static IMG_BOOL bUseLock = IMG_TRUE;
-
-PVRSRV_ERROR InitCACHEGENERICBridge(void);
-PVRSRV_ERROR DeinitCACHEGENERICBridge(void);
-
-/*
- * Register all CACHEGENERIC functions with services
- */
-PVRSRV_ERROR InitCACHEGENERICBridge(void)
-{
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_CACHEGENERIC, PVRSRV_BRIDGE_CACHEGENERIC_CACHEOPQUEUE, PVRSRVBridgeCacheOpQueue,
-					NULL, bUseLock);
-
-
-	return PVRSRV_OK;
-}
-
-/*
- * Unregister all cachegeneric functions with services
- */
-PVRSRV_ERROR DeinitCACHEGENERICBridge(void)
-{
-	return PVRSRV_OK;
-}
-
diff --git a/drivers/staging/imgtec/rogue/generated/cmm_bridge/common_cmm_bridge.h b/drivers/staging/imgtec/rogue/generated/cmm_bridge/common_cmm_bridge.h
index 79ce42a..4ca9bc5 100644
--- a/drivers/staging/imgtec/rogue/generated/cmm_bridge/common_cmm_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/cmm_bridge/common_cmm_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for cmm
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for cmm
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for cmm
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_CMM_BRIDGE_H
 #define COMMON_CMM_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/cmm_bridge/server_cmm_bridge.c b/drivers/staging/imgtec/rogue/generated/cmm_bridge/server_cmm_bridge.c
index 3895dae..d18c691 100644
--- a/drivers/staging/imgtec/rogue/generated/cmm_bridge/server_cmm_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/cmm_bridge/server_cmm_bridge.c
@@ -64,6 +64,9 @@
 
 
 
+#if !defined(EXCLUDE_CMM_BRIDGE)
+
+
 
 /* ***************************************************************************
  * Server-side bridge entry points
@@ -75,7 +78,9 @@
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTEXPORTCTX *psDevmemIntExportCtxOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hContext = psDevmemIntExportCtxIN->hContext;
 	DEVMEMINT_CTX * psContextInt = NULL;
+	IMG_HANDLE hPMR = psDevmemIntExportCtxIN->hPMR;
 	PMR * psPMRInt = NULL;
 	DEVMEMINT_CTX_EXPORT * psContextExportInt = NULL;
 
@@ -83,38 +88,50 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntExportCtxOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psContextInt,
-											psDevmemIntExportCtxIN->hContext,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+											hContext,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+											IMG_TRUE);
 					if(psDevmemIntExportCtxOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntExportCtx_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntExportCtxOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntExportCtxIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntExportCtxOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntExportCtx_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntExportCtxOUT->eError =
 		DevmemIntExportCtx(
@@ -124,13 +141,18 @@
 	/* Exit early if bridged call fails */
 	if(psDevmemIntExportCtxOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto DevmemIntExportCtx_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psDevmemIntExportCtxOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psDevmemIntExportCtxOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntExportCtxOUT->hContextExport,
 							(void *) psContextExportInt,
 							PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT,
@@ -138,13 +160,51 @@
 							,(PFN_HANDLE_RELEASE)&DevmemIntUnexportCtx);
 	if (psDevmemIntExportCtxOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntExportCtx_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DevmemIntExportCtx_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hContext,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDevmemIntExportCtxOUT->eError != PVRSRV_OK)
 	{
 		if (psContextExportInt)
@@ -157,6 +217,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntUnexportCtx(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTUNEXPORTCTX *psDevmemIntUnexportCtxIN,
@@ -168,60 +229,87 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psDevmemIntUnexportCtxOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDevmemIntUnexportCtxIN->hContextExport,
 					PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
-	if ((psDevmemIntUnexportCtxOUT->eError != PVRSRV_OK) && (psDevmemIntUnexportCtxOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDevmemIntUnexportCtxOUT->eError != PVRSRV_OK) &&
+	    (psDevmemIntUnexportCtxOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDevmemIntUnexportCtx: %s",
+		        PVRSRVGetErrorStringKM(psDevmemIntUnexportCtxOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto DevmemIntUnexportCtx_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DevmemIntUnexportCtx_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntAcquireRemoteCtx(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTACQUIREREMOTECTX *psDevmemIntAcquireRemoteCtxIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTACQUIREREMOTECTX *psDevmemIntAcquireRemoteCtxOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psDevmemIntAcquireRemoteCtxIN->hPMR;
 	PMR * psPMRInt = NULL;
 	DEVMEMINT_CTX * psContextInt = NULL;
 	IMG_HANDLE hPrivDataInt = NULL;
 
 
 
+
+
 	psDevmemIntAcquireRemoteCtxOUT->hContext = NULL;
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntAcquireRemoteCtxOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntAcquireRemoteCtxIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntAcquireRemoteCtxOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntAcquireRemoteCtx_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntAcquireRemoteCtxOUT->eError =
 		DevmemIntAcquireRemoteCtx(
@@ -234,8 +322,15 @@
 		goto DevmemIntAcquireRemoteCtx_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDevmemIntAcquireRemoteCtxOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDevmemIntAcquireRemoteCtxOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntAcquireRemoteCtxOUT->hContext,
 							(void *) psContextInt,
 							PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
@@ -243,11 +338,17 @@
 							,(PFN_HANDLE_RELEASE)&DevmemIntCtxDestroy);
 	if (psDevmemIntAcquireRemoteCtxOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntAcquireRemoteCtx_exit;
 	}
 
 
-	psDevmemIntAcquireRemoteCtxOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+
+
+
+
+	psDevmemIntAcquireRemoteCtxOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntAcquireRemoteCtxOUT->hPrivData,
 							(void *) hPrivDataInt,
 							PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
@@ -255,22 +356,56 @@
 							,psDevmemIntAcquireRemoteCtxOUT->hContext);
 	if (psDevmemIntAcquireRemoteCtxOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntAcquireRemoteCtx_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DevmemIntAcquireRemoteCtx_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDevmemIntAcquireRemoteCtxOUT->eError != PVRSRV_OK)
 	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
 		if (psDevmemIntAcquireRemoteCtxOUT->hContext)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 						(IMG_HANDLE) psDevmemIntAcquireRemoteCtxOUT->hContext,
 						PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgeDevmemIntAcquireRemoteCtx: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 			/* Avoid freeing/destroying/releasing the resource a second time below */
@@ -278,6 +413,8 @@
 		}
 
 
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
 		if (psContextInt)
 		{
 			DevmemIntCtxDestroy(psContextInt);
@@ -290,12 +427,15 @@
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
 
 static IMG_BOOL bUseLock = IMG_TRUE;
+#endif /* EXCLUDE_CMM_BRIDGE */
 
+#if !defined(EXCLUDE_CMM_BRIDGE)
 PVRSRV_ERROR InitCMMBridge(void);
 PVRSRV_ERROR DeinitCMMBridge(void);
 
@@ -325,4 +465,14 @@
 {
 	return PVRSRV_OK;
 }
+#else /* EXCLUDE_CMM_BRIDGE */
+/* This bridge is conditional on EXCLUDE_CMM_BRIDGE - when defined,
+ * do not populate the dispatch table with its functions
+ */
+#define InitCMMBridge() \
+	PVRSRV_OK
 
+#define DeinitCMMBridge() \
+	PVRSRV_OK
+
+#endif /* EXCLUDE_CMM_BRIDGE */
diff --git a/drivers/staging/imgtec/rogue/generated/dc_bridge/common_dc_bridge.h b/drivers/staging/imgtec/rogue/generated/dc_bridge/common_dc_bridge.h
index af3e13b..727f7a5 100644
--- a/drivers/staging/imgtec/rogue/generated/dc_bridge/common_dc_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/dc_bridge/common_dc_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for dc
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for dc
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for dc
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,12 +45,13 @@
 #ifndef COMMON_DC_BRIDGE_H
 #define COMMON_DC_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "pvrsrv_surface.h"
 #include "dc_external.h"
-#include "dc_common.h"
 
 
 #define PVRSRV_BRIDGE_DC_CMD_FIRST			0
diff --git a/drivers/staging/imgtec/rogue/generated/dc_bridge/server_dc_bridge.c b/drivers/staging/imgtec/rogue/generated/dc_bridge/server_dc_bridge.c
index f463709..5091cce 100644
--- a/drivers/staging/imgtec/rogue/generated/dc_bridge/server_dc_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/dc_bridge/server_dc_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -75,6 +77,8 @@
 					 CONNECTION_DATA *psConnection)
 {
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psDCDevicesQueryCountIN);
 
@@ -82,7 +86,6 @@
 
 
 
-
 	psDCDevicesQueryCountOUT->eError =
 		DCDevicesQueryCount(
 					&psDCDevicesQueryCountOUT->ui32DeviceCount);
@@ -91,9 +94,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDevicesEnumerate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDEVICESENUMERATE *psDCDevicesEnumerateIN,
@@ -102,50 +109,95 @@
 {
 	IMG_UINT32 *pui32DeviceIndexInt = NULL;
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCDevicesEnumerateIN->ui32DeviceArraySize * sizeof(IMG_UINT32)) +
+			0;
+
+
 
 	psDCDevicesEnumerateOUT->pui32DeviceIndex = psDCDevicesEnumerateIN->pui32DeviceIndex;
 
 
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCDevicesEnumerateIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCDevicesEnumerateIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCDevicesEnumerateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCDevicesEnumerate_exit;
+			}
+		}
+	}
+
 	if (psDCDevicesEnumerateIN->ui32DeviceArraySize != 0)
 	{
-		pui32DeviceIndexInt = OSAllocMemNoStats(psDCDevicesEnumerateIN->ui32DeviceArraySize * sizeof(IMG_UINT32));
-		if (!pui32DeviceIndexInt)
-		{
-			psDCDevicesEnumerateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDevicesEnumerate_exit;
-		}
+		pui32DeviceIndexInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDevicesEnumerateIN->ui32DeviceArraySize * sizeof(IMG_UINT32);
 	}
 
 
 
-
 	psDCDevicesEnumerateOUT->eError =
-		DCDevicesEnumerate(
+		DCDevicesEnumerate(psConnection, OSGetDevData(psConnection),
 					psDCDevicesEnumerateIN->ui32DeviceArraySize,
 					&psDCDevicesEnumerateOUT->ui32DeviceCount,
 					pui32DeviceIndexInt);
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psDCDevicesEnumerateOUT->pui32DeviceIndex, (psDCDevicesEnumerateOUT->ui32DeviceCount * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psDCDevicesEnumerateOUT->pui32DeviceIndex, pui32DeviceIndexInt,
-		(psDCDevicesEnumerateOUT->ui32DeviceCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psDCDevicesEnumerateOUT->ui32DeviceCount * sizeof(IMG_UINT32)) > 0)
 	{
-		psDCDevicesEnumerateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psDCDevicesEnumerateOUT->pui32DeviceIndex, pui32DeviceIndexInt,
+			(psDCDevicesEnumerateOUT->ui32DeviceCount * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psDCDevicesEnumerateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto DCDevicesEnumerate_exit;
+			goto DCDevicesEnumerate_exit;
+		}
 	}
 
 
 DCDevicesEnumerate_exit:
-	if (pui32DeviceIndexInt)
-		OSFreeMemNoStats(pui32DeviceIndexInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDeviceAcquire(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDEVICEACQUIRE *psDCDeviceAcquireIN,
@@ -160,8 +212,9 @@
 
 
 
+
 	psDCDeviceAcquireOUT->eError =
-		DCDeviceAcquire(
+		DCDeviceAcquire(psConnection, OSGetDevData(psConnection),
 					psDCDeviceAcquireIN->ui32DeviceIndex,
 					&psDeviceInt);
 	/* Exit early if bridged call fails */
@@ -170,8 +223,15 @@
 		goto DCDeviceAcquire_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDCDeviceAcquireOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDCDeviceAcquireOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCDeviceAcquireOUT->hDevice,
 							(void *) psDeviceInt,
 							PVRSRV_HANDLE_TYPE_DC_DEVICE,
@@ -179,13 +239,19 @@
 							,(PFN_HANDLE_RELEASE)&DCDeviceRelease);
 	if (psDCDeviceAcquireOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCDeviceAcquire_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCDeviceAcquire_exit:
+
+
+
 	if (psDCDeviceAcquireOUT->eError != PVRSRV_OK)
 	{
 		if (psDeviceInt)
@@ -198,6 +264,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDeviceRelease(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDEVICERELEASE *psDCDeviceReleaseIN,
@@ -213,29 +280,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psDCDeviceReleaseOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCDeviceReleaseIN->hDevice,
 					PVRSRV_HANDLE_TYPE_DC_DEVICE);
-	if ((psDCDeviceReleaseOUT->eError != PVRSRV_OK) && (psDCDeviceReleaseOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCDeviceReleaseOUT->eError != PVRSRV_OK) &&
+	    (psDCDeviceReleaseOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCDeviceRelease: %s",
+		        PVRSRVGetErrorStringKM(psDCDeviceReleaseOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto DCDeviceRelease_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCDeviceRelease_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCGetInfo(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCGETINFO *psDCGetInfoIN,
 					  PVRSRV_BRIDGE_OUT_DCGETINFO *psDCGetInfoOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCGetInfoIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 
 
@@ -244,19 +331,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCGetInfoOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCGetInfoIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCGetInfoOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCGetInfo_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCGetInfoOUT->eError =
 		DCGetInfo(
@@ -268,15 +365,38 @@
 
 DCGetInfo_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCPanelQueryCount(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCPANELQUERYCOUNT *psDCPanelQueryCountIN,
 					  PVRSRV_BRIDGE_OUT_DCPANELQUERYCOUNT *psDCPanelQueryCountOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCPanelQueryCountIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 
 
@@ -285,19 +405,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCPanelQueryCountOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCPanelQueryCountIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCPanelQueryCountOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCPanelQueryCount_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCPanelQueryCountOUT->eError =
 		DCPanelQueryCount(
@@ -309,49 +439,113 @@
 
 DCPanelQueryCount_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCPanelQuery(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCPANELQUERY *psDCPanelQueryIN,
 					  PVRSRV_BRIDGE_OUT_DCPANELQUERY *psDCPanelQueryOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCPanelQueryIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 	PVRSRV_PANEL_INFO *psPanelInfoInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCPanelQueryIN->ui32PanelsArraySize * sizeof(PVRSRV_PANEL_INFO)) +
+			0;
+
+
 
 	psDCPanelQueryOUT->psPanelInfo = psDCPanelQueryIN->psPanelInfo;
 
 
-	if (psDCPanelQueryIN->ui32PanelsArraySize != 0)
+	if (ui32BufferSize != 0)
 	{
-		psPanelInfoInt = OSAllocMemNoStats(psDCPanelQueryIN->ui32PanelsArraySize * sizeof(PVRSRV_PANEL_INFO));
-		if (!psPanelInfoInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCPanelQueryIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDCPanelQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCPanelQuery_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCPanelQueryIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCPanelQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCPanelQuery_exit;
+			}
 		}
 	}
 
+	if (psDCPanelQueryIN->ui32PanelsArraySize != 0)
+	{
+		psPanelInfoInt = (PVRSRV_PANEL_INFO*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCPanelQueryIN->ui32PanelsArraySize * sizeof(PVRSRV_PANEL_INFO);
+	}
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
 
 
 
 				{
 					/* Look up the address from the handle */
 					psDCPanelQueryOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCPanelQueryIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCPanelQueryOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCPanelQuery_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCPanelQueryOUT->eError =
 		DCPanelQuery(
@@ -362,84 +556,155 @@
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psDCPanelQueryOUT->psPanelInfo, (psDCPanelQueryOUT->ui32NumPanels * sizeof(PVRSRV_PANEL_INFO)))
-		|| (OSCopyToUser(NULL, psDCPanelQueryOUT->psPanelInfo, psPanelInfoInt,
-		(psDCPanelQueryOUT->ui32NumPanels * sizeof(PVRSRV_PANEL_INFO))) != PVRSRV_OK) )
+	if ((psDCPanelQueryOUT->ui32NumPanels * sizeof(PVRSRV_PANEL_INFO)) > 0)
 	{
-		psDCPanelQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psDCPanelQueryOUT->psPanelInfo, psPanelInfoInt,
+			(psDCPanelQueryOUT->ui32NumPanels * sizeof(PVRSRV_PANEL_INFO))) != PVRSRV_OK )
+		{
+			psDCPanelQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto DCPanelQuery_exit;
+			goto DCPanelQuery_exit;
+		}
 	}
 
 
 DCPanelQuery_exit:
-	if (psPanelInfoInt)
-		OSFreeMemNoStats(psPanelInfoInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCFormatQuery(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCFORMATQUERY *psDCFormatQueryIN,
 					  PVRSRV_BRIDGE_OUT_DCFORMATQUERY *psDCFormatQueryOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCFormatQueryIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 	PVRSRV_SURFACE_FORMAT *psFormatInt = NULL;
 	IMG_UINT32 *pui32SupportedInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT)) +
+			(psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32)) +
+			0;
+
+
 
 	psDCFormatQueryOUT->pui32Supported = psDCFormatQueryIN->pui32Supported;
 
 
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCFormatQueryIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCFormatQueryIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCFormatQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCFormatQuery_exit;
+			}
+		}
+	}
+
 	if (psDCFormatQueryIN->ui32NumFormats != 0)
 	{
-		psFormatInt = OSAllocMemNoStats(psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT));
-		if (!psFormatInt)
-		{
-			psDCFormatQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCFormatQuery_exit;
-		}
+		psFormatInt = (PVRSRV_SURFACE_FORMAT*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCFormatQueryIN->psFormat, psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT))
-				|| (OSCopyFromUser(NULL, psFormatInt, psDCFormatQueryIN->psFormat,
-				psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT)) != PVRSRV_OK) )
+			if (psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT) > 0)
 			{
-				psDCFormatQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psFormatInt, psDCFormatQueryIN->psFormat, psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT)) != PVRSRV_OK )
+				{
+					psDCFormatQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCFormatQuery_exit;
+					goto DCFormatQuery_exit;
+				}
 			}
 	if (psDCFormatQueryIN->ui32NumFormats != 0)
 	{
-		pui32SupportedInt = OSAllocMemNoStats(psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32));
-		if (!pui32SupportedInt)
-		{
-			psDCFormatQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCFormatQuery_exit;
-		}
+		pui32SupportedInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32);
 	}
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDCFormatQueryOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCFormatQueryIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCFormatQueryOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCFormatQuery_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCFormatQueryOUT->eError =
 		DCFormatQuery(
@@ -450,86 +715,155 @@
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psDCFormatQueryOUT->pui32Supported, (psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psDCFormatQueryOUT->pui32Supported, pui32SupportedInt,
-		(psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32)) > 0)
 	{
-		psDCFormatQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psDCFormatQueryOUT->pui32Supported, pui32SupportedInt,
+			(psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psDCFormatQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto DCFormatQuery_exit;
+			goto DCFormatQuery_exit;
+		}
 	}
 
 
 DCFormatQuery_exit:
-	if (psFormatInt)
-		OSFreeMemNoStats(psFormatInt);
-	if (pui32SupportedInt)
-		OSFreeMemNoStats(pui32SupportedInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDimQuery(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDIMQUERY *psDCDimQueryIN,
 					  PVRSRV_BRIDGE_OUT_DCDIMQUERY *psDCDimQueryOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCDimQueryIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 	PVRSRV_SURFACE_DIMS *psDimInt = NULL;
 	IMG_UINT32 *pui32SupportedInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS)) +
+			(psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32)) +
+			0;
+
+
 
 	psDCDimQueryOUT->pui32Supported = psDCDimQueryIN->pui32Supported;
 
 
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCDimQueryIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCDimQueryIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCDimQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCDimQuery_exit;
+			}
+		}
+	}
+
 	if (psDCDimQueryIN->ui32NumDims != 0)
 	{
-		psDimInt = OSAllocMemNoStats(psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS));
-		if (!psDimInt)
-		{
-			psDCDimQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDimQuery_exit;
-		}
+		psDimInt = (PVRSRV_SURFACE_DIMS*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDimQueryIN->psDim, psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS))
-				|| (OSCopyFromUser(NULL, psDimInt, psDCDimQueryIN->psDim,
-				psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS)) != PVRSRV_OK) )
+			if (psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS) > 0)
 			{
-				psDCDimQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psDimInt, psDCDimQueryIN->psDim, psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS)) != PVRSRV_OK )
+				{
+					psDCDimQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCDimQuery_exit;
+					goto DCDimQuery_exit;
+				}
 			}
 	if (psDCDimQueryIN->ui32NumDims != 0)
 	{
-		pui32SupportedInt = OSAllocMemNoStats(psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32));
-		if (!pui32SupportedInt)
-		{
-			psDCDimQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDimQuery_exit;
-		}
+		pui32SupportedInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32);
 	}
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDCDimQueryOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCDimQueryIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCDimQueryOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDimQuery_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCDimQueryOUT->eError =
 		DCDimQuery(
@@ -540,31 +874,62 @@
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psDCDimQueryOUT->pui32Supported, (psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psDCDimQueryOUT->pui32Supported, pui32SupportedInt,
-		(psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32)) > 0)
 	{
-		psDCDimQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psDCDimQueryOUT->pui32Supported, pui32SupportedInt,
+			(psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psDCDimQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto DCDimQuery_exit;
+			goto DCDimQuery_exit;
+		}
 	}
 
 
 DCDimQuery_exit:
-	if (psDimInt)
-		OSFreeMemNoStats(psDimInt);
-	if (pui32SupportedInt)
-		OSFreeMemNoStats(pui32SupportedInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCSetBlank(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCSETBLANK *psDCSetBlankIN,
 					  PVRSRV_BRIDGE_OUT_DCSETBLANK *psDCSetBlankOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCSetBlankIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 
 
@@ -573,19 +938,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCSetBlankOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCSetBlankIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCSetBlankOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCSetBlank_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCSetBlankOUT->eError =
 		DCSetBlank(
@@ -597,15 +972,38 @@
 
 DCSetBlank_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCSetVSyncReporting(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCSETVSYNCREPORTING *psDCSetVSyncReportingIN,
 					  PVRSRV_BRIDGE_OUT_DCSETVSYNCREPORTING *psDCSetVSyncReportingOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCSetVSyncReportingIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 
 
@@ -614,19 +1012,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCSetVSyncReportingOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCSetVSyncReportingIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCSetVSyncReportingOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCSetVSyncReporting_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCSetVSyncReportingOUT->eError =
 		DCSetVSyncReporting(
@@ -638,15 +1046,38 @@
 
 DCSetVSyncReporting_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCLastVSyncQuery(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCLASTVSYNCQUERY *psDCLastVSyncQueryIN,
 					  PVRSRV_BRIDGE_OUT_DCLASTVSYNCQUERY *psDCLastVSyncQueryOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCLastVSyncQueryIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 
 
@@ -655,19 +1086,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCLastVSyncQueryOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCLastVSyncQueryIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCLastVSyncQueryOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCLastVSyncQuery_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCLastVSyncQueryOUT->eError =
 		DCLastVSyncQuery(
@@ -679,15 +1120,38 @@
 
 DCLastVSyncQuery_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCSystemBufferAcquire(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERACQUIRE *psDCSystemBufferAcquireIN,
 					  PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERACQUIRE *psDCSystemBufferAcquireOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCSystemBufferAcquireIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 	DC_BUFFER * psBufferInt = NULL;
 
@@ -695,23 +1159,31 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDCSystemBufferAcquireOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCSystemBufferAcquireIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DCSystemBufferAcquire_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCSystemBufferAcquireOUT->eError =
 		DCSystemBufferAcquire(
@@ -721,13 +1193,18 @@
 	/* Exit early if bridged call fails */
 	if(psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto DCSystemBufferAcquire_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psDCSystemBufferAcquireOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psDCSystemBufferAcquireOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCSystemBufferAcquireOUT->hBuffer,
 							(void *) psBufferInt,
 							PVRSRV_HANDLE_TYPE_DC_BUFFER,
@@ -735,13 +1212,37 @@
 							,(PFN_HANDLE_RELEASE)&DCSystemBufferRelease);
 	if (psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCSystemBufferAcquire_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCSystemBufferAcquire_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
 	{
 		if (psBufferInt)
@@ -754,6 +1255,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCSystemBufferRelease(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERRELEASE *psDCSystemBufferReleaseIN,
@@ -769,29 +1271,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psDCSystemBufferReleaseOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCSystemBufferReleaseIN->hBuffer,
 					PVRSRV_HANDLE_TYPE_DC_BUFFER);
-	if ((psDCSystemBufferReleaseOUT->eError != PVRSRV_OK) && (psDCSystemBufferReleaseOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCSystemBufferReleaseOUT->eError != PVRSRV_OK) &&
+	    (psDCSystemBufferReleaseOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCSystemBufferRelease: %s",
+		        PVRSRVGetErrorStringKM(psDCSystemBufferReleaseOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto DCSystemBufferRelease_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCSystemBufferRelease_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDisplayContextCreate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCREATE *psDCDisplayContextCreateIN,
 					  PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCREATE *psDCDisplayContextCreateOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevice = psDCDisplayContextCreateIN->hDevice;
 	DC_DEVICE * psDeviceInt = NULL;
 	DC_DISPLAY_CONTEXT * psDisplayContextInt = NULL;
 
@@ -801,19 +1323,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCDisplayContextCreateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDeviceInt,
-											psDCDisplayContextCreateIN->hDevice,
-											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE,
+											IMG_TRUE);
 					if(psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDisplayContextCreate_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCDisplayContextCreateOUT->eError =
 		DCDisplayContextCreate(
@@ -825,8 +1357,15 @@
 		goto DCDisplayContextCreate_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDCDisplayContextCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDCDisplayContextCreateOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCDisplayContextCreateOUT->hDisplayContext,
 							(void *) psDisplayContextInt,
 							PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
@@ -834,13 +1373,37 @@
 							,(PFN_HANDLE_RELEASE)&DCDisplayContextDestroy);
 	if (psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCDisplayContextCreate_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCDisplayContextCreate_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDeviceInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevice,
+											PVRSRV_HANDLE_TYPE_DC_DEVICE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
 	{
 		if (psDisplayContextInt)
@@ -853,84 +1416,123 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDisplayContextConfigureCheck(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURECHECK *psDCDisplayContextConfigureCheckIN,
 					  PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURECHECK *psDCDisplayContextConfigureCheckOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDisplayContext = psDCDisplayContextConfigureCheckIN->hDisplayContext;
 	DC_DISPLAY_CONTEXT * psDisplayContextInt = NULL;
 	PVRSRV_SURFACE_CONFIG_INFO *psSurfInfoInt = NULL;
 	DC_BUFFER * *psBuffersInt = NULL;
 	IMG_HANDLE *hBuffersInt2 = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) +
+			(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(DC_BUFFER *)) +
+			(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE)) +
+			0;
 
 
 
-	if (psDCDisplayContextConfigureCheckIN->ui32PipeCount != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		psSurfInfoInt = OSAllocMemNoStats(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO));
-		if (!psSurfInfoInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCDisplayContextConfigureCheckIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigureCheck_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCDisplayContextConfigureCheckIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCDisplayContextConfigureCheck_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDisplayContextConfigureCheckIN->psSurfInfo, psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO))
-				|| (OSCopyFromUser(NULL, psSurfInfoInt, psDCDisplayContextConfigureCheckIN->psSurfInfo,
-				psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) != PVRSRV_OK) )
-			{
-				psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto DCDisplayContextConfigureCheck_exit;
-			}
 	if (psDCDisplayContextConfigureCheckIN->ui32PipeCount != 0)
 	{
-		psBuffersInt = OSAllocMemNoStats(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(DC_BUFFER *));
-		if (!psBuffersInt)
-		{
-			psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigureCheck_exit;
-		}
-		hBuffersInt2 = OSAllocMemNoStats(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE));
-		if (!hBuffersInt2)
-		{
-			psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigureCheck_exit;
-		}
+		psSurfInfoInt = (PVRSRV_SURFACE_CONFIG_INFO*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDisplayContextConfigureCheckIN->phBuffers, psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hBuffersInt2, psDCDisplayContextConfigureCheckIN->phBuffers,
-				psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO) > 0)
 			{
-				psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psSurfInfoInt, psDCDisplayContextConfigureCheckIN->psSurfInfo, psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) != PVRSRV_OK )
+				{
+					psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCDisplayContextConfigureCheck_exit;
+					goto DCDisplayContextConfigureCheck_exit;
+				}
 			}
+	if (psDCDisplayContextConfigureCheckIN->ui32PipeCount != 0)
+	{
+		psBuffersInt = (DC_BUFFER **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(DC_BUFFER *);
+		hBuffersInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hBuffersInt2, psDCDisplayContextConfigureCheckIN->phBuffers, psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DCDisplayContextConfigureCheck_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
 
 
 
 				{
 					/* Look up the address from the handle */
 					psDCDisplayContextConfigureCheckOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDisplayContextInt,
-											psDCDisplayContextConfigureCheckIN->hDisplayContext,
-											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
+											IMG_TRUE);
 					if(psDCDisplayContextConfigureCheckOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDisplayContextConfigureCheck_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -939,18 +1541,21 @@
 				{
 					/* Look up the address from the handle */
 					psDCDisplayContextConfigureCheckOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psBuffersInt[i],
 											hBuffersInt2[i],
-											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+											PVRSRV_HANDLE_TYPE_DC_BUFFER,
+											IMG_TRUE);
 					if(psDCDisplayContextConfigureCheckOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDisplayContextConfigureCheck_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCDisplayContextConfigureCheckOUT->eError =
 		DCDisplayContextConfigureCheck(
@@ -963,22 +1568,72 @@
 
 
 DCDisplayContextConfigureCheck_exit:
-	if (psSurfInfoInt)
-		OSFreeMemNoStats(psSurfInfoInt);
-	if (psBuffersInt)
-		OSFreeMemNoStats(psBuffersInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDisplayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+						}
+				}
+
+
+
+
+
+
 	if (hBuffersInt2)
-		OSFreeMemNoStats(hBuffersInt2);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psDCDisplayContextConfigureCheckIN->ui32PipeCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psBuffersInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hBuffersInt2[i],
+											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDisplayContextConfigure(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURE *psDCDisplayContextConfigureIN,
 					  PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURE *psDCDisplayContextConfigureOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDisplayContext = psDCDisplayContextConfigureIN->hDisplayContext;
 	DC_DISPLAY_CONTEXT * psDisplayContextInt = NULL;
 	PVRSRV_SURFACE_CONFIG_INFO *psSurfInfoInt = NULL;
 	DC_BUFFER * *psBuffersInt = NULL;
@@ -987,120 +1642,147 @@
 	IMG_HANDLE *hSyncInt2 = NULL;
 	IMG_BOOL *bUpdateInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) +
+			(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(DC_BUFFER *)) +
+			(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE)) +
+			(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE)) +
+			(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL)) +
+			0;
 
 
 
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCDisplayContextConfigureIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCDisplayContextConfigureIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCDisplayContextConfigure_exit;
+			}
+		}
+	}
+
 	if (psDCDisplayContextConfigureIN->ui32PipeCount != 0)
 	{
-		psSurfInfoInt = OSAllocMemNoStats(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO));
-		if (!psSurfInfoInt)
-		{
-			psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigure_exit;
-		}
+		psSurfInfoInt = (PVRSRV_SURFACE_CONFIG_INFO*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDisplayContextConfigureIN->psSurfInfo, psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO))
-				|| (OSCopyFromUser(NULL, psSurfInfoInt, psDCDisplayContextConfigureIN->psSurfInfo,
-				psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) != PVRSRV_OK) )
+			if (psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO) > 0)
 			{
-				psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psSurfInfoInt, psDCDisplayContextConfigureIN->psSurfInfo, psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) != PVRSRV_OK )
+				{
+					psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCDisplayContextConfigure_exit;
+					goto DCDisplayContextConfigure_exit;
+				}
 			}
 	if (psDCDisplayContextConfigureIN->ui32PipeCount != 0)
 	{
-		psBuffersInt = OSAllocMemNoStats(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(DC_BUFFER *));
-		if (!psBuffersInt)
-		{
-			psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigure_exit;
-		}
-		hBuffersInt2 = OSAllocMemNoStats(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE));
-		if (!hBuffersInt2)
-		{
-			psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigure_exit;
-		}
+		psBuffersInt = (DC_BUFFER **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(DC_BUFFER *);
+		hBuffersInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDisplayContextConfigureIN->phBuffers, psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hBuffersInt2, psDCDisplayContextConfigureIN->phBuffers,
-				psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hBuffersInt2, psDCDisplayContextConfigureIN->phBuffers, psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCDisplayContextConfigure_exit;
+					goto DCDisplayContextConfigure_exit;
+				}
 			}
 	if (psDCDisplayContextConfigureIN->ui32SyncCount != 0)
 	{
-		psSyncInt = OSAllocMemNoStats(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psSyncInt)
-		{
-			psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigure_exit;
-		}
-		hSyncInt2 = OSAllocMemNoStats(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE));
-		if (!hSyncInt2)
-		{
-			psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigure_exit;
-		}
+		psSyncInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hSyncInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDisplayContextConfigureIN->phSync, psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hSyncInt2, psDCDisplayContextConfigureIN->phSync,
-				psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hSyncInt2, psDCDisplayContextConfigureIN->phSync, psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCDisplayContextConfigure_exit;
+					goto DCDisplayContextConfigure_exit;
+				}
 			}
 	if (psDCDisplayContextConfigureIN->ui32SyncCount != 0)
 	{
-		bUpdateInt = OSAllocMemNoStats(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL));
-		if (!bUpdateInt)
-		{
-			psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCDisplayContextConfigure_exit;
-		}
+		bUpdateInt = (IMG_BOOL*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCDisplayContextConfigureIN->pbUpdate, psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL))
-				|| (OSCopyFromUser(NULL, bUpdateInt, psDCDisplayContextConfigureIN->pbUpdate,
-				psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL)) != PVRSRV_OK) )
+			if (psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL) > 0)
 			{
-				psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, bUpdateInt, psDCDisplayContextConfigureIN->pbUpdate, psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL)) != PVRSRV_OK )
+				{
+					psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DCDisplayContextConfigure_exit;
+					goto DCDisplayContextConfigure_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDCDisplayContextConfigureOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDisplayContextInt,
-											psDCDisplayContextConfigureIN->hDisplayContext,
-											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
+											IMG_TRUE);
 					if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDisplayContextConfigure_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1109,19 +1791,24 @@
 				{
 					/* Look up the address from the handle */
 					psDCDisplayContextConfigureOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psBuffersInt[i],
 											hBuffersInt2[i],
-											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+											PVRSRV_HANDLE_TYPE_DC_BUFFER,
+											IMG_TRUE);
 					if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDisplayContextConfigure_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1130,18 +1817,21 @@
 				{
 					/* Look up the address from the handle */
 					psDCDisplayContextConfigureOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncInt[i],
 											hSyncInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCDisplayContextConfigure_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCDisplayContextConfigureOUT->eError =
 		DCDisplayContextConfigure(
@@ -1161,22 +1851,88 @@
 
 
 DCDisplayContextConfigure_exit:
-	if (psSurfInfoInt)
-		OSFreeMemNoStats(psSurfInfoInt);
-	if (psBuffersInt)
-		OSFreeMemNoStats(psBuffersInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDisplayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+						}
+				}
+
+
+
+
+
+
 	if (hBuffersInt2)
-		OSFreeMemNoStats(hBuffersInt2);
-	if (psSyncInt)
-		OSFreeMemNoStats(psSyncInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psDCDisplayContextConfigureIN->ui32PipeCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psBuffersInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hBuffersInt2[i],
+											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hSyncInt2)
-		OSFreeMemNoStats(hSyncInt2);
-	if (bUpdateInt)
-		OSFreeMemNoStats(bUpdateInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psDCDisplayContextConfigureIN->ui32SyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCDisplayContextDestroy(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTDESTROY *psDCDisplayContextDestroyIN,
@@ -1192,29 +1948,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psDCDisplayContextDestroyOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCDisplayContextDestroyIN->hDisplayContext,
 					PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
-	if ((psDCDisplayContextDestroyOUT->eError != PVRSRV_OK) && (psDCDisplayContextDestroyOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCDisplayContextDestroyOUT->eError != PVRSRV_OK) &&
+	    (psDCDisplayContextDestroyOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCDisplayContextDestroy: %s",
+		        PVRSRVGetErrorStringKM(psDCDisplayContextDestroyOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto DCDisplayContextDestroy_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCDisplayContextDestroy_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferAlloc(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERALLOC *psDCBufferAllocIN,
 					  PVRSRV_BRIDGE_OUT_DCBUFFERALLOC *psDCBufferAllocOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDisplayContext = psDCBufferAllocIN->hDisplayContext;
 	DC_DISPLAY_CONTEXT * psDisplayContextInt = NULL;
 	DC_BUFFER * psBufferInt = NULL;
 
@@ -1224,19 +2000,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCBufferAllocOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDisplayContextInt,
-											psDCBufferAllocIN->hDisplayContext,
-											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
+											IMG_TRUE);
 					if(psDCBufferAllocOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCBufferAlloc_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCBufferAllocOUT->eError =
 		DCBufferAlloc(
@@ -1250,8 +2036,15 @@
 		goto DCBufferAlloc_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDCBufferAllocOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDCBufferAllocOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCBufferAllocOUT->hBuffer,
 							(void *) psBufferInt,
 							PVRSRV_HANDLE_TYPE_DC_BUFFER,
@@ -1259,13 +2052,37 @@
 							,(PFN_HANDLE_RELEASE)&DCBufferFree);
 	if (psDCBufferAllocOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCBufferAlloc_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCBufferAlloc_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDisplayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDCBufferAllocOUT->eError != PVRSRV_OK)
 	{
 		if (psBufferInt)
@@ -1278,66 +2095,106 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferImport(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERIMPORT *psDCBufferImportIN,
 					  PVRSRV_BRIDGE_OUT_DCBUFFERIMPORT *psDCBufferImportOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDisplayContext = psDCBufferImportIN->hDisplayContext;
 	DC_DISPLAY_CONTEXT * psDisplayContextInt = NULL;
 	PMR * *psImportInt = NULL;
 	IMG_HANDLE *hImportInt2 = NULL;
 	DC_BUFFER * psBufferInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDCBufferImportIN->ui32NumPlanes * sizeof(PMR *)) +
+			(psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE)) +
+			0;
 
 
 
-	if (psDCBufferImportIN->ui32NumPlanes != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		psImportInt = OSAllocMemNoStats(psDCBufferImportIN->ui32NumPlanes * sizeof(PMR *));
-		if (!psImportInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDCBufferImportIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDCBufferImportOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCBufferImport_exit;
-		}
-		hImportInt2 = OSAllocMemNoStats(psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE));
-		if (!hImportInt2)
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDCBufferImportIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
 		{
-			psDCBufferImportOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DCBufferImport_exit;
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDCBufferImportOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DCBufferImport_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDCBufferImportIN->phImport, psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hImportInt2, psDCBufferImportIN->phImport,
-				psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
-			{
-				psDCBufferImportOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psDCBufferImportIN->ui32NumPlanes != 0)
+	{
+		psImportInt = (PMR **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDCBufferImportIN->ui32NumPlanes * sizeof(PMR *);
+		hImportInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE);
+	}
 
-				goto DCBufferImport_exit;
+			/* Copy the data over */
+			if (psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hImportInt2, psDCBufferImportIN->phImport, psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psDCBufferImportOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DCBufferImport_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDCBufferImportOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDisplayContextInt,
-											psDCBufferImportIN->hDisplayContext,
-											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
+											IMG_TRUE);
 					if(psDCBufferImportOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DCBufferImport_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1346,19 +2203,21 @@
 				{
 					/* Look up the address from the handle */
 					psDCBufferImportOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psImportInt[i],
 											hImportInt2[i],
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDCBufferImportOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DCBufferImport_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCBufferImportOUT->eError =
 		DCBufferImport(
@@ -1370,13 +2229,18 @@
 	/* Exit early if bridged call fails */
 	if(psDCBufferImportOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto DCBufferImport_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psDCBufferImportOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psDCBufferImportOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCBufferImportOUT->hBuffer,
 							(void *) psBufferInt,
 							PVRSRV_HANDLE_TYPE_DC_BUFFER,
@@ -1384,13 +2248,60 @@
 							,(PFN_HANDLE_RELEASE)&DCBufferFree);
 	if (psDCBufferImportOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCBufferImport_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCBufferImport_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDisplayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDisplayContext,
+											PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+						}
+				}
+
+
+
+
+
+
+	if (hImportInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psDCBufferImportIN->ui32NumPlanes;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psImportInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hImportInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDCBufferImportOUT->eError != PVRSRV_OK)
 	{
 		if (psBufferInt)
@@ -1399,14 +2310,21 @@
 		}
 	}
 
-	if (psImportInt)
-		OSFreeMemNoStats(psImportInt);
-	if (hImportInt2)
-		OSFreeMemNoStats(hImportInt2);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferFree(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERFREE *psDCBufferFreeIN,
@@ -1418,30 +2336,46 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psDCBufferFreeOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCBufferFreeIN->hBuffer,
 					PVRSRV_HANDLE_TYPE_DC_BUFFER);
-	if ((psDCBufferFreeOUT->eError != PVRSRV_OK) && (psDCBufferFreeOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCBufferFreeOUT->eError != PVRSRV_OK) &&
+	    (psDCBufferFreeOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCBufferFree: %s",
+		        PVRSRVGetErrorStringKM(psDCBufferFreeOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto DCBufferFree_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCBufferFree_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferUnimport(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERUNIMPORT *psDCBufferUnimportIN,
@@ -1453,36 +2387,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psDCBufferUnimportOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCBufferUnimportIN->hBuffer,
 					PVRSRV_HANDLE_TYPE_DC_BUFFER);
-	if ((psDCBufferUnimportOUT->eError != PVRSRV_OK) && (psDCBufferUnimportOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCBufferUnimportOUT->eError != PVRSRV_OK) &&
+	    (psDCBufferUnimportOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCBufferUnimport: %s",
+		        PVRSRVGetErrorStringKM(psDCBufferUnimportOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto DCBufferUnimport_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCBufferUnimport_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferPin(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERPIN *psDCBufferPinIN,
 					  PVRSRV_BRIDGE_OUT_DCBUFFERPIN *psDCBufferPinOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hBuffer = psDCBufferPinIN->hBuffer;
 	DC_BUFFER * psBufferInt = NULL;
 	DC_PIN_HANDLE hPinHandleInt = NULL;
 
@@ -1492,19 +2443,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDCBufferPinOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psBufferInt,
-											psDCBufferPinIN->hBuffer,
-											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+											hBuffer,
+											PVRSRV_HANDLE_TYPE_DC_BUFFER,
+											IMG_TRUE);
 					if(psDCBufferPinOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DCBufferPin_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCBufferPinOUT->eError =
 		DCBufferPin(
@@ -1516,8 +2477,15 @@
 		goto DCBufferPin_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDCBufferPinOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDCBufferPinOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCBufferPinOUT->hPinHandle,
 							(void *) hPinHandleInt,
 							PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE,
@@ -1525,13 +2493,37 @@
 							,(PFN_HANDLE_RELEASE)&DCBufferUnpin);
 	if (psDCBufferPinOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCBufferPin_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCBufferPin_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psBufferInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hBuffer,
+											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDCBufferPinOUT->eError != PVRSRV_OK)
 	{
 		if (hPinHandleInt)
@@ -1544,6 +2536,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferUnpin(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERUNPIN *psDCBufferUnpinIN,
@@ -1559,29 +2552,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psDCBufferUnpinOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCBufferUnpinIN->hPinHandle,
 					PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE);
-	if ((psDCBufferUnpinOUT->eError != PVRSRV_OK) && (psDCBufferUnpinOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCBufferUnpinOUT->eError != PVRSRV_OK) &&
+	    (psDCBufferUnpinOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCBufferUnpin: %s",
+		        PVRSRVGetErrorStringKM(psDCBufferUnpinOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto DCBufferUnpin_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCBufferUnpin_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferAcquire(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERACQUIRE *psDCBufferAcquireIN,
 					  PVRSRV_BRIDGE_OUT_DCBUFFERACQUIRE *psDCBufferAcquireOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hBuffer = psDCBufferAcquireIN->hBuffer;
 	DC_BUFFER * psBufferInt = NULL;
 	PMR * psExtMemInt = NULL;
 
@@ -1589,23 +2602,31 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDCBufferAcquireOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psBufferInt,
-											psDCBufferAcquireIN->hBuffer,
-											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+											hBuffer,
+											PVRSRV_HANDLE_TYPE_DC_BUFFER,
+											IMG_TRUE);
 					if(psDCBufferAcquireOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DCBufferAcquire_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDCBufferAcquireOUT->eError =
 		DCBufferAcquire(
@@ -1614,13 +2635,18 @@
 	/* Exit early if bridged call fails */
 	if(psDCBufferAcquireOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto DCBufferAcquire_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psDCBufferAcquireOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psDCBufferAcquireOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDCBufferAcquireOUT->hExtMem,
 							(void *) psExtMemInt,
 							PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT,
@@ -1628,13 +2654,37 @@
 							,(PFN_HANDLE_RELEASE)&DCBufferRelease);
 	if (psDCBufferAcquireOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DCBufferAcquire_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DCBufferAcquire_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psBufferInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hBuffer,
+											PVRSRV_HANDLE_TYPE_DC_BUFFER);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDCBufferAcquireOUT->eError != PVRSRV_OK)
 	{
 		if (psExtMemInt)
@@ -1647,6 +2697,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDCBufferRelease(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DCBUFFERRELEASE *psDCBufferReleaseIN,
@@ -1658,32 +2709,48 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psDCBufferReleaseOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDCBufferReleaseIN->hExtMem,
 					PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
-	if ((psDCBufferReleaseOUT->eError != PVRSRV_OK) && (psDCBufferReleaseOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDCBufferReleaseOUT->eError != PVRSRV_OK) &&
+	    (psDCBufferReleaseOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDCBufferRelease: %s",
+		        PVRSRVGetErrorStringKM(psDCBufferReleaseOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto DCBufferRelease_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DCBufferRelease_exit:
 
+
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -1788,4 +2855,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h b/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h
index b2a5501..23656ae 100644
--- a/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for debugmisc
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for debugmisc
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for debugmisc
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_DEBUGMISC_BRIDGE_H
 #define COMMON_DEBUGMISC_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -58,7 +60,10 @@
 #define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETFWLOG			PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+1
 #define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCDUMPFREELISTPAGELIST			PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+2
 #define PVRSRV_BRIDGE_DEBUGMISC_PHYSMEMIMPORTSECBUF			PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+3
-#define PVRSRV_BRIDGE_DEBUGMISC_CMD_LAST			(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETHCSDEADLINE			PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+4
+#define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETOSIDPRIORITY			PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+5
+#define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETOSNEWONLINESTATE			PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+6
+#define PVRSRV_BRIDGE_DEBUGMISC_CMD_LAST			(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+6)
 
 
 /*******************************************
@@ -121,17 +126,70 @@
 typedef struct PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSECBUF_TAG
 {
 	IMG_DEVMEM_SIZE_T uiSize;
+	IMG_UINT32 ui32Log2Align;
 	PVRSRV_MEMALLOCFLAGS_T uiFlags;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSECBUF;
 
 /* Bridge out structure for PhysmemImportSecBuf */
 typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSECBUF_TAG
 {
-	IMG_UINT32 ui32Align;
 	IMG_HANDLE hPMRPtr;
 	IMG_UINT64 ui64SecBufHandle;
 	PVRSRV_ERROR eError;
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSECBUF;
 
 
+/*******************************************
+            RGXDebugMiscSetHCSDeadline          
+ *******************************************/
+
+/* Bridge in structure for RGXDebugMiscSetHCSDeadline */
+typedef struct PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETHCSDEADLINE_TAG
+{
+	IMG_UINT32 ui32RGXHCSDeadline;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETHCSDEADLINE;
+
+/* Bridge out structure for RGXDebugMiscSetHCSDeadline */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETHCSDEADLINE_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETHCSDEADLINE;
+
+
+/*******************************************
+            RGXDebugMiscSetOSidPriority          
+ *******************************************/
+
+/* Bridge in structure for RGXDebugMiscSetOSidPriority */
+typedef struct PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETOSIDPRIORITY_TAG
+{
+	IMG_UINT32 ui32OSid;
+	IMG_UINT32 ui32Priority;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETOSIDPRIORITY;
+
+/* Bridge out structure for RGXDebugMiscSetOSidPriority */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETOSIDPRIORITY_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETOSIDPRIORITY;
+
+
+/*******************************************
+            RGXDebugMiscSetOSNewOnlineState          
+ *******************************************/
+
+/* Bridge in structure for RGXDebugMiscSetOSNewOnlineState */
+typedef struct PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETOSNEWONLINESTATE_TAG
+{
+	IMG_UINT32 ui32OSid;
+	IMG_UINT32 ui32OSNewState;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETOSNEWONLINESTATE;
+
+/* Bridge out structure for RGXDebugMiscSetOSNewOnlineState */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETOSNEWONLINESTATE_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETOSNEWONLINESTATE;
+
+
 #endif /* COMMON_DEBUGMISC_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c b/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c
index 6dcf4b1..c3f5677 100644
--- a/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c
@@ -67,6 +67,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -84,6 +86,7 @@
 
 
 
+
 	psDebugMiscSLCSetBypassStateOUT->eError =
 		PVRSRVDebugMiscSLCSetBypassStateKM(psConnection, OSGetDevData(psConnection),
 					psDebugMiscSLCSetBypassStateIN->ui32Flags,
@@ -93,9 +96,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDebugMiscSetFWLog(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETFWLOG *psRGXDebugMiscSetFWLogIN,
@@ -109,6 +116,7 @@
 
 
 
+
 	psRGXDebugMiscSetFWLogOUT->eError =
 		PVRSRVRGXDebugMiscSetFWLogKM(psConnection, OSGetDevData(psConnection),
 					psRGXDebugMiscSetFWLogIN->ui32RGXFWLogType);
@@ -117,9 +125,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDebugMiscDumpFreelistPageList(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDEBUGMISCDUMPFREELISTPAGELIST *psRGXDebugMiscDumpFreelistPageListIN,
@@ -127,9 +139,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psRGXDebugMiscDumpFreelistPageListIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psRGXDebugMiscDumpFreelistPageListIN);
+
 
 
 
@@ -142,9 +155,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePhysmemImportSecBuf(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSECBUF *psPhysmemImportSecBufIN,
@@ -157,26 +174,31 @@
 
 
 
-	PMRLock();
+
 
 
 	psPhysmemImportSecBufOUT->eError =
 		PhysmemImportSecBuf(psConnection, OSGetDevData(psConnection),
 					psPhysmemImportSecBufIN->uiSize,
+					psPhysmemImportSecBufIN->ui32Log2Align,
 					psPhysmemImportSecBufIN->uiFlags,
-					&psPhysmemImportSecBufOUT->ui32Align,
 					&psPMRPtrInt,
 					&psPhysmemImportSecBufOUT->ui64SecBufHandle);
 	/* Exit early if bridged call fails */
 	if(psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PhysmemImportSecBuf_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPhysmemImportSecBufOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPhysmemImportSecBufOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPhysmemImportSecBufOUT->hPMRPtr,
 							(void *) psPMRPtrInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
@@ -184,13 +206,19 @@
 							,(PFN_HANDLE_RELEASE)&PMRUnrefPMR);
 	if (psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PhysmemImportSecBuf_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PhysmemImportSecBuf_exit:
+
+
+
 	if (psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
 	{
 		if (psPMRPtrInt)
@@ -204,6 +232,96 @@
 }
 
 
+static IMG_INT
+PVRSRVBridgeRGXDebugMiscSetHCSDeadline(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETHCSDEADLINE *psRGXDebugMiscSetHCSDeadlineIN,
+					  PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETHCSDEADLINE *psRGXDebugMiscSetHCSDeadlineOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+
+
+
+
+
+	psRGXDebugMiscSetHCSDeadlineOUT->eError =
+		PVRSRVRGXDebugMiscSetHCSDeadlineKM(psConnection, OSGetDevData(psConnection),
+					psRGXDebugMiscSetHCSDeadlineIN->ui32RGXHCSDeadline);
+
+
+
+
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXDebugMiscSetOSidPriority(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETOSIDPRIORITY *psRGXDebugMiscSetOSidPriorityIN,
+					  PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETOSIDPRIORITY *psRGXDebugMiscSetOSidPriorityOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+
+
+
+
+
+	psRGXDebugMiscSetOSidPriorityOUT->eError =
+		PVRSRVRGXDebugMiscSetOSidPriorityKM(psConnection, OSGetDevData(psConnection),
+					psRGXDebugMiscSetOSidPriorityIN->ui32OSid,
+					psRGXDebugMiscSetOSidPriorityIN->ui32Priority);
+
+
+
+
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXDebugMiscSetOSNewOnlineState(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETOSNEWONLINESTATE *psRGXDebugMiscSetOSNewOnlineStateIN,
+					  PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETOSNEWONLINESTATE *psRGXDebugMiscSetOSNewOnlineStateOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+
+
+
+
+
+	psRGXDebugMiscSetOSNewOnlineStateOUT->eError =
+		PVRSRVRGXDebugMiscSetOSNewOnlineStateKM(psConnection, OSGetDevData(psConnection),
+					psRGXDebugMiscSetOSNewOnlineStateIN->ui32OSid,
+					psRGXDebugMiscSetOSNewOnlineStateIN->ui32OSNewState);
+
+
+
+
+
+
+
+
+	return 0;
+}
+
+
+
 
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
@@ -232,6 +350,15 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC, PVRSRV_BRIDGE_DEBUGMISC_PHYSMEMIMPORTSECBUF, PVRSRVBridgePhysmemImportSecBuf,
 					NULL, bUseLock);
 
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC, PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETHCSDEADLINE, PVRSRVBridgeRGXDebugMiscSetHCSDeadline,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC, PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETOSIDPRIORITY, PVRSRVBridgeRGXDebugMiscSetOSidPriority,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC, PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETOSNEWONLINESTATE, PVRSRVBridgeRGXDebugMiscSetOSNewOnlineState,
+					NULL, bUseLock);
+
 
 	return PVRSRV_OK;
 }
@@ -243,4 +370,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_bridge.h b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_bridge.h
index 1ed68b1..a47e2e4 100644
--- a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_bridge.h
@@ -64,5 +64,59 @@
 								   IMG_DEVMEM_SIZE_T uiSize,
 								   const IMG_CHAR *puiText);
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryMapNew(IMG_HANDLE hBridge,
+								    IMG_HANDLE hPMR,
+								    IMG_DEVMEM_SIZE_T uiOffset,
+								    IMG_DEV_VIRTADDR sDevVAddr,
+								    IMG_DEVMEM_SIZE_T uiSize,
+								    const IMG_CHAR *puiText,
+								    IMG_UINT32 ui32Log2PageSize,
+								    IMG_UINT32 ui32AllocationIndex,
+								    IMG_UINT32 *pui32AllocationIndexOut);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryUnmapNew(IMG_HANDLE hBridge,
+								      IMG_HANDLE hPMR,
+								      IMG_DEVMEM_SIZE_T uiOffset,
+								      IMG_DEV_VIRTADDR sDevVAddr,
+								      IMG_DEVMEM_SIZE_T uiSize,
+								      const IMG_CHAR *puiText,
+								      IMG_UINT32 ui32Log2PageSize,
+								      IMG_UINT32 ui32AllocationIndex,
+								      IMG_UINT32 *pui32AllocationIndexOut);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryMapVRange(IMG_HANDLE hBridge,
+								       IMG_DEV_VIRTADDR sBaseDevVAddr,
+								       IMG_UINT32 ui32ui32StartPage,
+								       IMG_UINT32 ui32NumPages,
+								       IMG_DEVMEM_SIZE_T uiAllocSize,
+								       const IMG_CHAR *puiText,
+								       IMG_UINT32 ui32Log2PageSize,
+								       IMG_UINT32 ui32AllocationIndex,
+								       IMG_UINT32 *pui32AllocationIndexOut);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryUnmapVRange(IMG_HANDLE hBridge,
+									 IMG_DEV_VIRTADDR sBaseDevVAddr,
+									 IMG_UINT32 ui32ui32StartPage,
+									 IMG_UINT32 ui32NumPages,
+									 IMG_DEVMEM_SIZE_T uiAllocSize,
+									 const IMG_CHAR *puiText,
+									 IMG_UINT32 ui32Log2PageSize,
+									 IMG_UINT32 ui32AllocationIndex,
+									 IMG_UINT32 *pui32AllocationIndexOut);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistorySparseChange(IMG_HANDLE hBridge,
+									  IMG_HANDLE hPMR,
+									  IMG_DEVMEM_SIZE_T uiOffset,
+									  IMG_DEV_VIRTADDR sDevVAddr,
+									  IMG_DEVMEM_SIZE_T uiSize,
+									  const IMG_CHAR *puiText,
+									  IMG_UINT32 ui32Log2PageSize,
+									  IMG_UINT32 ui32AllocPageCount,
+									  IMG_UINT32 *pui32AllocPageIndices,
+									  IMG_UINT32 ui32FreePageCount,
+									  IMG_UINT32 *pui32FreePageIndices,
+									  IMG_UINT32 ui32AllocationIndex,
+									  IMG_UINT32 *pui32AllocationIndexOut);
+
 
 #endif /* CLIENT_DEVICEMEMHISTORY_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_direct_bridge.c
index 21225f7..4d11c82 100644
--- a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/client_devicememhistory_direct_bridge.c
@@ -86,3 +86,157 @@
 	return eError;
 }
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryMapNew(IMG_HANDLE hBridge,
+								    IMG_HANDLE hPMR,
+								    IMG_DEVMEM_SIZE_T uiOffset,
+								    IMG_DEV_VIRTADDR sDevVAddr,
+								    IMG_DEVMEM_SIZE_T uiSize,
+								    const IMG_CHAR *puiText,
+								    IMG_UINT32 ui32Log2PageSize,
+								    IMG_UINT32 ui32AllocationIndex,
+								    IMG_UINT32 *pui32AllocationIndexOut)
+{
+	PVRSRV_ERROR eError;
+	PMR * psPMRInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psPMRInt = (PMR *) hPMR;
+
+	eError =
+		DevicememHistoryMapNewKM(
+					psPMRInt,
+					uiOffset,
+					sDevVAddr,
+					uiSize,
+					puiText,
+					ui32Log2PageSize,
+					ui32AllocationIndex,
+					pui32AllocationIndexOut);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryUnmapNew(IMG_HANDLE hBridge,
+								      IMG_HANDLE hPMR,
+								      IMG_DEVMEM_SIZE_T uiOffset,
+								      IMG_DEV_VIRTADDR sDevVAddr,
+								      IMG_DEVMEM_SIZE_T uiSize,
+								      const IMG_CHAR *puiText,
+								      IMG_UINT32 ui32Log2PageSize,
+								      IMG_UINT32 ui32AllocationIndex,
+								      IMG_UINT32 *pui32AllocationIndexOut)
+{
+	PVRSRV_ERROR eError;
+	PMR * psPMRInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psPMRInt = (PMR *) hPMR;
+
+	eError =
+		DevicememHistoryUnmapNewKM(
+					psPMRInt,
+					uiOffset,
+					sDevVAddr,
+					uiSize,
+					puiText,
+					ui32Log2PageSize,
+					ui32AllocationIndex,
+					pui32AllocationIndexOut);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryMapVRange(IMG_HANDLE hBridge,
+								       IMG_DEV_VIRTADDR sBaseDevVAddr,
+								       IMG_UINT32 ui32ui32StartPage,
+								       IMG_UINT32 ui32NumPages,
+								       IMG_DEVMEM_SIZE_T uiAllocSize,
+								       const IMG_CHAR *puiText,
+								       IMG_UINT32 ui32Log2PageSize,
+								       IMG_UINT32 ui32AllocationIndex,
+								       IMG_UINT32 *pui32AllocationIndexOut)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		DevicememHistoryMapVRangeKM(
+					sBaseDevVAddr,
+					ui32ui32StartPage,
+					ui32NumPages,
+					uiAllocSize,
+					puiText,
+					ui32Log2PageSize,
+					ui32AllocationIndex,
+					pui32AllocationIndexOut);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistoryUnmapVRange(IMG_HANDLE hBridge,
+									 IMG_DEV_VIRTADDR sBaseDevVAddr,
+									 IMG_UINT32 ui32ui32StartPage,
+									 IMG_UINT32 ui32NumPages,
+									 IMG_DEVMEM_SIZE_T uiAllocSize,
+									 const IMG_CHAR *puiText,
+									 IMG_UINT32 ui32Log2PageSize,
+									 IMG_UINT32 ui32AllocationIndex,
+									 IMG_UINT32 *pui32AllocationIndexOut)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		DevicememHistoryUnmapVRangeKM(
+					sBaseDevVAddr,
+					ui32ui32StartPage,
+					ui32NumPages,
+					uiAllocSize,
+					puiText,
+					ui32Log2PageSize,
+					ui32AllocationIndex,
+					pui32AllocationIndexOut);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevicememHistorySparseChange(IMG_HANDLE hBridge,
+									  IMG_HANDLE hPMR,
+									  IMG_DEVMEM_SIZE_T uiOffset,
+									  IMG_DEV_VIRTADDR sDevVAddr,
+									  IMG_DEVMEM_SIZE_T uiSize,
+									  const IMG_CHAR *puiText,
+									  IMG_UINT32 ui32Log2PageSize,
+									  IMG_UINT32 ui32AllocPageCount,
+									  IMG_UINT32 *pui32AllocPageIndices,
+									  IMG_UINT32 ui32FreePageCount,
+									  IMG_UINT32 *pui32FreePageIndices,
+									  IMG_UINT32 ui32AllocationIndex,
+									  IMG_UINT32 *pui32AllocationIndexOut)
+{
+	PVRSRV_ERROR eError;
+	PMR * psPMRInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psPMRInt = (PMR *) hPMR;
+
+	eError =
+		DevicememHistorySparseChangeKM(
+					psPMRInt,
+					uiOffset,
+					sDevVAddr,
+					uiSize,
+					puiText,
+					ui32Log2PageSize,
+					ui32AllocPageCount,
+					pui32AllocPageIndices,
+					ui32FreePageCount,
+					pui32FreePageIndices,
+					ui32AllocationIndex,
+					pui32AllocationIndexOut);
+
+	return eError;
+}
+
diff --git a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/common_devicememhistory_bridge.h b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/common_devicememhistory_bridge.h
index 63c6ec3..ed0a59a 100644
--- a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/common_devicememhistory_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/common_devicememhistory_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for devicememhistory
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for devicememhistory
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for devicememhistory
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_DEVICEMEMHISTORY_BRIDGE_H
 #define COMMON_DEVICEMEMHISTORY_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -55,7 +57,12 @@
 #define PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST			0
 #define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAP			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+0
 #define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAP			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+1
-#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_LAST			(PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAPNEW			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+2
+#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAPNEW			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+3
+#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAPVRANGE			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+4
+#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAPVRANGE			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+5
+#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYSPARSECHANGE			PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+6
+#define PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_LAST			(PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_FIRST+6)
 
 
 /*******************************************
@@ -96,4 +103,128 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAP;
 
 
+/*******************************************
+            DevicememHistoryMapNew          
+ *******************************************/
+
+/* Bridge in structure for DevicememHistoryMapNew */
+typedef struct PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPNEW_TAG
+{
+	IMG_HANDLE hPMR;
+	IMG_DEVMEM_SIZE_T uiOffset;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEVMEM_SIZE_T uiSize;
+	const IMG_CHAR * puiText;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32AllocationIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPNEW;
+
+/* Bridge out structure for DevicememHistoryMapNew */
+typedef struct PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPNEW_TAG
+{
+	IMG_UINT32 ui32AllocationIndexOut;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPNEW;
+
+
+/*******************************************
+            DevicememHistoryUnmapNew          
+ *******************************************/
+
+/* Bridge in structure for DevicememHistoryUnmapNew */
+typedef struct PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPNEW_TAG
+{
+	IMG_HANDLE hPMR;
+	IMG_DEVMEM_SIZE_T uiOffset;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEVMEM_SIZE_T uiSize;
+	const IMG_CHAR * puiText;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32AllocationIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPNEW;
+
+/* Bridge out structure for DevicememHistoryUnmapNew */
+typedef struct PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPNEW_TAG
+{
+	IMG_UINT32 ui32AllocationIndexOut;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPNEW;
+
+
+/*******************************************
+            DevicememHistoryMapVRange          
+ *******************************************/
+
+/* Bridge in structure for DevicememHistoryMapVRange */
+typedef struct PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPVRANGE_TAG
+{
+	IMG_DEV_VIRTADDR sBaseDevVAddr;
+	IMG_UINT32 ui32ui32StartPage;
+	IMG_UINT32 ui32NumPages;
+	IMG_DEVMEM_SIZE_T uiAllocSize;
+	const IMG_CHAR * puiText;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32AllocationIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPVRANGE;
+
+/* Bridge out structure for DevicememHistoryMapVRange */
+typedef struct PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPVRANGE_TAG
+{
+	IMG_UINT32 ui32AllocationIndexOut;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPVRANGE;
+
+
+/*******************************************
+            DevicememHistoryUnmapVRange          
+ *******************************************/
+
+/* Bridge in structure for DevicememHistoryUnmapVRange */
+typedef struct PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPVRANGE_TAG
+{
+	IMG_DEV_VIRTADDR sBaseDevVAddr;
+	IMG_UINT32 ui32ui32StartPage;
+	IMG_UINT32 ui32NumPages;
+	IMG_DEVMEM_SIZE_T uiAllocSize;
+	const IMG_CHAR * puiText;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32AllocationIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPVRANGE;
+
+/* Bridge out structure for DevicememHistoryUnmapVRange */
+typedef struct PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPVRANGE_TAG
+{
+	IMG_UINT32 ui32AllocationIndexOut;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPVRANGE;
+
+
+/*******************************************
+            DevicememHistorySparseChange          
+ *******************************************/
+
+/* Bridge in structure for DevicememHistorySparseChange */
+typedef struct PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYSPARSECHANGE_TAG
+{
+	IMG_HANDLE hPMR;
+	IMG_DEVMEM_SIZE_T uiOffset;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEVMEM_SIZE_T uiSize;
+	const IMG_CHAR * puiText;
+	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32AllocPageCount;
+	IMG_UINT32 * pui32AllocPageIndices;
+	IMG_UINT32 ui32FreePageCount;
+	IMG_UINT32 * pui32FreePageIndices;
+	IMG_UINT32 ui32AllocationIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYSPARSECHANGE;
+
+/* Bridge out structure for DevicememHistorySparseChange */
+typedef struct PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYSPARSECHANGE_TAG
+{
+	IMG_UINT32 ui32AllocationIndexOut;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYSPARSECHANGE;
+
+
 #endif /* COMMON_DEVICEMEMHISTORY_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/server_devicememhistory_bridge.c b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/server_devicememhistory_bridge.c
index 3641b3b..cb8bc58 100644
--- a/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/server_devicememhistory_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/devicememhistory_bridge/server_devicememhistory_bridge.c
@@ -64,6 +64,9 @@
 #include "lock.h"
 
 
+#if defined(SUPPORT_DEVICEMEMHISTORY_BRIDGE)
+
+
 
 /* ***************************************************************************
  * Server-side bridge entry points
@@ -77,33 +80,66 @@
 {
 	IMG_CHAR *uiTextInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			0;
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
-	
+	if (ui32BufferSize != 0)
 	{
-		uiTextInt = OSAllocMemNoStats(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR));
-		if (!uiTextInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistoryMapIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DevicememHistoryMap_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistoryMapIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistoryMap_exit;
+			}
 		}
 	}
 
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDevicememHistoryMapIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryMapIN->puiText,
-				DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
 			{
-				psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryMapIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DevicememHistoryMap_exit;
+					goto DevicememHistoryMap_exit;
+				}
 			}
 
 
-
 	psDevicememHistoryMapOUT->eError =
 		DevicememHistoryMapKM(
 					psDevicememHistoryMapIN->sDevVAddr,
@@ -114,12 +150,24 @@
 
 
 DevicememHistoryMap_exit:
-	if (uiTextInt)
-		OSFreeMemNoStats(uiTextInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevicememHistoryUnmap(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAP *psDevicememHistoryUnmapIN,
@@ -128,33 +176,66 @@
 {
 	IMG_CHAR *uiTextInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			0;
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
-	
+	if (ui32BufferSize != 0)
 	{
-		uiTextInt = OSAllocMemNoStats(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR));
-		if (!uiTextInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistoryUnmapIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DevicememHistoryUnmap_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistoryUnmapIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistoryUnmap_exit;
+			}
 		}
 	}
 
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDevicememHistoryUnmapIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryUnmapIN->puiText,
-				DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
 			{
-				psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryUnmapIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto DevicememHistoryUnmap_exit;
+					goto DevicememHistoryUnmap_exit;
+				}
 			}
 
 
-
 	psDevicememHistoryUnmapOUT->eError =
 		DevicememHistoryUnmapKM(
 					psDevicememHistoryUnmapIN->sDevVAddr,
@@ -165,13 +246,696 @@
 
 
 DevicememHistoryUnmap_exit:
-	if (uiTextInt)
-		OSFreeMemNoStats(uiTextInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
 
+static IMG_INT
+PVRSRVBridgeDevicememHistoryMapNew(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPNEW *psDevicememHistoryMapNewIN,
+					  PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPNEW *psDevicememHistoryMapNewOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hPMR = psDevicememHistoryMapNewIN->hPMR;
+	PMR * psPMRInt = NULL;
+	IMG_CHAR *uiTextInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistoryMapNewIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistoryMapNewIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistoryMapNewOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistoryMapNew_exit;
+			}
+		}
+	}
+
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryMapNewIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistoryMapNewOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistoryMapNew_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psDevicememHistoryMapNewOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psPMRInt,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psDevicememHistoryMapNewOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto DevicememHistoryMapNew_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psDevicememHistoryMapNewOUT->eError =
+		DevicememHistoryMapNewKM(
+					psPMRInt,
+					psDevicememHistoryMapNewIN->uiOffset,
+					psDevicememHistoryMapNewIN->sDevVAddr,
+					psDevicememHistoryMapNewIN->uiSize,
+					uiTextInt,
+					psDevicememHistoryMapNewIN->ui32Log2PageSize,
+					psDevicememHistoryMapNewIN->ui32AllocationIndex,
+					&psDevicememHistoryMapNewOUT->ui32AllocationIndexOut);
+
+
+
+
+DevicememHistoryMapNew_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeDevicememHistoryUnmapNew(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPNEW *psDevicememHistoryUnmapNewIN,
+					  PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPNEW *psDevicememHistoryUnmapNewOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hPMR = psDevicememHistoryUnmapNewIN->hPMR;
+	PMR * psPMRInt = NULL;
+	IMG_CHAR *uiTextInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistoryUnmapNewIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistoryUnmapNewIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistoryUnmapNewOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistoryUnmapNew_exit;
+			}
+		}
+	}
+
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryUnmapNewIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistoryUnmapNewOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistoryUnmapNew_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psDevicememHistoryUnmapNewOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psPMRInt,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psDevicememHistoryUnmapNewOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto DevicememHistoryUnmapNew_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psDevicememHistoryUnmapNewOUT->eError =
+		DevicememHistoryUnmapNewKM(
+					psPMRInt,
+					psDevicememHistoryUnmapNewIN->uiOffset,
+					psDevicememHistoryUnmapNewIN->sDevVAddr,
+					psDevicememHistoryUnmapNewIN->uiSize,
+					uiTextInt,
+					psDevicememHistoryUnmapNewIN->ui32Log2PageSize,
+					psDevicememHistoryUnmapNewIN->ui32AllocationIndex,
+					&psDevicememHistoryUnmapNewOUT->ui32AllocationIndexOut);
+
+
+
+
+DevicememHistoryUnmapNew_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYMAPVRANGE *psDevicememHistoryMapVRangeIN,
+					  PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYMAPVRANGE *psDevicememHistoryMapVRangeOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_CHAR *uiTextInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			0;
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistoryMapVRangeIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistoryMapVRangeIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistoryMapVRangeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistoryMapVRange_exit;
+			}
+		}
+	}
+
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryMapVRangeIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistoryMapVRangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistoryMapVRange_exit;
+				}
+			}
+
+
+	psDevicememHistoryMapVRangeOUT->eError =
+		DevicememHistoryMapVRangeKM(
+					psDevicememHistoryMapVRangeIN->sBaseDevVAddr,
+					psDevicememHistoryMapVRangeIN->ui32ui32StartPage,
+					psDevicememHistoryMapVRangeIN->ui32NumPages,
+					psDevicememHistoryMapVRangeIN->uiAllocSize,
+					uiTextInt,
+					psDevicememHistoryMapVRangeIN->ui32Log2PageSize,
+					psDevicememHistoryMapVRangeIN->ui32AllocationIndex,
+					&psDevicememHistoryMapVRangeOUT->ui32AllocationIndexOut);
+
+
+
+
+DevicememHistoryMapVRange_exit:
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYUNMAPVRANGE *psDevicememHistoryUnmapVRangeIN,
+					  PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYUNMAPVRANGE *psDevicememHistoryUnmapVRangeOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_CHAR *uiTextInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			0;
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistoryUnmapVRangeIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistoryUnmapVRangeIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistoryUnmapVRangeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistoryUnmapVRange_exit;
+			}
+		}
+	}
+
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistoryUnmapVRangeIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistoryUnmapVRangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistoryUnmapVRange_exit;
+				}
+			}
+
+
+	psDevicememHistoryUnmapVRangeOUT->eError =
+		DevicememHistoryUnmapVRangeKM(
+					psDevicememHistoryUnmapVRangeIN->sBaseDevVAddr,
+					psDevicememHistoryUnmapVRangeIN->ui32ui32StartPage,
+					psDevicememHistoryUnmapVRangeIN->ui32NumPages,
+					psDevicememHistoryUnmapVRangeIN->uiAllocSize,
+					uiTextInt,
+					psDevicememHistoryUnmapVRangeIN->ui32Log2PageSize,
+					psDevicememHistoryUnmapVRangeIN->ui32AllocationIndex,
+					&psDevicememHistoryUnmapVRangeOUT->ui32AllocationIndexOut);
+
+
+
+
+DevicememHistoryUnmapVRange_exit:
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeDevicememHistorySparseChange(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_DEVICEMEMHISTORYSPARSECHANGE *psDevicememHistorySparseChangeIN,
+					  PVRSRV_BRIDGE_OUT_DEVICEMEMHISTORYSPARSECHANGE *psDevicememHistorySparseChangeOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hPMR = psDevicememHistorySparseChangeIN->hPMR;
+	PMR * psPMRInt = NULL;
+	IMG_CHAR *uiTextInt = NULL;
+	IMG_UINT32 *ui32AllocPageIndicesInt = NULL;
+	IMG_UINT32 *ui32FreePageIndicesInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) +
+			(psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32)) +
+			(psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevicememHistorySparseChangeIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevicememHistorySparseChangeIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevicememHistorySparseChange_exit;
+			}
+		}
+	}
+
+	
+	{
+		uiTextInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextInt, psDevicememHistorySparseChangeIN->puiText, DEVICEMEM_HISTORY_TEXT_BUFSZ * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistorySparseChange_exit;
+				}
+			}
+	if (psDevicememHistorySparseChangeIN->ui32AllocPageCount != 0)
+	{
+		ui32AllocPageIndicesInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32AllocPageIndicesInt, psDevicememHistorySparseChangeIN->pui32AllocPageIndices, psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistorySparseChange_exit;
+				}
+			}
+	if (psDevicememHistorySparseChangeIN->ui32FreePageCount != 0)
+	{
+		ui32FreePageIndicesInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32FreePageIndicesInt, psDevicememHistorySparseChangeIN->pui32FreePageIndices, psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevicememHistorySparseChange_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psDevicememHistorySparseChangeOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psPMRInt,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psDevicememHistorySparseChangeOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto DevicememHistorySparseChange_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psDevicememHistorySparseChangeOUT->eError =
+		DevicememHistorySparseChangeKM(
+					psPMRInt,
+					psDevicememHistorySparseChangeIN->uiOffset,
+					psDevicememHistorySparseChangeIN->sDevVAddr,
+					psDevicememHistorySparseChangeIN->uiSize,
+					uiTextInt,
+					psDevicememHistorySparseChangeIN->ui32Log2PageSize,
+					psDevicememHistorySparseChangeIN->ui32AllocPageCount,
+					ui32AllocPageIndicesInt,
+					psDevicememHistorySparseChangeIN->ui32FreePageCount,
+					ui32FreePageIndicesInt,
+					psDevicememHistorySparseChangeIN->ui32AllocationIndex,
+					&psDevicememHistorySparseChangeOUT->ui32AllocationIndexOut);
+
+
+
+
+DevicememHistorySparseChange_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+
 
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
@@ -179,7 +943,9 @@
 
 static POS_LOCK pDEVICEMEMHISTORYBridgeLock;
 static IMG_BOOL bUseLock = IMG_TRUE;
+#endif /* SUPPORT_DEVICEMEMHISTORY_BRIDGE */
 
+#if defined(SUPPORT_DEVICEMEMHISTORY_BRIDGE)
 PVRSRV_ERROR InitDEVICEMEMHISTORYBridge(void);
 PVRSRV_ERROR DeinitDEVICEMEMHISTORYBridge(void);
 
@@ -196,6 +962,21 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY, PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAP, PVRSRVBridgeDevicememHistoryUnmap,
 					pDEVICEMEMHISTORYBridgeLock, bUseLock);
 
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY, PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAPNEW, PVRSRVBridgeDevicememHistoryMapNew,
+					pDEVICEMEMHISTORYBridgeLock, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY, PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAPNEW, PVRSRVBridgeDevicememHistoryUnmapNew,
+					pDEVICEMEMHISTORYBridgeLock, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY, PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAPVRANGE, PVRSRVBridgeDevicememHistoryMapVRange,
+					pDEVICEMEMHISTORYBridgeLock, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY, PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYUNMAPVRANGE, PVRSRVBridgeDevicememHistoryUnmapVRange,
+					pDEVICEMEMHISTORYBridgeLock, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY, PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYSPARSECHANGE, PVRSRVBridgeDevicememHistorySparseChange,
+					pDEVICEMEMHISTORYBridgeLock, bUseLock);
+
 
 	return PVRSRV_OK;
 }
@@ -208,4 +989,14 @@
 	PVR_LOGR_IF_ERROR(OSLockDestroy(pDEVICEMEMHISTORYBridgeLock), "OSLockDestroy");
 	return PVRSRV_OK;
 }
+#else /* SUPPORT_DEVICEMEMHISTORY_BRIDGE */
+/* This bridge is conditional on SUPPORT_DEVICEMEMHISTORY_BRIDGE - when not defined,
+ * do not populate the dispatch table with its functions
+ */
+#define InitDEVICEMEMHISTORYBridge() \
+	PVRSRV_OK
 
+#define DeinitDEVICEMEMHISTORYBridge() \
+	PVRSRV_OK
+
+#endif /* SUPPORT_DEVICEMEMHISTORY_BRIDGE */
diff --git a/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h b/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h
index fc4c5a5..5647cbd 100644
--- a/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for dmabuf
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for dmabuf
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for dmabuf
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_DMABUF_BRIDGE_H
 #define COMMON_DMABUF_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -54,7 +56,8 @@
 #define PVRSRV_BRIDGE_DMABUF_CMD_FIRST			0
 #define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF			PVRSRV_BRIDGE_DMABUF_CMD_FIRST+0
 #define PVRSRV_BRIDGE_DMABUF_PHYSMEMEXPORTDMABUF			PVRSRV_BRIDGE_DMABUF_CMD_FIRST+1
-#define PVRSRV_BRIDGE_DMABUF_CMD_LAST			(PVRSRV_BRIDGE_DMABUF_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTSPARSEDMABUF			PVRSRV_BRIDGE_DMABUF_CMD_FIRST+2
+#define PVRSRV_BRIDGE_DMABUF_CMD_LAST			(PVRSRV_BRIDGE_DMABUF_CMD_FIRST+2)
 
 
 /*******************************************
@@ -96,4 +99,29 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_PHYSMEMEXPORTDMABUF;
 
 
+/*******************************************
+            PhysmemImportSparseDmaBuf          
+ *******************************************/
+
+/* Bridge in structure for PhysmemImportSparseDmaBuf */
+typedef struct PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSPARSEDMABUF_TAG
+{
+	IMG_INT ifd;
+	PVRSRV_MEMALLOCFLAGS_T uiFlags;
+	IMG_DEVMEM_SIZE_T uiChunkSize;
+	IMG_UINT32 ui32NumPhysChunks;
+	IMG_UINT32 ui32NumVirtChunks;
+	IMG_UINT32 * pui32MappingTable;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSPARSEDMABUF;
+
+/* Bridge out structure for PhysmemImportSparseDmaBuf */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSPARSEDMABUF_TAG
+{
+	IMG_HANDLE hPMRPtr;
+	IMG_DEVMEM_SIZE_T uiSize;
+	IMG_DEVMEM_ALIGN_T sAlign;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSPARSEDMABUF;
+
+
 #endif /* COMMON_DMABUF_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c b/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c
index f2df3a1..01b289b 100644
--- a/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c
@@ -65,6 +65,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -81,7 +83,7 @@
 
 
 
-	PMRLock();
+
 
 
 	psPhysmemImportDmaBufOUT->eError =
@@ -94,27 +96,38 @@
 	/* Exit early if bridged call fails */
 	if(psPhysmemImportDmaBufOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PhysmemImportDmaBuf_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPhysmemImportDmaBufOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPhysmemImportDmaBufOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPhysmemImportDmaBufOUT->hPMRPtr,
 							(void *) psPMRPtrInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
-							PVRSRV_HANDLE_ALLOC_FLAG_SHARED
+							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
 							,(PFN_HANDLE_RELEASE)&PMRUnrefPMR);
 	if (psPhysmemImportDmaBufOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PhysmemImportDmaBuf_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PhysmemImportDmaBuf_exit:
+
+
+
 	if (psPhysmemImportDmaBufOUT->eError != PVRSRV_OK)
 	{
 		if (psPMRPtrInt)
@@ -127,51 +140,219 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePhysmemExportDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PHYSMEMEXPORTDMABUF *psPhysmemExportDmaBufIN,
 					  PVRSRV_BRIDGE_OUT_PHYSMEMEXPORTDMABUF *psPhysmemExportDmaBufOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPhysmemExportDmaBufIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPhysmemExportDmaBufOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPhysmemExportDmaBufIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPhysmemExportDmaBufOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PhysmemExportDmaBuf_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPhysmemExportDmaBufOUT->eError =
 		PhysmemExportDmaBuf(psConnection, OSGetDevData(psConnection),
 					psPMRInt,
 					&psPhysmemExportDmaBufOUT->iFd);
-	PMRUnlock();
 
 
 
 
 PhysmemExportDmaBuf_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
 
+static IMG_INT
+PVRSRVBridgePhysmemImportSparseDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSPARSEDMABUF *psPhysmemImportSparseDmaBufIN,
+					  PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSPARSEDMABUF *psPhysmemImportSparseDmaBufOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_UINT32 *ui32MappingTableInt = NULL;
+	PMR * psPMRPtrInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psPhysmemImportSparseDmaBufIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psPhysmemImportSparseDmaBufIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psPhysmemImportSparseDmaBufOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto PhysmemImportSparseDmaBuf_exit;
+			}
+		}
+	}
+
+	if (psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks != 0)
+	{
+		ui32MappingTableInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32MappingTableInt, psPhysmemImportSparseDmaBufIN->pui32MappingTable, psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psPhysmemImportSparseDmaBufOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto PhysmemImportSparseDmaBuf_exit;
+				}
+			}
+
+
+	psPhysmemImportSparseDmaBufOUT->eError =
+		PhysmemImportSparseDmaBuf(psConnection, OSGetDevData(psConnection),
+					psPhysmemImportSparseDmaBufIN->ifd,
+					psPhysmemImportSparseDmaBufIN->uiFlags,
+					psPhysmemImportSparseDmaBufIN->uiChunkSize,
+					psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks,
+					psPhysmemImportSparseDmaBufIN->ui32NumVirtChunks,
+					ui32MappingTableInt,
+					&psPMRPtrInt,
+					&psPhysmemImportSparseDmaBufOUT->uiSize,
+					&psPhysmemImportSparseDmaBufOUT->sAlign);
+	/* Exit early if bridged call fails */
+	if(psPhysmemImportSparseDmaBufOUT->eError != PVRSRV_OK)
+	{
+		goto PhysmemImportSparseDmaBuf_exit;
+	}
+
+	/* Lock over handle creation. */
+	LockHandle();
+
+
+
+
+
+	psPhysmemImportSparseDmaBufOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
+							&psPhysmemImportSparseDmaBufOUT->hPMRPtr,
+							(void *) psPMRPtrInt,
+							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+							,(PFN_HANDLE_RELEASE)&PMRUnrefPMR);
+	if (psPhysmemImportSparseDmaBufOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto PhysmemImportSparseDmaBuf_exit;
+	}
+
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+PhysmemImportSparseDmaBuf_exit:
+
+
+
+	if (psPhysmemImportSparseDmaBufOUT->eError != PVRSRV_OK)
+	{
+		if (psPMRPtrInt)
+		{
+			PMRUnrefPMR(psPMRPtrInt);
+		}
+	}
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+
 
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
@@ -194,6 +375,9 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMEXPORTDMABUF, PVRSRVBridgePhysmemExportDmaBuf,
 					NULL, bUseLock);
 
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTSPARSEDMABUF, PVRSRVBridgePhysmemImportSparseDmaBuf,
+					NULL, bUseLock);
+
 
 	return PVRSRV_OK;
 }
@@ -205,4 +389,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/common_htbuffer_bridge.h b/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/common_htbuffer_bridge.h
index c77cd1f..496d736 100644
--- a/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/common_htbuffer_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/common_htbuffer_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for htbuffer
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for htbuffer
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for htbuffer
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_HTBUFFER_BRIDGE_H
 #define COMMON_HTBUFFER_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/server_htbuffer_bridge.c b/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/server_htbuffer_bridge.c
index d4cf4f5..6356b7a 100644
--- a/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/server_htbuffer_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/htbuffer_bridge/server_htbuffer_bridge.c
@@ -64,6 +64,9 @@
 #include "lock.h"
 
 
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
+
+
 
 /* ***************************************************************************
  * Server-side bridge entry points
@@ -77,33 +80,66 @@
 {
 	IMG_CHAR *uiNameInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR)) +
+			0;
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
-	if (psHTBConfigureIN->ui32NameSize != 0)
+	if (ui32BufferSize != 0)
 	{
-		uiNameInt = OSAllocMemNoStats(psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR));
-		if (!uiNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psHTBConfigureIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psHTBConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto HTBConfigure_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psHTBConfigureIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psHTBConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto HTBConfigure_exit;
+			}
 		}
 	}
 
+	if (psHTBConfigureIN->ui32NameSize != 0)
+	{
+		uiNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psHTBConfigureIN->puiName, psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiNameInt, psHTBConfigureIN->puiName,
-				psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR) > 0)
 			{
-				psHTBConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiNameInt, psHTBConfigureIN->puiName, psHTBConfigureIN->ui32NameSize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psHTBConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto HTBConfigure_exit;
+					goto HTBConfigure_exit;
+				}
 			}
 
 
-
 	psHTBConfigureOUT->eError =
 		HTBConfigureKM(
 					psHTBConfigureIN->ui32NameSize,
@@ -114,12 +150,24 @@
 
 
 HTBConfigure_exit:
-	if (uiNameInt)
-		OSFreeMemNoStats(uiNameInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHTBControl(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HTBCONTROL *psHTBControlIN,
@@ -128,33 +176,66 @@
 {
 	IMG_UINT32 *ui32GroupEnableInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32)) +
+			0;
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
-	if (psHTBControlIN->ui32NumGroups != 0)
+	if (ui32BufferSize != 0)
 	{
-		ui32GroupEnableInt = OSAllocMemNoStats(psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32));
-		if (!ui32GroupEnableInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psHTBControlIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psHTBControlOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto HTBControl_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psHTBControlIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psHTBControlOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto HTBControl_exit;
+			}
 		}
 	}
 
+	if (psHTBControlIN->ui32NumGroups != 0)
+	{
+		ui32GroupEnableInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psHTBControlIN->pui32GroupEnable, psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32GroupEnableInt, psHTBControlIN->pui32GroupEnable,
-				psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32) > 0)
 			{
-				psHTBControlOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32GroupEnableInt, psHTBControlIN->pui32GroupEnable, psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psHTBControlOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto HTBControl_exit;
+					goto HTBControl_exit;
+				}
 			}
 
 
-
 	psHTBControlOUT->eError =
 		HTBControlKM(
 					psHTBControlIN->ui32NumGroups,
@@ -168,12 +249,24 @@
 
 
 HTBControl_exit:
-	if (ui32GroupEnableInt)
-		OSFreeMemNoStats(ui32GroupEnableInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHTBLog(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HTBLOG *psHTBLogIN,
@@ -182,33 +275,66 @@
 {
 	IMG_UINT32 *ui32ArgsInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32)) +
+			0;
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
-	if (psHTBLogIN->ui32NumArgs != 0)
+	if (ui32BufferSize != 0)
 	{
-		ui32ArgsInt = OSAllocMemNoStats(psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32));
-		if (!ui32ArgsInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psHTBLogIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psHTBLogOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto HTBLog_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psHTBLogIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psHTBLogOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto HTBLog_exit;
+			}
 		}
 	}
 
+	if (psHTBLogIN->ui32NumArgs != 0)
+	{
+		ui32ArgsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psHTBLogIN->pui32Args, psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ArgsInt, psHTBLogIN->pui32Args,
-				psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32) > 0)
 			{
-				psHTBLogOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ArgsInt, psHTBLogIN->pui32Args, psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psHTBLogOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto HTBLog_exit;
+					goto HTBLog_exit;
+				}
 			}
 
 
-
 	psHTBLogOUT->eError =
 		HTBLogKM(
 					psHTBLogIN->ui32PID,
@@ -221,21 +347,35 @@
 
 
 HTBLog_exit:
-	if (ui32ArgsInt)
-		OSFreeMemNoStats(ui32ArgsInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
 
 static POS_LOCK pHTBUFFERBridgeLock;
 static IMG_BOOL bUseLock = IMG_TRUE;
+#endif /* EXCLUDE_HTBUFFER_BRIDGE */
 
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 PVRSRV_ERROR InitHTBUFFERBridge(void);
 PVRSRV_ERROR DeinitHTBUFFERBridge(void);
 
@@ -267,4 +407,14 @@
 	PVR_LOGR_IF_ERROR(OSLockDestroy(pHTBUFFERBridgeLock), "OSLockDestroy");
 	return PVRSRV_OK;
 }
+#else /* EXCLUDE_HTBUFFER_BRIDGE */
+/* This bridge is conditional on EXCLUDE_HTBUFFER_BRIDGE - when defined,
+ * do not populate the dispatch table with its functions
+ */
+#define InitHTBUFFERBridge() \
+	PVRSRV_OK
 
+#define DeinitHTBUFFERBridge() \
+	PVRSRV_OK
+
+#endif /* EXCLUDE_HTBUFFER_BRIDGE */
diff --git a/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_bridge.h b/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_bridge.h
index eec0210..5e470cb 100644
--- a/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_bridge.h
@@ -102,6 +102,8 @@
 								    IMG_UINT32 *pui32MappingTable,
 								    IMG_UINT32 ui32Log2PageSize,
 								    PVRSRV_MEMALLOCFLAGS_T uiFlags,
+								    IMG_UINT32 ui32AnnotationLength,
+								    const IMG_CHAR *puiAnnotation,
 								    IMG_HANDLE *phPMRPtr);
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePhysmemNewRamBackedLockedPMR(IMG_HANDLE hBridge,
@@ -112,6 +114,8 @@
 									  IMG_UINT32 *pui32MappingTable,
 									  IMG_UINT32 ui32Log2PageSize,
 									  PVRSRV_MEMALLOCFLAGS_T uiFlags,
+									  IMG_UINT32 ui32AnnotationLength,
+									  const IMG_CHAR *puiAnnotation,
 									  IMG_HANDLE *phPMRPtr);
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntPin(IMG_HANDLE hBridge,
@@ -131,7 +135,8 @@
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxCreate(IMG_HANDLE hBridge,
 								IMG_BOOL bbKernelMemoryCtx,
 								IMG_HANDLE *phDevMemServerContext,
-								IMG_HANDLE *phPrivData);
+								IMG_HANDLE *phPrivData,
+								IMG_UINT32 *pui32CPUCacheLineSize);
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxDestroy(IMG_HANDLE hBridge,
 								 IMG_HANDLE hDevmemServerContext);
@@ -175,8 +180,7 @@
 							     IMG_UINT32 ui32SparseFlags,
 							     PVRSRV_MEMALLOCFLAGS_T uiFlags,
 							     IMG_DEV_VIRTADDR sDevVAddr,
-							     IMG_UINT64 ui64CPUVAddr,
-							     IMG_UINT32 *pui32Status);
+							     IMG_UINT64 ui64CPUVAddr);
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntMapPages(IMG_HANDLE hBridge,
 							       IMG_HANDLE hReservation,
@@ -191,10 +195,6 @@
 								 IMG_DEV_VIRTADDR sDevVAddr,
 								 IMG_UINT32 ui32PageCount);
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemSLCFlushInvalRequest(IMG_HANDLE hBridge,
-									IMG_HANDLE hDeviceNode,
-									IMG_HANDLE hPmr);
-
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIsVDevAddrValid(IMG_HANDLE hBridge,
 								   IMG_HANDLE hDevmemCtx,
 								   IMG_DEV_VIRTADDR sAddress);
@@ -221,11 +221,10 @@
 								IMG_UINT32 *pui32Log2DataPageSizeOut,
 								IMG_UINT32 *pui32Log2ImportAlignmentOut);
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxCreateCLS(IMG_HANDLE hBridge,
-								   IMG_BOOL bbKernelMemoryCtx,
-								   IMG_HANDLE *phDevMemServerContext,
-								   IMG_HANDLE *phPrivData,
-								   IMG_UINT32 *pui32CPUCacheLineSize);
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntRegisterPFNotifyKM(IMG_HANDLE hBridge,
+									 IMG_HANDLE hDevmemCtx,
+									 IMG_UINT32 ui32PID,
+									 IMG_BOOL bRegister);
 
 
 #endif /* CLIENT_MM_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_direct_bridge.c
index 0182976..cff3aaa 100644
--- a/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/mm_bridge/client_mm_direct_bridge.c
@@ -47,6 +47,7 @@
 #include "pvrsrv_memallocflags.h"
 #include "devicemem_typedefs.h"
 
+#include "devicemem.h"
 #include "devicemem_server.h"
 #include "pmr.h"
 #include "devicemem_heapcfg.h"
@@ -159,12 +160,12 @@
 	PVRSRV_ERROR eError;
 	PMR_EXPORT * psPMRExportInt;
 	PMR * psPMRInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
 
 	psPMRExportInt = (PMR_EXPORT *) hPMRExport;
 
 	eError =
-		PMRImportPMR(
+		PMRImportPMR(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
 					psPMRExportInt,
 					ui64uiPassword,
 					ui64uiSize,
@@ -239,6 +240,8 @@
 								    IMG_UINT32 *pui32MappingTable,
 								    IMG_UINT32 ui32Log2PageSize,
 								    PVRSRV_MEMALLOCFLAGS_T uiFlags,
+								    IMG_UINT32 ui32AnnotationLength,
+								    const IMG_CHAR *puiAnnotation,
 								    IMG_HANDLE *phPMRPtr)
 {
 	PVRSRV_ERROR eError;
@@ -255,6 +258,8 @@
 					pui32MappingTable,
 					ui32Log2PageSize,
 					uiFlags,
+					ui32AnnotationLength,
+					puiAnnotation,
 					&psPMRPtrInt);
 
 	*phPMRPtr = psPMRPtrInt;
@@ -269,6 +274,8 @@
 									  IMG_UINT32 *pui32MappingTable,
 									  IMG_UINT32 ui32Log2PageSize,
 									  PVRSRV_MEMALLOCFLAGS_T uiFlags,
+									  IMG_UINT32 ui32AnnotationLength,
+									  const IMG_CHAR *puiAnnotation,
 									  IMG_HANDLE *phPMRPtr)
 {
 	PVRSRV_ERROR eError;
@@ -285,6 +292,8 @@
 					pui32MappingTable,
 					ui32Log2PageSize,
 					uiFlags,
+					ui32AnnotationLength,
+					puiAnnotation,
 					&psPMRPtrInt);
 
 	*phPMRPtr = psPMRPtrInt;
@@ -366,7 +375,8 @@
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxCreate(IMG_HANDLE hBridge,
 								IMG_BOOL bbKernelMemoryCtx,
 								IMG_HANDLE *phDevMemServerContext,
-								IMG_HANDLE *phPrivData)
+								IMG_HANDLE *phPrivData,
+								IMG_UINT32 *pui32CPUCacheLineSize)
 {
 	PVRSRV_ERROR eError;
 	DEVMEMINT_CTX * psDevMemServerContextInt;
@@ -378,7 +388,8 @@
 		,
 					bbKernelMemoryCtx,
 					&psDevMemServerContextInt,
-					&hPrivDataInt);
+					&hPrivDataInt,
+					pui32CPUCacheLineSize);
 
 	*phDevMemServerContext = psDevMemServerContextInt;
 	*phPrivData = hPrivDataInt;
@@ -539,8 +550,7 @@
 							     IMG_UINT32 ui32SparseFlags,
 							     PVRSRV_MEMALLOCFLAGS_T uiFlags,
 							     IMG_DEV_VIRTADDR sDevVAddr,
-							     IMG_UINT64 ui64CPUVAddr,
-							     IMG_UINT32 *pui32Status)
+							     IMG_UINT64 ui64CPUVAddr)
 {
 	PVRSRV_ERROR eError;
 	DEVMEMINT_HEAP * psSrvDevMemHeapInt;
@@ -551,7 +561,7 @@
 	psPMRInt = (PMR *) hPMR;
 
 	eError =
-		DeviceMemChangeSparseServer(
+		DevmemIntChangeSparse(
 					psSrvDevMemHeapInt,
 					psPMRInt,
 					ui32AllocPageCount,
@@ -561,8 +571,7 @@
 					ui32SparseFlags,
 					uiFlags,
 					sDevVAddr,
-					ui64CPUVAddr,
-					pui32Status);
+					ui64CPUVAddr);
 
 	return eError;
 }
@@ -615,38 +624,18 @@
 	return eError;
 }
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemSLCFlushInvalRequest(IMG_HANDLE hBridge,
-									IMG_HANDLE hDeviceNode,
-									IMG_HANDLE hPmr)
-{
-	PVRSRV_ERROR eError;
-	IMG_HANDLE hDeviceNodeInt;
-	PMR * psPmrInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
-
-	hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
-	psPmrInt = (PMR *) hPmr;
-
-	eError =
-		DevmemSLCFlushInvalRequest(
-					hDeviceNodeInt,
-					psPmrInt);
-
-	return eError;
-}
-
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIsVDevAddrValid(IMG_HANDLE hBridge,
 								   IMG_HANDLE hDevmemCtx,
 								   IMG_DEV_VIRTADDR sAddress)
 {
 	PVRSRV_ERROR eError;
 	DEVMEMINT_CTX * psDevmemCtxInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
 
 	psDevmemCtxInt = (DEVMEMINT_CTX *) hDevmemCtx;
 
 	eError =
-		DevmemIntIsVDevAddrValid(
+		DevmemIntIsVDevAddrValid(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
 					psDevmemCtxInt,
 					sAddress);
 
@@ -729,27 +718,23 @@
 	return eError;
 }
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxCreateCLS(IMG_HANDLE hBridge,
-								   IMG_BOOL bbKernelMemoryCtx,
-								   IMG_HANDLE *phDevMemServerContext,
-								   IMG_HANDLE *phPrivData,
-								   IMG_UINT32 *pui32CPUCacheLineSize)
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntRegisterPFNotifyKM(IMG_HANDLE hBridge,
+									 IMG_HANDLE hDevmemCtx,
+									 IMG_UINT32 ui32PID,
+									 IMG_BOOL bRegister)
 {
 	PVRSRV_ERROR eError;
-	DEVMEMINT_CTX * psDevMemServerContextInt;
-	IMG_HANDLE hPrivDataInt;
+	DEVMEMINT_CTX * psDevmemCtxInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
 
+	psDevmemCtxInt = (DEVMEMINT_CTX *) hDevmemCtx;
 
 	eError =
-		DevmemIntCtxCreateCLS(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
-		,
-					bbKernelMemoryCtx,
-					&psDevMemServerContextInt,
-					&hPrivDataInt,
-					pui32CPUCacheLineSize);
+		DevmemIntRegisterPFNotifyKM(
+					psDevmemCtxInt,
+					ui32PID,
+					bRegister);
 
-	*phDevMemServerContext = psDevMemServerContextInt;
-	*phPrivData = hPrivDataInt;
 	return eError;
 }
 
diff --git a/drivers/staging/imgtec/rogue/generated/mm_bridge/common_mm_bridge.h b/drivers/staging/imgtec/rogue/generated/mm_bridge/common_mm_bridge.h
index f6344d2..0cd734d 100644
--- a/drivers/staging/imgtec/rogue/generated/mm_bridge/common_mm_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/mm_bridge/common_mm_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for mm
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for mm
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for mm
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_MM_BRIDGE_H
 #define COMMON_MM_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -79,14 +81,13 @@
 #define PVRSRV_BRIDGE_MM_CHANGESPARSEMEM			PVRSRV_BRIDGE_MM_CMD_FIRST+23
 #define PVRSRV_BRIDGE_MM_DEVMEMINTMAPPAGES			PVRSRV_BRIDGE_MM_CMD_FIRST+24
 #define PVRSRV_BRIDGE_MM_DEVMEMINTUNMAPPAGES			PVRSRV_BRIDGE_MM_CMD_FIRST+25
-#define PVRSRV_BRIDGE_MM_DEVMEMSLCFLUSHINVALREQUEST			PVRSRV_BRIDGE_MM_CMD_FIRST+26
-#define PVRSRV_BRIDGE_MM_DEVMEMISVDEVADDRVALID			PVRSRV_BRIDGE_MM_CMD_FIRST+27
-#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGCOUNT			PVRSRV_BRIDGE_MM_CMD_FIRST+28
-#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCOUNT			PVRSRV_BRIDGE_MM_CMD_FIRST+29
-#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGNAME			PVRSRV_BRIDGE_MM_CMD_FIRST+30
-#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS			PVRSRV_BRIDGE_MM_CMD_FIRST+31
-#define PVRSRV_BRIDGE_MM_DEVMEMINTCTXCREATECLS			PVRSRV_BRIDGE_MM_CMD_FIRST+32
-#define PVRSRV_BRIDGE_MM_CMD_LAST			(PVRSRV_BRIDGE_MM_CMD_FIRST+32)
+#define PVRSRV_BRIDGE_MM_DEVMEMISVDEVADDRVALID			PVRSRV_BRIDGE_MM_CMD_FIRST+26
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGCOUNT			PVRSRV_BRIDGE_MM_CMD_FIRST+27
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCOUNT			PVRSRV_BRIDGE_MM_CMD_FIRST+28
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGNAME			PVRSRV_BRIDGE_MM_CMD_FIRST+29
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS			PVRSRV_BRIDGE_MM_CMD_FIRST+30
+#define PVRSRV_BRIDGE_MM_DEVMEMINTREGISTERPFNOTIFYKM			PVRSRV_BRIDGE_MM_CMD_FIRST+31
+#define PVRSRV_BRIDGE_MM_CMD_LAST			(PVRSRV_BRIDGE_MM_CMD_FIRST+31)
 
 
 /*******************************************
@@ -269,6 +270,8 @@
 	IMG_UINT32 * pui32MappingTable;
 	IMG_UINT32 ui32Log2PageSize;
 	PVRSRV_MEMALLOCFLAGS_T uiFlags;
+	IMG_UINT32 ui32AnnotationLength;
+	const IMG_CHAR * puiAnnotation;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDPMR;
 
 /* Bridge out structure for PhysmemNewRamBackedPMR */
@@ -293,6 +296,8 @@
 	IMG_UINT32 * pui32MappingTable;
 	IMG_UINT32 ui32Log2PageSize;
 	PVRSRV_MEMALLOCFLAGS_T uiFlags;
+	IMG_UINT32 ui32AnnotationLength;
+	const IMG_CHAR * puiAnnotation;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDLOCKEDPMR;
 
 /* Bridge out structure for PhysmemNewRamBackedLockedPMR */
@@ -388,6 +393,7 @@
 {
 	IMG_HANDLE hDevMemServerContext;
 	IMG_HANDLE hPrivData;
+	IMG_UINT32 ui32CPUCacheLineSize;
 	PVRSRV_ERROR eError;
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATE;
 
@@ -544,7 +550,6 @@
 /* Bridge out structure for ChangeSparseMem */
 typedef struct PVRSRV_BRIDGE_OUT_CHANGESPARSEMEM_TAG
 {
-	IMG_UINT32 ui32Status;
 	PVRSRV_ERROR eError;
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_CHANGESPARSEMEM;
 
@@ -591,24 +596,6 @@
 
 
 /*******************************************
-            DevmemSLCFlushInvalRequest          
- *******************************************/
-
-/* Bridge in structure for DevmemSLCFlushInvalRequest */
-typedef struct PVRSRV_BRIDGE_IN_DEVMEMSLCFLUSHINVALREQUEST_TAG
-{
-	IMG_HANDLE hDeviceNode;
-	IMG_HANDLE hPmr;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMSLCFLUSHINVALREQUEST;
-
-/* Bridge out structure for DevmemSLCFlushInvalRequest */
-typedef struct PVRSRV_BRIDGE_OUT_DEVMEMSLCFLUSHINVALREQUEST_TAG
-{
-	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMSLCFLUSHINVALREQUEST;
-
-
-/*******************************************
             DevmemIsVDevAddrValid          
  *******************************************/
 
@@ -710,23 +697,22 @@
 
 
 /*******************************************
-            DevmemIntCtxCreateCLS          
+            DevmemIntRegisterPFNotifyKM          
  *******************************************/
 
-/* Bridge in structure for DevmemIntCtxCreateCLS */
-typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATECLS_TAG
+/* Bridge in structure for DevmemIntRegisterPFNotifyKM */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTREGISTERPFNOTIFYKM_TAG
 {
-	IMG_BOOL bbKernelMemoryCtx;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATECLS;
+	IMG_HANDLE hDevmemCtx;
+	IMG_UINT32 ui32PID;
+	IMG_BOOL bRegister;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTREGISTERPFNOTIFYKM;
 
-/* Bridge out structure for DevmemIntCtxCreateCLS */
-typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATECLS_TAG
+/* Bridge out structure for DevmemIntRegisterPFNotifyKM */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTREGISTERPFNOTIFYKM_TAG
 {
-	IMG_HANDLE hDevMemServerContext;
-	IMG_HANDLE hPrivData;
-	IMG_UINT32 ui32CPUCacheLineSize;
 	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATECLS;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTREGISTERPFNOTIFYKM;
 
 
 #endif /* COMMON_MM_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/mm_bridge/server_mm_bridge.c b/drivers/staging/imgtec/rogue/generated/mm_bridge/server_mm_bridge.c
index e6592fa..58fa70c 100644
--- a/drivers/staging/imgtec/rogue/generated/mm_bridge/server_mm_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/mm_bridge/server_mm_bridge.c
@@ -46,6 +46,7 @@
 
 #include "img_defs.h"
 
+#include "devicemem.h"
 #include "devicemem_server.h"
 #include "pmr.h"
 #include "devicemem_heapcfg.h"
@@ -65,6 +66,8 @@
 #include <linux/slab.h>
 
 
+
+
 static PVRSRV_ERROR ReleasePMRExport(void *pvData)
 {
 	PVR_UNREFERENCED_PARAMETER(pvData);
@@ -83,6 +86,7 @@
 					  PVRSRV_BRIDGE_OUT_PMREXPORTPMR *psPMRExportPMROUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRExportPMRIN->hPMR;
 	PMR * psPMRInt = NULL;
 	PMR_EXPORT * psPMRExportInt = NULL;
 	IMG_HANDLE hPMRExportInt = NULL;
@@ -91,23 +95,31 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRExportPMROUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRExportPMRIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRExportPMROUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRExportPMR_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRExportPMROUT->eError =
 		PMRExportPMR(
@@ -119,11 +131,11 @@
 	/* Exit early if bridged call fails */
 	if(psPMRExportPMROUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PMRExportPMR_exit;
 	}
-	PMRUnlock();
 
+	/* Lock over handle creation. */
+	LockHandle();
 
 	/*
 	 * For cases where we need a cross process handle we actually allocate two.
@@ -139,18 +151,24 @@
 	 * The second one is a cross process handle and it gets given a noop release
 	 * function. This handle does get returned to the caller.
 	 */
-	psPMRExportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psPMRExportPMROUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+
 							&hPMRExportInt,
 							(void *) psPMRExportInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
-							PVRSRV_HANDLE_ALLOC_FLAG_SHARED
+							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
 							,(PFN_HANDLE_RELEASE)&PMRUnexportPMR);
 	if (psPMRExportPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PMRExportPMR_exit;
 	}
 
-	psPMRExportPMROUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+	psPMRExportPMROUT->eError = PVRSRVAllocHandleUnlocked(KERNEL_HANDLE_BASE,
 							&psPMRExportPMROUT->hPMRExport,
 							(void *) psPMRExportInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
@@ -158,38 +176,80 @@
 							(PFN_HANDLE_RELEASE)&ReleasePMRExport);
 	if (psPMRExportPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PMRExportPMR_exit;
 	}
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PMRExportPMR_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psPMRExportPMROUT->eError != PVRSRV_OK)
 	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
 		if (psPMRExportPMROUT->hPMRExport)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(KERNEL_HANDLE_BASE,
 						(IMG_HANDLE) psPMRExportPMROUT->hPMRExport,
 						PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgePMRExportPMR: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 		}
 
 		if (hPMRExportInt)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
 						hPMRExportInt,
 						PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgePMRExportPMR: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 			/* Avoid freeing/destroying/releasing the resource a second time below */
 			psPMRExportInt = NULL;
 		}
 
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
 		if (psPMRExportInt)
 		{
 			PMRUnexportPMR(psPMRExportInt);
@@ -200,6 +260,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRUnexportPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRUNEXPORTPMR *psPMRUnexportPMRIN,
@@ -209,20 +270,31 @@
 	PMR_EXPORT * psPMRExportInt = NULL;
 	IMG_HANDLE hPMRExportInt = NULL;
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
 
-	PMRLock();
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 	psPMRUnexportPMROUT->eError =
-		PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+		PVRSRVLookupHandleUnlocked(KERNEL_HANDLE_BASE,
 					(void **) &psPMRExportInt,
 					(IMG_HANDLE) psPMRUnexportPMRIN->hPMRExport,
-					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
+					IMG_FALSE);
+	if (psPMRUnexportPMROUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnexportPMR: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnexportPMROUT->eError)));
+	}
 	PVR_ASSERT(psPMRUnexportPMROUT->eError == PVRSRV_OK);
 
 	/*
@@ -232,87 +304,146 @@
 	 * process handle is allocated for more details).
 	 */
 	psPMRUnexportPMROUT->eError =
-		PVRSRVFindHandle(psConnection->psHandleBase,
+		PVRSRVFindHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
 					&hPMRExportInt,
 					psPMRExportInt,
 					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+	if (psPMRUnexportPMROUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnexportPMR: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnexportPMROUT->eError)));
+	}
 	PVR_ASSERT(psPMRUnexportPMROUT->eError == PVRSRV_OK);
 
 	psPMRUnexportPMROUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
 					hPMRExportInt,
 					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
-	PVR_ASSERT((psPMRUnexportPMROUT->eError == PVRSRV_OK) || (psPMRUnexportPMROUT->eError == PVRSRV_ERROR_RETRY));
+	if ((psPMRUnexportPMROUT->eError != PVRSRV_OK) &&
+	    (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_RETRY))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnexportPMR: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnexportPMROUT->eError)));
+	}
+	PVR_ASSERT((psPMRUnexportPMROUT->eError == PVRSRV_OK) ||
+	           (psPMRUnexportPMROUT->eError == PVRSRV_ERROR_RETRY));
+
+
+
+
 
 	psPMRUnexportPMROUT->eError =
-		PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+		PVRSRVReleaseHandleUnlocked(KERNEL_HANDLE_BASE,
 					(IMG_HANDLE) psPMRUnexportPMRIN->hPMRExport,
 					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
-	if ((psPMRUnexportPMROUT->eError != PVRSRV_OK) && (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psPMRUnexportPMROUT->eError != PVRSRV_OK) &&
+	    (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnexportPMR: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnexportPMROUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto PMRUnexportPMR_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 PMRUnexportPMR_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRGetUID(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRGETUID *psPMRGetUIDIN,
 					  PVRSRV_BRIDGE_OUT_PMRGETUID *psPMRGetUIDOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRGetUIDIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRGetUIDOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRGetUIDIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRGetUIDOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRGetUID_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRGetUIDOUT->eError =
 		PMRGetUID(
 					psPMRInt,
 					&psPMRGetUIDOUT->ui64UID);
-	PMRUnlock();
 
 
 
 
 PMRGetUID_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRMakeLocalImportHandle(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRMAKELOCALIMPORTHANDLE *psPMRMakeLocalImportHandleIN,
 					  PVRSRV_BRIDGE_OUT_PMRMAKELOCALIMPORTHANDLE *psPMRMakeLocalImportHandleOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hBuffer = psPMRMakeLocalImportHandleIN->hBuffer;
 	PMR * psBufferInt = NULL;
 	PMR * psExtMemInt = NULL;
 
@@ -320,23 +451,31 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRMakeLocalImportHandleOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psBufferInt,
-											psPMRMakeLocalImportHandleIN->hBuffer,
-											PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
+											hBuffer,
+											PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
+											IMG_TRUE);
 					if(psPMRMakeLocalImportHandleOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRMakeLocalImportHandle_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRMakeLocalImportHandleOUT->eError =
 		PMRMakeLocalImportHandle(
@@ -345,13 +484,18 @@
 	/* Exit early if bridged call fails */
 	if(psPMRMakeLocalImportHandleOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PMRMakeLocalImportHandle_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPMRMakeLocalImportHandleOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPMRMakeLocalImportHandleOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPMRMakeLocalImportHandleOUT->hExtMem,
 							(void *) psExtMemInt,
 							PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT,
@@ -359,13 +503,37 @@
 							,(PFN_HANDLE_RELEASE)&PMRUnmakeLocalImportHandle);
 	if (psPMRMakeLocalImportHandleOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PMRMakeLocalImportHandle_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PMRMakeLocalImportHandle_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psBufferInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hBuffer,
+											PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psPMRMakeLocalImportHandleOUT->eError != PVRSRV_OK)
 	{
 		if (psExtMemInt)
@@ -378,6 +546,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRUnmakeLocalImportHandle(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRUNMAKELOCALIMPORTHANDLE *psPMRUnmakeLocalImportHandleIN,
@@ -389,36 +558,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psPMRUnmakeLocalImportHandleOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psPMRUnmakeLocalImportHandleIN->hExtMem,
 					PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
-	if ((psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_OK) && (psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_OK) &&
+	    (psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnmakeLocalImportHandle: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnmakeLocalImportHandleOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto PMRUnmakeLocalImportHandle_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 PMRUnmakeLocalImportHandle_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRImportPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRIMPORTPMR *psPMRImportPMRIN,
 					  PVRSRV_BRIDGE_OUT_PMRIMPORTPMR *psPMRImportPMROUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMRExport = psPMRImportPMRIN->hPMRExport;
 	PMR_EXPORT * psPMRExportInt = NULL;
 	PMR * psPMRInt = NULL;
 
@@ -426,26 +612,34 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRImportPMROUT->eError =
-						PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+						PVRSRVLookupHandleUnlocked(KERNEL_HANDLE_BASE,
 											(void **) &psPMRExportInt,
-											psPMRImportPMRIN->hPMRExport,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+											hPMRExport,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
+											IMG_TRUE);
 					if(psPMRImportPMROUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRImportPMR_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRImportPMROUT->eError =
-		PMRImportPMR(
+		PMRImportPMR(psConnection, OSGetDevData(psConnection),
 					psPMRExportInt,
 					psPMRImportPMRIN->ui64uiPassword,
 					psPMRImportPMRIN->ui64uiSize,
@@ -454,13 +648,18 @@
 	/* Exit early if bridged call fails */
 	if(psPMRImportPMROUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PMRImportPMR_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPMRImportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPMRImportPMROUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPMRImportPMROUT->hPMR,
 							(void *) psPMRInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
@@ -468,13 +667,37 @@
 							,(PFN_HANDLE_RELEASE)&PMRUnrefPMR);
 	if (psPMRImportPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PMRImportPMR_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PMRImportPMR_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRExportInt)
+						{
+							PVRSRVReleaseHandleUnlocked(KERNEL_HANDLE_BASE,
+											hPMRExport,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psPMRImportPMROUT->eError != PVRSRV_OK)
 	{
 		if (psPMRInt)
@@ -487,12 +710,14 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRLocalImportPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRLOCALIMPORTPMR *psPMRLocalImportPMRIN,
 					  PVRSRV_BRIDGE_OUT_PMRLOCALIMPORTPMR *psPMRLocalImportPMROUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hExtHandle = psPMRLocalImportPMRIN->hExtHandle;
 	PMR * psExtHandleInt = NULL;
 	PMR * psPMRInt = NULL;
 
@@ -500,23 +725,31 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRLocalImportPMROUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psExtHandleInt,
-											psPMRLocalImportPMRIN->hExtHandle,
-											PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+											hExtHandle,
+											PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT,
+											IMG_TRUE);
 					if(psPMRLocalImportPMROUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRLocalImportPMR_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRLocalImportPMROUT->eError =
 		PMRLocalImportPMR(
@@ -527,13 +760,18 @@
 	/* Exit early if bridged call fails */
 	if(psPMRLocalImportPMROUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PMRLocalImportPMR_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPMRLocalImportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPMRLocalImportPMROUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPMRLocalImportPMROUT->hPMR,
 							(void *) psPMRInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
@@ -541,13 +779,37 @@
 							,(PFN_HANDLE_RELEASE)&PMRUnrefPMR);
 	if (psPMRLocalImportPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PMRLocalImportPMR_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PMRLocalImportPMR_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psExtHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hExtHandle,
+											PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psPMRLocalImportPMROUT->eError != PVRSRV_OK)
 	{
 		if (psPMRInt)
@@ -560,6 +822,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRUnrefPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRUNREFPMR *psPMRUnrefPMRIN,
@@ -571,30 +834,46 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psPMRUnrefPMROUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psPMRUnrefPMRIN->hPMR,
 					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
-	if ((psPMRUnrefPMROUT->eError != PVRSRV_OK) && (psPMRUnrefPMROUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psPMRUnrefPMROUT->eError != PVRSRV_OK) &&
+	    (psPMRUnrefPMROUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnrefPMR: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnrefPMROUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto PMRUnrefPMR_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 PMRUnrefPMR_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRUnrefUnlockPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRUNREFUNLOCKPMR *psPMRUnrefUnlockPMRIN,
@@ -606,30 +885,46 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psPMRUnrefUnlockPMROUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psPMRUnrefUnlockPMRIN->hPMR,
 					PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
-	if ((psPMRUnrefUnlockPMROUT->eError != PVRSRV_OK) && (psPMRUnrefUnlockPMROUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psPMRUnrefUnlockPMROUT->eError != PVRSRV_OK) &&
+	    (psPMRUnrefUnlockPMROUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgePMRUnrefUnlockPMR: %s",
+		        PVRSRVGetErrorStringKM(psPMRUnrefUnlockPMROUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto PMRUnrefUnlockPMR_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 PMRUnrefUnlockPMR_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDPMR *psPhysmemNewRamBackedPMRIN,
@@ -637,33 +932,83 @@
 					 CONNECTION_DATA *psConnection)
 {
 	IMG_UINT32 *ui32MappingTableInt = NULL;
+	IMG_CHAR *uiAnnotationInt = NULL;
 	PMR * psPMRPtrInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) +
+			(psPhysmemNewRamBackedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		ui32MappingTableInt = OSAllocMemNoStats(psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32));
-		if (!ui32MappingTableInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psPhysmemNewRamBackedPMRIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto PhysmemNewRamBackedPMR_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psPhysmemNewRamBackedPMRIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto PhysmemNewRamBackedPMR_exit;
+			}
 		}
 	}
 
+	if (psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks != 0)
+	{
+		ui32MappingTableInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPhysmemNewRamBackedPMRIN->pui32MappingTable, psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32MappingTableInt, psPhysmemNewRamBackedPMRIN->pui32MappingTable,
-				psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32) > 0)
 			{
-				psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32MappingTableInt, psPhysmemNewRamBackedPMRIN->pui32MappingTable, psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto PhysmemNewRamBackedPMR_exit;
+					goto PhysmemNewRamBackedPMR_exit;
+				}
 			}
+	if (psPhysmemNewRamBackedPMRIN->ui32AnnotationLength != 0)
+	{
+		uiAnnotationInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPhysmemNewRamBackedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR);
+	}
 
-	PMRLock();
+			/* Copy the data over */
+			if (psPhysmemNewRamBackedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiAnnotationInt, psPhysmemNewRamBackedPMRIN->puiAnnotation, psPhysmemNewRamBackedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto PhysmemNewRamBackedPMR_exit;
+				}
+			}
 
 
 	psPhysmemNewRamBackedPMROUT->eError =
@@ -675,17 +1020,24 @@
 					ui32MappingTableInt,
 					psPhysmemNewRamBackedPMRIN->ui32Log2PageSize,
 					psPhysmemNewRamBackedPMRIN->uiFlags,
+					psPhysmemNewRamBackedPMRIN->ui32AnnotationLength,
+					uiAnnotationInt,
 					&psPMRPtrInt);
 	/* Exit early if bridged call fails */
 	if(psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PhysmemNewRamBackedPMR_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPhysmemNewRamBackedPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPhysmemNewRamBackedPMROUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPhysmemNewRamBackedPMROUT->hPMRPtr,
 							(void *) psPMRPtrInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
@@ -693,13 +1045,19 @@
 							,(PFN_HANDLE_RELEASE)&PMRUnrefPMR);
 	if (psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PhysmemNewRamBackedPMR_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PhysmemNewRamBackedPMR_exit:
+
+
+
 	if (psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
 	{
 		if (psPMRPtrInt)
@@ -708,12 +1066,21 @@
 		}
 	}
 
-	if (ui32MappingTableInt)
-		OSFreeMemNoStats(ui32MappingTableInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePhysmemNewRamBackedLockedPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDLOCKEDPMR *psPhysmemNewRamBackedLockedPMRIN,
@@ -721,33 +1088,83 @@
 					 CONNECTION_DATA *psConnection)
 {
 	IMG_UINT32 *ui32MappingTableInt = NULL;
+	IMG_CHAR *uiAnnotationInt = NULL;
 	PMR * psPMRPtrInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32)) +
+			(psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		ui32MappingTableInt = OSAllocMemNoStats(psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32));
-		if (!ui32MappingTableInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psPhysmemNewRamBackedLockedPMRIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto PhysmemNewRamBackedLockedPMR_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psPhysmemNewRamBackedLockedPMRIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto PhysmemNewRamBackedLockedPMR_exit;
+			}
 		}
 	}
 
+	if (psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks != 0)
+	{
+		ui32MappingTableInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPhysmemNewRamBackedLockedPMRIN->pui32MappingTable, psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32MappingTableInt, psPhysmemNewRamBackedLockedPMRIN->pui32MappingTable,
-				psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32) > 0)
 			{
-				psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32MappingTableInt, psPhysmemNewRamBackedLockedPMRIN->pui32MappingTable, psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto PhysmemNewRamBackedLockedPMR_exit;
+					goto PhysmemNewRamBackedLockedPMR_exit;
+				}
 			}
+	if (psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength != 0)
+	{
+		uiAnnotationInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR);
+	}
 
-	PMRLock();
+			/* Copy the data over */
+			if (psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiAnnotationInt, psPhysmemNewRamBackedLockedPMRIN->puiAnnotation, psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto PhysmemNewRamBackedLockedPMR_exit;
+				}
+			}
 
 
 	psPhysmemNewRamBackedLockedPMROUT->eError =
@@ -759,17 +1176,24 @@
 					ui32MappingTableInt,
 					psPhysmemNewRamBackedLockedPMRIN->ui32Log2PageSize,
 					psPhysmemNewRamBackedLockedPMRIN->uiFlags,
+					psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength,
+					uiAnnotationInt,
 					&psPMRPtrInt);
 	/* Exit early if bridged call fails */
 	if(psPhysmemNewRamBackedLockedPMROUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto PhysmemNewRamBackedLockedPMR_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psPhysmemNewRamBackedLockedPMROUT->hPMRPtr,
 							(void *) psPMRPtrInt,
 							PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
@@ -777,13 +1201,19 @@
 							,(PFN_HANDLE_RELEASE)&PMRUnrefUnlockPMR);
 	if (psPhysmemNewRamBackedLockedPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto PhysmemNewRamBackedLockedPMR_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 PhysmemNewRamBackedLockedPMR_exit:
+
+
+
 	if (psPhysmemNewRamBackedLockedPMROUT->eError != PVRSRV_OK)
 	{
 		if (psPMRPtrInt)
@@ -792,105 +1222,176 @@
 		}
 	}
 
-	if (ui32MappingTableInt)
-		OSFreeMemNoStats(ui32MappingTableInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntPin(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTPIN *psDevmemIntPinIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTPIN *psDevmemIntPinOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psDevmemIntPinIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntPinOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntPinIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntPinOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntPin_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntPinOUT->eError =
 		DevmemIntPin(
 					psPMRInt);
-	PMRUnlock();
 
 
 
 
 DevmemIntPin_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntUnpin(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTUNPIN *psDevmemIntUnpinIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTUNPIN *psDevmemIntUnpinOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psDevmemIntUnpinIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntUnpinOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntUnpinIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntUnpinOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntUnpin_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntUnpinOUT->eError =
 		DevmemIntUnpin(
 					psPMRInt);
-	PMRUnlock();
 
 
 
 
 DevmemIntUnpin_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntPinValidate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTPINVALIDATE *psDevmemIntPinValidateIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTPINVALIDATE *psDevmemIntPinValidateOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hMapping = psDevmemIntPinValidateIN->hMapping;
 	DEVMEMINT_MAPPING * psMappingInt = NULL;
+	IMG_HANDLE hPMR = psDevmemIntPinValidateIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
@@ -899,33 +1400,48 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntPinValidateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psMappingInt,
-											psDevmemIntPinValidateIN->hMapping,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+											hMapping,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING,
+											IMG_TRUE);
 					if(psDevmemIntPinValidateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntPinValidate_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntPinValidateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntPinValidateIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntPinValidateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntPinValidate_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntPinValidateOUT->eError =
 		DevmemIntPinValidate(
@@ -937,16 +1453,54 @@
 
 DevmemIntPinValidate_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psMappingInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hMapping,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntUnpinInvalidate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTUNPININVALIDATE *psDevmemIntUnpinInvalidateIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTUNPININVALIDATE *psDevmemIntUnpinInvalidateOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hMapping = psDevmemIntUnpinInvalidateIN->hMapping;
 	DEVMEMINT_MAPPING * psMappingInt = NULL;
+	IMG_HANDLE hPMR = psDevmemIntUnpinInvalidateIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
@@ -955,33 +1509,48 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntUnpinInvalidateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psMappingInt,
-											psDevmemIntUnpinInvalidateIN->hMapping,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+											hMapping,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING,
+											IMG_TRUE);
 					if(psDevmemIntUnpinInvalidateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntUnpinInvalidate_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntUnpinInvalidateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntUnpinInvalidateIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntUnpinInvalidateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntUnpinInvalidate_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntUnpinInvalidateOUT->eError =
 		DevmemIntUnpinInvalidate(
@@ -993,9 +1562,45 @@
 
 DevmemIntUnpinInvalidate_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psMappingInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hMapping,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntCtxCreate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATE *psDevmemIntCtxCreateIN,
@@ -1007,27 +1612,33 @@
 
 
 
+
+
 	psDevmemIntCtxCreateOUT->hDevMemServerContext = NULL;
 
 
-	PMRLock();
-
 
 	psDevmemIntCtxCreateOUT->eError =
 		DevmemIntCtxCreate(psConnection, OSGetDevData(psConnection),
 					psDevmemIntCtxCreateIN->bbKernelMemoryCtx,
 					&psDevMemServerContextInt,
-					&hPrivDataInt);
+					&hPrivDataInt,
+					&psDevmemIntCtxCreateOUT->ui32CPUCacheLineSize);
 	/* Exit early if bridged call fails */
 	if(psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto DevmemIntCtxCreate_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psDevmemIntCtxCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psDevmemIntCtxCreateOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntCtxCreateOUT->hDevMemServerContext,
 							(void *) psDevMemServerContextInt,
 							PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
@@ -1035,11 +1646,17 @@
 							,(PFN_HANDLE_RELEASE)&DevmemIntCtxDestroy);
 	if (psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntCtxCreate_exit;
 	}
 
 
-	psDevmemIntCtxCreateOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+
+
+
+
+	psDevmemIntCtxCreateOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntCtxCreateOUT->hPrivData,
 							(void *) hPrivDataInt,
 							PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
@@ -1047,22 +1664,38 @@
 							,psDevmemIntCtxCreateOUT->hDevMemServerContext);
 	if (psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntCtxCreate_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DevmemIntCtxCreate_exit:
+
+
+
 	if (psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
 	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
 		if (psDevmemIntCtxCreateOUT->hDevMemServerContext)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 						(IMG_HANDLE) psDevmemIntCtxCreateOUT->hDevMemServerContext,
 						PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgeDevmemIntCtxCreate: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 			/* Avoid freeing/destroying/releasing the resource a second time below */
@@ -1070,6 +1703,8 @@
 		}
 
 
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
 		if (psDevMemServerContextInt)
 		{
 			DevmemIntCtxDestroy(psDevMemServerContextInt);
@@ -1080,6 +1715,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntCtxDestroy(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTCTXDESTROY *psDevmemIntCtxDestroyIN,
@@ -1091,36 +1727,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psDevmemIntCtxDestroyOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDevmemIntCtxDestroyIN->hDevmemServerContext,
 					PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
-	if ((psDevmemIntCtxDestroyOUT->eError != PVRSRV_OK) && (psDevmemIntCtxDestroyOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDevmemIntCtxDestroyOUT->eError != PVRSRV_OK) &&
+	    (psDevmemIntCtxDestroyOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDevmemIntCtxDestroy: %s",
+		        PVRSRVGetErrorStringKM(psDevmemIntCtxDestroyOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto DevmemIntCtxDestroy_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DevmemIntCtxDestroy_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntHeapCreate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTHEAPCREATE *psDevmemIntHeapCreateIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPCREATE *psDevmemIntHeapCreateOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevmemCtx = psDevmemIntHeapCreateIN->hDevmemCtx;
 	DEVMEMINT_CTX * psDevmemCtxInt = NULL;
 	DEVMEMINT_HEAP * psDevmemHeapPtrInt = NULL;
 
@@ -1130,19 +1783,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntHeapCreateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDevmemCtxInt,
-											psDevmemIntHeapCreateIN->hDevmemCtx,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+											IMG_TRUE);
 					if(psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntHeapCreate_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntHeapCreateOUT->eError =
 		DevmemIntHeapCreate(
@@ -1157,8 +1820,15 @@
 		goto DevmemIntHeapCreate_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDevmemIntHeapCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDevmemIntHeapCreateOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntHeapCreateOUT->hDevmemHeapPtr,
 							(void *) psDevmemHeapPtrInt,
 							PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
@@ -1166,13 +1836,37 @@
 							,(PFN_HANDLE_RELEASE)&DevmemIntHeapDestroy);
 	if (psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntHeapCreate_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DevmemIntHeapCreate_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemCtxInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
 	{
 		if (psDevmemHeapPtrInt)
@@ -1185,6 +1879,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntHeapDestroy(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTHEAPDESTROY *psDevmemIntHeapDestroyIN,
@@ -1200,31 +1895,53 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psDevmemIntHeapDestroyOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDevmemIntHeapDestroyIN->hDevmemHeap,
 					PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
-	if ((psDevmemIntHeapDestroyOUT->eError != PVRSRV_OK) && (psDevmemIntHeapDestroyOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDevmemIntHeapDestroyOUT->eError != PVRSRV_OK) &&
+	    (psDevmemIntHeapDestroyOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDevmemIntHeapDestroy: %s",
+		        PVRSRVGetErrorStringKM(psDevmemIntHeapDestroyOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto DevmemIntHeapDestroy_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DevmemIntHeapDestroy_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntMapPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTMAPPMR *psDevmemIntMapPMRIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTMAPPMR *psDevmemIntMapPMROUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevmemServerHeap = psDevmemIntMapPMRIN->hDevmemServerHeap;
 	DEVMEMINT_HEAP * psDevmemServerHeapInt = NULL;
+	IMG_HANDLE hReservation = psDevmemIntMapPMRIN->hReservation;
 	DEVMEMINT_RESERVATION * psReservationInt = NULL;
+	IMG_HANDLE hPMR = psDevmemIntMapPMRIN->hPMR;
 	PMR * psPMRInt = NULL;
 	DEVMEMINT_MAPPING * psMappingInt = NULL;
 
@@ -1232,53 +1949,69 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntMapPMROUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDevmemServerHeapInt,
-											psDevmemIntMapPMRIN->hDevmemServerHeap,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+											hDevmemServerHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+											IMG_TRUE);
 					if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntMapPMR_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntMapPMROUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psReservationInt,
-											psDevmemIntMapPMRIN->hReservation,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
+											IMG_TRUE);
 					if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntMapPMR_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntMapPMROUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntMapPMRIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntMapPMR_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntMapPMROUT->eError =
 		DevmemIntMapPMR(
@@ -1290,13 +2023,18 @@
 	/* Exit early if bridged call fails */
 	if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto DevmemIntMapPMR_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psDevmemIntMapPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psDevmemIntMapPMROUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntMapPMROUT->hMapping,
 							(void *) psMappingInt,
 							PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING,
@@ -1304,13 +2042,65 @@
 							,(PFN_HANDLE_RELEASE)&DevmemIntUnmapPMR);
 	if (psDevmemIntMapPMROUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntMapPMR_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DevmemIntMapPMR_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemServerHeapInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemServerHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psReservationInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDevmemIntMapPMROUT->eError != PVRSRV_OK)
 	{
 		if (psMappingInt)
@@ -1323,6 +2113,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntUnmapPMR(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTUNMAPPMR *psDevmemIntUnmapPMRIN,
@@ -1334,36 +2125,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psDevmemIntUnmapPMROUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDevmemIntUnmapPMRIN->hMapping,
 					PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
-	if ((psDevmemIntUnmapPMROUT->eError != PVRSRV_OK) && (psDevmemIntUnmapPMROUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDevmemIntUnmapPMROUT->eError != PVRSRV_OK) &&
+	    (psDevmemIntUnmapPMROUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDevmemIntUnmapPMR: %s",
+		        PVRSRVGetErrorStringKM(psDevmemIntUnmapPMROUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto DevmemIntUnmapPMR_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DevmemIntUnmapPMR_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntReserveRange(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTRESERVERANGE *psDevmemIntReserveRangeIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTRESERVERANGE *psDevmemIntReserveRangeOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevmemServerHeap = psDevmemIntReserveRangeIN->hDevmemServerHeap;
 	DEVMEMINT_HEAP * psDevmemServerHeapInt = NULL;
 	DEVMEMINT_RESERVATION * psReservationInt = NULL;
 
@@ -1373,19 +2181,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntReserveRangeOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDevmemServerHeapInt,
-											psDevmemIntReserveRangeIN->hDevmemServerHeap,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+											hDevmemServerHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+											IMG_TRUE);
 					if(psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntReserveRange_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntReserveRangeOUT->eError =
 		DevmemIntReserveRange(
@@ -1399,8 +2217,15 @@
 		goto DevmemIntReserveRange_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psDevmemIntReserveRangeOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psDevmemIntReserveRangeOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psDevmemIntReserveRangeOUT->hReservation,
 							(void *) psReservationInt,
 							PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
@@ -1408,13 +2233,37 @@
 							,(PFN_HANDLE_RELEASE)&DevmemIntUnreserveRange);
 	if (psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto DevmemIntReserveRange_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 DevmemIntReserveRange_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemServerHeapInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemServerHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
 	{
 		if (psReservationInt)
@@ -1427,6 +2276,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntUnreserveRange(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTUNRESERVERANGE *psDevmemIntUnreserveRangeIN,
@@ -1442,113 +2292,175 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psDevmemIntUnreserveRangeOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psDevmemIntUnreserveRangeIN->hReservation,
 					PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
-	if ((psDevmemIntUnreserveRangeOUT->eError != PVRSRV_OK) && (psDevmemIntUnreserveRangeOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psDevmemIntUnreserveRangeOUT->eError != PVRSRV_OK) &&
+	    (psDevmemIntUnreserveRangeOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeDevmemIntUnreserveRange: %s",
+		        PVRSRVGetErrorStringKM(psDevmemIntUnreserveRangeOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto DevmemIntUnreserveRange_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 DevmemIntUnreserveRange_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeChangeSparseMem(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_CHANGESPARSEMEM *psChangeSparseMemIN,
 					  PVRSRV_BRIDGE_OUT_CHANGESPARSEMEM *psChangeSparseMemOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSrvDevMemHeap = psChangeSparseMemIN->hSrvDevMemHeap;
 	DEVMEMINT_HEAP * psSrvDevMemHeapInt = NULL;
+	IMG_HANDLE hPMR = psChangeSparseMemIN->hPMR;
 	PMR * psPMRInt = NULL;
 	IMG_UINT32 *ui32AllocPageIndicesInt = NULL;
 	IMG_UINT32 *ui32FreePageIndicesInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32)) +
+			(psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32)) +
+			0;
 
 
 
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psChangeSparseMemIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psChangeSparseMemIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psChangeSparseMemOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto ChangeSparseMem_exit;
+			}
+		}
+	}
+
 	if (psChangeSparseMemIN->ui32AllocPageCount != 0)
 	{
-		ui32AllocPageIndicesInt = OSAllocMemNoStats(psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32));
-		if (!ui32AllocPageIndicesInt)
-		{
-			psChangeSparseMemOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ChangeSparseMem_exit;
-		}
+		ui32AllocPageIndicesInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psChangeSparseMemIN->pui32AllocPageIndices, psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32AllocPageIndicesInt, psChangeSparseMemIN->pui32AllocPageIndices,
-				psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32) > 0)
 			{
-				psChangeSparseMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32AllocPageIndicesInt, psChangeSparseMemIN->pui32AllocPageIndices, psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psChangeSparseMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto ChangeSparseMem_exit;
+					goto ChangeSparseMem_exit;
+				}
 			}
 	if (psChangeSparseMemIN->ui32FreePageCount != 0)
 	{
-		ui32FreePageIndicesInt = OSAllocMemNoStats(psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32));
-		if (!ui32FreePageIndicesInt)
-		{
-			psChangeSparseMemOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ChangeSparseMem_exit;
-		}
+		ui32FreePageIndicesInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psChangeSparseMemIN->pui32FreePageIndices, psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32FreePageIndicesInt, psChangeSparseMemIN->pui32FreePageIndices,
-				psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32) > 0)
 			{
-				psChangeSparseMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32FreePageIndicesInt, psChangeSparseMemIN->pui32FreePageIndices, psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psChangeSparseMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto ChangeSparseMem_exit;
+					goto ChangeSparseMem_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psChangeSparseMemOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSrvDevMemHeapInt,
-											psChangeSparseMemIN->hSrvDevMemHeap,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+											hSrvDevMemHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+											IMG_TRUE);
 					if(psChangeSparseMemOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto ChangeSparseMem_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psChangeSparseMemOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psChangeSparseMemIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psChangeSparseMemOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto ChangeSparseMem_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psChangeSparseMemOUT->eError =
-		DeviceMemChangeSparseServer(
+		DevmemIntChangeSparse(
 					psSrvDevMemHeapInt,
 					psPMRInt,
 					psChangeSparseMemIN->ui32AllocPageCount,
@@ -1558,67 +2470,121 @@
 					psChangeSparseMemIN->ui32SparseFlags,
 					psChangeSparseMemIN->uiFlags,
 					psChangeSparseMemIN->sDevVAddr,
-					psChangeSparseMemIN->ui64CPUVAddr,
-					&psChangeSparseMemOUT->ui32Status);
-	PMRUnlock();
+					psChangeSparseMemIN->ui64CPUVAddr);
 
 
 
 
 ChangeSparseMem_exit:
-	if (ui32AllocPageIndicesInt)
-		OSFreeMemNoStats(ui32AllocPageIndicesInt);
-	if (ui32FreePageIndicesInt)
-		OSFreeMemNoStats(ui32FreePageIndicesInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSrvDevMemHeapInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSrvDevMemHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntMapPages(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTMAPPAGES *psDevmemIntMapPagesIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTMAPPAGES *psDevmemIntMapPagesOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hReservation = psDevmemIntMapPagesIN->hReservation;
 	DEVMEMINT_RESERVATION * psReservationInt = NULL;
+	IMG_HANDLE hPMR = psDevmemIntMapPagesIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntMapPagesOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psReservationInt,
-											psDevmemIntMapPagesIN->hReservation,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
+											IMG_TRUE);
 					if(psDevmemIntMapPagesOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntMapPages_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntMapPagesOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psDevmemIntMapPagesIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psDevmemIntMapPagesOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto DevmemIntMapPages_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntMapPagesOUT->eError =
 		DevmemIntMapPages(
@@ -1628,22 +2594,58 @@
 					psDevmemIntMapPagesIN->ui32PhysicalPgOffset,
 					psDevmemIntMapPagesIN->uiFlags,
 					psDevmemIntMapPagesIN->sDevVAddr);
-	PMRUnlock();
 
 
 
 
 DevmemIntMapPages_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psReservationInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntUnmapPages(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTUNMAPPAGES *psDevmemIntUnmapPagesIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTUNMAPPAGES *psDevmemIntUnmapPagesOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hReservation = psDevmemIntUnmapPagesIN->hReservation;
 	DEVMEMINT_RESERVATION * psReservationInt = NULL;
 
 
@@ -1652,19 +2654,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIntUnmapPagesOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psReservationInt,
-											psDevmemIntUnmapPagesIN->hReservation,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
+											IMG_TRUE);
 					if(psDevmemIntUnmapPagesOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntUnmapPages_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntUnmapPagesOUT->eError =
 		DevmemIntUnmapPages(
@@ -1677,18 +2689,8 @@
 
 DevmemIntUnmapPages_exit:
 
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeDevmemSLCFlushInvalRequest(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_DEVMEMSLCFLUSHINVALREQUEST *psDevmemSLCFlushInvalRequestIN,
-					  PVRSRV_BRIDGE_OUT_DEVMEMSLCFLUSHINVALREQUEST *psDevmemSLCFlushInvalRequestOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	IMG_HANDLE hDeviceNodeInt = NULL;
-	PMR * psPmrInt = NULL;
-
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
 
 
 
@@ -1696,52 +2698,29 @@
 
 
 				{
-					/* Look up the address from the handle */
-					psDevmemSLCFlushInvalRequestOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &hDeviceNodeInt,
-											psDevmemSLCFlushInvalRequestIN->hDeviceNode,
-											PVRSRV_HANDLE_TYPE_DEV_NODE);
-					if(psDevmemSLCFlushInvalRequestOUT->eError != PVRSRV_OK)
-					{
-						goto DevmemSLCFlushInvalRequest_exit;
-					}
+					/* Unreference the previously looked up handle */
+						if(psReservationInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+						}
 				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
 
 
-				{
-					/* Look up the address from the handle */
-					psDevmemSLCFlushInvalRequestOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psPmrInt,
-											psDevmemSLCFlushInvalRequestIN->hPmr,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
-					if(psDevmemSLCFlushInvalRequestOUT->eError != PVRSRV_OK)
-					{
-						goto DevmemSLCFlushInvalRequest_exit;
-					}
-				}
-
-
-	psDevmemSLCFlushInvalRequestOUT->eError =
-		DevmemSLCFlushInvalRequest(
-					hDeviceNodeInt,
-					psPmrInt);
-
-
-
-
-DevmemSLCFlushInvalRequest_exit:
-
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIsVDevAddrValid(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMISVDEVADDRVALID *psDevmemIsVDevAddrValidIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMISVDEVADDRVALID *psDevmemIsVDevAddrValidOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevmemCtx = psDevmemIsVDevAddrValidIN->hDevmemCtx;
 	DEVMEMINT_CTX * psDevmemCtxInt = NULL;
 
 
@@ -1750,22 +2729,32 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psDevmemIsVDevAddrValidOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDevmemCtxInt,
-											psDevmemIsVDevAddrValidIN->hDevmemCtx,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+											IMG_TRUE);
 					if(psDevmemIsVDevAddrValidOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIsVDevAddrValid_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIsVDevAddrValidOUT->eError =
-		DevmemIntIsVDevAddrValid(
+		DevmemIntIsVDevAddrValid(psConnection, OSGetDevData(psConnection),
 					psDevmemCtxInt,
 					psDevmemIsVDevAddrValidIN->sAddress);
 
@@ -1774,9 +2763,31 @@
 
 DevmemIsVDevAddrValid_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemCtxInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHeapCfgHeapConfigCount(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGCOUNT *psHeapCfgHeapConfigCountIN,
@@ -1784,9 +2795,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psHeapCfgHeapConfigCountIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psHeapCfgHeapConfigCountIN);
+
 
 
 
@@ -1799,9 +2811,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHeapCfgHeapCount(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HEAPCFGHEAPCOUNT *psHeapCfgHeapCountIN,
@@ -1815,6 +2831,7 @@
 
 
 
+
 	psHeapCfgHeapCountOUT->eError =
 		HeapCfgHeapCount(psConnection, OSGetDevData(psConnection),
 					psHeapCfgHeapCountIN->ui32HeapConfigIndex,
@@ -1824,9 +2841,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGNAME *psHeapCfgHeapConfigNameIN,
@@ -1835,21 +2856,53 @@
 {
 	IMG_CHAR *puiHeapConfigNameInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR)) +
+			0;
+
+
 
 	psHeapCfgHeapConfigNameOUT->puiHeapConfigName = psHeapCfgHeapConfigNameIN->puiHeapConfigName;
 
 
-	if (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz != 0)
+	if (ui32BufferSize != 0)
 	{
-		puiHeapConfigNameInt = OSAllocMemNoStats(psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR));
-		if (!puiHeapConfigNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psHeapCfgHeapConfigNameIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto HeapCfgHeapConfigName_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psHeapCfgHeapConfigNameIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto HeapCfgHeapConfigName_exit;
+			}
 		}
 	}
 
+	if (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz != 0)
+	{
+		puiHeapConfigNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR);
+	}
 
 
 
@@ -1861,23 +2914,37 @@
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psHeapCfgHeapConfigNameOUT->puiHeapConfigName, (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR)))
-		|| (OSCopyToUser(NULL, psHeapCfgHeapConfigNameOUT->puiHeapConfigName, puiHeapConfigNameInt,
-		(psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+	if ((psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR)) > 0)
 	{
-		psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psHeapCfgHeapConfigNameOUT->puiHeapConfigName, puiHeapConfigNameInt,
+			(psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR))) != PVRSRV_OK )
+		{
+			psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto HeapCfgHeapConfigName_exit;
+			goto HeapCfgHeapConfigName_exit;
+		}
 	}
 
 
 HeapCfgHeapConfigName_exit:
-	if (puiHeapConfigNameInt)
-		OSFreeMemNoStats(puiHeapConfigNameInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HEAPCFGHEAPDETAILS *psHeapCfgHeapDetailsIN,
@@ -1886,21 +2953,53 @@
 {
 	IMG_CHAR *puiHeapNameOutInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR)) +
+			0;
+
+
 
 	psHeapCfgHeapDetailsOUT->puiHeapNameOut = psHeapCfgHeapDetailsIN->puiHeapNameOut;
 
 
-	if (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz != 0)
+	if (ui32BufferSize != 0)
 	{
-		puiHeapNameOutInt = OSAllocMemNoStats(psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR));
-		if (!puiHeapNameOutInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psHeapCfgHeapDetailsIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto HeapCfgHeapDetails_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psHeapCfgHeapDetailsIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto HeapCfgHeapDetails_exit;
+			}
 		}
 	}
 
+	if (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz != 0)
+	{
+		puiHeapNameOutInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR);
+	}
 
 
 
@@ -1917,103 +3016,106 @@
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psHeapCfgHeapDetailsOUT->puiHeapNameOut, (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR)))
-		|| (OSCopyToUser(NULL, psHeapCfgHeapDetailsOUT->puiHeapNameOut, puiHeapNameOutInt,
-		(psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+	if ((psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR)) > 0)
 	{
-		psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psHeapCfgHeapDetailsOUT->puiHeapNameOut, puiHeapNameOutInt,
+			(psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR))) != PVRSRV_OK )
+		{
+			psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto HeapCfgHeapDetails_exit;
+			goto HeapCfgHeapDetails_exit;
+		}
 	}
 
 
 HeapCfgHeapDetails_exit:
-	if (puiHeapNameOutInt)
-		OSFreeMemNoStats(puiHeapNameOutInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
-PVRSRVBridgeDevmemIntCtxCreateCLS(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATECLS *psDevmemIntCtxCreateCLSIN,
-					  PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATECLS *psDevmemIntCtxCreateCLSOUT,
+PVRSRVBridgeDevmemIntRegisterPFNotifyKM(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_DEVMEMINTREGISTERPFNOTIFYKM *psDevmemIntRegisterPFNotifyKMIN,
+					  PVRSRV_BRIDGE_OUT_DEVMEMINTREGISTERPFNOTIFYKM *psDevmemIntRegisterPFNotifyKMOUT,
 					 CONNECTION_DATA *psConnection)
 {
-	DEVMEMINT_CTX * psDevMemServerContextInt = NULL;
-	IMG_HANDLE hPrivDataInt = NULL;
-
-
-
-	psDevmemIntCtxCreateCLSOUT->hDevMemServerContext = NULL;
-
-
-	PMRLock();
-
-
-	psDevmemIntCtxCreateCLSOUT->eError =
-		DevmemIntCtxCreateCLS(psConnection, OSGetDevData(psConnection),
-					psDevmemIntCtxCreateCLSIN->bbKernelMemoryCtx,
-					&psDevMemServerContextInt,
-					&hPrivDataInt,
-					&psDevmemIntCtxCreateCLSOUT->ui32CPUCacheLineSize);
-	/* Exit early if bridged call fails */
-	if(psDevmemIntCtxCreateCLSOUT->eError != PVRSRV_OK)
-	{
-		PMRUnlock();
-		goto DevmemIntCtxCreateCLS_exit;
-	}
-	PMRUnlock();
-
-
-	psDevmemIntCtxCreateCLSOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
-							&psDevmemIntCtxCreateCLSOUT->hDevMemServerContext,
-							(void *) psDevMemServerContextInt,
-							PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
-							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
-							,(PFN_HANDLE_RELEASE)&DevmemIntCtxDestroy);
-	if (psDevmemIntCtxCreateCLSOUT->eError != PVRSRV_OK)
-	{
-		goto DevmemIntCtxCreateCLS_exit;
-	}
-
-
-	psDevmemIntCtxCreateCLSOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
-							&psDevmemIntCtxCreateCLSOUT->hPrivData,
-							(void *) hPrivDataInt,
-							PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
-							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
-							,psDevmemIntCtxCreateCLSOUT->hDevMemServerContext);
-	if (psDevmemIntCtxCreateCLSOUT->eError != PVRSRV_OK)
-	{
-		goto DevmemIntCtxCreateCLS_exit;
-	}
+	IMG_HANDLE hDevmemCtx = psDevmemIntRegisterPFNotifyKMIN->hDevmemCtx;
+	DEVMEMINT_CTX * psDevmemCtxInt = NULL;
 
 
 
 
-DevmemIntCtxCreateCLS_exit:
-	if (psDevmemIntCtxCreateCLSOUT->eError != PVRSRV_OK)
-	{
-		if (psDevmemIntCtxCreateCLSOUT->hDevMemServerContext)
-		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
-						(IMG_HANDLE) psDevmemIntCtxCreateCLSOUT->hDevMemServerContext,
-						PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
-			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
-
-			/* Avoid freeing/destroying/releasing the resource a second time below */
-			psDevMemServerContextInt = NULL;
-		}
 
 
-		if (psDevMemServerContextInt)
-		{
-			DevmemIntCtxDestroy(psDevMemServerContextInt);
-		}
-	}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psDevmemIntRegisterPFNotifyKMOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psDevmemCtxInt,
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+											IMG_TRUE);
+					if(psDevmemIntRegisterPFNotifyKMOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto DevmemIntRegisterPFNotifyKM_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psDevmemIntRegisterPFNotifyKMOUT->eError =
+		DevmemIntRegisterPFNotifyKM(
+					psDevmemCtxInt,
+					psDevmemIntRegisterPFNotifyKMIN->ui32PID,
+					psDevmemIntRegisterPFNotifyKMIN->bRegister);
+
+
+
+
+DevmemIntRegisterPFNotifyKM_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemCtxInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
 
 
 	return 0;
@@ -2021,6 +3123,7 @@
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -2114,9 +3217,6 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMINTUNMAPPAGES, PVRSRVBridgeDevmemIntUnmapPages,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMSLCFLUSHINVALREQUEST, PVRSRVBridgeDevmemSLCFlushInvalRequest,
-					NULL, bUseLock);
-
 	SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMISVDEVADDRVALID, PVRSRVBridgeDevmemIsVDevAddrValid,
 					NULL, bUseLock);
 
@@ -2132,7 +3232,7 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS, PVRSRVBridgeHeapCfgHeapDetails,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMINTCTXCREATECLS, PVRSRVBridgeDevmemIntCtxCreateCLS,
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMINTREGISTERPFNOTIFYKM, PVRSRVBridgeDevmemIntRegisterPFNotifyKM,
 					NULL, bUseLock);
 
 
@@ -2146,4 +3246,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h b/drivers/staging/imgtec/rogue/generated/pdump_bridge/client_pdump_bridge.h
similarity index 69%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
copy to drivers/staging/imgtec/rogue/generated/pdump_bridge/client_pdump_bridge.h
index 839a17a..b628b08 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pdump_bridge/client_pdump_bridge.h
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          Client bridge header for cachegeneric
+@Title          Client bridge header for pdump
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Exports the client bridge functions for cachegeneric
+@Description    Exports the client bridge functions for pdump
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,8 +41,8 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef CLIENT_CACHEGENERIC_BRIDGE_H
-#define CLIENT_CACHEGENERIC_BRIDGE_H
+#ifndef CLIENT_PDUMP_BRIDGE_H
+#define CLIENT_PDUMP_BRIDGE_H
 
 #include "img_defs.h"
 #include "pvrsrv_error.h"
@@ -52,13 +52,27 @@
 #include "pvr_bridge.h"
 #endif
 
-#include "common_cachegeneric_bridge.h"
+#include "common_pdump_bridge.h"
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp);
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemPDumpBitmap(IMG_HANDLE hBridge,
+							       IMG_CHAR *puiFileName,
+							       IMG_UINT32 ui32FileOffset,
+							       IMG_UINT32 ui32Width,
+							       IMG_UINT32 ui32Height,
+							       IMG_UINT32 ui32StrideInBytes,
+							       IMG_DEV_VIRTADDR sDevBaseAddr,
+							       IMG_HANDLE hDevmemCtx,
+							       IMG_UINT32 ui32Size,
+							       PDUMP_PIXEL_FORMAT ePixelFormat,
+							       IMG_UINT32 ui32AddrMode,
+							       IMG_UINT32 ui32PDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpComment(IMG_HANDLE hBridge,
+								IMG_CHAR *puiComment,
+								IMG_UINT32 ui32Flags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpSetFrame(IMG_HANDLE hBridge,
+								 IMG_UINT32 ui32Frame);
 
 
-#endif /* CLIENT_CACHEGENERIC_BRIDGE_H */
+#endif /* CLIENT_PDUMP_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/pdump_bridge/client_pdump_direct_bridge.c
similarity index 60%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
copy to drivers/staging/imgtec/rogue/generated/pdump_bridge/client_pdump_direct_bridge.c
index d0cdf5a..b4977ef 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pdump_bridge/client_pdump_direct_bridge.c
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          Direct client bridge for cachegeneric
+@Title          Direct client bridge for pdump
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,34 +39,80 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include "client_cachegeneric_bridge.h"
+#include "client_pdump_bridge.h"
 #include "img_defs.h"
 #include "pvr_debug.h"
 
 /* Module specific includes */
-#include "cache_external.h"
+#include "devicemem_typedefs.h"
+#include "pdumpdefs.h"
 
-#include "cache_generic.h"
+#include "devicemem_server.h"
+#include "pdump_km.h"
 
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp)
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemPDumpBitmap(IMG_HANDLE hBridge,
+							       IMG_CHAR *puiFileName,
+							       IMG_UINT32 ui32FileOffset,
+							       IMG_UINT32 ui32Width,
+							       IMG_UINT32 ui32Height,
+							       IMG_UINT32 ui32StrideInBytes,
+							       IMG_DEV_VIRTADDR sDevBaseAddr,
+							       IMG_HANDLE hDevmemCtx,
+							       IMG_UINT32 ui32Size,
+							       PDUMP_PIXEL_FORMAT ePixelFormat,
+							       IMG_UINT32 ui32AddrMode,
+							       IMG_UINT32 ui32PDumpFlags)
 {
 	PVRSRV_ERROR eError;
-	PMR * psPMRInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
+	DEVMEMINT_CTX * psDevmemCtxInt;
 
-	psPMRInt = (PMR *) hPMR;
+	psDevmemCtxInt = (DEVMEMINT_CTX *) hDevmemCtx;
 
 	eError =
-		CacheOpQueue(
-					psPMRInt,
-					uiOffset,
-					uiSize,
-					iuCacheOp);
+		DevmemIntPDumpBitmap(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					puiFileName,
+					ui32FileOffset,
+					ui32Width,
+					ui32Height,
+					ui32StrideInBytes,
+					sDevBaseAddr,
+					psDevmemCtxInt,
+					ui32Size,
+					ePixelFormat,
+					ui32AddrMode,
+					ui32PDumpFlags);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpComment(IMG_HANDLE hBridge,
+								IMG_CHAR *puiComment,
+								IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		PDumpCommentKM(
+					puiComment,
+					ui32Flags);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpSetFrame(IMG_HANDLE hBridge,
+								 IMG_UINT32 ui32Frame)
+{
+	PVRSRV_ERROR eError;
+
+
+	eError =
+		PDumpSetFrameKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					ui32Frame);
 
 	return eError;
 }
diff --git a/drivers/staging/imgtec/rogue/generated/pdump_bridge/common_pdump_bridge.h b/drivers/staging/imgtec/rogue/generated/pdump_bridge/common_pdump_bridge.h
index e11e056..0159b82 100644
--- a/drivers/staging/imgtec/rogue/generated/pdump_bridge/common_pdump_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pdump_bridge/common_pdump_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for pdump
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for pdump
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for pdump
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_PDUMP_BRIDGE_H
 #define COMMON_PDUMP_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/pdump_bridge/server_pdump_bridge.c b/drivers/staging/imgtec/rogue/generated/pdump_bridge/server_pdump_bridge.c
index f89a8a2..0b38a25 100644
--- a/drivers/staging/imgtec/rogue/generated/pdump_bridge/server_pdump_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pdump_bridge/server_pdump_bridge.c
@@ -65,6 +65,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -76,47 +78,90 @@
 					 CONNECTION_DATA *psConnection)
 {
 	IMG_CHAR *uiFileNameInt = NULL;
+	IMG_HANDLE hDevmemCtx = psDevmemPDumpBitmapIN->hDevmemCtx;
 	DEVMEMINT_CTX * psDevmemCtxInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiFileNameInt = OSAllocMemNoStats(PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR));
-		if (!uiFileNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevmemPDumpBitmapIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DevmemPDumpBitmap_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevmemPDumpBitmapIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevmemPDumpBitmap_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDevmemPDumpBitmapIN->puiFileName, PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiFileNameInt, psDevmemPDumpBitmapIN->puiFileName,
-				PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	
+	{
+		uiFileNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR);
+	}
 
-				goto DevmemPDumpBitmap_exit;
+			/* Copy the data over */
+			if (PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiFileNameInt, psDevmemPDumpBitmapIN->puiFileName, PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevmemPDumpBitmap_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemPDumpBitmapOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDevmemCtxInt,
-											psDevmemPDumpBitmapIN->hDevmemCtx,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+											IMG_TRUE);
 					if(psDevmemPDumpBitmapOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemPDumpBitmap_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemPDumpBitmapOUT->eError =
 		DevmemIntPDumpBitmap(psConnection, OSGetDevData(psConnection),
@@ -136,12 +181,42 @@
 
 
 DevmemPDumpBitmap_exit:
-	if (uiFileNameInt)
-		OSFreeMemNoStats(uiFileNameInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemCtxInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemCtx,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePVRSRVPDumpComment(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PVRSRVPDUMPCOMMENT *psPVRSRVPDumpCommentIN,
@@ -150,33 +225,66 @@
 {
 	IMG_CHAR *uiCommentInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) +
+			0;
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
 
-	
+	if (ui32BufferSize != 0)
 	{
-		uiCommentInt = OSAllocMemNoStats(PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR));
-		if (!uiCommentInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psPVRSRVPDumpCommentIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto PVRSRVPDumpComment_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psPVRSRVPDumpCommentIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto PVRSRVPDumpComment_exit;
+			}
 		}
 	}
 
+	
+	{
+		uiCommentInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPVRSRVPDumpCommentIN->puiComment, PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiCommentInt, psPVRSRVPDumpCommentIN->puiComment,
-				PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR) > 0)
 			{
-				psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiCommentInt, psPVRSRVPDumpCommentIN->puiComment, PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto PVRSRVPDumpComment_exit;
+					goto PVRSRVPDumpComment_exit;
+				}
 			}
 
 
-
 	psPVRSRVPDumpCommentOUT->eError =
 		PDumpCommentKM(
 					uiCommentInt,
@@ -186,12 +294,24 @@
 
 
 PVRSRVPDumpComment_exit:
-	if (uiCommentInt)
-		OSFreeMemNoStats(uiCommentInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePVRSRVPDumpSetFrame(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETFRAME *psPVRSRVPDumpSetFrameIN,
@@ -203,17 +323,15 @@
 
 
 
-#if defined(PDUMP)
-	PMRLock();
-#endif
+
 
 
 	psPVRSRVPDumpSetFrameOUT->eError =
 		PDumpSetFrameKM(psConnection, OSGetDevData(psConnection),
 					psPVRSRVPDumpSetFrameIN->ui32Frame);
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
+
+
+
 
 
 
@@ -224,6 +342,7 @@
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -259,4 +378,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/client_pdumpctrl_bridge.h
similarity index 71%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
copy to drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/client_pdumpctrl_bridge.h
index 839a17a..65ca48d 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/client_pdumpctrl_bridge.h
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          Client bridge header for cachegeneric
+@Title          Client bridge header for pdumpctrl
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Exports the client bridge functions for cachegeneric
+@Description    Exports the client bridge functions for pdumpctrl
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,8 +41,8 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef CLIENT_CACHEGENERIC_BRIDGE_H
-#define CLIENT_CACHEGENERIC_BRIDGE_H
+#ifndef CLIENT_PDUMPCTRL_BRIDGE_H
+#define CLIENT_PDUMPCTRL_BRIDGE_H
 
 #include "img_defs.h"
 #include "pvrsrv_error.h"
@@ -52,13 +52,23 @@
 #include "pvr_bridge.h"
 #endif
 
-#include "common_cachegeneric_bridge.h"
+#include "common_pdumpctrl_bridge.h"
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp);
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpIsCapturing(IMG_HANDLE hBridge,
+								    IMG_BOOL *pbIsCapturing);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpGetFrame(IMG_HANDLE hBridge,
+								 IMG_UINT32 *pui32Frame);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpSetDefaultCaptureParams(IMG_HANDLE hBridge,
+										IMG_UINT32 ui32Mode,
+										IMG_UINT32 ui32Start,
+										IMG_UINT32 ui32End,
+										IMG_UINT32 ui32Interval,
+										IMG_UINT32 ui32MaxParamFileSize);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpIsLastCaptureFrame(IMG_HANDLE hBridge,
+									   IMG_BOOL *pbpbIsLastCaptureFrame);
 
 
-#endif /* CLIENT_CACHEGENERIC_BRIDGE_H */
+#endif /* CLIENT_PDUMPCTRL_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/client_pdumpctrl_direct_bridge.c
similarity index 64%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
copy to drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/client_pdumpctrl_direct_bridge.c
index d0cdf5a..c8132fc 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/client_pdumpctrl_direct_bridge.c
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          Direct client bridge for cachegeneric
+@Title          Direct client bridge for pdumpctrl
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,34 +39,75 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include "client_cachegeneric_bridge.h"
+#include "client_pdumpctrl_bridge.h"
 #include "img_defs.h"
 #include "pvr_debug.h"
 
 /* Module specific includes */
-#include "cache_external.h"
 
-#include "cache_generic.h"
+#include "pdump_km.h"
 
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp)
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpIsCapturing(IMG_HANDLE hBridge,
+								    IMG_BOOL *pbIsCapturing)
 {
 	PVRSRV_ERROR eError;
-	PMR * psPMRInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
 
-	psPMRInt = (PMR *) hPMR;
 
 	eError =
-		CacheOpQueue(
-					psPMRInt,
-					uiOffset,
-					uiSize,
-					iuCacheOp);
+		PDumpIsCaptureFrameKM(
+					pbIsCapturing);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpGetFrame(IMG_HANDLE hBridge,
+								 IMG_UINT32 *pui32Frame)
+{
+	PVRSRV_ERROR eError;
+
+
+	eError =
+		PDumpGetFrameKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					pui32Frame);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpSetDefaultCaptureParams(IMG_HANDLE hBridge,
+										IMG_UINT32 ui32Mode,
+										IMG_UINT32 ui32Start,
+										IMG_UINT32 ui32End,
+										IMG_UINT32 ui32Interval,
+										IMG_UINT32 ui32MaxParamFileSize)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		PDumpSetDefaultCaptureParamsKM(
+					ui32Mode,
+					ui32Start,
+					ui32End,
+					ui32Interval,
+					ui32MaxParamFileSize);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePVRSRVPDumpIsLastCaptureFrame(IMG_HANDLE hBridge,
+									   IMG_BOOL *pbpbIsLastCaptureFrame)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		PDumpIsLastCaptureFrameKM(
+					pbpbIsLastCaptureFrame);
 
 	return eError;
 }
diff --git a/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/common_pdumpctrl_bridge.h b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/common_pdumpctrl_bridge.h
index 841ee1d..a165141 100644
--- a/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/common_pdumpctrl_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/common_pdumpctrl_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for pdumpctrl
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for pdumpctrl
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for pdumpctrl
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_PDUMPCTRL_BRIDGE_H
 #define COMMON_PDUMPCTRL_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -128,6 +130,7 @@
 /* Bridge out structure for PVRSRVPDumpIsLastCaptureFrame */
 typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISLASTCAPTUREFRAME_TAG
 {
+	IMG_BOOL bpbIsLastCaptureFrame;
 	PVRSRV_ERROR eError;
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISLASTCAPTUREFRAME;
 
diff --git a/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/server_pdumpctrl_bridge.c b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/server_pdumpctrl_bridge.c
index 54bfce0..148c726 100644
--- a/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/server_pdumpctrl_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pdumpctrl_bridge/server_pdumpctrl_bridge.c
@@ -65,6 +65,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -76,6 +78,8 @@
 					 CONNECTION_DATA *psConnection)
 {
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpIsCapturingIN);
 
@@ -83,7 +87,6 @@
 
 
 
-
 	psPVRSRVPDumpIsCapturingOUT->eError =
 		PDumpIsCaptureFrameKM(
 					&psPVRSRVPDumpIsCapturingOUT->bIsCapturing);
@@ -92,9 +95,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePVRSRVPDumpGetFrame(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PVRSRVPDUMPGETFRAME *psPVRSRVPDumpGetFrameIN,
@@ -102,9 +109,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpGetFrameIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpGetFrameIN);
+
 
 
 
@@ -117,9 +125,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePVRSRVPDumpSetDefaultCaptureParams(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS *psPVRSRVPDumpSetDefaultCaptureParamsIN,
@@ -127,9 +139,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
 
 
 
@@ -146,9 +159,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePVRSRVPDumpIsLastCaptureFrame(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PVRSRVPDUMPISLASTCAPTUREFRAME *psPVRSRVPDumpIsLastCaptureFrameIN,
@@ -156,6 +173,8 @@
 					 CONNECTION_DATA *psConnection)
 {
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpIsLastCaptureFrameIN);
 
@@ -163,10 +182,12 @@
 
 
 
-
 	psPVRSRVPDumpIsLastCaptureFrameOUT->eError =
 		PDumpIsLastCaptureFrameKM(
-					);
+					&psPVRSRVPDumpIsLastCaptureFrameOUT->bpbIsLastCaptureFrame);
+
+
+
 
 
 
@@ -177,6 +198,7 @@
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -218,4 +240,3 @@
 	PVR_LOGR_IF_ERROR(OSLockDestroy(pPDUMPCTRLBridgeLock), "OSLockDestroy");
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h b/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h
index 854a8f8..07e17b2 100644
--- a/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for pdumpmm
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for pdumpmm
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for pdumpmm
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_PDUMPMM_BRIDGE_H
 #define COMMON_PDUMPMM_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c b/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c
index fc3bf19..f5bab7c 100644
--- a/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c
@@ -66,6 +66,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -76,29 +78,38 @@
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEM *psPMRPDumpLoadMemOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpLoadMemIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpLoadMemOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpLoadMemIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpLoadMemOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpLoadMem_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpLoadMemOUT->eError =
 		PMRPDumpLoadMem(
@@ -107,45 +118,75 @@
 					psPMRPDumpLoadMemIN->uiSize,
 					psPMRPDumpLoadMemIN->ui32PDumpFlags,
 					psPMRPDumpLoadMemIN->bbZero);
-	PMRUnlock();
 
 
 
 
 PMRPDumpLoadMem_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRPDumpLoadMemValue32(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE32 *psPMRPDumpLoadMemValue32IN,
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE32 *psPMRPDumpLoadMemValue32OUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpLoadMemValue32IN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpLoadMemValue32OUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpLoadMemValue32IN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpLoadMemValue32OUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpLoadMemValue32_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpLoadMemValue32OUT->eError =
 		PMRPDumpLoadMemValue32(
@@ -153,45 +194,75 @@
 					psPMRPDumpLoadMemValue32IN->uiOffset,
 					psPMRPDumpLoadMemValue32IN->ui32Value,
 					psPMRPDumpLoadMemValue32IN->ui32PDumpFlags);
-	PMRUnlock();
 
 
 
 
 PMRPDumpLoadMemValue32_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRPDumpLoadMemValue64(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE64 *psPMRPDumpLoadMemValue64IN,
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE64 *psPMRPDumpLoadMemValue64OUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpLoadMemValue64IN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpLoadMemValue64OUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpLoadMemValue64IN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpLoadMemValue64OUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpLoadMemValue64_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpLoadMemValue64OUT->eError =
 		PMRPDumpLoadMemValue64(
@@ -199,66 +270,128 @@
 					psPMRPDumpLoadMemValue64IN->uiOffset,
 					psPMRPDumpLoadMemValue64IN->ui64Value,
 					psPMRPDumpLoadMemValue64IN->ui32PDumpFlags);
-	PMRUnlock();
 
 
 
 
 PMRPDumpLoadMemValue64_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRPDumpSaveToFile(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRPDUMPSAVETOFILE *psPMRPDumpSaveToFileIN,
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPSAVETOFILE *psPMRPDumpSaveToFileOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpSaveToFileIN->hPMR;
 	PMR * psPMRInt = NULL;
 	IMG_CHAR *uiFileNameInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psPMRPDumpSaveToFileIN->ui32ArraySize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiFileNameInt = OSAllocMemNoStats(psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR));
-		if (!uiFileNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psPMRPDumpSaveToFileIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto PMRPDumpSaveToFile_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psPMRPDumpSaveToFileIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto PMRPDumpSaveToFile_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPMRPDumpSaveToFileIN->puiFileName, psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiFileNameInt, psPMRPDumpSaveToFileIN->puiFileName,
-				psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psPMRPDumpSaveToFileIN->ui32ArraySize != 0)
+	{
+		uiFileNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR);
+	}
 
-				goto PMRPDumpSaveToFile_exit;
+			/* Copy the data over */
+			if (psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiFileNameInt, psPMRPDumpSaveToFileIN->puiFileName, psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto PMRPDumpSaveToFile_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpSaveToFileOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpSaveToFileIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpSaveToFileOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpSaveToFile_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpSaveToFileOUT->eError =
 		PMRPDumpSaveToFile(
@@ -268,73 +401,138 @@
 					psPMRPDumpSaveToFileIN->ui32ArraySize,
 					uiFileNameInt,
 					psPMRPDumpSaveToFileIN->ui32uiFileOffset);
-	PMRUnlock();
 
 
 
 
 PMRPDumpSaveToFile_exit:
-	if (uiFileNameInt)
-		OSFreeMemNoStats(uiFileNameInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRPDumpSymbolicAddr(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRPDUMPSYMBOLICADDR *psPMRPDumpSymbolicAddrIN,
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPSYMBOLICADDR *psPMRPDumpSymbolicAddrOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpSymbolicAddrIN->hPMR;
 	PMR * psPMRInt = NULL;
 	IMG_CHAR *puiMemspaceNameInt = NULL;
 	IMG_CHAR *puiSymbolicAddrInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR)) +
+			(psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR)) +
+			0;
+
+
 
 	psPMRPDumpSymbolicAddrOUT->puiMemspaceName = psPMRPDumpSymbolicAddrIN->puiMemspaceName;
 	psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr = psPMRPDumpSymbolicAddrIN->puiSymbolicAddr;
 
 
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psPMRPDumpSymbolicAddrIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psPMRPDumpSymbolicAddrIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto PMRPDumpSymbolicAddr_exit;
+			}
+		}
+	}
+
 	if (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen != 0)
 	{
-		puiMemspaceNameInt = OSAllocMemNoStats(psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR));
-		if (!puiMemspaceNameInt)
-		{
-			psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto PMRPDumpSymbolicAddr_exit;
-		}
+		puiMemspaceNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR);
 	}
 
 	if (psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen != 0)
 	{
-		puiSymbolicAddrInt = OSAllocMemNoStats(psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR));
-		if (!puiSymbolicAddrInt)
-		{
-			psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto PMRPDumpSymbolicAddr_exit;
-		}
+		puiSymbolicAddrInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR);
 	}
 
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpSymbolicAddrOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpSymbolicAddrIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpSymbolicAddrOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpSymbolicAddr_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpSymbolicAddrOUT->eError =
 		PMR_PDumpSymbolicAddr(
@@ -346,67 +544,107 @@
 					puiSymbolicAddrInt,
 					&psPMRPDumpSymbolicAddrOUT->uiNewOffset,
 					&psPMRPDumpSymbolicAddrOUT->uiNextSymName);
-	PMRUnlock();
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psPMRPDumpSymbolicAddrOUT->puiMemspaceName, (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR)))
-		|| (OSCopyToUser(NULL, psPMRPDumpSymbolicAddrOUT->puiMemspaceName, puiMemspaceNameInt,
-		(psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+	if ((psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR)) > 0)
 	{
-		psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psPMRPDumpSymbolicAddrOUT->puiMemspaceName, puiMemspaceNameInt,
+			(psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR))) != PVRSRV_OK )
+		{
+			psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto PMRPDumpSymbolicAddr_exit;
+			goto PMRPDumpSymbolicAddr_exit;
+		}
 	}
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr, (psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR)))
-		|| (OSCopyToUser(NULL, psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr, puiSymbolicAddrInt,
-		(psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+	if ((psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR)) > 0)
 	{
-		psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr, puiSymbolicAddrInt,
+			(psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR))) != PVRSRV_OK )
+		{
+			psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto PMRPDumpSymbolicAddr_exit;
+			goto PMRPDumpSymbolicAddr_exit;
+		}
 	}
 
 
 PMRPDumpSymbolicAddr_exit:
-	if (puiMemspaceNameInt)
-		OSFreeMemNoStats(puiMemspaceNameInt);
-	if (puiSymbolicAddrInt)
-		OSFreeMemNoStats(puiSymbolicAddrInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRPDumpPol32(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRPDUMPPOL32 *psPMRPDumpPol32IN,
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPPOL32 *psPMRPDumpPol32OUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpPol32IN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpPol32OUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpPol32IN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpPol32OUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpPol32_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpPol32OUT->eError =
 		PMRPDumpPol32(
@@ -416,45 +654,75 @@
 					psPMRPDumpPol32IN->ui32Mask,
 					psPMRPDumpPol32IN->eOperator,
 					psPMRPDumpPol32IN->ui32PDumpFlags);
-	PMRUnlock();
 
 
 
 
 PMRPDumpPol32_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePMRPDumpCBP(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PMRPDUMPCBP *psPMRPDumpCBPIN,
 					  PVRSRV_BRIDGE_OUT_PMRPDUMPCBP *psPMRPDumpCBPOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMR = psPMRPDumpCBPIN->hPMR;
 	PMR * psPMRInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psPMRPDumpCBPOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psPMRPDumpCBPIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psPMRPDumpCBPOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto PMRPDumpCBP_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psPMRPDumpCBPOUT->eError =
 		PMRPDumpCBP(
@@ -463,64 +731,128 @@
 					psPMRPDumpCBPIN->uiWriteOffset,
 					psPMRPDumpCBPIN->uiPacketSize,
 					psPMRPDumpCBPIN->uiBufferSize);
-	PMRUnlock();
 
 
 
 
 PMRPDumpCBP_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DEVMEMINTPDUMPSAVETOFILEVIRTUAL *psDevmemIntPDumpSaveToFileVirtualIN,
 					  PVRSRV_BRIDGE_OUT_DEVMEMINTPDUMPSAVETOFILEVIRTUAL *psDevmemIntPDumpSaveToFileVirtualOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hDevmemServerContext = psDevmemIntPDumpSaveToFileVirtualIN->hDevmemServerContext;
 	DEVMEMINT_CTX * psDevmemServerContextInt = NULL;
 	IMG_CHAR *uiFileNameInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiFileNameInt = OSAllocMemNoStats(psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR));
-		if (!uiFileNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psDevmemIntPDumpSaveToFileVirtualIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto DevmemIntPDumpSaveToFileVirtual_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psDevmemIntPDumpSaveToFileVirtualIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto DevmemIntPDumpSaveToFileVirtual_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psDevmemIntPDumpSaveToFileVirtualIN->puiFileName, psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiFileNameInt, psDevmemIntPDumpSaveToFileVirtualIN->puiFileName,
-				psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize != 0)
+	{
+		uiFileNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR);
+	}
 
-				goto DevmemIntPDumpSaveToFileVirtual_exit;
+			/* Copy the data over */
+			if (psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiFileNameInt, psDevmemIntPDumpSaveToFileVirtualIN->puiFileName, psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto DevmemIntPDumpSaveToFileVirtual_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psDevmemIntPDumpSaveToFileVirtualOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psDevmemServerContextInt,
-											psDevmemIntPDumpSaveToFileVirtualIN->hDevmemServerContext,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+											hDevmemServerContext,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+											IMG_TRUE);
 					if(psDevmemIntPDumpSaveToFileVirtualOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto DevmemIntPDumpSaveToFileVirtual_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psDevmemIntPDumpSaveToFileVirtualOUT->eError =
 		DevmemIntPDumpSaveToFileVirtual(
@@ -536,14 +868,44 @@
 
 
 DevmemIntPDumpSaveToFileVirtual_exit:
-	if (uiFileNameInt)
-		OSFreeMemNoStats(uiFileNameInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psDevmemServerContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hDevmemServerContext,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -594,4 +956,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h
index 124a261..4aacc8d 100644
--- a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h
@@ -55,7 +55,7 @@
 #include "common_pvrtl_bridge.h"
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLOpenStream(IMG_HANDLE hBridge,
-							  IMG_CHAR *puiName,
+							  const IMG_CHAR *puiName,
 							  IMG_UINT32 ui32Mode,
 							  IMG_HANDLE *phSD,
 							  IMG_HANDLE *phTLPMR);
@@ -73,5 +73,27 @@
 							   IMG_UINT32 ui32ReadOffset,
 							   IMG_UINT32 ui32ReadLen);
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLDiscoverStreams(IMG_HANDLE hBridge,
+							       const IMG_CHAR *puiNamePattern,
+							       IMG_UINT32 ui32Max,
+							       IMG_UINT32 *pui32Streams,
+							       IMG_UINT32 *pui32NumFound);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLReserveStream(IMG_HANDLE hBridge,
+							     IMG_HANDLE hSD,
+							     IMG_UINT32 *pui32BufferOffset,
+							     IMG_UINT32 ui32Size,
+							     IMG_UINT32 ui32SizeMin,
+							     IMG_UINT32 *pui32Available);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLCommitStream(IMG_HANDLE hBridge,
+							    IMG_HANDLE hSD,
+							    IMG_UINT32 ui32ReqSize);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLWriteData(IMG_HANDLE hBridge,
+							 IMG_HANDLE hSD,
+							 IMG_UINT32 ui32Size,
+							 IMG_BYTE *psData);
+
 
 #endif /* CLIENT_PVRTL_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_direct_bridge.c
index d671ffa..c6d793d 100644
--- a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/client_pvrtl_direct_bridge.c
@@ -45,13 +45,13 @@
 
 /* Module specific includes */
 #include "devicemem_typedefs.h"
-#include "pvr_tl.h"
+#include "pvrsrv_tlcommon.h"
 
 #include "tlserver.h"
 
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLOpenStream(IMG_HANDLE hBridge,
-							  IMG_CHAR *puiName,
+							  const IMG_CHAR *puiName,
 							  IMG_UINT32 ui32Mode,
 							  IMG_HANDLE *phSD,
 							  IMG_HANDLE *phTLPMR)
@@ -130,3 +130,85 @@
 	return eError;
 }
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLDiscoverStreams(IMG_HANDLE hBridge,
+							       const IMG_CHAR *puiNamePattern,
+							       IMG_UINT32 ui32Max,
+							       IMG_UINT32 *pui32Streams,
+							       IMG_UINT32 *pui32NumFound)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		TLServerDiscoverStreamsKM(
+					puiNamePattern,
+					ui32Max,
+					pui32Streams,
+					pui32NumFound);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLReserveStream(IMG_HANDLE hBridge,
+							     IMG_HANDLE hSD,
+							     IMG_UINT32 *pui32BufferOffset,
+							     IMG_UINT32 ui32Size,
+							     IMG_UINT32 ui32SizeMin,
+							     IMG_UINT32 *pui32Available)
+{
+	PVRSRV_ERROR eError;
+	TL_STREAM_DESC * psSDInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psSDInt = (TL_STREAM_DESC *) hSD;
+
+	eError =
+		TLServerReserveStreamKM(
+					psSDInt,
+					pui32BufferOffset,
+					ui32Size,
+					ui32SizeMin,
+					pui32Available);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLCommitStream(IMG_HANDLE hBridge,
+							    IMG_HANDLE hSD,
+							    IMG_UINT32 ui32ReqSize)
+{
+	PVRSRV_ERROR eError;
+	TL_STREAM_DESC * psSDInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psSDInt = (TL_STREAM_DESC *) hSD;
+
+	eError =
+		TLServerCommitStreamKM(
+					psSDInt,
+					ui32ReqSize);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLWriteData(IMG_HANDLE hBridge,
+							 IMG_HANDLE hSD,
+							 IMG_UINT32 ui32Size,
+							 IMG_BYTE *psData)
+{
+	PVRSRV_ERROR eError;
+	TL_STREAM_DESC * psSDInt;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+	psSDInt = (TL_STREAM_DESC *) hSD;
+
+	eError =
+		TLServerWriteDataKM(
+					psSDInt,
+					ui32Size,
+					psData);
+
+	return eError;
+}
+
diff --git a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h
index bb46797..173b9fc 100644
--- a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for pvrtl
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for pvrtl
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for pvrtl
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,11 +45,13 @@
 #ifndef COMMON_PVRTL_BRIDGE_H
 #define COMMON_PVRTL_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "devicemem_typedefs.h"
-#include "pvr_tl.h"
+#include "pvrsrv_tlcommon.h"
 
 
 #define PVRSRV_BRIDGE_PVRTL_CMD_FIRST			0
@@ -57,7 +59,11 @@
 #define PVRSRV_BRIDGE_PVRTL_TLCLOSESTREAM			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+1
 #define PVRSRV_BRIDGE_PVRTL_TLACQUIREDATA			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+2
 #define PVRSRV_BRIDGE_PVRTL_TLRELEASEDATA			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+3
-#define PVRSRV_BRIDGE_PVRTL_CMD_LAST			(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PVRTL_TLDISCOVERSTREAMS			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+4
+#define PVRSRV_BRIDGE_PVRTL_TLRESERVESTREAM			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+5
+#define PVRSRV_BRIDGE_PVRTL_TLCOMMITSTREAM			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+6
+#define PVRSRV_BRIDGE_PVRTL_TLWRITEDATA			PVRSRV_BRIDGE_PVRTL_CMD_FIRST+7
+#define PVRSRV_BRIDGE_PVRTL_CMD_LAST			(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+7)
 
 
 /*******************************************
@@ -67,7 +73,7 @@
 /* Bridge in structure for TLOpenStream */
 typedef struct PVRSRV_BRIDGE_IN_TLOPENSTREAM_TAG
 {
-	IMG_CHAR * puiName;
+	const IMG_CHAR * puiName;
 	IMG_UINT32 ui32Mode;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_TLOPENSTREAM;
 
@@ -135,4 +141,84 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLRELEASEDATA;
 
 
+/*******************************************
+            TLDiscoverStreams          
+ *******************************************/
+
+/* Bridge in structure for TLDiscoverStreams */
+typedef struct PVRSRV_BRIDGE_IN_TLDISCOVERSTREAMS_TAG
+{
+	const IMG_CHAR * puiNamePattern;
+	IMG_UINT32 ui32Max;
+	/* Output pointer pui32Streams is also an implied input */
+	IMG_UINT32 * pui32Streams;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLDISCOVERSTREAMS;
+
+/* Bridge out structure for TLDiscoverStreams */
+typedef struct PVRSRV_BRIDGE_OUT_TLDISCOVERSTREAMS_TAG
+{
+	IMG_UINT32 * pui32Streams;
+	IMG_UINT32 ui32NumFound;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLDISCOVERSTREAMS;
+
+
+/*******************************************
+            TLReserveStream          
+ *******************************************/
+
+/* Bridge in structure for TLReserveStream */
+typedef struct PVRSRV_BRIDGE_IN_TLRESERVESTREAM_TAG
+{
+	IMG_HANDLE hSD;
+	IMG_UINT32 ui32Size;
+	IMG_UINT32 ui32SizeMin;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLRESERVESTREAM;
+
+/* Bridge out structure for TLReserveStream */
+typedef struct PVRSRV_BRIDGE_OUT_TLRESERVESTREAM_TAG
+{
+	IMG_UINT32 ui32BufferOffset;
+	IMG_UINT32 ui32Available;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLRESERVESTREAM;
+
+
+/*******************************************
+            TLCommitStream          
+ *******************************************/
+
+/* Bridge in structure for TLCommitStream */
+typedef struct PVRSRV_BRIDGE_IN_TLCOMMITSTREAM_TAG
+{
+	IMG_HANDLE hSD;
+	IMG_UINT32 ui32ReqSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLCOMMITSTREAM;
+
+/* Bridge out structure for TLCommitStream */
+typedef struct PVRSRV_BRIDGE_OUT_TLCOMMITSTREAM_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLCOMMITSTREAM;
+
+
+/*******************************************
+            TLWriteData          
+ *******************************************/
+
+/* Bridge in structure for TLWriteData */
+typedef struct PVRSRV_BRIDGE_IN_TLWRITEDATA_TAG
+{
+	IMG_HANDLE hSD;
+	IMG_UINT32 ui32Size;
+	IMG_BYTE * psData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLWRITEDATA;
+
+/* Bridge out structure for TLWriteData */
+typedef struct PVRSRV_BRIDGE_OUT_TLWRITEDATA_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLWRITEDATA;
+
+
 #endif /* COMMON_PVRTL_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c
index 567e11c..f634b6b 100644
--- a/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -78,33 +80,66 @@
 	TL_STREAM_DESC * psSDInt = NULL;
 	PMR * psTLPMRInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) +
+			0;
+
+
 
 
 	psTLOpenStreamOUT->hSD = NULL;
 
-	
+	if (ui32BufferSize != 0)
 	{
-		uiNameInt = OSAllocMemNoStats(PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR));
-		if (!uiNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psTLOpenStreamIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psTLOpenStreamOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto TLOpenStream_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psTLOpenStreamIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psTLOpenStreamOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto TLOpenStream_exit;
+			}
 		}
 	}
 
+	
+	{
+		uiNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psTLOpenStreamIN->puiName, PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiNameInt, psTLOpenStreamIN->puiName,
-				PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR) > 0)
 			{
-				psTLOpenStreamOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiNameInt, psTLOpenStreamIN->puiName, PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psTLOpenStreamOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto TLOpenStream_exit;
+					goto TLOpenStream_exit;
+				}
 			}
 
 
-
 	psTLOpenStreamOUT->eError =
 		TLServerOpenStreamKM(
 					uiNameInt,
@@ -117,8 +152,15 @@
 		goto TLOpenStream_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psTLOpenStreamOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psTLOpenStreamOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psTLOpenStreamOUT->hSD,
 							(void *) psSDInt,
 							PVRSRV_HANDLE_TYPE_PVR_TL_SD,
@@ -126,34 +168,56 @@
 							,(PFN_HANDLE_RELEASE)&TLServerCloseStreamKM);
 	if (psTLOpenStreamOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto TLOpenStream_exit;
 	}
 
 
-	psTLOpenStreamOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+
+
+
+
+	psTLOpenStreamOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
 							&psTLOpenStreamOUT->hTLPMR,
 							(void *) psTLPMRInt,
 							PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
-							PVRSRV_HANDLE_ALLOC_FLAG_NONE
+							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
 							,psTLOpenStreamOUT->hSD);
 	if (psTLOpenStreamOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto TLOpenStream_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 TLOpenStream_exit:
+
+
+
 	if (psTLOpenStreamOUT->eError != PVRSRV_OK)
 	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
 		if (psTLOpenStreamOUT->hSD)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 						(IMG_HANDLE) psTLOpenStreamOUT->hSD,
 						PVRSRV_HANDLE_TYPE_PVR_TL_SD);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgeTLOpenStream: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 			/* Avoid freeing/destroying/releasing the resource a second time below */
@@ -161,18 +225,29 @@
 		}
 
 
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
 		if (psSDInt)
 		{
 			TLServerCloseStreamKM(psSDInt);
 		}
 	}
 
-	if (uiNameInt)
-		OSFreeMemNoStats(uiNameInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeTLCloseStream(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_TLCLOSESTREAM *psTLCloseStreamIN,
@@ -188,29 +263,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psTLCloseStreamOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psTLCloseStreamIN->hSD,
 					PVRSRV_HANDLE_TYPE_PVR_TL_SD);
-	if ((psTLCloseStreamOUT->eError != PVRSRV_OK) && (psTLCloseStreamOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psTLCloseStreamOUT->eError != PVRSRV_OK) &&
+	    (psTLCloseStreamOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeTLCloseStream: %s",
+		        PVRSRVGetErrorStringKM(psTLCloseStreamOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto TLCloseStream_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 TLCloseStream_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeTLAcquireData(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_TLACQUIREDATA *psTLAcquireDataIN,
 					  PVRSRV_BRIDGE_OUT_TLACQUIREDATA *psTLAcquireDataOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSD = psTLAcquireDataIN->hSD;
 	TL_STREAM_DESC * psSDInt = NULL;
 
 
@@ -219,19 +314,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psTLAcquireDataOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSDInt,
-											psTLAcquireDataIN->hSD,
-											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+											IMG_TRUE);
 					if(psTLAcquireDataOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto TLAcquireData_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psTLAcquireDataOUT->eError =
 		TLServerAcquireDataKM(
@@ -244,15 +349,38 @@
 
 TLAcquireData_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSDInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeTLReleaseData(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_TLRELEASEDATA *psTLReleaseDataIN,
 					  PVRSRV_BRIDGE_OUT_TLRELEASEDATA *psTLReleaseDataOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSD = psTLReleaseDataIN->hSD;
 	TL_STREAM_DESC * psSDInt = NULL;
 
 
@@ -261,19 +389,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psTLReleaseDataOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSDInt,
-											psTLReleaseDataIN->hSD,
-											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+											IMG_TRUE);
 					if(psTLReleaseDataOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto TLReleaseData_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psTLReleaseDataOUT->eError =
 		TLServerReleaseDataKM(
@@ -286,10 +424,438 @@
 
 TLReleaseData_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSDInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
 
+static IMG_INT
+PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_TLDISCOVERSTREAMS *psTLDiscoverStreamsIN,
+					  PVRSRV_BRIDGE_OUT_TLDISCOVERSTREAMS *psTLDiscoverStreamsOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_CHAR *uiNamePatternInt = NULL;
+	IMG_UINT32 *pui32StreamsInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) +
+			(psTLDiscoverStreamsIN->ui32Max * sizeof(IMG_UINT32)) +
+			0;
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	psTLDiscoverStreamsOUT->pui32Streams = psTLDiscoverStreamsIN->pui32Streams;
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psTLDiscoverStreamsIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psTLDiscoverStreamsIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psTLDiscoverStreamsOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto TLDiscoverStreams_exit;
+			}
+		}
+	}
+
+	
+	{
+		uiNamePatternInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiNamePatternInt, psTLDiscoverStreamsIN->puiNamePattern, PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psTLDiscoverStreamsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto TLDiscoverStreams_exit;
+				}
+			}
+	if (psTLDiscoverStreamsIN->ui32Max != 0)
+	{
+		pui32StreamsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psTLDiscoverStreamsIN->ui32Max * sizeof(IMG_UINT32);
+	}
+
+
+
+	psTLDiscoverStreamsOUT->eError =
+		TLServerDiscoverStreamsKM(
+					uiNamePatternInt,
+					psTLDiscoverStreamsIN->ui32Max,
+					pui32StreamsInt,
+					&psTLDiscoverStreamsOUT->ui32NumFound);
+
+
+
+	if ((psTLDiscoverStreamsIN->ui32Max * sizeof(IMG_UINT32)) > 0)
+	{
+		if ( OSCopyToUser(NULL, psTLDiscoverStreamsOUT->pui32Streams, pui32StreamsInt,
+			(psTLDiscoverStreamsIN->ui32Max * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psTLDiscoverStreamsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+			goto TLDiscoverStreams_exit;
+		}
+	}
+
+
+TLDiscoverStreams_exit:
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeTLReserveStream(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_TLRESERVESTREAM *psTLReserveStreamIN,
+					  PVRSRV_BRIDGE_OUT_TLRESERVESTREAM *psTLReserveStreamOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hSD = psTLReserveStreamIN->hSD;
+	TL_STREAM_DESC * psSDInt = NULL;
+
+
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psTLReserveStreamOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psSDInt,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+											IMG_TRUE);
+					if(psTLReserveStreamOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto TLReserveStream_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psTLReserveStreamOUT->eError =
+		TLServerReserveStreamKM(
+					psSDInt,
+					&psTLReserveStreamOUT->ui32BufferOffset,
+					psTLReserveStreamIN->ui32Size,
+					psTLReserveStreamIN->ui32SizeMin,
+					&psTLReserveStreamOUT->ui32Available);
+
+
+
+
+TLReserveStream_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSDInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeTLCommitStream(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_TLCOMMITSTREAM *psTLCommitStreamIN,
+					  PVRSRV_BRIDGE_OUT_TLCOMMITSTREAM *psTLCommitStreamOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hSD = psTLCommitStreamIN->hSD;
+	TL_STREAM_DESC * psSDInt = NULL;
+
+
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psTLCommitStreamOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psSDInt,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+											IMG_TRUE);
+					if(psTLCommitStreamOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto TLCommitStream_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psTLCommitStreamOUT->eError =
+		TLServerCommitStreamKM(
+					psSDInt,
+					psTLCommitStreamIN->ui32ReqSize);
+
+
+
+
+TLCommitStream_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSDInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeTLWriteData(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_TLWRITEDATA *psTLWriteDataIN,
+					  PVRSRV_BRIDGE_OUT_TLWRITEDATA *psTLWriteDataOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hSD = psTLWriteDataIN->hSD;
+	TL_STREAM_DESC * psSDInt = NULL;
+	IMG_BYTE *psDataInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psTLWriteDataIN->ui32Size * sizeof(IMG_BYTE)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psTLWriteDataIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psTLWriteDataIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psTLWriteDataOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto TLWriteData_exit;
+			}
+		}
+	}
+
+	if (psTLWriteDataIN->ui32Size != 0)
+	{
+		psDataInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psTLWriteDataIN->ui32Size * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psTLWriteDataIN->ui32Size * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psDataInt, psTLWriteDataIN->psData, psTLWriteDataIN->ui32Size * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psTLWriteDataOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto TLWriteData_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psTLWriteDataOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psSDInt,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+											IMG_TRUE);
+					if(psTLWriteDataOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto TLWriteData_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psTLWriteDataOUT->eError =
+		TLServerWriteDataKM(
+					psSDInt,
+					psTLWriteDataIN->ui32Size,
+					psDataInt);
+
+
+
+
+TLWriteData_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSDInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSD,
+											PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+
 
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
@@ -318,6 +884,18 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLRELEASEDATA, PVRSRVBridgeTLReleaseData,
 					NULL, bUseLock);
 
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLDISCOVERSTREAMS, PVRSRVBridgeTLDiscoverStreams,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLRESERVESTREAM, PVRSRVBridgeTLReserveStream,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLCOMMITSTREAM, PVRSRVBridgeTLCommitStream,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLWRITEDATA, PVRSRVBridgeTLWriteData,
+					NULL, bUseLock);
+
 
 	return PVRSRV_OK;
 }
@@ -329,4 +907,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/regconfig_bridge/common_regconfig_bridge.h b/drivers/staging/imgtec/rogue/generated/regconfig_bridge/common_regconfig_bridge.h
index 64a147c..ebd98e8 100644
--- a/drivers/staging/imgtec/rogue/generated/regconfig_bridge/common_regconfig_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/regconfig_bridge/common_regconfig_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for regconfig
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for regconfig
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for regconfig
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_REGCONFIG_BRIDGE_H
 #define COMMON_REGCONFIG_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/regconfig_bridge/server_regconfig_bridge.c b/drivers/staging/imgtec/rogue/generated/regconfig_bridge/server_regconfig_bridge.c
index 0e7aff2..2671e78 100644
--- a/drivers/staging/imgtec/rogue/generated/regconfig_bridge/server_regconfig_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/regconfig_bridge/server_regconfig_bridge.c
@@ -63,6 +63,9 @@
 
 
 
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
+
+
 
 /* ***************************************************************************
  * Server-side bridge entry points
@@ -81,6 +84,7 @@
 
 
 
+
 	psRGXSetRegConfigTypeOUT->eError =
 		PVRSRVRGXSetRegConfigTypeKM(psConnection, OSGetDevData(psConnection),
 					psRGXSetRegConfigTypeIN->ui8RegPowerIsland);
@@ -89,9 +93,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXAddRegconfig(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXADDREGCONFIG *psRGXAddRegconfigIN,
@@ -105,6 +113,7 @@
 
 
 
+
 	psRGXAddRegconfigOUT->eError =
 		PVRSRVRGXAddRegConfigKM(psConnection, OSGetDevData(psConnection),
 					psRGXAddRegconfigIN->ui32RegAddr,
@@ -115,9 +124,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXClearRegConfig(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCLEARREGCONFIG *psRGXClearRegConfigIN,
@@ -125,9 +138,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psRGXClearRegConfigIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psRGXClearRegConfigIN);
+
 
 
 
@@ -140,9 +154,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXEnableRegConfig(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXENABLEREGCONFIG *psRGXEnableRegConfigIN,
@@ -150,9 +168,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psRGXEnableRegConfigIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psRGXEnableRegConfigIN);
+
 
 
 
@@ -165,9 +184,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDisableRegConfig(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDISABLEREGCONFIG *psRGXDisableRegConfigIN,
@@ -175,9 +198,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psRGXDisableRegConfigIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psRGXDisableRegConfigIN);
+
 
 
 
@@ -190,17 +214,23 @@
 
 
 
+
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
 
 static IMG_BOOL bUseLock = IMG_TRUE;
+#endif /* EXCLUDE_REGCONFIG_BRIDGE */
 
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
 PVRSRV_ERROR InitREGCONFIGBridge(void);
 PVRSRV_ERROR DeinitREGCONFIGBridge(void);
 
@@ -236,4 +266,14 @@
 {
 	return PVRSRV_OK;
 }
+#else /* EXCLUDE_REGCONFIG_BRIDGE */
+/* This bridge is conditional on EXCLUDE_REGCONFIG_BRIDGE - when defined,
+ * do not populate the dispatch table with its functions
+ */
+#define InitREGCONFIGBridge() \
+	PVRSRV_OK
 
+#define DeinitREGCONFIGBridge() \
+	PVRSRV_OK
+
+#endif /* EXCLUDE_REGCONFIG_BRIDGE */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h
index dd86e79..a18075e 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxcmp
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxcmp
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxcmp
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,12 +45,13 @@
 #ifndef COMMON_RGXCMP_BRIDGE_H
 #define COMMON_RGXCMP_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "rgx_bridge.h"
-#include "sync_external.h"
-#include "rgx_fwif_shared.h"
+#include <powervr/sync_external.h>
 
 
 #define PVRSRV_BRIDGE_RGXCMP_CMD_FIRST			0
@@ -60,7 +61,8 @@
 #define PVRSRV_BRIDGE_RGXCMP_RGXFLUSHCOMPUTEDATA			PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+3
 #define PVRSRV_BRIDGE_RGXCMP_RGXSETCOMPUTECONTEXTPRIORITY			PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+4
 #define PVRSRV_BRIDGE_RGXCMP_RGXGETLASTCOMPUTECONTEXTRESETREASON			PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+5
-#define PVRSRV_BRIDGE_RGXCMP_CMD_LAST			(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_RGXCMP_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE			PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+6
+#define PVRSRV_BRIDGE_RGXCMP_CMD_LAST			(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+6)
 
 
 /*******************************************
@@ -75,6 +77,7 @@
 	IMG_UINT32 ui32FrameworkCmdize;
 	IMG_BYTE * psFrameworkCmd;
 	IMG_HANDLE hPrivData;
+	IMG_DEV_VIRTADDR sResumeSignalAddr;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATECOMPUTECONTEXT;
 
 /* Bridge out structure for RGXCreateComputeContext */
@@ -110,6 +113,7 @@
 typedef struct PVRSRV_BRIDGE_IN_RGXKICKCDM_TAG
 {
 	IMG_HANDLE hComputeContext;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
 	IMG_UINT32 ui32ClientFenceCount;
 	IMG_HANDLE * phClientFenceUFOSyncPrimBlock;
 	IMG_UINT32 * pui32ClientFenceOffset;
@@ -121,16 +125,19 @@
 	IMG_UINT32 ui32ServerSyncCount;
 	IMG_UINT32 * pui32ServerSyncFlags;
 	IMG_HANDLE * phServerSyncs;
+	IMG_INT32 i32CheckFenceFd;
+	IMG_INT32 i32UpdateTimelineFd;
+	IMG_CHAR * puiUpdateFenceName;
 	IMG_UINT32 ui32CmdSize;
 	IMG_BYTE * psDMCmd;
-	IMG_BOOL bbPDumpContinuous;
+	IMG_UINT32 ui32PDumpFlags;
 	IMG_UINT32 ui32ExtJobRef;
-	IMG_UINT32 ui32IntJobRef;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKCDM;
 
 /* Bridge out structure for RGXKickCDM */
 typedef struct PVRSRV_BRIDGE_OUT_RGXKICKCDM_TAG
 {
+	IMG_INT32 i32UpdateFenceFd;
 	PVRSRV_ERROR eError;
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKCDM;
 
@@ -189,4 +196,21 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXGETLASTCOMPUTECONTEXTRESETREASON;
 
 
+/*******************************************
+            RGXNotifyComputeWriteOffsetUpdate          
+ *******************************************/
+
+/* Bridge in structure for RGXNotifyComputeWriteOffsetUpdate */
+typedef struct PVRSRV_BRIDGE_IN_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE_TAG
+{
+	IMG_HANDLE hComputeContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE;
+
+/* Bridge out structure for RGXNotifyComputeWriteOffsetUpdate */
+typedef struct PVRSRV_BRIDGE_OUT_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE;
+
+
 #endif /* COMMON_RGXCMP_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c
index 43b0350..c531498 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c
@@ -62,6 +62,9 @@
 #include <linux/slab.h>
 
 
+#include "rgx_bvnc_defs_km.h"
+
+
 
 
 /* ***************************************************************************
@@ -75,50 +78,103 @@
 					 CONNECTION_DATA *psConnection)
 {
 	IMG_BYTE *psFrameworkCmdInt = NULL;
+	IMG_HANDLE hPrivData = psRGXCreateComputeContextIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 	RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
 
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) +
+			0;
 
-
-	if (psRGXCreateComputeContextIN->ui32FrameworkCmdize != 0)
 	{
-		psFrameworkCmdInt = OSAllocMemNoStats(psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE));
-		if (!psFrameworkCmdInt)
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
 		{
-			psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
+			psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
 			goto RGXCreateComputeContext_exit;
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXCreateComputeContextIN->psFrameworkCmd, psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateComputeContextIN->psFrameworkCmd,
-				psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
-			{
-				psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXCreateComputeContextIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXCreateComputeContextIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 				goto RGXCreateComputeContext_exit;
 			}
+		}
+	}
 
-	PMRLock();
+	if (psRGXCreateComputeContextIN->ui32FrameworkCmdize != 0)
+	{
+		psFrameworkCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateComputeContextIN->psFrameworkCmd, psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXCreateComputeContext_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXCreateComputeContextOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXCreateComputeContextIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateComputeContext_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateComputeContextOUT->eError =
 		PVRSRVRGXCreateComputeContextKM(psConnection, OSGetDevData(psConnection),
@@ -127,17 +183,23 @@
 					psRGXCreateComputeContextIN->ui32FrameworkCmdize,
 					psFrameworkCmdInt,
 					hPrivDataInt,
+					psRGXCreateComputeContextIN->sResumeSignalAddr,
 					&psComputeContextInt);
 	/* Exit early if bridged call fails */
 	if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateComputeContext_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateComputeContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateComputeContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateComputeContextOUT->hComputeContext,
 							(void *) psComputeContextInt,
 							PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
@@ -145,13 +207,37 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVRGXDestroyComputeContextKM);
 	if (psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateComputeContext_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateComputeContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
 	{
 		if (psComputeContextInt)
@@ -160,12 +246,21 @@
 		}
 	}
 
-	if (psFrameworkCmdInt)
-		OSFreeMemNoStats(psFrameworkCmdInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyComputeContext(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYCOMPUTECONTEXT *psRGXDestroyComputeContextIN,
@@ -174,39 +269,68 @@
 {
 
 
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
+		{
+			psRGXDestroyComputeContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXDestroyComputeContext_exit;
+		}
+	}
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyComputeContextOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyComputeContextIN->hComputeContext,
 					PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
-	if ((psRGXDestroyComputeContextOUT->eError != PVRSRV_OK) && (psRGXDestroyComputeContextOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyComputeContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyComputeContextOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyComputeContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyComputeContextOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyComputeContext_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyComputeContext_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXKickCDM(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXKICKCDM *psRGXKickCDMIN,
 					  PVRSRV_BRIDGE_OUT_RGXKICKCDM *psRGXKickCDMOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hComputeContext = psRGXKickCDMIN->hComputeContext;
 	RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = NULL;
 	SYNC_PRIMITIVE_BLOCK * *psClientFenceUFOSyncPrimBlockInt = NULL;
 	IMG_HANDLE *hClientFenceUFOSyncPrimBlockInt2 = NULL;
@@ -219,235 +343,267 @@
 	IMG_UINT32 *ui32ServerSyncFlagsInt = NULL;
 	SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = NULL;
 	IMG_HANDLE *hServerSyncsInt2 = NULL;
+	IMG_CHAR *uiUpdateFenceNameInt = NULL;
 	IMG_BYTE *psDMCmdInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) +
+			(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) +
+			(32 * sizeof(IMG_CHAR)) +
+			(psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE)) +
+			0;
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
+		{
+			psRGXKickCDMOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXKickCDM_exit;
+		}
+	}
 
 
 
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXKickCDMIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXKickCDMIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXKickCDM_exit;
+			}
+		}
+	}
+
 	if (psRGXKickCDMIN->ui32ClientFenceCount != 0)
 	{
-		psClientFenceUFOSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClientFenceUFOSyncPrimBlockInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
-		hClientFenceUFOSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE));
-		if (!hClientFenceUFOSyncPrimBlockInt2)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		psClientFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->phClientFenceUFOSyncPrimBlock, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClientFenceUFOSyncPrimBlockInt2, psRGXKickCDMIN->phClientFenceUFOSyncPrimBlock,
-				psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hClientFenceUFOSyncPrimBlockInt2, psRGXKickCDMIN->phClientFenceUFOSyncPrimBlock, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ClientFenceCount != 0)
 	{
-		ui32ClientFenceOffsetInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
-		if (!ui32ClientFenceOffsetInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		ui32ClientFenceOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->pui32ClientFenceOffset, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientFenceOffsetInt, psRGXKickCDMIN->pui32ClientFenceOffset,
-				psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientFenceOffsetInt, psRGXKickCDMIN->pui32ClientFenceOffset, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ClientFenceCount != 0)
 	{
-		ui32ClientFenceValueInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
-		if (!ui32ClientFenceValueInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		ui32ClientFenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->pui32ClientFenceValue, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickCDMIN->pui32ClientFenceValue,
-				psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickCDMIN->pui32ClientFenceValue, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ClientUpdateCount != 0)
 	{
-		psClientUpdateUFOSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClientUpdateUFOSyncPrimBlockInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
-		hClientUpdateUFOSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE));
-		if (!hClientUpdateUFOSyncPrimBlockInt2)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		psClientUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->phClientUpdateUFOSyncPrimBlock, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClientUpdateUFOSyncPrimBlockInt2, psRGXKickCDMIN->phClientUpdateUFOSyncPrimBlock,
-				psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hClientUpdateUFOSyncPrimBlockInt2, psRGXKickCDMIN->phClientUpdateUFOSyncPrimBlock, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ClientUpdateCount != 0)
 	{
-		ui32ClientUpdateOffsetInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32ClientUpdateOffsetInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		ui32ClientUpdateOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->pui32ClientUpdateOffset, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientUpdateOffsetInt, psRGXKickCDMIN->pui32ClientUpdateOffset,
-				psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateOffsetInt, psRGXKickCDMIN->pui32ClientUpdateOffset, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ClientUpdateCount != 0)
 	{
-		ui32ClientUpdateValueInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32ClientUpdateValueInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		ui32ClientUpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->pui32ClientUpdateValue, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickCDMIN->pui32ClientUpdateValue,
-				psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickCDMIN->pui32ClientUpdateValue, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ServerSyncCount != 0)
 	{
-		ui32ServerSyncFlagsInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
-		if (!ui32ServerSyncFlagsInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		ui32ServerSyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->pui32ServerSyncFlags, psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickCDMIN->pui32ServerSyncFlags,
-				psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickCDMIN->pui32ServerSyncFlags, psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32ServerSyncCount != 0)
 	{
-		psServerSyncsInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psServerSyncsInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
-		hServerSyncsInt2 = OSAllocMemNoStats(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
-		if (!hServerSyncsInt2)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		psServerSyncsInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerSyncsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->phServerSyncs, psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickCDMIN->phServerSyncs,
-				psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickCDMIN->phServerSyncs, psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
+			}
+	
+	{
+		uiUpdateFenceNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += 32 * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (32 * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXKickCDMIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickCDM_exit;
+				}
 			}
 	if (psRGXKickCDMIN->ui32CmdSize != 0)
 	{
-		psDMCmdInt = OSAllocMemNoStats(psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE));
-		if (!psDMCmdInt)
-		{
-			psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickCDM_exit;
-		}
+		psDMCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickCDMIN->psDMCmd, psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, psDMCmdInt, psRGXKickCDMIN->psDMCmd,
-				psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+			if (psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE) > 0)
 			{
-				psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psDMCmdInt, psRGXKickCDMIN->psDMCmd, psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickCDM_exit;
+					goto RGXKickCDM_exit;
+				}
 			}
 
-#if defined(PDUMP)
-	PMRLock();
-#endif
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXKickCDMOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psComputeContextInt,
-											psRGXKickCDMIN->hComputeContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+											IMG_TRUE);
 					if(psRGXKickCDMOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto RGXKickCDM_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -456,22 +612,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickCDMOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psClientFenceUFOSyncPrimBlockInt[i],
 											hClientFenceUFOSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickCDMOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto RGXKickCDM_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -480,22 +638,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickCDMOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psClientUpdateUFOSyncPrimBlockInt[i],
 											hClientUpdateUFOSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickCDMOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto RGXKickCDM_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -504,25 +664,26 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickCDMOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerSyncsInt[i],
 											hServerSyncsInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psRGXKickCDMOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto RGXKickCDM_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXKickCDMOUT->eError =
 		PVRSRVRGXKickCDMKM(
 					psComputeContextInt,
+					psRGXKickCDMIN->ui32ClientCacheOpSeqNum,
 					psRGXKickCDMIN->ui32ClientFenceCount,
 					psClientFenceUFOSyncPrimBlockInt,
 					ui32ClientFenceOffsetInt,
@@ -534,105 +695,238 @@
 					psRGXKickCDMIN->ui32ServerSyncCount,
 					ui32ServerSyncFlagsInt,
 					psServerSyncsInt,
+					psRGXKickCDMIN->i32CheckFenceFd,
+					psRGXKickCDMIN->i32UpdateTimelineFd,
+					&psRGXKickCDMOUT->i32UpdateFenceFd,
+					uiUpdateFenceNameInt,
 					psRGXKickCDMIN->ui32CmdSize,
 					psDMCmdInt,
-					psRGXKickCDMIN->bbPDumpContinuous,
-					psRGXKickCDMIN->ui32ExtJobRef,
-					psRGXKickCDMIN->ui32IntJobRef);
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
+					psRGXKickCDMIN->ui32PDumpFlags,
+					psRGXKickCDMIN->ui32ExtJobRef);
 
 
 
 
 RGXKickCDM_exit:
-	if (psClientFenceUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psClientFenceUFOSyncPrimBlockInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psComputeContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+						}
+				}
+
+
+
+
+
+
 	if (hClientFenceUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClientFenceUFOSyncPrimBlockInt2);
-	if (ui32ClientFenceOffsetInt)
-		OSFreeMemNoStats(ui32ClientFenceOffsetInt);
-	if (ui32ClientFenceValueInt)
-		OSFreeMemNoStats(ui32ClientFenceValueInt);
-	if (psClientUpdateUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psClientUpdateUFOSyncPrimBlockInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickCDMIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientFenceUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hClientUpdateUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClientUpdateUFOSyncPrimBlockInt2);
-	if (ui32ClientUpdateOffsetInt)
-		OSFreeMemNoStats(ui32ClientUpdateOffsetInt);
-	if (ui32ClientUpdateValueInt)
-		OSFreeMemNoStats(ui32ClientUpdateValueInt);
-	if (ui32ServerSyncFlagsInt)
-		OSFreeMemNoStats(ui32ServerSyncFlagsInt);
-	if (psServerSyncsInt)
-		OSFreeMemNoStats(psServerSyncsInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickCDMIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientUpdateUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hServerSyncsInt2)
-		OSFreeMemNoStats(hServerSyncsInt2);
-	if (psDMCmdInt)
-		OSFreeMemNoStats(psDMCmdInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickCDMIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXFlushComputeData(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXFLUSHCOMPUTEDATA *psRGXFlushComputeDataIN,
 					  PVRSRV_BRIDGE_OUT_RGXFLUSHCOMPUTEDATA *psRGXFlushComputeDataOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hComputeContext = psRGXFlushComputeDataIN->hComputeContext;
 	RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = NULL;
 
 
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
+		{
+			psRGXFlushComputeDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXFlushComputeData_exit;
+		}
+	}
 
 
 
-#if defined(PDUMP)
-	PMRLock();
-#endif
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXFlushComputeDataOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psComputeContextInt,
-											psRGXFlushComputeDataIN->hComputeContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+											IMG_TRUE);
 					if(psRGXFlushComputeDataOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto RGXFlushComputeData_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXFlushComputeDataOUT->eError =
 		PVRSRVRGXFlushComputeDataKM(
 					psComputeContextInt);
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
 
 
 
 
 RGXFlushComputeData_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psComputeContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXSetComputeContextPriority(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXSETCOMPUTECONTEXTPRIORITY *psRGXSetComputeContextPriorityIN,
 					  PVRSRV_BRIDGE_OUT_RGXSETCOMPUTECONTEXTPRIORITY *psRGXSetComputeContextPriorityOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hComputeContext = psRGXSetComputeContextPriorityIN->hComputeContext;
 	RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = NULL;
 
 
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
+		{
+			psRGXSetComputeContextPriorityOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXSetComputeContextPriority_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
 
 
 
@@ -641,16 +935,19 @@
 				{
 					/* Look up the address from the handle */
 					psRGXSetComputeContextPriorityOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psComputeContextInt,
-											psRGXSetComputeContextPriorityIN->hComputeContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+											IMG_TRUE);
 					if(psRGXSetComputeContextPriorityOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXSetComputeContextPriority_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXSetComputeContextPriorityOUT->eError =
 		PVRSRVRGXSetComputeContextPriorityKM(psConnection, OSGetDevData(psConnection),
@@ -662,18 +959,60 @@
 
 RGXSetComputeContextPriority_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psComputeContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXGetLastComputeContextResetReason(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXGETLASTCOMPUTECONTEXTRESETREASON *psRGXGetLastComputeContextResetReasonIN,
 					  PVRSRV_BRIDGE_OUT_RGXGETLASTCOMPUTECONTEXTRESETREASON *psRGXGetLastComputeContextResetReasonOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hComputeContext = psRGXGetLastComputeContextResetReasonIN->hComputeContext;
 	RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = NULL;
 
 
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
+		{
+			psRGXGetLastComputeContextResetReasonOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXGetLastComputeContextResetReason_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
 
 
 
@@ -682,16 +1021,19 @@
 				{
 					/* Look up the address from the handle */
 					psRGXGetLastComputeContextResetReasonOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psComputeContextInt,
-											psRGXGetLastComputeContextResetReasonIN->hComputeContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+											IMG_TRUE);
 					if(psRGXGetLastComputeContextResetReasonOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXGetLastComputeContextResetReason_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXGetLastComputeContextResetReasonOUT->eError =
 		PVRSRVRGXGetLastComputeContextResetReasonKM(
@@ -704,10 +1046,117 @@
 
 RGXGetLastComputeContextResetReason_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psComputeContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
 
+static IMG_INT
+PVRSRVBridgeRGXNotifyComputeWriteOffsetUpdate(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE *psRGXNotifyComputeWriteOffsetUpdateIN,
+					  PVRSRV_BRIDGE_OUT_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE *psRGXNotifyComputeWriteOffsetUpdateOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hComputeContext = psRGXNotifyComputeWriteOffsetUpdateIN->hComputeContext;
+	RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_COMPUTE_BIT_MASK))
+		{
+			psRGXNotifyComputeWriteOffsetUpdateOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXNotifyComputeWriteOffsetUpdate_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXNotifyComputeWriteOffsetUpdateOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psComputeContextInt,
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+											IMG_TRUE);
+					if(psRGXNotifyComputeWriteOffsetUpdateOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXNotifyComputeWriteOffsetUpdate_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXNotifyComputeWriteOffsetUpdateOUT->eError =
+		PVRSRVRGXNotifyComputeWriteOffsetUpdateKM(
+					psComputeContextInt);
+
+
+
+
+RGXNotifyComputeWriteOffsetUpdate_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psComputeContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hComputeContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+
 
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
@@ -742,6 +1191,9 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP, PVRSRV_BRIDGE_RGXCMP_RGXGETLASTCOMPUTECONTEXTRESETREASON, PVRSRVBridgeRGXGetLastComputeContextResetReason,
 					NULL, bUseLock);
 
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP, PVRSRV_BRIDGE_RGXCMP_RGXNOTIFYCOMPUTEWRITEOFFSETUPDATE, PVRSRVBridgeRGXNotifyComputeWriteOffsetUpdate,
+					NULL, bUseLock);
+
 
 	return PVRSRV_OK;
 }
@@ -753,4 +1205,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h
index f8ec275..2b96a84 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxhwperf
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxhwperf
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxhwperf
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_RGXHWPERF_BRIDGE_H
 #define COMMON_RGXHWPERF_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c
index fc74f10..f8becba 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -81,6 +83,7 @@
 
 
 
+
 	psRGXCtrlHWPerfOUT->eError =
 		PVRSRVRGXCtrlHWPerfKM(psConnection, OSGetDevData(psConnection),
 					psRGXCtrlHWPerfIN->ui32StreamId,
@@ -91,9 +94,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXConfigEnableHWPerfCounters(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS *psRGXConfigEnableHWPerfCountersIN,
@@ -102,32 +109,65 @@
 {
 	RGX_HWPERF_CONFIG_CNTBLK *psBlockConfigsInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK)) +
+			0;
 
 
 
-	if (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		psBlockConfigsInt = OSAllocMemNoStats(psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK));
-		if (!psBlockConfigsInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXConfigEnableHWPerfCountersIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXConfigEnableHWPerfCounters_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXConfigEnableHWPerfCountersIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXConfigEnableHWPerfCounters_exit;
+			}
 		}
 	}
 
+	if (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen != 0)
+	{
+		psBlockConfigsInt = (RGX_HWPERF_CONFIG_CNTBLK*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXConfigEnableHWPerfCountersIN->psBlockConfigs, psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK))
-				|| (OSCopyFromUser(NULL, psBlockConfigsInt, psRGXConfigEnableHWPerfCountersIN->psBlockConfigs,
-				psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK)) != PVRSRV_OK) )
+			if (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK) > 0)
 			{
-				psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psBlockConfigsInt, psRGXConfigEnableHWPerfCountersIN->psBlockConfigs, psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK)) != PVRSRV_OK )
+				{
+					psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXConfigEnableHWPerfCounters_exit;
+					goto RGXConfigEnableHWPerfCounters_exit;
+				}
 			}
 
 
-
 	psRGXConfigEnableHWPerfCountersOUT->eError =
 		PVRSRVRGXConfigEnableHWPerfCountersKM(psConnection, OSGetDevData(psConnection),
 					psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen,
@@ -137,12 +177,24 @@
 
 
 RGXConfigEnableHWPerfCounters_exit:
-	if (psBlockConfigsInt)
-		OSFreeMemNoStats(psBlockConfigsInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXCtrlHWPerfCounters(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCTRLHWPERFCOUNTERS *psRGXCtrlHWPerfCountersIN,
@@ -151,32 +203,65 @@
 {
 	IMG_UINT16 *ui16BlockIDsInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16)) +
+			0;
 
 
 
-	if (psRGXCtrlHWPerfCountersIN->ui32ArrayLen != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		ui16BlockIDsInt = OSAllocMemNoStats(psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16));
-		if (!ui16BlockIDsInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXCtrlHWPerfCountersIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRGXCtrlHWPerfCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXCtrlHWPerfCounters_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXCtrlHWPerfCountersIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXCtrlHWPerfCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXCtrlHWPerfCounters_exit;
+			}
 		}
 	}
 
+	if (psRGXCtrlHWPerfCountersIN->ui32ArrayLen != 0)
+	{
+		ui16BlockIDsInt = (IMG_UINT16*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXCtrlHWPerfCountersIN->pui16BlockIDs, psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16))
-				|| (OSCopyFromUser(NULL, ui16BlockIDsInt, psRGXCtrlHWPerfCountersIN->pui16BlockIDs,
-				psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16)) != PVRSRV_OK) )
+			if (psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16) > 0)
 			{
-				psRGXCtrlHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui16BlockIDsInt, psRGXCtrlHWPerfCountersIN->pui16BlockIDs, psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT16)) != PVRSRV_OK )
+				{
+					psRGXCtrlHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXCtrlHWPerfCounters_exit;
+					goto RGXCtrlHWPerfCounters_exit;
+				}
 			}
 
 
-
 	psRGXCtrlHWPerfCountersOUT->eError =
 		PVRSRVRGXCtrlHWPerfCountersKM(psConnection, OSGetDevData(psConnection),
 					psRGXCtrlHWPerfCountersIN->bEnable,
@@ -187,12 +272,24 @@
 
 
 RGXCtrlHWPerfCounters_exit:
-	if (ui16BlockIDsInt)
-		OSFreeMemNoStats(ui16BlockIDsInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCONFIGCUSTOMCOUNTERS *psRGXConfigCustomCountersIN,
@@ -201,32 +298,65 @@
 {
 	IMG_UINT32 *ui32CustomCounterIDsInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32)) +
+			0;
 
 
 
-	if (psRGXConfigCustomCountersIN->ui16NumCustomCounters != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		ui32CustomCounterIDsInt = OSAllocMemNoStats(psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32));
-		if (!ui32CustomCounterIDsInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXConfigCustomCountersIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXConfigCustomCounters_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXConfigCustomCountersIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXConfigCustomCounters_exit;
+			}
 		}
 	}
 
+	if (psRGXConfigCustomCountersIN->ui16NumCustomCounters != 0)
+	{
+		ui32CustomCounterIDsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXConfigCustomCountersIN->pui32CustomCounterIDs, psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32CustomCounterIDsInt, psRGXConfigCustomCountersIN->pui32CustomCounterIDs,
-				psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32CustomCounterIDsInt, psRGXConfigCustomCountersIN->pui32CustomCounterIDs, psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXConfigCustomCounters_exit;
+					goto RGXConfigCustomCounters_exit;
+				}
 			}
 
 
-
 	psRGXConfigCustomCountersOUT->eError =
 		PVRSRVRGXConfigCustomCountersKM(psConnection, OSGetDevData(psConnection),
 					psRGXConfigCustomCountersIN->ui16CustomBlockID,
@@ -237,14 +367,26 @@
 
 
 RGXConfigCustomCounters_exit:
-	if (ui32CustomCounterIDsInt)
-		OSFreeMemNoStats(ui32CustomCounterIDsInt);
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -283,4 +425,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_bridge.h
index 2e7bdd5..7a90352 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_bridge.h
@@ -72,7 +72,7 @@
 							     IMG_UINT32 ui32SignatureChecksBufSize,
 							     IMG_UINT32 ui32HWPerfFWBufSizeKB,
 							     IMG_UINT64 ui64HWPerfFilter,
-							     IMG_UINT32 ui32RGXFWAlignChecksSize,
+							     IMG_UINT32 ui32RGXFWAlignChecksArrLength,
 							     IMG_UINT32 *pui32RGXFWAlignChecks,
 							     IMG_UINT32 ui32ConfigFlags,
 							     IMG_UINT32 ui32LogType,
@@ -85,15 +85,12 @@
 							     RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
 							     FW_PERF_CONF eFirmwarePerf);
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitFinaliseFWImage(IMG_HANDLE hBridge,
-								    IMG_HANDLE hFWImagePMRImport,
-								    IMG_UINT64 ui64FWImgLen);
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitFinaliseFWImage(IMG_HANDLE hBridge);
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitDevPart2(IMG_HANDLE hBridge,
 							     RGX_INIT_COMMAND *psDbgScript,
-							     RGX_INIT_COMMAND *psDbgBusScript,
-							     RGX_INIT_COMMAND *psDeinitScript,
 							     IMG_UINT32 ui32DeviceFlags,
+							     IMG_UINT32 ui32HWPerfHostBufSize,
 							     IMG_UINT32 ui32HWPerfHostFilter,
 							     IMG_UINT32 ui32RGXActivePMConf,
 							     IMG_HANDLE hFWCodePMR,
@@ -103,7 +100,23 @@
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeGPUVIRTPopulateLMASubArenas(IMG_HANDLE hBridge,
 									 IMG_UINT32 ui32NumElements,
-									 IMG_UINT32 *pui32Elements);
+									 IMG_UINT32 *pui32Elements,
+									 IMG_BOOL bEnableTrustedDeviceAceConfig);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitGuest(IMG_HANDLE hBridge,
+							  IMG_BOOL bEnableSignatureChecks,
+							  IMG_UINT32 ui32SignatureChecksBufSize,
+							  IMG_UINT32 ui32RGXFWAlignChecksArrLength,
+							  IMG_UINT32 *pui32RGXFWAlignChecks,
+							  IMG_UINT32 ui32DeviceFlags,
+							  RGXFWIF_COMPCHECKS_BVNC *psClientBVNC);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitFirmwareExtended(IMG_HANDLE hBridge,
+								     IMG_UINT32 ui32RGXFWAlignChecksArrLength,
+								     IMG_UINT32 *pui32RGXFWAlignChecks,
+								     RGXFWIF_DEV_VIRTADDR *pspsRGXFwInit,
+								     IMG_HANDLE *phHWPerfPMR2,
+								     RGX_FW_INIT_IN_PARAMS *pspsInParams);
 
 
 #endif /* CLIENT_RGXINIT_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_direct_bridge.c
index 9add8ee..68958cb 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/client_rgxinit_direct_bridge.c
@@ -47,7 +47,6 @@
 #include "rgx_bridge.h"
 #include "rgxscript.h"
 #include "devicemem_typedefs.h"
-#include "rgx_fwif_shared.h"
 #include "rgx_fwif.h"
 
 #include "rgxinit.h"
@@ -98,7 +97,7 @@
 							     IMG_UINT32 ui32SignatureChecksBufSize,
 							     IMG_UINT32 ui32HWPerfFWBufSizeKB,
 							     IMG_UINT64 ui64HWPerfFilter,
-							     IMG_UINT32 ui32RGXFWAlignChecksSize,
+							     IMG_UINT32 ui32RGXFWAlignChecksArrLength,
 							     IMG_UINT32 *pui32RGXFWAlignChecks,
 							     IMG_UINT32 ui32ConfigFlags,
 							     IMG_UINT32 ui32LogType,
@@ -123,7 +122,7 @@
 					ui32SignatureChecksBufSize,
 					ui32HWPerfFWBufSizeKB,
 					ui64HWPerfFilter,
-					ui32RGXFWAlignChecksSize,
+					ui32RGXFWAlignChecksArrLength,
 					pui32RGXFWAlignChecks,
 					ui32ConfigFlags,
 					ui32LogType,
@@ -140,29 +139,21 @@
 	return eError;
 }
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitFinaliseFWImage(IMG_HANDLE hBridge,
-								    IMG_HANDLE hFWImagePMRImport,
-								    IMG_UINT64 ui64FWImgLen)
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitFinaliseFWImage(IMG_HANDLE hBridge)
 {
 	PVRSRV_ERROR eError;
-	PMR * psFWImagePMRImportInt;
 
-	psFWImagePMRImportInt = (PMR *) hFWImagePMRImport;
 
 	eError =
 		PVRSRVRGXInitFinaliseFWImageKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
-		,
-					psFWImagePMRImportInt,
-					ui64FWImgLen);
-
+					);
 	return eError;
 }
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitDevPart2(IMG_HANDLE hBridge,
 							     RGX_INIT_COMMAND *psDbgScript,
-							     RGX_INIT_COMMAND *psDbgBusScript,
-							     RGX_INIT_COMMAND *psDeinitScript,
 							     IMG_UINT32 ui32DeviceFlags,
+							     IMG_UINT32 ui32HWPerfHostBufSize,
 							     IMG_UINT32 ui32HWPerfHostFilter,
 							     IMG_UINT32 ui32RGXActivePMConf,
 							     IMG_HANDLE hFWCodePMR,
@@ -185,9 +176,8 @@
 		PVRSRVRGXInitDevPart2KM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
 		,
 					psDbgScript,
-					psDbgBusScript,
-					psDeinitScript,
 					ui32DeviceFlags,
+					ui32HWPerfHostBufSize,
 					ui32HWPerfHostFilter,
 					ui32RGXActivePMConf,
 					psFWCodePMRInt,
@@ -200,7 +190,8 @@
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeGPUVIRTPopulateLMASubArenas(IMG_HANDLE hBridge,
 									 IMG_UINT32 ui32NumElements,
-									 IMG_UINT32 *pui32Elements)
+									 IMG_UINT32 *pui32Elements,
+									 IMG_BOOL bEnableTrustedDeviceAceConfig)
 {
 	PVRSRV_ERROR eError;
 
@@ -209,8 +200,57 @@
 		PVRSRVGPUVIRTPopulateLMASubArenasKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
 		,
 					ui32NumElements,
-					pui32Elements);
+					pui32Elements,
+					bEnableTrustedDeviceAceConfig);
 
 	return eError;
 }
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitGuest(IMG_HANDLE hBridge,
+							  IMG_BOOL bEnableSignatureChecks,
+							  IMG_UINT32 ui32SignatureChecksBufSize,
+							  IMG_UINT32 ui32RGXFWAlignChecksArrLength,
+							  IMG_UINT32 *pui32RGXFWAlignChecks,
+							  IMG_UINT32 ui32DeviceFlags,
+							  RGXFWIF_COMPCHECKS_BVNC *psClientBVNC)
+{
+	PVRSRV_ERROR eError;
+
+
+	eError =
+		PVRSRVRGXInitGuestKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					bEnableSignatureChecks,
+					ui32SignatureChecksBufSize,
+					ui32RGXFWAlignChecksArrLength,
+					pui32RGXFWAlignChecks,
+					ui32DeviceFlags,
+					psClientBVNC);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRGXInitFirmwareExtended(IMG_HANDLE hBridge,
+								     IMG_UINT32 ui32RGXFWAlignChecksArrLength,
+								     IMG_UINT32 *pui32RGXFWAlignChecks,
+								     RGXFWIF_DEV_VIRTADDR *pspsRGXFwInit,
+								     IMG_HANDLE *phHWPerfPMR2,
+								     RGX_FW_INIT_IN_PARAMS *pspsInParams)
+{
+	PVRSRV_ERROR eError;
+	PMR * psHWPerfPMR2Int;
+
+
+	eError =
+		PVRSRVRGXInitFirmwareExtendedKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					ui32RGXFWAlignChecksArrLength,
+					pui32RGXFWAlignChecks,
+					pspsRGXFwInit,
+					&psHWPerfPMR2Int,
+					pspsInParams);
+
+	*phHWPerfPMR2 = psHWPerfPMR2Int;
+	return eError;
+}
+
diff --git a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h
index e565faf..55e948b 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxinit
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxinit
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxinit
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,13 +45,14 @@
 #ifndef COMMON_RGXINIT_BRIDGE_H
 #define COMMON_RGXINIT_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "rgx_bridge.h"
 #include "rgxscript.h"
 #include "devicemem_typedefs.h"
-#include "rgx_fwif_shared.h"
 #include "rgx_fwif.h"
 
 
@@ -61,7 +62,9 @@
 #define PVRSRV_BRIDGE_RGXINIT_RGXINITFINALISEFWIMAGE			PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+2
 #define PVRSRV_BRIDGE_RGXINIT_RGXINITDEVPART2			PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+3
 #define PVRSRV_BRIDGE_RGXINIT_GPUVIRTPOPULATELMASUBARENAS			PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+4
-#define PVRSRV_BRIDGE_RGXINIT_CMD_LAST			(PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RGXINIT_RGXINITGUEST			PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+5
+#define PVRSRV_BRIDGE_RGXINIT_RGXINITFIRMWAREEXTENDED			PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+6
+#define PVRSRV_BRIDGE_RGXINIT_CMD_LAST			(PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+6)
 
 
 /*******************************************
@@ -101,7 +104,7 @@
 	IMG_UINT32 ui32SignatureChecksBufSize;
 	IMG_UINT32 ui32HWPerfFWBufSizeKB;
 	IMG_UINT64 ui64HWPerfFilter;
-	IMG_UINT32 ui32RGXFWAlignChecksSize;
+	IMG_UINT32 ui32RGXFWAlignChecksArrLength;
 	IMG_UINT32 * pui32RGXFWAlignChecks;
 	IMG_UINT32 ui32ConfigFlags;
 	IMG_UINT32 ui32LogType;
@@ -130,8 +133,7 @@
 /* Bridge in structure for RGXInitFinaliseFWImage */
 typedef struct PVRSRV_BRIDGE_IN_RGXINITFINALISEFWIMAGE_TAG
 {
-	IMG_HANDLE hFWImagePMRImport;
-	IMG_UINT64 ui64FWImgLen;
+	 IMG_UINT32 ui32EmptyStructPlaceholder;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITFINALISEFWIMAGE;
 
 /* Bridge out structure for RGXInitFinaliseFWImage */
@@ -149,9 +151,8 @@
 typedef struct PVRSRV_BRIDGE_IN_RGXINITDEVPART2_TAG
 {
 	RGX_INIT_COMMAND * psDbgScript;
-	RGX_INIT_COMMAND * psDbgBusScript;
-	RGX_INIT_COMMAND * psDeinitScript;
 	IMG_UINT32 ui32DeviceFlags;
+	IMG_UINT32 ui32HWPerfHostBufSize;
 	IMG_UINT32 ui32HWPerfHostFilter;
 	IMG_UINT32 ui32RGXActivePMConf;
 	IMG_HANDLE hFWCodePMR;
@@ -176,6 +177,7 @@
 {
 	IMG_UINT32 ui32NumElements;
 	IMG_UINT32 * pui32Elements;
+	IMG_BOOL bEnableTrustedDeviceAceConfig;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_GPUVIRTPOPULATELMASUBARENAS;
 
 /* Bridge out structure for GPUVIRTPopulateLMASubArenas */
@@ -185,4 +187,47 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_GPUVIRTPOPULATELMASUBARENAS;
 
 
+/*******************************************
+            RGXInitGuest          
+ *******************************************/
+
+/* Bridge in structure for RGXInitGuest */
+typedef struct PVRSRV_BRIDGE_IN_RGXINITGUEST_TAG
+{
+	IMG_BOOL bEnableSignatureChecks;
+	IMG_UINT32 ui32SignatureChecksBufSize;
+	IMG_UINT32 ui32RGXFWAlignChecksArrLength;
+	IMG_UINT32 * pui32RGXFWAlignChecks;
+	IMG_UINT32 ui32DeviceFlags;
+	RGXFWIF_COMPCHECKS_BVNC sClientBVNC;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITGUEST;
+
+/* Bridge out structure for RGXInitGuest */
+typedef struct PVRSRV_BRIDGE_OUT_RGXINITGUEST_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXINITGUEST;
+
+
+/*******************************************
+            RGXInitFirmwareExtended          
+ *******************************************/
+
+/* Bridge in structure for RGXInitFirmwareExtended */
+typedef struct PVRSRV_BRIDGE_IN_RGXINITFIRMWAREEXTENDED_TAG
+{
+	IMG_UINT32 ui32RGXFWAlignChecksArrLength;
+	IMG_UINT32 * pui32RGXFWAlignChecks;
+	RGX_FW_INIT_IN_PARAMS spsInParams;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITFIRMWAREEXTENDED;
+
+/* Bridge out structure for RGXInitFirmwareExtended */
+typedef struct PVRSRV_BRIDGE_OUT_RGXINITFIRMWAREEXTENDED_TAG
+{
+	RGXFWIF_DEV_VIRTADDR spsRGXFwInit;
+	IMG_HANDLE hHWPerfPMR2;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXINITFIRMWAREEXTENDED;
+
+
 #endif /* COMMON_RGXINIT_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c
deleted file mode 100644
index 3aac66c..0000000
--- a/drivers/staging/imgtec/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Server bridge for rgxinit
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Implements the server side of the bridge for rgxinit
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include <stddef.h>
-#include <asm/uaccess.h>
-
-#include "img_defs.h"
-
-#include "rgxinit.h"
-#include "pmr.h"
-
-
-#include "common_rgxinit_bridge.h"
-
-#include "allocmem.h"
-#include "pvr_debug.h"
-#include "connection_server.h"
-#include "pvr_bridge.h"
-#include "rgx_bridge.h"
-#include "srvcore.h"
-#include "handle.h"
-
-#include <linux/slab.h>
-
-
-static PVRSRV_ERROR ReleaseFWCodePMR(void *pvData)
-{
-	PVR_UNREFERENCED_PARAMETER(pvData);
-
-	return PVRSRV_OK;
-}
-static PVRSRV_ERROR ReleaseFWDataPMR(void *pvData)
-{
-	PVR_UNREFERENCED_PARAMETER(pvData);
-
-	return PVRSRV_OK;
-}
-static PVRSRV_ERROR ReleaseFWCorememPMR(void *pvData)
-{
-	PVR_UNREFERENCED_PARAMETER(pvData);
-
-	return PVRSRV_OK;
-}
-static PVRSRV_ERROR ReleaseHWPerfPMR(void *pvData)
-{
-	PVR_UNREFERENCED_PARAMETER(pvData);
-
-	return PVRSRV_OK;
-}
-
-
-/* ***************************************************************************
- * Server-side bridge entry points
- */
- 
-static IMG_INT
-PVRSRVBridgeRGXInitAllocFWImgMem(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_RGXINITALLOCFWIMGMEM *psRGXInitAllocFWImgMemIN,
-					  PVRSRV_BRIDGE_OUT_RGXINITALLOCFWIMGMEM *psRGXInitAllocFWImgMemOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	PMR * psFWCodePMRInt = NULL;
-	PMR * psFWDataPMRInt = NULL;
-	PMR * psFWCorememPMRInt = NULL;
-
-
-
-
-
-
-
-	psRGXInitAllocFWImgMemOUT->eError =
-		PVRSRVRGXInitAllocFWImgMemKM(psConnection, OSGetDevData(psConnection),
-					psRGXInitAllocFWImgMemIN->uiFWCodeLen,
-					psRGXInitAllocFWImgMemIN->uiFWDataLen,
-					psRGXInitAllocFWImgMemIN->uiFWCoremem,
-					&psFWCodePMRInt,
-					&psRGXInitAllocFWImgMemOUT->sFWCodeDevVAddrBase,
-					&psFWDataPMRInt,
-					&psRGXInitAllocFWImgMemOUT->sFWDataDevVAddrBase,
-					&psFWCorememPMRInt,
-					&psRGXInitAllocFWImgMemOUT->sFWCorememDevVAddrBase,
-					&psRGXInitAllocFWImgMemOUT->sFWCorememMetaVAddrBase);
-	/* Exit early if bridged call fails */
-	if(psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
-	{
-		goto RGXInitAllocFWImgMem_exit;
-	}
-
-
-	psRGXInitAllocFWImgMemOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
-							&psRGXInitAllocFWImgMemOUT->hFWCodePMR,
-							(void *) psFWCodePMRInt,
-							PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
-							PVRSRV_HANDLE_ALLOC_FLAG_NONE
-							,(PFN_HANDLE_RELEASE)&ReleaseFWCodePMR);
-	if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
-	{
-		goto RGXInitAllocFWImgMem_exit;
-	}
-
-
-	psRGXInitAllocFWImgMemOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
-							&psRGXInitAllocFWImgMemOUT->hFWDataPMR,
-							(void *) psFWDataPMRInt,
-							PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
-							PVRSRV_HANDLE_ALLOC_FLAG_NONE
-							,(PFN_HANDLE_RELEASE)&ReleaseFWDataPMR);
-	if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
-	{
-		goto RGXInitAllocFWImgMem_exit;
-	}
-
-
-	psRGXInitAllocFWImgMemOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
-							&psRGXInitAllocFWImgMemOUT->hFWCorememPMR,
-							(void *) psFWCorememPMRInt,
-							PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
-							PVRSRV_HANDLE_ALLOC_FLAG_NONE
-							,(PFN_HANDLE_RELEASE)&ReleaseFWCorememPMR);
-	if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
-	{
-		goto RGXInitAllocFWImgMem_exit;
-	}
-
-
-
-
-RGXInitAllocFWImgMem_exit:
-	if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
-	{
-	}
-
-
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeRGXInitFirmware(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_RGXINITFIRMWARE *psRGXInitFirmwareIN,
-					  PVRSRV_BRIDGE_OUT_RGXINITFIRMWARE *psRGXInitFirmwareOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	IMG_UINT32 *ui32RGXFWAlignChecksInt = NULL;
-	PMR * psHWPerfPMRInt = NULL;
-
-
-
-
-	if (psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize != 0)
-	{
-		ui32RGXFWAlignChecksInt = OSAllocMemNoStats(psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize * sizeof(IMG_UINT32));
-		if (!ui32RGXFWAlignChecksInt)
-		{
-			psRGXInitFirmwareOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXInitFirmware_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXInitFirmwareIN->pui32RGXFWAlignChecks, psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32RGXFWAlignChecksInt, psRGXInitFirmwareIN->pui32RGXFWAlignChecks,
-				psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXInitFirmwareOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXInitFirmware_exit;
-			}
-
-
-
-	psRGXInitFirmwareOUT->eError =
-		PVRSRVRGXInitFirmwareKM(psConnection, OSGetDevData(psConnection),
-					&psRGXInitFirmwareOUT->spsRGXFwInit,
-					psRGXInitFirmwareIN->bEnableSignatureChecks,
-					psRGXInitFirmwareIN->ui32SignatureChecksBufSize,
-					psRGXInitFirmwareIN->ui32HWPerfFWBufSizeKB,
-					psRGXInitFirmwareIN->ui64HWPerfFilter,
-					psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize,
-					ui32RGXFWAlignChecksInt,
-					psRGXInitFirmwareIN->ui32ConfigFlags,
-					psRGXInitFirmwareIN->ui32LogType,
-					psRGXInitFirmwareIN->ui32FilterFlags,
-					psRGXInitFirmwareIN->ui32JonesDisableMask,
-					psRGXInitFirmwareIN->ui32ui32HWRDebugDumpLimit,
-					&psRGXInitFirmwareIN->sClientBVNC,
-					psRGXInitFirmwareIN->ui32HWPerfCountersDataSize,
-					&psHWPerfPMRInt,
-					psRGXInitFirmwareIN->eRGXRDPowerIslandConf,
-					psRGXInitFirmwareIN->eFirmwarePerf);
-	/* Exit early if bridged call fails */
-	if(psRGXInitFirmwareOUT->eError != PVRSRV_OK)
-	{
-		goto RGXInitFirmware_exit;
-	}
-
-
-	psRGXInitFirmwareOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
-							&psRGXInitFirmwareOUT->hHWPerfPMR,
-							(void *) psHWPerfPMRInt,
-							PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
-							PVRSRV_HANDLE_ALLOC_FLAG_NONE
-							,(PFN_HANDLE_RELEASE)&ReleaseHWPerfPMR);
-	if (psRGXInitFirmwareOUT->eError != PVRSRV_OK)
-	{
-		goto RGXInitFirmware_exit;
-	}
-
-
-
-
-RGXInitFirmware_exit:
-	if (psRGXInitFirmwareOUT->eError != PVRSRV_OK)
-	{
-	}
-
-	if (ui32RGXFWAlignChecksInt)
-		OSFreeMemNoStats(ui32RGXFWAlignChecksInt);
-
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeRGXInitFinaliseFWImage(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_RGXINITFINALISEFWIMAGE *psRGXInitFinaliseFWImageIN,
-					  PVRSRV_BRIDGE_OUT_RGXINITFINALISEFWIMAGE *psRGXInitFinaliseFWImageOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	PMR * psFWImagePMRImportInt = NULL;
-
-
-
-
-
-	PMRLock();
-
-
-				{
-					/* Look up the address from the handle */
-					psRGXInitFinaliseFWImageOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psFWImagePMRImportInt,
-											psRGXInitFinaliseFWImageIN->hFWImagePMRImport,
-											PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
-					if(psRGXInitFinaliseFWImageOUT->eError != PVRSRV_OK)
-					{
-						PMRUnlock();
-						goto RGXInitFinaliseFWImage_exit;
-					}
-				}
-
-
-	psRGXInitFinaliseFWImageOUT->eError =
-		PVRSRVRGXInitFinaliseFWImageKM(psConnection, OSGetDevData(psConnection),
-					psFWImagePMRImportInt,
-					psRGXInitFinaliseFWImageIN->ui64FWImgLen);
-	PMRUnlock();
-
-
-
-
-RGXInitFinaliseFWImage_exit:
-
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeRGXInitDevPart2(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_RGXINITDEVPART2 *psRGXInitDevPart2IN,
-					  PVRSRV_BRIDGE_OUT_RGXINITDEVPART2 *psRGXInitDevPart2OUT,
-					 CONNECTION_DATA *psConnection)
-{
-	RGX_INIT_COMMAND *psDbgScriptInt = NULL;
-	RGX_INIT_COMMAND *psDbgBusScriptInt = NULL;
-	RGX_INIT_COMMAND *psDeinitScriptInt = NULL;
-	PMR * psFWCodePMRInt = NULL;
-	PMR * psFWDataPMRInt = NULL;
-	PMR * psFWCorememPMRInt = NULL;
-	PMR * psHWPerfPMRInt = NULL;
-
-
-
-
-	
-	{
-		psDbgScriptInt = OSAllocMemNoStats(RGX_MAX_DEBUG_COMMANDS * sizeof(RGX_INIT_COMMAND));
-		if (!psDbgScriptInt)
-		{
-			psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXInitDevPart2_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXInitDevPart2IN->psDbgScript, RGX_MAX_DEBUG_COMMANDS * sizeof(RGX_INIT_COMMAND))
-				|| (OSCopyFromUser(NULL, psDbgScriptInt, psRGXInitDevPart2IN->psDbgScript,
-				RGX_MAX_DEBUG_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
-			{
-				psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXInitDevPart2_exit;
-			}
-	
-	{
-		psDbgBusScriptInt = OSAllocMemNoStats(RGX_MAX_DBGBUS_COMMANDS * sizeof(RGX_INIT_COMMAND));
-		if (!psDbgBusScriptInt)
-		{
-			psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXInitDevPart2_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXInitDevPart2IN->psDbgBusScript, RGX_MAX_DBGBUS_COMMANDS * sizeof(RGX_INIT_COMMAND))
-				|| (OSCopyFromUser(NULL, psDbgBusScriptInt, psRGXInitDevPart2IN->psDbgBusScript,
-				RGX_MAX_DBGBUS_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
-			{
-				psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXInitDevPart2_exit;
-			}
-	
-	{
-		psDeinitScriptInt = OSAllocMemNoStats(RGX_MAX_DEINIT_COMMANDS * sizeof(RGX_INIT_COMMAND));
-		if (!psDeinitScriptInt)
-		{
-			psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXInitDevPart2_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXInitDevPart2IN->psDeinitScript, RGX_MAX_DEINIT_COMMANDS * sizeof(RGX_INIT_COMMAND))
-				|| (OSCopyFromUser(NULL, psDeinitScriptInt, psRGXInitDevPart2IN->psDeinitScript,
-				RGX_MAX_DEINIT_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
-			{
-				psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXInitDevPart2_exit;
-			}
-
-	PMRLock();
-
-
-	psRGXInitDevPart2OUT->eError =
-		PVRSRVRGXInitDevPart2KM(psConnection, OSGetDevData(psConnection),
-					psDbgScriptInt,
-					psDbgBusScriptInt,
-					psDeinitScriptInt,
-					psRGXInitDevPart2IN->ui32DeviceFlags,
-					psRGXInitDevPart2IN->ui32HWPerfHostFilter,
-					psRGXInitDevPart2IN->ui32RGXActivePMConf,
-					psFWCodePMRInt,
-					psFWDataPMRInt,
-					psFWCorememPMRInt,
-					psHWPerfPMRInt);
-	PMRUnlock();
-
-
-	psRGXInitDevPart2OUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
-					(IMG_HANDLE) psRGXInitDevPart2IN->hFWCodePMR,
-					PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
-	if ((psRGXInitDevPart2OUT->eError != PVRSRV_OK) && (psRGXInitDevPart2OUT->eError != PVRSRV_ERROR_RETRY))
-	{
-		PVR_ASSERT(0);
-		PMRUnlock();
-		goto RGXInitDevPart2_exit;
-	}
-
-	psRGXInitDevPart2OUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
-					(IMG_HANDLE) psRGXInitDevPart2IN->hFWDataPMR,
-					PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
-	if ((psRGXInitDevPart2OUT->eError != PVRSRV_OK) && (psRGXInitDevPart2OUT->eError != PVRSRV_ERROR_RETRY))
-	{
-		PVR_ASSERT(0);
-		PMRUnlock();
-		goto RGXInitDevPart2_exit;
-	}
-
-	psRGXInitDevPart2OUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
-					(IMG_HANDLE) psRGXInitDevPart2IN->hFWCorememPMR,
-					PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
-	if ((psRGXInitDevPart2OUT->eError != PVRSRV_OK) && (psRGXInitDevPart2OUT->eError != PVRSRV_ERROR_RETRY))
-	{
-		PVR_ASSERT(0);
-		PMRUnlock();
-		goto RGXInitDevPart2_exit;
-	}
-
-	psRGXInitDevPart2OUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
-					(IMG_HANDLE) psRGXInitDevPart2IN->hHWPerfPMR,
-					PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
-	if ((psRGXInitDevPart2OUT->eError != PVRSRV_OK) && (psRGXInitDevPart2OUT->eError != PVRSRV_ERROR_RETRY))
-	{
-		PVR_ASSERT(0);
-		PMRUnlock();
-		goto RGXInitDevPart2_exit;
-	}
-
-
-
-RGXInitDevPart2_exit:
-	if (psDbgScriptInt)
-		OSFreeMemNoStats(psDbgScriptInt);
-	if (psDbgBusScriptInt)
-		OSFreeMemNoStats(psDbgBusScriptInt);
-	if (psDeinitScriptInt)
-		OSFreeMemNoStats(psDeinitScriptInt);
-
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeGPUVIRTPopulateLMASubArenas(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_GPUVIRTPOPULATELMASUBARENAS *psGPUVIRTPopulateLMASubArenasIN,
-					  PVRSRV_BRIDGE_OUT_GPUVIRTPOPULATELMASUBARENAS *psGPUVIRTPopulateLMASubArenasOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	IMG_UINT32 *ui32ElementsInt = NULL;
-
-
-
-
-	if (psGPUVIRTPopulateLMASubArenasIN->ui32NumElements != 0)
-	{
-		ui32ElementsInt = OSAllocMemNoStats(psGPUVIRTPopulateLMASubArenasIN->ui32NumElements * sizeof(IMG_UINT32));
-		if (!ui32ElementsInt)
-		{
-			psGPUVIRTPopulateLMASubArenasOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto GPUVIRTPopulateLMASubArenas_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psGPUVIRTPopulateLMASubArenasIN->pui32Elements, psGPUVIRTPopulateLMASubArenasIN->ui32NumElements * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ElementsInt, psGPUVIRTPopulateLMASubArenasIN->pui32Elements,
-				psGPUVIRTPopulateLMASubArenasIN->ui32NumElements * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psGPUVIRTPopulateLMASubArenasOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto GPUVIRTPopulateLMASubArenas_exit;
-			}
-
-
-
-	psGPUVIRTPopulateLMASubArenasOUT->eError =
-		PVRSRVGPUVIRTPopulateLMASubArenasKM(psConnection, OSGetDevData(psConnection),
-					psGPUVIRTPopulateLMASubArenasIN->ui32NumElements,
-					ui32ElementsInt);
-
-
-
-
-GPUVIRTPopulateLMASubArenas_exit:
-	if (ui32ElementsInt)
-		OSFreeMemNoStats(ui32ElementsInt);
-
-	return 0;
-}
-
-
-
-/* *************************************************************************** 
- * Server bridge dispatch related glue 
- */
-
-static IMG_BOOL bUseLock = IMG_TRUE;
-
-PVRSRV_ERROR InitRGXINITBridge(void);
-PVRSRV_ERROR DeinitRGXINITBridge(void);
-
-/*
- * Register all RGXINIT functions with services
- */
-PVRSRV_ERROR InitRGXINITBridge(void)
-{
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT, PVRSRV_BRIDGE_RGXINIT_RGXINITALLOCFWIMGMEM, PVRSRVBridgeRGXInitAllocFWImgMem,
-					NULL, bUseLock);
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT, PVRSRV_BRIDGE_RGXINIT_RGXINITFIRMWARE, PVRSRVBridgeRGXInitFirmware,
-					NULL, bUseLock);
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT, PVRSRV_BRIDGE_RGXINIT_RGXINITFINALISEFWIMAGE, PVRSRVBridgeRGXInitFinaliseFWImage,
-					NULL, bUseLock);
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT, PVRSRV_BRIDGE_RGXINIT_RGXINITDEVPART2, PVRSRVBridgeRGXInitDevPart2,
-					NULL, bUseLock);
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT, PVRSRV_BRIDGE_RGXINIT_GPUVIRTPOPULATELMASUBARENAS, PVRSRVBridgeGPUVIRTPopulateLMASubArenas,
-					NULL, bUseLock);
-
-
-	return PVRSRV_OK;
-}
-
-/*
- * Unregister all rgxinit functions with services
- */
-PVRSRV_ERROR DeinitRGXINITBridge(void)
-{
-	return PVRSRV_OK;
-}
-
diff --git a/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/common_rgxkicksync_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/common_rgxkicksync_bridge.h
index 4221e29..b1b6fae 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/common_rgxkicksync_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/common_rgxkicksync_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxkicksync
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxkicksync
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxkicksync
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,12 +45,13 @@
 #ifndef COMMON_RGXKICKSYNC_BRIDGE_H
 #define COMMON_RGXKICKSYNC_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "rgx_bridge.h"
-#include "sync_external.h"
-#include "rgx_fwif_shared.h"
+#include <powervr/sync_external.h>
 
 
 #define PVRSRV_BRIDGE_RGXKICKSYNC_CMD_FIRST			0
@@ -103,6 +104,7 @@
 typedef struct PVRSRV_BRIDGE_IN_RGXKICKSYNC_TAG
 {
 	IMG_HANDLE hKickSyncContext;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
 	IMG_UINT32 ui32ClientFenceCount;
 	IMG_HANDLE * phFenceUFOSyncPrimBlock;
 	IMG_UINT32 * pui32FenceSyncOffset;
@@ -118,7 +120,6 @@
 	IMG_INT32 i32TimelineFenceFD;
 	IMG_CHAR * puiUpdateFenceName;
 	IMG_UINT32 ui32ExtJobRef;
-	IMG_UINT32 ui32IntJobRef;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKSYNC;
 
 /* Bridge out structure for RGXKickSync */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/server_rgxkicksync_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/server_rgxkicksync_bridge.c
index 19c9c41..7739b38 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/server_rgxkicksync_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxkicksync_bridge/server_rgxkicksync_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -74,6 +76,7 @@
 					  PVRSRV_BRIDGE_OUT_RGXCREATEKICKSYNCCONTEXT *psRGXCreateKickSyncContextOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPrivData = psRGXCreateKickSyncContextIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 	RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContextInt = NULL;
 
@@ -83,19 +86,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXCreateKickSyncContextOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXCreateKickSyncContextIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXCreateKickSyncContextOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXCreateKickSyncContext_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateKickSyncContextOUT->eError =
 		PVRSRVRGXCreateKickSyncContextKM(psConnection, OSGetDevData(psConnection),
@@ -107,8 +120,15 @@
 		goto RGXCreateKickSyncContext_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psRGXCreateKickSyncContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psRGXCreateKickSyncContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateKickSyncContextOUT->hKickSyncContext,
 							(void *) psKickSyncContextInt,
 							PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT,
@@ -116,13 +136,37 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVRGXDestroyKickSyncContextKM);
 	if (psRGXCreateKickSyncContextOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateKickSyncContext_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateKickSyncContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateKickSyncContextOUT->eError != PVRSRV_OK)
 	{
 		if (psKickSyncContextInt)
@@ -135,6 +179,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyKickSyncContext(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYKICKSYNCCONTEXT *psRGXDestroyKickSyncContextIN,
@@ -150,29 +195,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psRGXDestroyKickSyncContextOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyKickSyncContextIN->hKickSyncContext,
 					PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT);
-	if ((psRGXDestroyKickSyncContextOUT->eError != PVRSRV_OK) && (psRGXDestroyKickSyncContextOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyKickSyncContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyKickSyncContextOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyKickSyncContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyKickSyncContextOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto RGXDestroyKickSyncContext_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyKickSyncContext_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXKickSync(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXKICKSYNC *psRGXKickSyncIN,
 					  PVRSRV_BRIDGE_OUT_RGXKICKSYNC *psRGXKickSyncOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hKickSyncContext = psRGXKickSyncIN->hKickSyncContext;
 	RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContextInt = NULL;
 	SYNC_PRIMITIVE_BLOCK * *psFenceUFOSyncPrimBlockInt = NULL;
 	IMG_HANDLE *hFenceUFOSyncPrimBlockInt2 = NULL;
@@ -187,227 +252,235 @@
 	IMG_HANDLE *hServerSyncInt2 = NULL;
 	IMG_CHAR *uiUpdateFenceNameInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) +
+			(psRGXKickSyncIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) +
+			(32 * sizeof(IMG_CHAR)) +
+			0;
 
 
 
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXKickSyncIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXKickSyncIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXKickSync_exit;
+			}
+		}
+	}
+
 	if (psRGXKickSyncIN->ui32ClientFenceCount != 0)
 	{
-		psFenceUFOSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psFenceUFOSyncPrimBlockInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
-		hFenceUFOSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE));
-		if (!hFenceUFOSyncPrimBlockInt2)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		psFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->phFenceUFOSyncPrimBlock, psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hFenceUFOSyncPrimBlockInt2, psRGXKickSyncIN->phFenceUFOSyncPrimBlock,
-				psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hFenceUFOSyncPrimBlockInt2, psRGXKickSyncIN->phFenceUFOSyncPrimBlock, psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ClientFenceCount != 0)
 	{
-		ui32FenceSyncOffsetInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
-		if (!ui32FenceSyncOffsetInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		ui32FenceSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->pui32FenceSyncOffset, psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32FenceSyncOffsetInt, psRGXKickSyncIN->pui32FenceSyncOffset,
-				psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32FenceSyncOffsetInt, psRGXKickSyncIN->pui32FenceSyncOffset, psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ClientFenceCount != 0)
 	{
-		ui32FenceValueInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
-		if (!ui32FenceValueInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		ui32FenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->pui32FenceValue, psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32FenceValueInt, psRGXKickSyncIN->pui32FenceValue,
-				psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32FenceValueInt, psRGXKickSyncIN->pui32FenceValue, psRGXKickSyncIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ClientUpdateCount != 0)
 	{
-		psUpdateUFOSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psUpdateUFOSyncPrimBlockInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
-		hUpdateUFOSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE));
-		if (!hUpdateUFOSyncPrimBlockInt2)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		psUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->phUpdateUFOSyncPrimBlock, psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hUpdateUFOSyncPrimBlockInt2, psRGXKickSyncIN->phUpdateUFOSyncPrimBlock,
-				psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hUpdateUFOSyncPrimBlockInt2, psRGXKickSyncIN->phUpdateUFOSyncPrimBlock, psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ClientUpdateCount != 0)
 	{
-		ui32UpdateSyncOffsetInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32UpdateSyncOffsetInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		ui32UpdateSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->pui32UpdateSyncOffset, psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32UpdateSyncOffsetInt, psRGXKickSyncIN->pui32UpdateSyncOffset,
-				psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32UpdateSyncOffsetInt, psRGXKickSyncIN->pui32UpdateSyncOffset, psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ClientUpdateCount != 0)
 	{
-		ui32UpdateValueInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32UpdateValueInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		ui32UpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->pui32UpdateValue, psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32UpdateValueInt, psRGXKickSyncIN->pui32UpdateValue,
-				psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32UpdateValueInt, psRGXKickSyncIN->pui32UpdateValue, psRGXKickSyncIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ServerSyncCount != 0)
 	{
-		ui32ServerSyncFlagsInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
-		if (!ui32ServerSyncFlagsInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		ui32ServerSyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->pui32ServerSyncFlags, psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickSyncIN->pui32ServerSyncFlags,
-				psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickSyncIN->pui32ServerSyncFlags, psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	if (psRGXKickSyncIN->ui32ServerSyncCount != 0)
 	{
-		psServerSyncInt = OSAllocMemNoStats(psRGXKickSyncIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psServerSyncInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
-		hServerSyncInt2 = OSAllocMemNoStats(psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
-		if (!hServerSyncInt2)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		psServerSyncInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickSyncIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerSyncInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->phServerSync, psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hServerSyncInt2, psRGXKickSyncIN->phServerSync,
-				psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hServerSyncInt2, psRGXKickSyncIN->phServerSync, psRGXKickSyncIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 	
 	{
-		uiUpdateFenceNameInt = OSAllocMemNoStats(32 * sizeof(IMG_CHAR));
-		if (!uiUpdateFenceNameInt)
-		{
-			psRGXKickSyncOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSync_exit;
-		}
+		uiUpdateFenceNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += 32 * sizeof(IMG_CHAR);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXKickSyncIN->puiUpdateFenceName,
-				32 * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (32 * sizeof(IMG_CHAR) > 0)
 			{
-				psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXKickSyncIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRGXKickSyncOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickSync_exit;
+					goto RGXKickSync_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXKickSyncOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psKickSyncContextInt,
-											psRGXKickSyncIN->hKickSyncContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT);
+											hKickSyncContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT,
+											IMG_TRUE);
 					if(psRGXKickSyncOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXKickSync_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -416,19 +489,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickSyncOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psFenceUFOSyncPrimBlockInt[i],
 											hFenceUFOSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickSyncOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXKickSync_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -437,19 +515,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickSyncOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psUpdateUFOSyncPrimBlockInt[i],
 											hUpdateUFOSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickSyncOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXKickSync_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -458,22 +541,26 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickSyncOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerSyncInt[i],
 											hServerSyncInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psRGXKickSyncOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXKickSync_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXKickSyncOUT->eError =
 		PVRSRVRGXKickSyncKM(
 					psKickSyncContextInt,
+					psRGXKickSyncIN->ui32ClientCacheOpSeqNum,
 					psRGXKickSyncIN->ui32ClientFenceCount,
 					psFenceUFOSyncPrimBlockInt,
 					ui32FenceSyncOffsetInt,
@@ -489,43 +576,119 @@
 					psRGXKickSyncIN->i32TimelineFenceFD,
 					&psRGXKickSyncOUT->i32UpdateFenceFD,
 					uiUpdateFenceNameInt,
-					psRGXKickSyncIN->ui32ExtJobRef,
-					psRGXKickSyncIN->ui32IntJobRef);
+					psRGXKickSyncIN->ui32ExtJobRef);
 
 
 
 
 RGXKickSync_exit:
-	if (psFenceUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psFenceUFOSyncPrimBlockInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psKickSyncContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hKickSyncContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT);
+						}
+				}
+
+
+
+
+
+
 	if (hFenceUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hFenceUFOSyncPrimBlockInt2);
-	if (ui32FenceSyncOffsetInt)
-		OSFreeMemNoStats(ui32FenceSyncOffsetInt);
-	if (ui32FenceValueInt)
-		OSFreeMemNoStats(ui32FenceValueInt);
-	if (psUpdateUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psUpdateUFOSyncPrimBlockInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickSyncIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psFenceUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hUpdateUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hUpdateUFOSyncPrimBlockInt2);
-	if (ui32UpdateSyncOffsetInt)
-		OSFreeMemNoStats(ui32UpdateSyncOffsetInt);
-	if (ui32UpdateValueInt)
-		OSFreeMemNoStats(ui32UpdateValueInt);
-	if (ui32ServerSyncFlagsInt)
-		OSFreeMemNoStats(ui32ServerSyncFlagsInt);
-	if (psServerSyncInt)
-		OSFreeMemNoStats(psServerSyncInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickSyncIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psUpdateUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hServerSyncInt2)
-		OSFreeMemNoStats(hServerSyncInt2);
-	if (uiUpdateFenceNameInt)
-		OSFreeMemNoStats(uiUpdateFenceNameInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickSyncIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -561,4 +724,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/client_rgxpdump_bridge.h
similarity index 82%
rename from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
rename to drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/client_rgxpdump_bridge.h
index 839a17a..bedac78 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/client_rgxpdump_bridge.h
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          Client bridge header for cachegeneric
+@Title          Client bridge header for rgxpdump
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Exports the client bridge functions for cachegeneric
+@Description    Exports the client bridge functions for rgxpdump
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,8 +41,8 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef CLIENT_CACHEGENERIC_BRIDGE_H
-#define CLIENT_CACHEGENERIC_BRIDGE_H
+#ifndef CLIENT_RGXPDUMP_BRIDGE_H
+#define CLIENT_RGXPDUMP_BRIDGE_H
 
 #include "img_defs.h"
 #include "pvrsrv_error.h"
@@ -52,13 +52,13 @@
 #include "pvr_bridge.h"
 #endif
 
-#include "common_cachegeneric_bridge.h"
+#include "common_rgxpdump_bridge.h"
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp);
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePDumpTraceBuffer(IMG_HANDLE hBridge,
+							      IMG_UINT32 ui32PDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePDumpSignatureBuffer(IMG_HANDLE hBridge,
+								  IMG_UINT32 ui32PDumpFlags);
 
 
-#endif /* CLIENT_CACHEGENERIC_BRIDGE_H */
+#endif /* CLIENT_RGXPDUMP_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/client_rgxpdump_direct_bridge.c
similarity index 78%
rename from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
rename to drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/client_rgxpdump_direct_bridge.c
index d0cdf5a..e669f50 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/client_rgxpdump_direct_bridge.c
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          Direct client bridge for cachegeneric
+@Title          Direct client bridge for rgxpdump
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,34 +39,40 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include "client_cachegeneric_bridge.h"
+#include "client_rgxpdump_bridge.h"
 #include "img_defs.h"
 #include "pvr_debug.h"
 
 /* Module specific includes */
-#include "cache_external.h"
+#include "rgx_bridge.h"
 
-#include "cache_generic.h"
+#include "rgxpdump.h"
 
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp)
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePDumpTraceBuffer(IMG_HANDLE hBridge,
+							      IMG_UINT32 ui32PDumpFlags)
 {
 	PVRSRV_ERROR eError;
-	PMR * psPMRInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
 
-	psPMRInt = (PMR *) hPMR;
 
 	eError =
-		CacheOpQueue(
-					psPMRInt,
-					uiOffset,
-					uiSize,
-					iuCacheOp);
+		PVRSRVPDumpTraceBufferKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					ui32PDumpFlags);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePDumpSignatureBuffer(IMG_HANDLE hBridge,
+								  IMG_UINT32 ui32PDumpFlags)
+{
+	PVRSRV_ERROR eError;
+
+
+	eError =
+		PVRSRVPDumpSignatureBufferKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					ui32PDumpFlags);
 
 	return eError;
 }
diff --git a/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h
index d44bbe9..f1aacd5 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxpdump
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxpdump
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxpdump
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_RGXPDUMP_BRIDGE_H
 #define COMMON_RGXPDUMP_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c
index 0b0edf3..152450d 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -81,6 +83,7 @@
 
 
 
+
 	psPDumpTraceBufferOUT->eError =
 		PVRSRVPDumpTraceBufferKM(psConnection, OSGetDevData(psConnection),
 					psPDumpTraceBufferIN->ui32PDumpFlags);
@@ -89,9 +92,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgePDumpSignatureBuffer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_PDUMPSIGNATUREBUFFER *psPDumpSignatureBufferIN,
@@ -105,6 +112,7 @@
 
 
 
+
 	psPDumpSignatureBufferOUT->eError =
 		PVRSRVPDumpSignatureBufferKM(psConnection, OSGetDevData(psConnection),
 					psPDumpSignatureBufferIN->ui32PDumpFlags);
@@ -113,11 +121,15 @@
 
 
 
+
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -150,4 +162,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/rgxray_bridge/common_rgxray_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxray_bridge/common_rgxray_bridge.h
new file mode 100644
index 0000000..a76cc2e
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/rgxray_bridge/common_rgxray_bridge.h
@@ -0,0 +1,281 @@
+/*************************************************************************/ /*!
+@File
+@Title          Common bridge header for rgxray
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxray
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef COMMON_RGXRAY_BRIDGE_H
+#define COMMON_RGXRAY_BRIDGE_H
+
+#include <powervr/mem_types.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+#include "rgx_bridge.h"
+#include "pvrsrv_devmem.h"
+#include "devicemem_typedefs.h"
+
+
+#define PVRSRV_BRIDGE_RGXRAY_CMD_FIRST			0
+#define PVRSRV_BRIDGE_RGXRAY_RGXCREATERPMFREELIST			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+0
+#define PVRSRV_BRIDGE_RGXRAY_RGXDESTROYRPMFREELIST			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+1
+#define PVRSRV_BRIDGE_RGXRAY_RGXCREATERPMCONTEXT			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+2
+#define PVRSRV_BRIDGE_RGXRAY_RGXDESTROYRPMCONTEXT			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+3
+#define PVRSRV_BRIDGE_RGXRAY_RGXKICKRS			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+4
+#define PVRSRV_BRIDGE_RGXRAY_RGXKICKVRDM			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+5
+#define PVRSRV_BRIDGE_RGXRAY_RGXCREATERAYCONTEXT			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+6
+#define PVRSRV_BRIDGE_RGXRAY_RGXDESTROYRAYCONTEXT			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+7
+#define PVRSRV_BRIDGE_RGXRAY_RGXSETRAYCONTEXTPRIORITY			PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+8
+#define PVRSRV_BRIDGE_RGXRAY_CMD_LAST			(PVRSRV_BRIDGE_RGXRAY_CMD_FIRST+8)
+
+
+/*******************************************
+            RGXCreateRPMFreeList          
+ *******************************************/
+
+/* Bridge in structure for RGXCreateRPMFreeList */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATERPMFREELIST_TAG
+{
+	IMG_HANDLE hRPMContext;
+	IMG_UINT32 ui32InitFLPages;
+	IMG_UINT32 ui32GrowFLPages;
+	IMG_DEV_VIRTADDR sFreeListDevVAddr;
+	IMG_BOOL bIsExternal;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATERPMFREELIST;
+
+/* Bridge out structure for RGXCreateRPMFreeList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATERPMFREELIST_TAG
+{
+	IMG_HANDLE hCleanupCookie;
+	IMG_UINT32 ui32HWFreeList;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATERPMFREELIST;
+
+
+/*******************************************
+            RGXDestroyRPMFreeList          
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyRPMFreeList */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYRPMFREELIST_TAG
+{
+	IMG_HANDLE hCleanupCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYRPMFREELIST;
+
+/* Bridge out structure for RGXDestroyRPMFreeList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYRPMFREELIST_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYRPMFREELIST;
+
+
+/*******************************************
+            RGXCreateRPMContext          
+ *******************************************/
+
+/* Bridge in structure for RGXCreateRPMContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATERPMCONTEXT_TAG
+{
+	IMG_UINT32 ui32TotalRPMPages;
+	IMG_UINT32 ui32Log2DopplerPageSize;
+	IMG_DEV_VIRTADDR sSceneMemoryBaseAddr;
+	IMG_DEV_VIRTADDR sDopplerHeapBaseAddr;
+	IMG_HANDLE hSceneHeap;
+	IMG_DEV_VIRTADDR sRPMPageTableBaseAddr;
+	IMG_HANDLE hRPMPageTableHeap;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATERPMCONTEXT;
+
+/* Bridge out structure for RGXCreateRPMContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATERPMCONTEXT_TAG
+{
+	IMG_HANDLE hCleanupCookie;
+	IMG_HANDLE hHWMemDesc;
+	IMG_UINT32 ui32HWFrameData;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATERPMCONTEXT;
+
+
+/*******************************************
+            RGXDestroyRPMContext          
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyRPMContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYRPMCONTEXT_TAG
+{
+	IMG_HANDLE hCleanupCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYRPMCONTEXT;
+
+/* Bridge out structure for RGXDestroyRPMContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYRPMCONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYRPMCONTEXT;
+
+
+/*******************************************
+            RGXKickRS          
+ *******************************************/
+
+/* Bridge in structure for RGXKickRS */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKRS_TAG
+{
+	IMG_HANDLE hRayContext;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
+	IMG_UINT32 ui32ClientFenceCount;
+	IMG_HANDLE * phClientFenceUFOSyncPrimBlock;
+	IMG_UINT32 * pui32ClientFenceSyncOffset;
+	IMG_UINT32 * pui32ClientFenceValue;
+	IMG_UINT32 ui32ClientUpdateCount;
+	IMG_HANDLE * phClientUpdateUFOSyncPrimBlock;
+	IMG_UINT32 * pui32ClientUpdateSyncOffset;
+	IMG_UINT32 * pui32ClientUpdateValue;
+	IMG_UINT32 ui32ServerSyncCount;
+	IMG_UINT32 * pui32ServerSyncFlags;
+	IMG_HANDLE * phServerSyncs;
+	IMG_UINT32 ui32CmdSize;
+	IMG_BYTE * psDMCmd;
+	IMG_UINT32 ui32FCCmdSize;
+	IMG_BYTE * psFCDMCmd;
+	IMG_UINT32 ui32FrameContext;
+	IMG_UINT32 ui32PDumpFlags;
+	IMG_UINT32 ui32ExtJobRef;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKRS;
+
+/* Bridge out structure for RGXKickRS */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKRS_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKRS;
+
+
+/*******************************************
+            RGXKickVRDM          
+ *******************************************/
+
+/* Bridge in structure for RGXKickVRDM */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKVRDM_TAG
+{
+	IMG_HANDLE hRayContext;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
+	IMG_UINT32 ui32ClientFenceCount;
+	IMG_HANDLE * phClientFenceUFOSyncPrimBlock;
+	IMG_UINT32 * pui32ClientFenceSyncOffset;
+	IMG_UINT32 * pui32ClientFenceValue;
+	IMG_UINT32 ui32ClientUpdateCount;
+	IMG_HANDLE * phClientUpdateUFOSyncPrimBlock;
+	IMG_UINT32 * pui32ClientUpdateSyncOffset;
+	IMG_UINT32 * pui32ClientUpdateValue;
+	IMG_UINT32 ui32ServerSyncCount;
+	IMG_UINT32 * pui32ServerSyncFlags;
+	IMG_HANDLE * phServerSyncs;
+	IMG_UINT32 ui32CmdSize;
+	IMG_BYTE * psDMCmd;
+	IMG_UINT32 ui32PDumpFlags;
+	IMG_UINT32 ui32ExtJobRef;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKVRDM;
+
+/* Bridge out structure for RGXKickVRDM */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKVRDM_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKVRDM;
+
+
+/*******************************************
+            RGXCreateRayContext          
+ *******************************************/
+
+/* Bridge in structure for RGXCreateRayContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATERAYCONTEXT_TAG
+{
+	IMG_UINT32 ui32Priority;
+	IMG_DEV_VIRTADDR sMCUFenceAddr;
+	IMG_DEV_VIRTADDR sVRMCallStackAddr;
+	IMG_UINT32 ui32FrameworkCmdSize;
+	IMG_BYTE * psFrameworkCmd;
+	IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATERAYCONTEXT;
+
+/* Bridge out structure for RGXCreateRayContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATERAYCONTEXT_TAG
+{
+	IMG_HANDLE hRayContext;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATERAYCONTEXT;
+
+
+/*******************************************
+            RGXDestroyRayContext          
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyRayContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYRAYCONTEXT_TAG
+{
+	IMG_HANDLE hRayContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYRAYCONTEXT;
+
+/* Bridge out structure for RGXDestroyRayContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYRAYCONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYRAYCONTEXT;
+
+
+/*******************************************
+            RGXSetRayContextPriority          
+ *******************************************/
+
+/* Bridge in structure for RGXSetRayContextPriority */
+typedef struct PVRSRV_BRIDGE_IN_RGXSETRAYCONTEXTPRIORITY_TAG
+{
+	IMG_HANDLE hRayContext;
+	IMG_UINT32 ui32Priority;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSETRAYCONTEXTPRIORITY;
+
+/* Bridge out structure for RGXSetRayContextPriority */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSETRAYCONTEXTPRIORITY_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETRAYCONTEXTPRIORITY;
+
+
+#endif /* COMMON_RGXRAY_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxray_bridge/server_rgxray_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxray_bridge/server_rgxray_bridge.c
new file mode 100644
index 0000000..2246f93
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/rgxray_bridge/server_rgxray_bridge.c
@@ -0,0 +1,1887 @@
+/*************************************************************************/ /*!
+@File
+@Title          Server bridge for rgxray
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements the server side of the bridge for rgxray
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxray.h"
+#include "devicemem_server.h"
+
+
+#include "common_rgxray_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#include <linux/slab.h>
+
+
+#include "rgx_bvnc_defs_km.h"
+
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+ 
+static IMG_INT
+PVRSRVBridgeRGXCreateRPMFreeList(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXCREATERPMFREELIST *psRGXCreateRPMFreeListIN,
+					  PVRSRV_BRIDGE_OUT_RGXCREATERPMFREELIST *psRGXCreateRPMFreeListOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hRPMContext = psRGXCreateRPMFreeListIN->hRPMContext;
+	RGX_SERVER_RPM_CONTEXT * psRPMContextInt = NULL;
+	RGX_RPM_FREELIST * psCleanupCookieInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXCreateRPMFreeListOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXCreateRPMFreeList_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXCreateRPMFreeListOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psRPMContextInt,
+											hRPMContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT,
+											IMG_TRUE);
+					if(psRGXCreateRPMFreeListOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXCreateRPMFreeList_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXCreateRPMFreeListOUT->eError =
+		RGXCreateRPMFreeList(psConnection, OSGetDevData(psConnection),
+					psRPMContextInt,
+					psRGXCreateRPMFreeListIN->ui32InitFLPages,
+					psRGXCreateRPMFreeListIN->ui32GrowFLPages,
+					psRGXCreateRPMFreeListIN->sFreeListDevVAddr,
+					&psCleanupCookieInt,
+					&psRGXCreateRPMFreeListOUT->ui32HWFreeList,
+					psRGXCreateRPMFreeListIN->bIsExternal);
+	/* Exit early if bridged call fails */
+	if(psRGXCreateRPMFreeListOUT->eError != PVRSRV_OK)
+	{
+		goto RGXCreateRPMFreeList_exit;
+	}
+
+	/* Lock over handle creation. */
+	LockHandle();
+
+
+
+
+
+	psRGXCreateRPMFreeListOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
+							&psRGXCreateRPMFreeListOUT->hCleanupCookie,
+							(void *) psCleanupCookieInt,
+							PVRSRV_HANDLE_TYPE_RGX_RPM_FREELIST,
+							PVRSRV_HANDLE_ALLOC_FLAG_NONE
+							,(PFN_HANDLE_RELEASE)&RGXDestroyRPMFreeList);
+	if (psRGXCreateRPMFreeListOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto RGXCreateRPMFreeList_exit;
+	}
+
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+RGXCreateRPMFreeList_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRPMContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRPMContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	if (psRGXCreateRPMFreeListOUT->eError != PVRSRV_OK)
+	{
+		if (psCleanupCookieInt)
+		{
+			RGXDestroyRPMFreeList(psCleanupCookieInt);
+		}
+	}
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyRPMFreeList(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXDESTROYRPMFREELIST *psRGXDestroyRPMFreeListIN,
+					  PVRSRV_BRIDGE_OUT_RGXDESTROYRPMFREELIST *psRGXDestroyRPMFreeListOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXDestroyRPMFreeListOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXDestroyRPMFreeList_exit;
+		}
+	}
+
+
+
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
+	psRGXDestroyRPMFreeListOUT->eError =
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+					(IMG_HANDLE) psRGXDestroyRPMFreeListIN->hCleanupCookie,
+					PVRSRV_HANDLE_TYPE_RGX_RPM_FREELIST);
+	if ((psRGXDestroyRPMFreeListOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyRPMFreeListOUT->eError != PVRSRV_ERROR_RETRY))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyRPMFreeList: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyRPMFreeListOUT->eError)));
+		PVR_ASSERT(0);
+		UnlockHandle();
+		goto RGXDestroyRPMFreeList_exit;
+	}
+
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
+
+
+RGXDestroyRPMFreeList_exit:
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXCreateRPMContext(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXCREATERPMCONTEXT *psRGXCreateRPMContextIN,
+					  PVRSRV_BRIDGE_OUT_RGXCREATERPMCONTEXT *psRGXCreateRPMContextOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	RGX_SERVER_RPM_CONTEXT * psCleanupCookieInt = NULL;
+	IMG_HANDLE hSceneHeap = psRGXCreateRPMContextIN->hSceneHeap;
+	DEVMEMINT_HEAP * psSceneHeapInt = NULL;
+	IMG_HANDLE hRPMPageTableHeap = psRGXCreateRPMContextIN->hRPMPageTableHeap;
+	DEVMEMINT_HEAP * psRPMPageTableHeapInt = NULL;
+	DEVMEM_MEMDESC * psHWMemDescInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXCreateRPMContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXCreateRPMContext_exit;
+		}
+	}
+
+
+
+	psRGXCreateRPMContextOUT->hCleanupCookie = NULL;
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXCreateRPMContextOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psSceneHeapInt,
+											hSceneHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+											IMG_TRUE);
+					if(psRGXCreateRPMContextOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXCreateRPMContext_exit;
+					}
+				}
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXCreateRPMContextOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psRPMPageTableHeapInt,
+											hRPMPageTableHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+											IMG_TRUE);
+					if(psRGXCreateRPMContextOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXCreateRPMContext_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXCreateRPMContextOUT->eError =
+		RGXCreateRPMContext(psConnection, OSGetDevData(psConnection),
+					&psCleanupCookieInt,
+					psRGXCreateRPMContextIN->ui32TotalRPMPages,
+					psRGXCreateRPMContextIN->ui32Log2DopplerPageSize,
+					psRGXCreateRPMContextIN->sSceneMemoryBaseAddr,
+					psRGXCreateRPMContextIN->sDopplerHeapBaseAddr,
+					psSceneHeapInt,
+					psRGXCreateRPMContextIN->sRPMPageTableBaseAddr,
+					psRPMPageTableHeapInt,
+					&psHWMemDescInt,
+					&psRGXCreateRPMContextOUT->ui32HWFrameData);
+	/* Exit early if bridged call fails */
+	if(psRGXCreateRPMContextOUT->eError != PVRSRV_OK)
+	{
+		goto RGXCreateRPMContext_exit;
+	}
+
+	/* Lock over handle creation. */
+	LockHandle();
+
+
+
+
+
+	psRGXCreateRPMContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
+							&psRGXCreateRPMContextOUT->hCleanupCookie,
+							(void *) psCleanupCookieInt,
+							PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT,
+							PVRSRV_HANDLE_ALLOC_FLAG_NONE
+							,(PFN_HANDLE_RELEASE)&RGXDestroyRPMContext);
+	if (psRGXCreateRPMContextOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto RGXCreateRPMContext_exit;
+	}
+
+
+
+
+
+
+	psRGXCreateRPMContextOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
+							&psRGXCreateRPMContextOUT->hHWMemDesc,
+							(void *) psHWMemDescInt,
+							PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
+							PVRSRV_HANDLE_ALLOC_FLAG_NONE
+							,psRGXCreateRPMContextOUT->hCleanupCookie);
+	if (psRGXCreateRPMContextOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto RGXCreateRPMContext_exit;
+	}
+
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+RGXCreateRPMContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSceneHeapInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSceneHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRPMPageTableHeapInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRPMPageTableHeap,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	if (psRGXCreateRPMContextOUT->eError != PVRSRV_OK)
+	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
+		if (psRGXCreateRPMContextOUT->hCleanupCookie)
+		{
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+						(IMG_HANDLE) psRGXCreateRPMContextOUT->hCleanupCookie,
+						PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT);
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgeRGXCreateRPMContext: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
+			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+			/* Avoid freeing/destroying/releasing the resource a second time below */
+			psCleanupCookieInt = NULL;
+		}
+
+
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
+		if (psCleanupCookieInt)
+		{
+			RGXDestroyRPMContext(psCleanupCookieInt);
+		}
+	}
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyRPMContext(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXDESTROYRPMCONTEXT *psRGXDestroyRPMContextIN,
+					  PVRSRV_BRIDGE_OUT_RGXDESTROYRPMCONTEXT *psRGXDestroyRPMContextOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXDestroyRPMContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXDestroyRPMContext_exit;
+		}
+	}
+
+
+
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
+	psRGXDestroyRPMContextOUT->eError =
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+					(IMG_HANDLE) psRGXDestroyRPMContextIN->hCleanupCookie,
+					PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT);
+	if ((psRGXDestroyRPMContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyRPMContextOUT->eError != PVRSRV_ERROR_RETRY))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyRPMContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyRPMContextOUT->eError)));
+		PVR_ASSERT(0);
+		UnlockHandle();
+		goto RGXDestroyRPMContext_exit;
+	}
+
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
+
+
+RGXDestroyRPMContext_exit:
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXKickRS(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXKICKRS *psRGXKickRSIN,
+					  PVRSRV_BRIDGE_OUT_RGXKICKRS *psRGXKickRSOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hRayContext = psRGXKickRSIN->hRayContext;
+	RGX_SERVER_RAY_CONTEXT * psRayContextInt = NULL;
+	SYNC_PRIMITIVE_BLOCK * *psClientFenceUFOSyncPrimBlockInt = NULL;
+	IMG_HANDLE *hClientFenceUFOSyncPrimBlockInt2 = NULL;
+	IMG_UINT32 *ui32ClientFenceSyncOffsetInt = NULL;
+	IMG_UINT32 *ui32ClientFenceValueInt = NULL;
+	SYNC_PRIMITIVE_BLOCK * *psClientUpdateUFOSyncPrimBlockInt = NULL;
+	IMG_HANDLE *hClientUpdateUFOSyncPrimBlockInt2 = NULL;
+	IMG_UINT32 *ui32ClientUpdateSyncOffsetInt = NULL;
+	IMG_UINT32 *ui32ClientUpdateValueInt = NULL;
+	IMG_UINT32 *ui32ServerSyncFlagsInt = NULL;
+	SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = NULL;
+	IMG_HANDLE *hServerSyncsInt2 = NULL;
+	IMG_BYTE *psDMCmdInt = NULL;
+	IMG_BYTE *psFCDMCmdInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXKickRSIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickRSIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) +
+			(psRGXKickRSIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickRSIN->ui32CmdSize * sizeof(IMG_BYTE)) +
+			(psRGXKickRSIN->ui32FCCmdSize * sizeof(IMG_BYTE)) +
+			0;
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXKickRSOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXKickRS_exit;
+		}
+	}
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXKickRSIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXKickRSIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXKickRSOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXKickRS_exit;
+			}
+		}
+	}
+
+	if (psRGXKickRSIN->ui32ClientFenceCount != 0)
+	{
+		psClientFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hClientFenceUFOSyncPrimBlockInt2, psRGXKickRSIN->phClientFenceUFOSyncPrimBlock, psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ClientFenceCount != 0)
+	{
+		ui32ClientFenceSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientFenceSyncOffsetInt, psRGXKickRSIN->pui32ClientFenceSyncOffset, psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ClientFenceCount != 0)
+	{
+		ui32ClientFenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickRSIN->pui32ClientFenceValue, psRGXKickRSIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ClientUpdateCount != 0)
+	{
+		psClientUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hClientUpdateUFOSyncPrimBlockInt2, psRGXKickRSIN->phClientUpdateUFOSyncPrimBlock, psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ClientUpdateCount != 0)
+	{
+		ui32ClientUpdateSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateSyncOffsetInt, psRGXKickRSIN->pui32ClientUpdateSyncOffset, psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ClientUpdateCount != 0)
+	{
+		ui32ClientUpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickRSIN->pui32ClientUpdateValue, psRGXKickRSIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ServerSyncCount != 0)
+	{
+		ui32ServerSyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickRSIN->pui32ServerSyncFlags, psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32ServerSyncCount != 0)
+	{
+		psServerSyncsInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerSyncsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickRSIN->phServerSyncs, psRGXKickRSIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32CmdSize != 0)
+	{
+		psDMCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32CmdSize * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32CmdSize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psDMCmdInt, psRGXKickRSIN->psDMCmd, psRGXKickRSIN->ui32CmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+	if (psRGXKickRSIN->ui32FCCmdSize != 0)
+	{
+		psFCDMCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickRSIN->ui32FCCmdSize * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickRSIN->ui32FCCmdSize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psFCDMCmdInt, psRGXKickRSIN->psFCDMCmd, psRGXKickRSIN->ui32FCCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickRSOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickRS_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXKickRSOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psRayContextInt,
+											hRayContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
+											IMG_TRUE);
+					if(psRGXKickRSOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickRS_exit;
+					}
+				}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickRSIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXKickRSOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psClientFenceUFOSyncPrimBlockInt[i],
+											hClientFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psRGXKickRSOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickRS_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickRSIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXKickRSOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psClientUpdateUFOSyncPrimBlockInt[i],
+											hClientUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psRGXKickRSOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickRS_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickRSIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXKickRSOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psServerSyncsInt[i],
+											hServerSyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
+					if(psRGXKickRSOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickRS_exit;
+					}
+				}
+		}
+	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXKickRSOUT->eError =
+		PVRSRVRGXKickRSKM(
+					psRayContextInt,
+					psRGXKickRSIN->ui32ClientCacheOpSeqNum,
+					psRGXKickRSIN->ui32ClientFenceCount,
+					psClientFenceUFOSyncPrimBlockInt,
+					ui32ClientFenceSyncOffsetInt,
+					ui32ClientFenceValueInt,
+					psRGXKickRSIN->ui32ClientUpdateCount,
+					psClientUpdateUFOSyncPrimBlockInt,
+					ui32ClientUpdateSyncOffsetInt,
+					ui32ClientUpdateValueInt,
+					psRGXKickRSIN->ui32ServerSyncCount,
+					ui32ServerSyncFlagsInt,
+					psServerSyncsInt,
+					psRGXKickRSIN->ui32CmdSize,
+					psDMCmdInt,
+					psRGXKickRSIN->ui32FCCmdSize,
+					psFCDMCmdInt,
+					psRGXKickRSIN->ui32FrameContext,
+					psRGXKickRSIN->ui32PDumpFlags,
+					psRGXKickRSIN->ui32ExtJobRef);
+
+
+
+
+RGXKickRS_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRayContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT);
+						}
+				}
+
+
+
+
+
+
+	if (hClientFenceUFOSyncPrimBlockInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickRSIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientFenceUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hClientUpdateUFOSyncPrimBlockInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickRSIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientUpdateUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hServerSyncsInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickRSIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXKickVRDM(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXKICKVRDM *psRGXKickVRDMIN,
+					  PVRSRV_BRIDGE_OUT_RGXKICKVRDM *psRGXKickVRDMOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hRayContext = psRGXKickVRDMIN->hRayContext;
+	RGX_SERVER_RAY_CONTEXT * psRayContextInt = NULL;
+	SYNC_PRIMITIVE_BLOCK * *psClientFenceUFOSyncPrimBlockInt = NULL;
+	IMG_HANDLE *hClientFenceUFOSyncPrimBlockInt2 = NULL;
+	IMG_UINT32 *ui32ClientFenceSyncOffsetInt = NULL;
+	IMG_UINT32 *ui32ClientFenceValueInt = NULL;
+	SYNC_PRIMITIVE_BLOCK * *psClientUpdateUFOSyncPrimBlockInt = NULL;
+	IMG_HANDLE *hClientUpdateUFOSyncPrimBlockInt2 = NULL;
+	IMG_UINT32 *ui32ClientUpdateSyncOffsetInt = NULL;
+	IMG_UINT32 *ui32ClientUpdateValueInt = NULL;
+	IMG_UINT32 *ui32ServerSyncFlagsInt = NULL;
+	SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = NULL;
+	IMG_HANDLE *hServerSyncsInt2 = NULL;
+	IMG_BYTE *psDMCmdInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) +
+			(psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickVRDMIN->ui32CmdSize * sizeof(IMG_BYTE)) +
+			0;
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXKickVRDMOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXKickVRDM_exit;
+		}
+	}
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXKickVRDMIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXKickVRDMIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXKickVRDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXKickVRDM_exit;
+			}
+		}
+	}
+
+	if (psRGXKickVRDMIN->ui32ClientFenceCount != 0)
+	{
+		psClientFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hClientFenceUFOSyncPrimBlockInt2, psRGXKickVRDMIN->phClientFenceUFOSyncPrimBlock, psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ClientFenceCount != 0)
+	{
+		ui32ClientFenceSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientFenceSyncOffsetInt, psRGXKickVRDMIN->pui32ClientFenceSyncOffset, psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ClientFenceCount != 0)
+	{
+		ui32ClientFenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickVRDMIN->pui32ClientFenceValue, psRGXKickVRDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ClientUpdateCount != 0)
+	{
+		psClientUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hClientUpdateUFOSyncPrimBlockInt2, psRGXKickVRDMIN->phClientUpdateUFOSyncPrimBlock, psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ClientUpdateCount != 0)
+	{
+		ui32ClientUpdateSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateSyncOffsetInt, psRGXKickVRDMIN->pui32ClientUpdateSyncOffset, psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ClientUpdateCount != 0)
+	{
+		ui32ClientUpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickVRDMIN->pui32ClientUpdateValue, psRGXKickVRDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ServerSyncCount != 0)
+	{
+		ui32ServerSyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickVRDMIN->pui32ServerSyncFlags, psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32ServerSyncCount != 0)
+	{
+		psServerSyncsInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerSyncsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickVRDMIN->phServerSyncs, psRGXKickVRDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+	if (psRGXKickVRDMIN->ui32CmdSize != 0)
+	{
+		psDMCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickVRDMIN->ui32CmdSize * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psRGXKickVRDMIN->ui32CmdSize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psDMCmdInt, psRGXKickVRDMIN->psDMCmd, psRGXKickVRDMIN->ui32CmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickVRDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXKickVRDM_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXKickVRDMOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psRayContextInt,
+											hRayContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
+											IMG_TRUE);
+					if(psRGXKickVRDMOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickVRDM_exit;
+					}
+				}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickVRDMIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXKickVRDMOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psClientFenceUFOSyncPrimBlockInt[i],
+											hClientFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psRGXKickVRDMOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickVRDM_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickVRDMIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXKickVRDMOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psClientUpdateUFOSyncPrimBlockInt[i],
+											hClientUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psRGXKickVRDMOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickVRDM_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickVRDMIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXKickVRDMOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psServerSyncsInt[i],
+											hServerSyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
+					if(psRGXKickVRDMOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXKickVRDM_exit;
+					}
+				}
+		}
+	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXKickVRDMOUT->eError =
+		PVRSRVRGXKickVRDMKM(
+					psRayContextInt,
+					psRGXKickVRDMIN->ui32ClientCacheOpSeqNum,
+					psRGXKickVRDMIN->ui32ClientFenceCount,
+					psClientFenceUFOSyncPrimBlockInt,
+					ui32ClientFenceSyncOffsetInt,
+					ui32ClientFenceValueInt,
+					psRGXKickVRDMIN->ui32ClientUpdateCount,
+					psClientUpdateUFOSyncPrimBlockInt,
+					ui32ClientUpdateSyncOffsetInt,
+					ui32ClientUpdateValueInt,
+					psRGXKickVRDMIN->ui32ServerSyncCount,
+					ui32ServerSyncFlagsInt,
+					psServerSyncsInt,
+					psRGXKickVRDMIN->ui32CmdSize,
+					psDMCmdInt,
+					psRGXKickVRDMIN->ui32PDumpFlags,
+					psRGXKickVRDMIN->ui32ExtJobRef);
+
+
+
+
+RGXKickVRDM_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRayContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT);
+						}
+				}
+
+
+
+
+
+
+	if (hClientFenceUFOSyncPrimBlockInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickVRDMIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientFenceUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hClientUpdateUFOSyncPrimBlockInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickVRDMIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientUpdateUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hServerSyncsInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickVRDMIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXCreateRayContext(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXCREATERAYCONTEXT *psRGXCreateRayContextIN,
+					  PVRSRV_BRIDGE_OUT_RGXCREATERAYCONTEXT *psRGXCreateRayContextOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_BYTE *psFrameworkCmdInt = NULL;
+	IMG_HANDLE hPrivData = psRGXCreateRayContextIN->hPrivData;
+	IMG_HANDLE hPrivDataInt = NULL;
+	RGX_SERVER_RAY_CONTEXT * psRayContextInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXCreateRayContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE)) +
+			0;
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXCreateRayContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXCreateRayContext_exit;
+		}
+	}
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXCreateRayContextIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXCreateRayContextIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXCreateRayContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXCreateRayContext_exit;
+			}
+		}
+	}
+
+	if (psRGXCreateRayContextIN->ui32FrameworkCmdSize != 0)
+	{
+		psFrameworkCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXCreateRayContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psRGXCreateRayContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateRayContextIN->psFrameworkCmd, psRGXCreateRayContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXCreateRayContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXCreateRayContext_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXCreateRayContextOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &hPrivDataInt,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
+					if(psRGXCreateRayContextOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXCreateRayContext_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXCreateRayContextOUT->eError =
+		PVRSRVRGXCreateRayContextKM(psConnection, OSGetDevData(psConnection),
+					psRGXCreateRayContextIN->ui32Priority,
+					psRGXCreateRayContextIN->sMCUFenceAddr,
+					psRGXCreateRayContextIN->sVRMCallStackAddr,
+					psRGXCreateRayContextIN->ui32FrameworkCmdSize,
+					psFrameworkCmdInt,
+					hPrivDataInt,
+					&psRayContextInt);
+	/* Exit early if bridged call fails */
+	if(psRGXCreateRayContextOUT->eError != PVRSRV_OK)
+	{
+		goto RGXCreateRayContext_exit;
+	}
+
+	/* Lock over handle creation. */
+	LockHandle();
+
+
+
+
+
+	psRGXCreateRayContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
+							&psRGXCreateRayContextOUT->hRayContext,
+							(void *) psRayContextInt,
+							PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
+							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+							,(PFN_HANDLE_RELEASE)&PVRSRVRGXDestroyRayContextKM);
+	if (psRGXCreateRayContextOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto RGXCreateRayContext_exit;
+	}
+
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+RGXCreateRayContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	if (psRGXCreateRayContextOUT->eError != PVRSRV_OK)
+	{
+		if (psRayContextInt)
+		{
+			PVRSRVRGXDestroyRayContextKM(psRayContextInt);
+		}
+	}
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyRayContext(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXDESTROYRAYCONTEXT *psRGXDestroyRayContextIN,
+					  PVRSRV_BRIDGE_OUT_RGXDESTROYRAYCONTEXT *psRGXDestroyRayContextOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXDestroyRayContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXDestroyRayContext_exit;
+		}
+	}
+
+
+
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
+	psRGXDestroyRayContextOUT->eError =
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+					(IMG_HANDLE) psRGXDestroyRayContextIN->hRayContext,
+					PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT);
+	if ((psRGXDestroyRayContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyRayContextOUT->eError != PVRSRV_ERROR_RETRY))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyRayContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyRayContextOUT->eError)));
+		PVR_ASSERT(0);
+		UnlockHandle();
+		goto RGXDestroyRayContext_exit;
+	}
+
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
+
+
+RGXDestroyRayContext_exit:
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXSetRayContextPriority(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXSETRAYCONTEXTPRIORITY *psRGXSetRayContextPriorityIN,
+					  PVRSRV_BRIDGE_OUT_RGXSETRAYCONTEXTPRIORITY *psRGXSetRayContextPriorityOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hRayContext = psRGXSetRayContextPriorityIN->hRayContext;
+	RGX_SERVER_RAY_CONTEXT * psRayContextInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_RAY_TRACING_BIT_MASK))
+		{
+			psRGXSetRayContextPriorityOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXSetRayContextPriority_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXSetRayContextPriorityOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psRayContextInt,
+											hRayContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
+											IMG_TRUE);
+					if(psRGXSetRayContextPriorityOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXSetRayContextPriority_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXSetRayContextPriorityOUT->eError =
+		PVRSRVRGXSetRayContextPriorityKM(psConnection, OSGetDevData(psConnection),
+					psRayContextInt,
+					psRGXSetRayContextPriorityIN->ui32Priority);
+
+
+
+
+RGXSetRayContextPriority_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRayContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRayContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+
+
+/* *************************************************************************** 
+ * Server bridge dispatch related glue 
+ */
+
+static IMG_BOOL bUseLock = IMG_TRUE;
+
+PVRSRV_ERROR InitRGXRAYBridge(void);
+PVRSRV_ERROR DeinitRGXRAYBridge(void);
+
+/*
+ * Register all RGXRAY functions with services
+ */
+PVRSRV_ERROR InitRGXRAYBridge(void)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXCREATERPMFREELIST, PVRSRVBridgeRGXCreateRPMFreeList,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXDESTROYRPMFREELIST, PVRSRVBridgeRGXDestroyRPMFreeList,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXCREATERPMCONTEXT, PVRSRVBridgeRGXCreateRPMContext,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXDESTROYRPMCONTEXT, PVRSRVBridgeRGXDestroyRPMContext,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXKICKRS, PVRSRVBridgeRGXKickRS,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXKICKVRDM, PVRSRVBridgeRGXKickVRDM,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXCREATERAYCONTEXT, PVRSRVBridgeRGXCreateRayContext,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXDESTROYRAYCONTEXT, PVRSRVBridgeRGXDestroyRayContext,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXRAY, PVRSRV_BRIDGE_RGXRAY_RGXSETRAYCONTEXTPRIORITY, PVRSRVBridgeRGXSetRayContextPriority,
+					NULL, bUseLock);
+
+
+	return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxray functions with services
+ */
+PVRSRV_ERROR DeinitRGXRAYBridge(void)
+{
+	return PVRSRV_OK;
+}
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxsignals_bridge/common_rgxsignals_bridge.h
similarity index 69%
rename from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h
rename to drivers/staging/imgtec/rogue/generated/rgxsignals_bridge/common_rgxsignals_bridge.h
index ff34c80..18d747e 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxsignals_bridge/common_rgxsignals_bridge.h
@@ -1,9 +1,9 @@
 /*************************************************************************/ /*!
 @File
-@Title          Common bridge header for cachegeneric
+@Title          Common bridge header for rgxsignals
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for cachegeneric
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxsignals
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -42,38 +42,38 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef COMMON_CACHEGENERIC_BRIDGE_H
-#define COMMON_CACHEGENERIC_BRIDGE_H
+#ifndef COMMON_RGXSIGNALS_BRIDGE_H
+#define COMMON_RGXSIGNALS_BRIDGE_H
+
+#include <powervr/mem_types.h>
 
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
-#include "cache_external.h"
+#include "rgx_bridge.h"
 
 
-#define PVRSRV_BRIDGE_CACHEGENERIC_CMD_FIRST			0
-#define PVRSRV_BRIDGE_CACHEGENERIC_CACHEOPQUEUE			PVRSRV_BRIDGE_CACHEGENERIC_CMD_FIRST+0
-#define PVRSRV_BRIDGE_CACHEGENERIC_CMD_LAST			(PVRSRV_BRIDGE_CACHEGENERIC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXSIGNALS_CMD_FIRST			0
+#define PVRSRV_BRIDGE_RGXSIGNALS_RGXNOTIFYSIGNALUPDATE			PVRSRV_BRIDGE_RGXSIGNALS_CMD_FIRST+0
+#define PVRSRV_BRIDGE_RGXSIGNALS_CMD_LAST			(PVRSRV_BRIDGE_RGXSIGNALS_CMD_FIRST+0)
 
 
 /*******************************************
-            CacheOpQueue          
+            RGXNotifySignalUpdate          
  *******************************************/
 
-/* Bridge in structure for CacheOpQueue */
-typedef struct PVRSRV_BRIDGE_IN_CACHEOPQUEUE_TAG
+/* Bridge in structure for RGXNotifySignalUpdate */
+typedef struct PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE_TAG
 {
-	IMG_HANDLE hPMR;
-	IMG_DEVMEM_OFFSET_T uiOffset;
-	IMG_DEVMEM_SIZE_T uiSize;
-	PVRSRV_CACHE_OP iuCacheOp;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_CACHEOPQUEUE;
+	IMG_HANDLE hPrivData;
+	IMG_DEV_VIRTADDR sDevSignalAddress;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE;
 
-/* Bridge out structure for CacheOpQueue */
-typedef struct PVRSRV_BRIDGE_OUT_CACHEOPQUEUE_TAG
+/* Bridge out structure for RGXNotifySignalUpdate */
+typedef struct PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE_TAG
 {
 	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CACHEOPQUEUE;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE;
 
 
-#endif /* COMMON_CACHEGENERIC_BRIDGE_H */
+#endif /* COMMON_RGXSIGNALS_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxsignals_bridge/server_rgxsignals_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxsignals_bridge/server_rgxsignals_bridge.c
new file mode 100644
index 0000000..7b9db97
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/rgxsignals_bridge/server_rgxsignals_bridge.c
@@ -0,0 +1,190 @@
+/*************************************************************************/ /*!
+@File
+@Title          Server bridge for rgxsignals
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements the server side of the bridge for rgxsignals
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxsignals.h"
+
+
+#include "common_rgxsignals_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#include <linux/slab.h>
+
+
+#include "rgx_bvnc_defs_km.h"
+
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+ 
+static IMG_INT
+PVRSRVBridgeRGXNotifySignalUpdate(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE *psRGXNotifySignalUpdateIN,
+					  PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE *psRGXNotifySignalUpdateOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hPrivData = psRGXNotifySignalUpdateIN->hPrivData;
+	IMG_HANDLE hPrivDataInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK))
+		{
+			psRGXNotifySignalUpdateOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXNotifySignalUpdate_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXNotifySignalUpdateOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &hPrivDataInt,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
+					if(psRGXNotifySignalUpdateOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXNotifySignalUpdate_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXNotifySignalUpdateOUT->eError =
+		PVRSRVRGXNotifySignalUpdateKM(psConnection, OSGetDevData(psConnection),
+					hPrivDataInt,
+					psRGXNotifySignalUpdateIN->sDevSignalAddress);
+
+
+
+
+RGXNotifySignalUpdate_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+
+
+/* *************************************************************************** 
+ * Server bridge dispatch related glue 
+ */
+
+static IMG_BOOL bUseLock = IMG_TRUE;
+
+PVRSRV_ERROR InitRGXSIGNALSBridge(void);
+PVRSRV_ERROR DeinitRGXSIGNALSBridge(void);
+
+/*
+ * Register all RGXSIGNALS functions with services
+ */
+PVRSRV_ERROR InitRGXSIGNALSBridge(void)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXSIGNALS, PVRSRV_BRIDGE_RGXSIGNALS_RGXNOTIFYSIGNALUPDATE, PVRSRVBridgeRGXNotifySignalUpdate,
+					NULL, bUseLock);
+
+
+	return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxsignals functions with services
+ */
+PVRSRV_ERROR DeinitRGXSIGNALSBridge(void)
+{
+	return PVRSRV_OK;
+}
diff --git a/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h
index 4a07ac2..9f062c4 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxta3d
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxta3d
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxta3d
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,11 +45,13 @@
 #ifndef COMMON_RGXTA3D_BRIDGE_H
 #define COMMON_RGXTA3D_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "rgx_bridge.h"
-#include "sync_external.h"
+#include <powervr/sync_external.h>
 #include "rgx_fwif_shared.h"
 
 
@@ -253,6 +255,7 @@
 	IMG_UINT32 ui32ui32MaxFLPages;
 	IMG_UINT32 ui32ui32InitFLPages;
 	IMG_UINT32 ui32ui32GrowFLPages;
+	IMG_HANDLE hsGlobalFreeList;
 	IMG_BOOL bbFreeListCheck;
 	IMG_DEV_VIRTADDR spsFreeListDevVAddr;
 	IMG_HANDLE hsFreeListPMR;
@@ -367,6 +370,7 @@
 typedef struct PVRSRV_BRIDGE_IN_RGXKICKTA3D_TAG
 {
 	IMG_HANDLE hRenderContext;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
 	IMG_UINT32 ui32ClientTAFenceCount;
 	IMG_HANDLE * phClientTAFenceSyncPrimBlock;
 	IMG_UINT32 * pui32ClientTAFenceSyncOffset;
@@ -402,13 +406,12 @@
 	IMG_UINT32 ui323DCmdSize;
 	IMG_BYTE * ps3DCmd;
 	IMG_UINT32 ui32ExtJobRef;
-	IMG_UINT32 ui32IntJobRef;
 	IMG_BOOL bbLastTAInScene;
 	IMG_BOOL bbKickTA;
 	IMG_BOOL bbKickPR;
 	IMG_BOOL bbKick3D;
 	IMG_BOOL bbAbort;
-	IMG_BOOL bbPDumpContinuous;
+	IMG_UINT32 ui32PDumpFlags;
 	IMG_HANDLE hRTDataCleanup;
 	IMG_HANDLE hZBuffer;
 	IMG_HANDLE hSBuffer;
@@ -417,6 +420,11 @@
 	IMG_UINT32 ui32SyncPMRCount;
 	IMG_UINT32 * pui32SyncPMRFlags;
 	IMG_HANDLE * phSyncPMRs;
+	IMG_UINT32 ui32RenderTargetSize;
+	IMG_UINT32 ui32NumberOfDrawCalls;
+	IMG_UINT32 ui32NumberOfIndices;
+	IMG_UINT32 ui32NumberOfMRTs;
+	IMG_UINT64 ui64Deadline;
 } __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKTA3D;
 
 /* Bridge out structure for RGXKickTA3D */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c
index 8ad589f..e5596a4 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -80,39 +82,73 @@
 	DEVMEM_MEMDESC * psRTACtlMemDescInt = NULL;
 	DEVMEM_MEMDESC * pssHWRTDataMemDescInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(RGXFW_MAX_FREELISTS * sizeof(RGX_FREELIST *)) +
+			(RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE)) +
+			0;
+
+
 
 
 	psRGXCreateHWRTDataOUT->hCleanupCookie = NULL;
 
-	
+	if (ui32BufferSize != 0)
 	{
-		psapsFreeListsInt = OSAllocMemNoStats(RGXFW_MAX_FREELISTS * sizeof(RGX_FREELIST *));
-		if (!psapsFreeListsInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXCreateHWRTDataIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXCreateHWRTData_exit;
-		}
-		hapsFreeListsInt2 = OSAllocMemNoStats(RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE));
-		if (!hapsFreeListsInt2)
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXCreateHWRTDataIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
 		{
-			psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXCreateHWRTData_exit;
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXCreateHWRTData_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXCreateHWRTDataIN->phapsFreeLists, RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hapsFreeListsInt2, psRGXCreateHWRTDataIN->phapsFreeLists,
-				RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
-			{
-				psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	
+	{
+		psapsFreeListsInt = (RGX_FREELIST **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += RGXFW_MAX_FREELISTS * sizeof(RGX_FREELIST *);
+		hapsFreeListsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE);
+	}
 
-				goto RGXCreateHWRTData_exit;
+			/* Copy the data over */
+			if (RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hapsFreeListsInt2, psRGXCreateHWRTDataIN->phapsFreeLists, RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXCreateHWRTData_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 	{
@@ -123,19 +159,21 @@
 				{
 					/* Look up the address from the handle */
 					psRGXCreateHWRTDataOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psapsFreeListsInt[i],
 											hapsFreeListsInt2[i],
-											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST,
+											IMG_TRUE);
 					if(psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateHWRTData_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateHWRTDataOUT->eError =
 		RGXCreateHWRTData(psConnection, OSGetDevData(psConnection),
@@ -168,13 +206,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateHWRTData_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateHWRTDataOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateHWRTDataOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateHWRTDataOUT->hCleanupCookie,
 							(void *) psCleanupCookieInt,
 							PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
@@ -182,11 +225,17 @@
 							,(PFN_HANDLE_RELEASE)&RGXDestroyHWRTData);
 	if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateHWRTData_exit;
 	}
 
 
-	psRGXCreateHWRTDataOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+
+
+
+
+	psRGXCreateHWRTDataOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateHWRTDataOUT->hRTACtlMemDesc,
 							(void *) psRTACtlMemDescInt,
 							PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
@@ -194,11 +243,17 @@
 							,psRGXCreateHWRTDataOUT->hCleanupCookie);
 	if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateHWRTData_exit;
 	}
 
 
-	psRGXCreateHWRTDataOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+
+
+
+
+	psRGXCreateHWRTDataOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateHWRTDataOUT->hsHWRTDataMemDesc,
 							(void *) pssHWRTDataMemDescInt,
 							PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
@@ -206,22 +261,65 @@
 							,psRGXCreateHWRTDataOUT->hCleanupCookie);
 	if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateHWRTData_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateHWRTData_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+
+	if (hapsFreeListsInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<RGXFW_MAX_FREELISTS;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psapsFreeListsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hapsFreeListsInt2[i],
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
 	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
 		if (psRGXCreateHWRTDataOUT->hCleanupCookie)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 						(IMG_HANDLE) psRGXCreateHWRTDataOUT->hCleanupCookie,
 						PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgeRGXCreateHWRTData: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 			/* Avoid freeing/destroying/releasing the resource a second time below */
@@ -229,20 +327,29 @@
 		}
 
 
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
 		if (psCleanupCookieInt)
 		{
 			RGXDestroyHWRTData(psCleanupCookieInt);
 		}
 	}
 
-	if (psapsFreeListsInt)
-		OSFreeMemNoStats(psapsFreeListsInt);
-	if (hapsFreeListsInt2)
-		OSFreeMemNoStats(hapsFreeListsInt2);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyHWRTData(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYHWRTDATA *psRGXDestroyHWRTDataIN,
@@ -254,30 +361,46 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyHWRTDataOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyHWRTDataIN->hCleanupCookie,
 					PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
-	if ((psRGXDestroyHWRTDataOUT->eError != PVRSRV_OK) && (psRGXDestroyHWRTDataOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyHWRTDataOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyHWRTDataOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyHWRTData: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyHWRTDataOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyHWRTData_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyHWRTData_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXCreateRenderTarget(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCREATERENDERTARGET *psRGXCreateRenderTargetIN,
@@ -290,7 +413,7 @@
 
 
 
-	PMRLock();
+
 
 
 	psRGXCreateRenderTargetOUT->eError =
@@ -301,13 +424,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateRenderTarget_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateRenderTargetOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateRenderTargetOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateRenderTargetOUT->hsRenderTargetMemDesc,
 							(void *) pssRenderTargetMemDescInt,
 							PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET,
@@ -315,13 +443,19 @@
 							,(PFN_HANDLE_RELEASE)&RGXDestroyRenderTarget);
 	if (psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateRenderTarget_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateRenderTarget_exit:
+
+
+
 	if (psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
 	{
 		if (pssRenderTargetMemDescInt)
@@ -334,6 +468,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyRenderTarget(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYRENDERTARGET *psRGXDestroyRenderTargetIN,
@@ -345,37 +480,55 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyRenderTargetOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyRenderTargetIN->hsRenderTargetMemDesc,
 					PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET);
-	if ((psRGXDestroyRenderTargetOUT->eError != PVRSRV_OK) && (psRGXDestroyRenderTargetOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyRenderTargetOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyRenderTargetOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyRenderTarget: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyRenderTargetOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyRenderTarget_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyRenderTarget_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXCreateZSBuffer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCREATEZSBUFFER *psRGXCreateZSBufferIN,
 					  PVRSRV_BRIDGE_OUT_RGXCREATEZSBUFFER *psRGXCreateZSBufferOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hReservation = psRGXCreateZSBufferIN->hReservation;
 	DEVMEMINT_RESERVATION * psReservationInt = NULL;
+	IMG_HANDLE hPMR = psRGXCreateZSBufferIN->hPMR;
 	PMR * psPMRInt = NULL;
 	RGX_ZSBUFFER_DATA * pssZSBufferKMInt = NULL;
 
@@ -383,38 +536,50 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXCreateZSBufferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psReservationInt,
-											psRGXCreateZSBufferIN->hReservation,
-											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
+											IMG_TRUE);
 					if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateZSBuffer_exit;
 					}
 				}
 
 
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXCreateZSBufferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRInt,
-											psRGXCreateZSBufferIN->hPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateZSBuffer_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateZSBufferOUT->eError =
 		RGXCreateZSBufferKM(psConnection, OSGetDevData(psConnection),
@@ -426,13 +591,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateZSBuffer_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateZSBufferOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateZSBufferOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateZSBufferOUT->hsZSBufferKM,
 							(void *) pssZSBufferKMInt,
 							PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
@@ -440,13 +610,51 @@
 							,(PFN_HANDLE_RELEASE)&RGXDestroyZSBufferKM);
 	if (psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateZSBuffer_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateZSBuffer_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psReservationInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hReservation,
+											PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
 	{
 		if (pssZSBufferKMInt)
@@ -459,6 +667,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyZSBuffer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYZSBUFFER *psRGXDestroyZSBufferIN,
@@ -470,36 +679,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyZSBufferOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyZSBufferIN->hsZSBufferMemDesc,
 					PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
-	if ((psRGXDestroyZSBufferOUT->eError != PVRSRV_OK) && (psRGXDestroyZSBufferOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyZSBufferOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyZSBufferOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyZSBuffer: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyZSBufferOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyZSBuffer_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyZSBuffer_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXPopulateZSBuffer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXPOPULATEZSBUFFER *psRGXPopulateZSBufferIN,
 					  PVRSRV_BRIDGE_OUT_RGXPOPULATEZSBUFFER *psRGXPopulateZSBufferOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hsZSBufferKM = psRGXPopulateZSBufferIN->hsZSBufferKM;
 	RGX_ZSBUFFER_DATA * pssZSBufferKMInt = NULL;
 	RGX_POPULATION * pssPopulationInt = NULL;
 
@@ -507,23 +733,31 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXPopulateZSBufferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &pssZSBufferKMInt,
-											psRGXPopulateZSBufferIN->hsZSBufferKM,
-											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+											hsZSBufferKM,
+											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
+											IMG_TRUE);
 					if(psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXPopulateZSBuffer_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXPopulateZSBufferOUT->eError =
 		RGXPopulateZSBufferKM(
@@ -532,13 +766,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXPopulateZSBuffer_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXPopulateZSBufferOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXPopulateZSBufferOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXPopulateZSBufferOUT->hsPopulation,
 							(void *) pssPopulationInt,
 							PVRSRV_HANDLE_TYPE_RGX_POPULATION,
@@ -546,13 +785,37 @@
 							,(PFN_HANDLE_RELEASE)&RGXUnpopulateZSBufferKM);
 	if (psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXPopulateZSBuffer_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXPopulateZSBuffer_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(pssZSBufferKMInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hsZSBufferKM,
+											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
 	{
 		if (pssPopulationInt)
@@ -565,6 +828,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXUnpopulateZSBuffer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXUNPOPULATEZSBUFFER *psRGXUnpopulateZSBufferIN,
@@ -576,36 +840,55 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXUnpopulateZSBufferOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXUnpopulateZSBufferIN->hsPopulation,
 					PVRSRV_HANDLE_TYPE_RGX_POPULATION);
-	if ((psRGXUnpopulateZSBufferOUT->eError != PVRSRV_OK) && (psRGXUnpopulateZSBufferOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXUnpopulateZSBufferOUT->eError != PVRSRV_OK) &&
+	    (psRGXUnpopulateZSBufferOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXUnpopulateZSBuffer: %s",
+		        PVRSRVGetErrorStringKM(psRGXUnpopulateZSBufferOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXUnpopulateZSBuffer_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXUnpopulateZSBuffer_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXCreateFreeList(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCREATEFREELIST *psRGXCreateFreeListIN,
 					  PVRSRV_BRIDGE_OUT_RGXCREATEFREELIST *psRGXCreateFreeListOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hsGlobalFreeList = psRGXCreateFreeListIN->hsGlobalFreeList;
+	RGX_FREELIST * pssGlobalFreeListInt = NULL;
+	IMG_HANDLE hsFreeListPMR = psRGXCreateFreeListIN->hsFreeListPMR;
 	PMR * pssFreeListPMRInt = NULL;
 	RGX_FREELIST * psCleanupCookieInt = NULL;
 
@@ -613,29 +896,58 @@
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				if (psRGXCreateFreeListIN->hsGlobalFreeList)
+				{
+					/* Look up the address from the handle */
+					psRGXCreateFreeListOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &pssGlobalFreeListInt,
+											hsGlobalFreeList,
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST,
+											IMG_TRUE);
+					if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXCreateFreeList_exit;
+					}
+				}
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXCreateFreeListOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &pssFreeListPMRInt,
-											psRGXCreateFreeListIN->hsFreeListPMR,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hsFreeListPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateFreeList_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateFreeListOUT->eError =
 		RGXCreateFreeList(psConnection, OSGetDevData(psConnection),
 					psRGXCreateFreeListIN->ui32ui32MaxFLPages,
 					psRGXCreateFreeListIN->ui32ui32InitFLPages,
 					psRGXCreateFreeListIN->ui32ui32GrowFLPages,
+					pssGlobalFreeListInt,
 					psRGXCreateFreeListIN->bbFreeListCheck,
 					psRGXCreateFreeListIN->spsFreeListDevVAddr,
 					pssFreeListPMRInt,
@@ -644,13 +956,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateFreeList_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateFreeListOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateFreeListOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateFreeListOUT->hCleanupCookie,
 							(void *) psCleanupCookieInt,
 							PVRSRV_HANDLE_TYPE_RGX_FREELIST,
@@ -658,13 +975,52 @@
 							,(PFN_HANDLE_RELEASE)&RGXDestroyFreeList);
 	if (psRGXCreateFreeListOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateFreeList_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateFreeList_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				if (psRGXCreateFreeListIN->hsGlobalFreeList)
+				{
+					/* Unreference the previously looked up handle */
+						if(pssGlobalFreeListInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hsGlobalFreeList,
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+						}
+				}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(pssFreeListPMRInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hsFreeListPMR,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateFreeListOUT->eError != PVRSRV_OK)
 	{
 		if (psCleanupCookieInt)
@@ -677,6 +1033,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyFreeList(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYFREELIST *psRGXDestroyFreeListIN,
@@ -688,36 +1045,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyFreeListOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyFreeListIN->hCleanupCookie,
 					PVRSRV_HANDLE_TYPE_RGX_FREELIST);
-	if ((psRGXDestroyFreeListOUT->eError != PVRSRV_OK) && (psRGXDestroyFreeListOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyFreeListOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyFreeListOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyFreeList: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyFreeListOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyFreeList_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyFreeList_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXAddBlockToFreeList(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXADDBLOCKTOFREELIST *psRGXAddBlockToFreeListIN,
 					  PVRSRV_BRIDGE_OUT_RGXADDBLOCKTOFREELIST *psRGXAddBlockToFreeListOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hsFreeList = psRGXAddBlockToFreeListIN->hsFreeList;
 	RGX_FREELIST * pssFreeListInt = NULL;
 
 
@@ -726,19 +1100,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXAddBlockToFreeListOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &pssFreeListInt,
-											psRGXAddBlockToFreeListIN->hsFreeList,
-											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+											hsFreeList,
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST,
+											IMG_TRUE);
 					if(psRGXAddBlockToFreeListOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXAddBlockToFreeList_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXAddBlockToFreeListOUT->eError =
 		RGXAddBlockToFreeListKM(
@@ -750,15 +1134,38 @@
 
 RGXAddBlockToFreeList_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(pssFreeListInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hsFreeList,
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXRemoveBlockFromFreeList(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXREMOVEBLOCKFROMFREELIST *psRGXRemoveBlockFromFreeListIN,
 					  PVRSRV_BRIDGE_OUT_RGXREMOVEBLOCKFROMFREELIST *psRGXRemoveBlockFromFreeListOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hsFreeList = psRGXRemoveBlockFromFreeListIN->hsFreeList;
 	RGX_FREELIST * pssFreeListInt = NULL;
 
 
@@ -767,19 +1174,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXRemoveBlockFromFreeListOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &pssFreeListInt,
-											psRGXRemoveBlockFromFreeListIN->hsFreeList,
-											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+											hsFreeList,
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST,
+											IMG_TRUE);
 					if(psRGXRemoveBlockFromFreeListOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXRemoveBlockFromFreeList_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXRemoveBlockFromFreeListOUT->eError =
 		RGXRemoveBlockFromFreeListKM(
@@ -790,9 +1207,31 @@
 
 RGXRemoveBlockFromFreeList_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(pssFreeListInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hsFreeList,
+											PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCREATERENDERCONTEXT *psRGXCreateRenderContextIN,
@@ -800,50 +1239,91 @@
 					 CONNECTION_DATA *psConnection)
 {
 	IMG_BYTE *psFrameworkCmdInt = NULL;
+	IMG_HANDLE hPrivData = psRGXCreateRenderContextIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 	RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) +
+			0;
 
 
 
-	if (psRGXCreateRenderContextIN->ui32FrameworkCmdize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		psFrameworkCmdInt = OSAllocMemNoStats(psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE));
-		if (!psFrameworkCmdInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXCreateRenderContextIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXCreateRenderContext_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXCreateRenderContextIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXCreateRenderContext_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXCreateRenderContextIN->psFrameworkCmd, psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateRenderContextIN->psFrameworkCmd,
-				psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
-			{
-				psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psRGXCreateRenderContextIN->ui32FrameworkCmdize != 0)
+	{
+		psFrameworkCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE);
+	}
 
-				goto RGXCreateRenderContext_exit;
+			/* Copy the data over */
+			if (psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateRenderContextIN->psFrameworkCmd, psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXCreateRenderContext_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXCreateRenderContextOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXCreateRenderContextIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateRenderContext_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateRenderContextOUT->eError =
 		PVRSRVRGXCreateRenderContextKM(psConnection, OSGetDevData(psConnection),
@@ -857,13 +1337,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateRenderContext_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateRenderContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateRenderContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateRenderContextOUT->hRenderContext,
 							(void *) psRenderContextInt,
 							PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
@@ -871,13 +1356,37 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVRGXDestroyRenderContextKM);
 	if (psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateRenderContext_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateRenderContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
 	{
 		if (psRenderContextInt)
@@ -886,12 +1395,21 @@
 		}
 	}
 
-	if (psFrameworkCmdInt)
-		OSFreeMemNoStats(psFrameworkCmdInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyRenderContext(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYRENDERCONTEXT *psRGXDestroyRenderContextIN,
@@ -903,36 +1421,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyRenderContextOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyRenderContextIN->hCleanupCookie,
 					PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
-	if ((psRGXDestroyRenderContextOUT->eError != PVRSRV_OK) && (psRGXDestroyRenderContextOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyRenderContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyRenderContextOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyRenderContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyRenderContextOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyRenderContext_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyRenderContext_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXKickTA3D(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXKICKTA3D *psRGXKickTA3DIN,
 					  PVRSRV_BRIDGE_OUT_RGXKICKTA3D *psRGXKickTA3DOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hRenderContext = psRGXKickTA3DIN->hRenderContext;
 	RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = NULL;
 	SYNC_PRIMITIVE_BLOCK * *psClientTAFenceSyncPrimBlockInt = NULL;
 	IMG_HANDLE *hClientTAFenceSyncPrimBlockInt2 = NULL;
@@ -956,529 +1491,484 @@
 	IMG_UINT32 *ui32Server3DSyncFlagsInt = NULL;
 	SERVER_SYNC_PRIMITIVE * *psServer3DSyncsInt = NULL;
 	IMG_HANDLE *hServer3DSyncsInt2 = NULL;
+	IMG_HANDLE hPRFenceUFOSyncPrimBlock = psRGXKickTA3DIN->hPRFenceUFOSyncPrimBlock;
 	SYNC_PRIMITIVE_BLOCK * psPRFenceUFOSyncPrimBlockInt = NULL;
 	IMG_CHAR *uiUpdateFenceNameInt = NULL;
 	IMG_BYTE *psTACmdInt = NULL;
 	IMG_BYTE *ps3DPRCmdInt = NULL;
 	IMG_BYTE *ps3DCmdInt = NULL;
+	IMG_HANDLE hRTDataCleanup = psRGXKickTA3DIN->hRTDataCleanup;
 	RGX_RTDATA_CLEANUP_DATA * psRTDataCleanupInt = NULL;
+	IMG_HANDLE hZBuffer = psRGXKickTA3DIN->hZBuffer;
 	RGX_ZSBUFFER_DATA * psZBufferInt = NULL;
+	IMG_HANDLE hSBuffer = psRGXKickTA3DIN->hSBuffer;
 	RGX_ZSBUFFER_DATA * psSBufferInt = NULL;
 	IMG_UINT32 *ui32SyncPMRFlagsInt = NULL;
 	PMR * *psSyncPMRsInt = NULL;
 	IMG_HANDLE *hSyncPMRsInt2 = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE)) +
+			(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE)) +
+			(32 * sizeof(IMG_CHAR)) +
+			(psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE)) +
+			(psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE)) +
+			(psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE)) +
+			(psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+			(psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(PMR *)) +
+			(psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) +
+			0;
 
 
 
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXKickTA3DIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXKickTA3DIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXKickTA3D_exit;
+			}
+		}
+	}
+
 	if (psRGXKickTA3DIN->ui32ClientTAFenceCount != 0)
 	{
-		psClientTAFenceSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClientTAFenceSyncPrimBlockInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hClientTAFenceSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE));
-		if (!hClientTAFenceSyncPrimBlockInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psClientTAFenceSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientTAFenceSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phClientTAFenceSyncPrimBlock, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClientTAFenceSyncPrimBlockInt2, psRGXKickTA3DIN->phClientTAFenceSyncPrimBlock,
-				psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hClientTAFenceSyncPrimBlockInt2, psRGXKickTA3DIN->phClientTAFenceSyncPrimBlock, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ClientTAFenceCount != 0)
 	{
-		ui32ClientTAFenceSyncOffsetInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32));
-		if (!ui32ClientTAFenceSyncOffsetInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32ClientTAFenceSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32ClientTAFenceSyncOffset, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientTAFenceSyncOffsetInt, psRGXKickTA3DIN->pui32ClientTAFenceSyncOffset,
-				psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientTAFenceSyncOffsetInt, psRGXKickTA3DIN->pui32ClientTAFenceSyncOffset, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ClientTAFenceCount != 0)
 	{
-		ui32ClientTAFenceValueInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32));
-		if (!ui32ClientTAFenceValueInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32ClientTAFenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32ClientTAFenceValue, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientTAFenceValueInt, psRGXKickTA3DIN->pui32ClientTAFenceValue,
-				psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientTAFenceValueInt, psRGXKickTA3DIN->pui32ClientTAFenceValue, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ClientTAUpdateCount != 0)
 	{
-		psClientTAUpdateSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClientTAUpdateSyncPrimBlockInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hClientTAUpdateSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE));
-		if (!hClientTAUpdateSyncPrimBlockInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psClientTAUpdateSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClientTAUpdateSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phClientTAUpdateSyncPrimBlock, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClientTAUpdateSyncPrimBlockInt2, psRGXKickTA3DIN->phClientTAUpdateSyncPrimBlock,
-				psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hClientTAUpdateSyncPrimBlockInt2, psRGXKickTA3DIN->phClientTAUpdateSyncPrimBlock, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ClientTAUpdateCount != 0)
 	{
-		ui32ClientTAUpdateSyncOffsetInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32ClientTAUpdateSyncOffsetInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32ClientTAUpdateSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32ClientTAUpdateSyncOffset, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientTAUpdateSyncOffsetInt, psRGXKickTA3DIN->pui32ClientTAUpdateSyncOffset,
-				psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientTAUpdateSyncOffsetInt, psRGXKickTA3DIN->pui32ClientTAUpdateSyncOffset, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ClientTAUpdateCount != 0)
 	{
-		ui32ClientTAUpdateValueInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32ClientTAUpdateValueInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32ClientTAUpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32ClientTAUpdateValue, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientTAUpdateValueInt, psRGXKickTA3DIN->pui32ClientTAUpdateValue,
-				psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ClientTAUpdateValueInt, psRGXKickTA3DIN->pui32ClientTAUpdateValue, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ServerTASyncPrims != 0)
 	{
-		ui32ServerTASyncFlagsInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32));
-		if (!ui32ServerTASyncFlagsInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32ServerTASyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32ServerTASyncFlags, psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ServerTASyncFlagsInt, psRGXKickTA3DIN->pui32ServerTASyncFlags,
-				psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ServerTASyncFlagsInt, psRGXKickTA3DIN->pui32ServerTASyncFlags, psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32ServerTASyncPrims != 0)
 	{
-		psServerTASyncsInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psServerTASyncsInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hServerTASyncsInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE));
-		if (!hServerTASyncsInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psServerTASyncsInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerTASyncsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phServerTASyncs, psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hServerTASyncsInt2, psRGXKickTA3DIN->phServerTASyncs,
-				psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hServerTASyncsInt2, psRGXKickTA3DIN->phServerTASyncs, psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Client3DFenceCount != 0)
 	{
-		psClient3DFenceSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClient3DFenceSyncPrimBlockInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hClient3DFenceSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE));
-		if (!hClient3DFenceSyncPrimBlockInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psClient3DFenceSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClient3DFenceSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phClient3DFenceSyncPrimBlock, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClient3DFenceSyncPrimBlockInt2, psRGXKickTA3DIN->phClient3DFenceSyncPrimBlock,
-				psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hClient3DFenceSyncPrimBlockInt2, psRGXKickTA3DIN->phClient3DFenceSyncPrimBlock, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Client3DFenceCount != 0)
 	{
-		ui32Client3DFenceSyncOffsetInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32));
-		if (!ui32Client3DFenceSyncOffsetInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32Client3DFenceSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32Client3DFenceSyncOffset, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32Client3DFenceSyncOffsetInt, psRGXKickTA3DIN->pui32Client3DFenceSyncOffset,
-				psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32Client3DFenceSyncOffsetInt, psRGXKickTA3DIN->pui32Client3DFenceSyncOffset, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Client3DFenceCount != 0)
 	{
-		ui32Client3DFenceValueInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32));
-		if (!ui32Client3DFenceValueInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32Client3DFenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32Client3DFenceValue, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32Client3DFenceValueInt, psRGXKickTA3DIN->pui32Client3DFenceValue,
-				psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32Client3DFenceValueInt, psRGXKickTA3DIN->pui32Client3DFenceValue, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Client3DUpdateCount != 0)
 	{
-		psClient3DUpdateSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClient3DUpdateSyncPrimBlockInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hClient3DUpdateSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE));
-		if (!hClient3DUpdateSyncPrimBlockInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psClient3DUpdateSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hClient3DUpdateSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phClient3DUpdateSyncPrimBlock, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClient3DUpdateSyncPrimBlockInt2, psRGXKickTA3DIN->phClient3DUpdateSyncPrimBlock,
-				psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hClient3DUpdateSyncPrimBlockInt2, psRGXKickTA3DIN->phClient3DUpdateSyncPrimBlock, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Client3DUpdateCount != 0)
 	{
-		ui32Client3DUpdateSyncOffsetInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32Client3DUpdateSyncOffsetInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32Client3DUpdateSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32Client3DUpdateSyncOffset, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32Client3DUpdateSyncOffsetInt, psRGXKickTA3DIN->pui32Client3DUpdateSyncOffset,
-				psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32Client3DUpdateSyncOffsetInt, psRGXKickTA3DIN->pui32Client3DUpdateSyncOffset, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Client3DUpdateCount != 0)
 	{
-		ui32Client3DUpdateValueInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32Client3DUpdateValueInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32Client3DUpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32Client3DUpdateValue, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32Client3DUpdateValueInt, psRGXKickTA3DIN->pui32Client3DUpdateValue,
-				psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32Client3DUpdateValueInt, psRGXKickTA3DIN->pui32Client3DUpdateValue, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Server3DSyncPrims != 0)
 	{
-		ui32Server3DSyncFlagsInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32));
-		if (!ui32Server3DSyncFlagsInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32Server3DSyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32Server3DSyncFlags, psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32Server3DSyncFlagsInt, psRGXKickTA3DIN->pui32Server3DSyncFlags,
-				psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32Server3DSyncFlagsInt, psRGXKickTA3DIN->pui32Server3DSyncFlags, psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32Server3DSyncPrims != 0)
 	{
-		psServer3DSyncsInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psServer3DSyncsInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hServer3DSyncsInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE));
-		if (!hServer3DSyncsInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psServer3DSyncsInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServer3DSyncsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phServer3DSyncs, psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hServer3DSyncsInt2, psRGXKickTA3DIN->phServer3DSyncs,
-				psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hServer3DSyncsInt2, psRGXKickTA3DIN->phServer3DSyncs, psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	
 	{
-		uiUpdateFenceNameInt = OSAllocMemNoStats(32 * sizeof(IMG_CHAR));
-		if (!uiUpdateFenceNameInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		uiUpdateFenceNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += 32 * sizeof(IMG_CHAR);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXKickTA3DIN->puiUpdateFenceName,
-				32 * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (32 * sizeof(IMG_CHAR) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXKickTA3DIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32TACmdSize != 0)
 	{
-		psTACmdInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE));
-		if (!psTACmdInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psTACmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->psTACmd, psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, psTACmdInt, psRGXKickTA3DIN->psTACmd,
-				psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, psTACmdInt, psRGXKickTA3DIN->psTACmd, psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui323DPRCmdSize != 0)
 	{
-		ps3DPRCmdInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE));
-		if (!ps3DPRCmdInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ps3DPRCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->ps3DPRCmd, psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, ps3DPRCmdInt, psRGXKickTA3DIN->ps3DPRCmd,
-				psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ps3DPRCmdInt, psRGXKickTA3DIN->ps3DPRCmd, psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui323DCmdSize != 0)
 	{
-		ps3DCmdInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE));
-		if (!ps3DCmdInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ps3DCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->ps3DCmd, psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, ps3DCmdInt, psRGXKickTA3DIN->ps3DCmd,
-				psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ps3DCmdInt, psRGXKickTA3DIN->ps3DCmd, psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32SyncPMRCount != 0)
 	{
-		ui32SyncPMRFlagsInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32));
-		if (!ui32SyncPMRFlagsInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		ui32SyncPMRFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->pui32SyncPMRFlags, psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32SyncPMRFlagsInt, psRGXKickTA3DIN->pui32SyncPMRFlags,
-				psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32SyncPMRFlagsInt, psRGXKickTA3DIN->pui32SyncPMRFlags, psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 	if (psRGXKickTA3DIN->ui32SyncPMRCount != 0)
 	{
-		psSyncPMRsInt = OSAllocMemNoStats(psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(PMR *));
-		if (!psSyncPMRsInt)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
-		hSyncPMRsInt2 = OSAllocMemNoStats(psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE));
-		if (!hSyncPMRsInt2)
-		{
-			psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickTA3D_exit;
-		}
+		psSyncPMRsInt = (PMR **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(PMR *);
+		hSyncPMRsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickTA3DIN->phSyncPMRs, psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hSyncPMRsInt2, psRGXKickTA3DIN->phSyncPMRs,
-				psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hSyncPMRsInt2, psRGXKickTA3DIN->phSyncPMRs, psRGXKickTA3DIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXKickTA3D_exit;
+					goto RGXKickTA3D_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRenderContextInt,
-											psRGXKickTA3DIN->hRenderContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+											hRenderContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1487,20 +1977,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psClientTAFenceSyncPrimBlockInt[i],
 											hClientTAFenceSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1509,20 +2003,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psClientTAUpdateSyncPrimBlockInt[i],
 											hClientTAUpdateSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1531,20 +2029,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerTASyncsInt[i],
 											hServerTASyncsInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1553,20 +2055,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psClient3DFenceSyncPrimBlockInt[i],
 											hClient3DFenceSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1575,20 +2081,24 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psClient3DUpdateSyncPrimBlockInt[i],
 											hClient3DUpdateSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1597,83 +2107,103 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServer3DSyncsInt[i],
 											hServer3DSyncsInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPRFenceUFOSyncPrimBlockInt,
-											psRGXKickTA3DIN->hPRFenceUFOSyncPrimBlock,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											hPRFenceUFOSyncPrimBlock,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
 
 
+
+
+
 				if (psRGXKickTA3DIN->hRTDataCleanup)
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRTDataCleanupInt,
-											psRGXKickTA3DIN->hRTDataCleanup,
-											PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
+											hRTDataCleanup,
+											PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
 
 
+
+
+
 				if (psRGXKickTA3DIN->hZBuffer)
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psZBufferInt,
-											psRGXKickTA3DIN->hZBuffer,
-											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+											hZBuffer,
+											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
 
 
+
+
+
 				if (psRGXKickTA3DIN->hSBuffer)
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSBufferInt,
-											psRGXKickTA3DIN->hSBuffer,
-											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+											hSBuffer,
+											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1682,23 +2212,26 @@
 				{
 					/* Look up the address from the handle */
 					psRGXKickTA3DOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncPMRsInt[i],
 											hSyncPMRsInt2[i],
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXKickTA3D_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXKickTA3DOUT->eError =
 		PVRSRVRGXKickTA3DKM(
 					psRenderContextInt,
+					psRGXKickTA3DIN->ui32ClientCacheOpSeqNum,
 					psRGXKickTA3DIN->ui32ClientTAFenceCount,
 					psClientTAFenceSyncPrimBlockInt,
 					ui32ClientTAFenceSyncOffsetInt,
@@ -1735,13 +2268,12 @@
 					psRGXKickTA3DIN->ui323DCmdSize,
 					ps3DCmdInt,
 					psRGXKickTA3DIN->ui32ExtJobRef,
-					psRGXKickTA3DIN->ui32IntJobRef,
 					psRGXKickTA3DIN->bbLastTAInScene,
 					psRGXKickTA3DIN->bbKickTA,
 					psRGXKickTA3DIN->bbKickPR,
 					psRGXKickTA3DIN->bbKick3D,
 					psRGXKickTA3DIN->bbAbort,
-					psRGXKickTA3DIN->bbPDumpContinuous,
+					psRGXKickTA3DIN->ui32PDumpFlags,
 					psRTDataCleanupInt,
 					psZBufferInt,
 					psSBufferInt,
@@ -1751,81 +2283,280 @@
 					&psRGXKickTA3DOUT->bbCommittedRefCounts3D,
 					psRGXKickTA3DIN->ui32SyncPMRCount,
 					ui32SyncPMRFlagsInt,
-					psSyncPMRsInt);
-	PMRUnlock();
+					psSyncPMRsInt,
+					psRGXKickTA3DIN->ui32RenderTargetSize,
+					psRGXKickTA3DIN->ui32NumberOfDrawCalls,
+					psRGXKickTA3DIN->ui32NumberOfIndices,
+					psRGXKickTA3DIN->ui32NumberOfMRTs,
+					psRGXKickTA3DIN->ui64Deadline);
 
 
 
 
 RGXKickTA3D_exit:
-	if (psClientTAFenceSyncPrimBlockInt)
-		OSFreeMemNoStats(psClientTAFenceSyncPrimBlockInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRenderContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRenderContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+						}
+				}
+
+
+
+
+
+
 	if (hClientTAFenceSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClientTAFenceSyncPrimBlockInt2);
-	if (ui32ClientTAFenceSyncOffsetInt)
-		OSFreeMemNoStats(ui32ClientTAFenceSyncOffsetInt);
-	if (ui32ClientTAFenceValueInt)
-		OSFreeMemNoStats(ui32ClientTAFenceValueInt);
-	if (psClientTAUpdateSyncPrimBlockInt)
-		OSFreeMemNoStats(psClientTAUpdateSyncPrimBlockInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32ClientTAFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientTAFenceSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientTAFenceSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hClientTAUpdateSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClientTAUpdateSyncPrimBlockInt2);
-	if (ui32ClientTAUpdateSyncOffsetInt)
-		OSFreeMemNoStats(ui32ClientTAUpdateSyncOffsetInt);
-	if (ui32ClientTAUpdateValueInt)
-		OSFreeMemNoStats(ui32ClientTAUpdateValueInt);
-	if (ui32ServerTASyncFlagsInt)
-		OSFreeMemNoStats(ui32ServerTASyncFlagsInt);
-	if (psServerTASyncsInt)
-		OSFreeMemNoStats(psServerTASyncsInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32ClientTAUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClientTAUpdateSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClientTAUpdateSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hServerTASyncsInt2)
-		OSFreeMemNoStats(hServerTASyncsInt2);
-	if (psClient3DFenceSyncPrimBlockInt)
-		OSFreeMemNoStats(psClient3DFenceSyncPrimBlockInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32ServerTASyncPrims;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerTASyncsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerTASyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hClient3DFenceSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClient3DFenceSyncPrimBlockInt2);
-	if (ui32Client3DFenceSyncOffsetInt)
-		OSFreeMemNoStats(ui32Client3DFenceSyncOffsetInt);
-	if (ui32Client3DFenceValueInt)
-		OSFreeMemNoStats(ui32Client3DFenceValueInt);
-	if (psClient3DUpdateSyncPrimBlockInt)
-		OSFreeMemNoStats(psClient3DUpdateSyncPrimBlockInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32Client3DFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClient3DFenceSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClient3DFenceSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hClient3DUpdateSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClient3DUpdateSyncPrimBlockInt2);
-	if (ui32Client3DUpdateSyncOffsetInt)
-		OSFreeMemNoStats(ui32Client3DUpdateSyncOffsetInt);
-	if (ui32Client3DUpdateValueInt)
-		OSFreeMemNoStats(ui32Client3DUpdateValueInt);
-	if (ui32Server3DSyncFlagsInt)
-		OSFreeMemNoStats(ui32Server3DSyncFlagsInt);
-	if (psServer3DSyncsInt)
-		OSFreeMemNoStats(psServer3DSyncsInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32Client3DUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psClient3DUpdateSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hClient3DUpdateSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
 	if (hServer3DSyncsInt2)
-		OSFreeMemNoStats(hServer3DSyncsInt2);
-	if (uiUpdateFenceNameInt)
-		OSFreeMemNoStats(uiUpdateFenceNameInt);
-	if (psTACmdInt)
-		OSFreeMemNoStats(psTACmdInt);
-	if (ps3DPRCmdInt)
-		OSFreeMemNoStats(ps3DPRCmdInt);
-	if (ps3DCmdInt)
-		OSFreeMemNoStats(ps3DCmdInt);
-	if (ui32SyncPMRFlagsInt)
-		OSFreeMemNoStats(ui32SyncPMRFlagsInt);
-	if (psSyncPMRsInt)
-		OSFreeMemNoStats(psSyncPMRsInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32Server3DSyncPrims;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServer3DSyncsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServer3DSyncsInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPRFenceUFOSyncPrimBlockInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPRFenceUFOSyncPrimBlock,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+
+
+
+
+
+				if (psRGXKickTA3DIN->hRTDataCleanup)
+				{
+					/* Unreference the previously looked up handle */
+						if(psRTDataCleanupInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRTDataCleanup,
+											PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
+						}
+				}
+
+
+
+
+
+				if (psRGXKickTA3DIN->hZBuffer)
+				{
+					/* Unreference the previously looked up handle */
+						if(psZBufferInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hZBuffer,
+											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+						}
+				}
+
+
+
+
+
+				if (psRGXKickTA3DIN->hSBuffer)
+				{
+					/* Unreference the previously looked up handle */
+						if(psSBufferInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSBuffer,
+											PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+						}
+				}
+
+
+
+
+
+
 	if (hSyncPMRsInt2)
-		OSFreeMemNoStats(hSyncPMRsInt2);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXKickTA3DIN->ui32SyncPMRCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncPMRsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncPMRsInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXSetRenderContextPriority(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXSETRENDERCONTEXTPRIORITY *psRGXSetRenderContextPriorityIN,
 					  PVRSRV_BRIDGE_OUT_RGXSETRENDERCONTEXTPRIORITY *psRGXSetRenderContextPriorityOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hRenderContext = psRGXSetRenderContextPriorityIN->hRenderContext;
 	RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = NULL;
 
 
@@ -1834,19 +2565,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXSetRenderContextPriorityOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRenderContextInt,
-											psRGXSetRenderContextPriorityIN->hRenderContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+											hRenderContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
+											IMG_TRUE);
 					if(psRGXSetRenderContextPriorityOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXSetRenderContextPriority_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXSetRenderContextPriorityOUT->eError =
 		PVRSRVRGXSetRenderContextPriorityKM(psConnection, OSGetDevData(psConnection),
@@ -1858,15 +2599,38 @@
 
 RGXSetRenderContextPriority_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRenderContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRenderContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXGetLastRenderContextResetReason(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXGETLASTRENDERCONTEXTRESETREASON *psRGXGetLastRenderContextResetReasonIN,
 					  PVRSRV_BRIDGE_OUT_RGXGETLASTRENDERCONTEXTRESETREASON *psRGXGetLastRenderContextResetReasonOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hRenderContext = psRGXGetLastRenderContextResetReasonIN->hRenderContext;
 	RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = NULL;
 
 
@@ -1875,19 +2639,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXGetLastRenderContextResetReasonOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRenderContextInt,
-											psRGXGetLastRenderContextResetReasonIN->hRenderContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+											hRenderContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
+											IMG_TRUE);
 					if(psRGXGetLastRenderContextResetReasonOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXGetLastRenderContextResetReason_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXGetLastRenderContextResetReasonOUT->eError =
 		PVRSRVRGXGetLastRenderContextResetReasonKM(
@@ -1900,15 +2674,38 @@
 
 RGXGetLastRenderContextResetReason_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRenderContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRenderContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXGetPartialRenderCount(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXGETPARTIALRENDERCOUNT *psRGXGetPartialRenderCountIN,
 					  PVRSRV_BRIDGE_OUT_RGXGETPARTIALRENDERCOUNT *psRGXGetPartialRenderCountOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hHWRTDataMemDesc = psRGXGetPartialRenderCountIN->hHWRTDataMemDesc;
 	DEVMEM_MEMDESC * psHWRTDataMemDescInt = NULL;
 
 
@@ -1917,19 +2714,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRGXGetPartialRenderCountOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psHWRTDataMemDescInt,
-											psRGXGetPartialRenderCountIN->hHWRTDataMemDesc,
-											PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC);
+											hHWRTDataMemDesc,
+											PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
+											IMG_TRUE);
 					if(psRGXGetPartialRenderCountOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RGXGetPartialRenderCount_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXGetPartialRenderCountOUT->eError =
 		PVRSRVRGXGetPartialRenderCountKM(
@@ -1941,11 +2748,33 @@
 
 RGXGetPartialRenderCount_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psHWRTDataMemDescInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hHWRTDataMemDesc,
+											PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -2026,4 +2855,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/rgxtq2_bridge/common_rgxtq2_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxtq2_bridge/common_rgxtq2_bridge.h
new file mode 100644
index 0000000..f3e2b65
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/rgxtq2_bridge/common_rgxtq2_bridge.h
@@ -0,0 +1,181 @@
+/*************************************************************************/ /*!
+@File
+@Title          Common bridge header for rgxtq2
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxtq2
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef COMMON_RGXTQ2_BRIDGE_H
+#define COMMON_RGXTQ2_BRIDGE_H
+
+#include <powervr/mem_types.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+#include "rgx_bridge.h"
+#include <powervr/sync_external.h>
+
+
+#define PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST			0
+#define PVRSRV_BRIDGE_RGXTQ2_RGXTDMCREATETRANSFERCONTEXT			PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST+0
+#define PVRSRV_BRIDGE_RGXTQ2_RGXTDMDESTROYTRANSFERCONTEXT			PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST+1
+#define PVRSRV_BRIDGE_RGXTQ2_RGXTDMSUBMITTRANSFER			PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST+2
+#define PVRSRV_BRIDGE_RGXTQ2_RGXTDMSETTRANSFERCONTEXTPRIORITY			PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST+3
+#define PVRSRV_BRIDGE_RGXTQ2_RGXTDMNOTIFYWRITEOFFSETUPDATE			PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST+4
+#define PVRSRV_BRIDGE_RGXTQ2_CMD_LAST			(PVRSRV_BRIDGE_RGXTQ2_CMD_FIRST+4)
+
+
+/*******************************************
+            RGXTDMCreateTransferContext          
+ *******************************************/
+
+/* Bridge in structure for RGXTDMCreateTransferContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXTDMCREATETRANSFERCONTEXT_TAG
+{
+	IMG_UINT32 ui32Priority;
+	IMG_DEV_VIRTADDR sMCUFenceAddr;
+	IMG_UINT32 ui32FrameworkCmdize;
+	IMG_BYTE * psFrameworkCmd;
+	IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXTDMCREATETRANSFERCONTEXT;
+
+/* Bridge out structure for RGXTDMCreateTransferContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXTDMCREATETRANSFERCONTEXT_TAG
+{
+	IMG_HANDLE hTransferContext;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXTDMCREATETRANSFERCONTEXT;
+
+
+/*******************************************
+            RGXTDMDestroyTransferContext          
+ *******************************************/
+
+/* Bridge in structure for RGXTDMDestroyTransferContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXTDMDESTROYTRANSFERCONTEXT_TAG
+{
+	IMG_HANDLE hTransferContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXTDMDESTROYTRANSFERCONTEXT;
+
+/* Bridge out structure for RGXTDMDestroyTransferContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXTDMDESTROYTRANSFERCONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXTDMDESTROYTRANSFERCONTEXT;
+
+
+/*******************************************
+            RGXTDMSubmitTransfer          
+ *******************************************/
+
+/* Bridge in structure for RGXTDMSubmitTransfer */
+typedef struct PVRSRV_BRIDGE_IN_RGXTDMSUBMITTRANSFER_TAG
+{
+	IMG_HANDLE hTransferContext;
+	IMG_UINT32 ui32PDumpFlags;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
+	IMG_UINT32 ui32ClientFenceCount;
+	IMG_HANDLE * phFenceUFOSyncPrimBlock;
+	IMG_UINT32 * pui32FenceSyncOffset;
+	IMG_UINT32 * pui32FenceValue;
+	IMG_UINT32 ui32ClientUpdateCount;
+	IMG_HANDLE * phUpdateUFOSyncPrimBlock;
+	IMG_UINT32 * pui32UpdateSyncOffset;
+	IMG_UINT32 * pui32UpdateValue;
+	IMG_UINT32 ui32ServerSyncCount;
+	IMG_UINT32 * pui32ServerSyncFlags;
+	IMG_HANDLE * phServerSync;
+	IMG_INT32 i32CheckFenceFD;
+	IMG_INT32 i32UpdateTimelineFD;
+	IMG_CHAR * puiUpdateFenceName;
+	IMG_UINT32 ui32CommandSize;
+	IMG_UINT8 * pui8FWCommand;
+	IMG_UINT32 ui32ExternalJobReference;
+	IMG_UINT32 ui32SyncPMRCount;
+	IMG_UINT32 * pui32SyncPMRFlags;
+	IMG_HANDLE * phSyncPMRs;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXTDMSUBMITTRANSFER;
+
+/* Bridge out structure for RGXTDMSubmitTransfer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXTDMSUBMITTRANSFER_TAG
+{
+	IMG_INT32 i32UpdateFenceFD;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXTDMSUBMITTRANSFER;
+
+
+/*******************************************
+            RGXTDMSetTransferContextPriority          
+ *******************************************/
+
+/* Bridge in structure for RGXTDMSetTransferContextPriority */
+typedef struct PVRSRV_BRIDGE_IN_RGXTDMSETTRANSFERCONTEXTPRIORITY_TAG
+{
+	IMG_HANDLE hTransferContext;
+	IMG_UINT32 ui32Priority;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXTDMSETTRANSFERCONTEXTPRIORITY;
+
+/* Bridge out structure for RGXTDMSetTransferContextPriority */
+typedef struct PVRSRV_BRIDGE_OUT_RGXTDMSETTRANSFERCONTEXTPRIORITY_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXTDMSETTRANSFERCONTEXTPRIORITY;
+
+
+/*******************************************
+            RGXTDMNotifyWriteOffsetUpdate          
+ *******************************************/
+
+/* Bridge in structure for RGXTDMNotifyWriteOffsetUpdate */
+typedef struct PVRSRV_BRIDGE_IN_RGXTDMNOTIFYWRITEOFFSETUPDATE_TAG
+{
+	IMG_HANDLE hTransferContext;
+	IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXTDMNOTIFYWRITEOFFSETUPDATE;
+
+/* Bridge out structure for RGXTDMNotifyWriteOffsetUpdate */
+typedef struct PVRSRV_BRIDGE_OUT_RGXTDMNOTIFYWRITEOFFSETUPDATE_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXTDMNOTIFYWRITEOFFSETUPDATE;
+
+
+#endif /* COMMON_RGXTQ2_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxtq2_bridge/server_rgxtq2_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxtq2_bridge/server_rgxtq2_bridge.c
new file mode 100644
index 0000000..9f011c0
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/rgxtq2_bridge/server_rgxtq2_bridge.c
@@ -0,0 +1,1121 @@
+/*************************************************************************/ /*!
+@File
+@Title          Server bridge for rgxtq2
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements the server side of the bridge for rgxtq2
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxtdmtransfer.h"
+
+
+#include "common_rgxtq2_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#include <linux/slab.h>
+
+
+#include "rgx_bvnc_defs_km.h"
+
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+ 
+static IMG_INT
+PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXTDMCREATETRANSFERCONTEXT *psRGXTDMCreateTransferContextIN,
+					  PVRSRV_BRIDGE_OUT_RGXTDMCREATETRANSFERCONTEXT *psRGXTDMCreateTransferContextOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_BYTE *psFrameworkCmdInt = NULL;
+	IMG_HANDLE hPrivData = psRGXTDMCreateTransferContextIN->hPrivData;
+	IMG_HANDLE hPrivDataInt = NULL;
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContextInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) +
+			0;
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
+		{
+			psRGXTDMCreateTransferContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXTDMCreateTransferContext_exit;
+		}
+	}
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXTDMCreateTransferContextIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXTDMCreateTransferContextIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXTDMCreateTransferContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXTDMCreateTransferContext_exit;
+			}
+		}
+	}
+
+	if (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize != 0)
+	{
+		psFrameworkCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXTDMCreateTransferContextIN->psFrameworkCmd, psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXTDMCreateTransferContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMCreateTransferContext_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXTDMCreateTransferContextOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &hPrivDataInt,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
+					if(psRGXTDMCreateTransferContextOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMCreateTransferContext_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXTDMCreateTransferContextOUT->eError =
+		PVRSRVRGXTDMCreateTransferContextKM(psConnection, OSGetDevData(psConnection),
+					psRGXTDMCreateTransferContextIN->ui32Priority,
+					psRGXTDMCreateTransferContextIN->sMCUFenceAddr,
+					psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize,
+					psFrameworkCmdInt,
+					hPrivDataInt,
+					&psTransferContextInt);
+	/* Exit early if bridged call fails */
+	if(psRGXTDMCreateTransferContextOUT->eError != PVRSRV_OK)
+	{
+		goto RGXTDMCreateTransferContext_exit;
+	}
+
+	/* Lock over handle creation. */
+	LockHandle();
+
+
+
+
+
+	psRGXTDMCreateTransferContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
+							&psRGXTDMCreateTransferContextOUT->hTransferContext,
+							(void *) psTransferContextInt,
+							PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
+							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+							,(PFN_HANDLE_RELEASE)&PVRSRVRGXTDMDestroyTransferContextKM);
+	if (psRGXTDMCreateTransferContextOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto RGXTDMCreateTransferContext_exit;
+	}
+
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+RGXTDMCreateTransferContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	if (psRGXTDMCreateTransferContextOUT->eError != PVRSRV_OK)
+	{
+		if (psTransferContextInt)
+		{
+			PVRSRVRGXTDMDestroyTransferContextKM(psTransferContextInt);
+		}
+	}
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXTDMDestroyTransferContext(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXTDMDESTROYTRANSFERCONTEXT *psRGXTDMDestroyTransferContextIN,
+					  PVRSRV_BRIDGE_OUT_RGXTDMDESTROYTRANSFERCONTEXT *psRGXTDMDestroyTransferContextOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
+		{
+			psRGXTDMDestroyTransferContextOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXTDMDestroyTransferContext_exit;
+		}
+	}
+
+
+
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
+	psRGXTDMDestroyTransferContextOUT->eError =
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+					(IMG_HANDLE) psRGXTDMDestroyTransferContextIN->hTransferContext,
+					PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT);
+	if ((psRGXTDMDestroyTransferContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXTDMDestroyTransferContextOUT->eError != PVRSRV_ERROR_RETRY))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXTDMDestroyTransferContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXTDMDestroyTransferContextOUT->eError)));
+		PVR_ASSERT(0);
+		UnlockHandle();
+		goto RGXTDMDestroyTransferContext_exit;
+	}
+
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
+
+
+RGXTDMDestroyTransferContext_exit:
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXTDMSubmitTransfer(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXTDMSUBMITTRANSFER *psRGXTDMSubmitTransferIN,
+					  PVRSRV_BRIDGE_OUT_RGXTDMSUBMITTRANSFER *psRGXTDMSubmitTransferOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hTransferContext = psRGXTDMSubmitTransferIN->hTransferContext;
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContextInt = NULL;
+	SYNC_PRIMITIVE_BLOCK * *psFenceUFOSyncPrimBlockInt = NULL;
+	IMG_HANDLE *hFenceUFOSyncPrimBlockInt2 = NULL;
+	IMG_UINT32 *ui32FenceSyncOffsetInt = NULL;
+	IMG_UINT32 *ui32FenceValueInt = NULL;
+	SYNC_PRIMITIVE_BLOCK * *psUpdateUFOSyncPrimBlockInt = NULL;
+	IMG_HANDLE *hUpdateUFOSyncPrimBlockInt2 = NULL;
+	IMG_UINT32 *ui32UpdateSyncOffsetInt = NULL;
+	IMG_UINT32 *ui32UpdateValueInt = NULL;
+	IMG_UINT32 *ui32ServerSyncFlagsInt = NULL;
+	SERVER_SYNC_PRIMITIVE * *psServerSyncInt = NULL;
+	IMG_HANDLE *hServerSyncInt2 = NULL;
+	IMG_CHAR *uiUpdateFenceNameInt = NULL;
+	IMG_UINT8 *ui8FWCommandInt = NULL;
+	IMG_UINT32 *ui32SyncPMRFlagsInt = NULL;
+	PMR * *psSyncPMRsInt = NULL;
+	IMG_HANDLE *hSyncPMRsInt2 = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+			(psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) +
+			(psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) +
+			(32 * sizeof(IMG_CHAR)) +
+			(psRGXTDMSubmitTransferIN->ui32CommandSize * sizeof(IMG_UINT8)) +
+			(psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+			(psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(PMR *)) +
+			(psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) +
+			0;
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
+		{
+			psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXTDMSubmitTransfer_exit;
+		}
+	}
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXTDMSubmitTransferIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXTDMSubmitTransferIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXTDMSubmitTransfer_exit;
+			}
+		}
+	}
+
+	if (psRGXTDMSubmitTransferIN->ui32ClientFenceCount != 0)
+	{
+		psFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hFenceUFOSyncPrimBlockInt2, psRGXTDMSubmitTransferIN->phFenceUFOSyncPrimBlock, psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ClientFenceCount != 0)
+	{
+		ui32FenceSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32FenceSyncOffsetInt, psRGXTDMSubmitTransferIN->pui32FenceSyncOffset, psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ClientFenceCount != 0)
+	{
+		ui32FenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32FenceValueInt, psRGXTDMSubmitTransferIN->pui32FenceValue, psRGXTDMSubmitTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ClientUpdateCount != 0)
+	{
+		psUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hUpdateUFOSyncPrimBlockInt2, psRGXTDMSubmitTransferIN->phUpdateUFOSyncPrimBlock, psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ClientUpdateCount != 0)
+	{
+		ui32UpdateSyncOffsetInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32UpdateSyncOffsetInt, psRGXTDMSubmitTransferIN->pui32UpdateSyncOffset, psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ClientUpdateCount != 0)
+	{
+		ui32UpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32UpdateValueInt, psRGXTDMSubmitTransferIN->pui32UpdateValue, psRGXTDMSubmitTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ServerSyncCount != 0)
+	{
+		ui32ServerSyncFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXTDMSubmitTransferIN->pui32ServerSyncFlags, psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32ServerSyncCount != 0)
+	{
+		psServerSyncInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerSyncInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hServerSyncInt2, psRGXTDMSubmitTransferIN->phServerSync, psRGXTDMSubmitTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	
+	{
+		uiUpdateFenceNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += 32 * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (32 * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXTDMSubmitTransferIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32CommandSize != 0)
+	{
+		ui8FWCommandInt = (IMG_UINT8*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32CommandSize * sizeof(IMG_UINT8);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32CommandSize * sizeof(IMG_UINT8) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui8FWCommandInt, psRGXTDMSubmitTransferIN->pui8FWCommand, psRGXTDMSubmitTransferIN->ui32CommandSize * sizeof(IMG_UINT8)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32SyncPMRCount != 0)
+	{
+		ui32SyncPMRFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32SyncPMRFlagsInt, psRGXTDMSubmitTransferIN->pui32SyncPMRFlags, psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+	if (psRGXTDMSubmitTransferIN->ui32SyncPMRCount != 0)
+	{
+		psSyncPMRsInt = (PMR **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(PMR *);
+		hSyncPMRsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hSyncPMRsInt2, psRGXTDMSubmitTransferIN->phSyncPMRs, psRGXTDMSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXTDMSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXTDMSubmitTransfer_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXTDMSubmitTransferOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psTransferContextInt,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
+											IMG_TRUE);
+					if(psRGXTDMSubmitTransferOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMSubmitTransfer_exit;
+					}
+				}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXTDMSubmitTransferOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psFenceUFOSyncPrimBlockInt[i],
+											hFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psRGXTDMSubmitTransferOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMSubmitTransfer_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXTDMSubmitTransferOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psUpdateUFOSyncPrimBlockInt[i],
+											hUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psRGXTDMSubmitTransferOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMSubmitTransfer_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXTDMSubmitTransferOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psServerSyncInt[i],
+											hServerSyncInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
+					if(psRGXTDMSubmitTransferOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMSubmitTransfer_exit;
+					}
+				}
+		}
+	}
+
+
+
+
+
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32SyncPMRCount;i++)
+		{
+				{
+					/* Look up the address from the handle */
+					psRGXTDMSubmitTransferOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psSyncPMRsInt[i],
+											hSyncPMRsInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
+					if(psRGXTDMSubmitTransferOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMSubmitTransfer_exit;
+					}
+				}
+		}
+	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXTDMSubmitTransferOUT->eError =
+		PVRSRVRGXTDMSubmitTransferKM(
+					psTransferContextInt,
+					psRGXTDMSubmitTransferIN->ui32PDumpFlags,
+					psRGXTDMSubmitTransferIN->ui32ClientCacheOpSeqNum,
+					psRGXTDMSubmitTransferIN->ui32ClientFenceCount,
+					psFenceUFOSyncPrimBlockInt,
+					ui32FenceSyncOffsetInt,
+					ui32FenceValueInt,
+					psRGXTDMSubmitTransferIN->ui32ClientUpdateCount,
+					psUpdateUFOSyncPrimBlockInt,
+					ui32UpdateSyncOffsetInt,
+					ui32UpdateValueInt,
+					psRGXTDMSubmitTransferIN->ui32ServerSyncCount,
+					ui32ServerSyncFlagsInt,
+					psServerSyncInt,
+					psRGXTDMSubmitTransferIN->i32CheckFenceFD,
+					psRGXTDMSubmitTransferIN->i32UpdateTimelineFD,
+					&psRGXTDMSubmitTransferOUT->i32UpdateFenceFD,
+					uiUpdateFenceNameInt,
+					psRGXTDMSubmitTransferIN->ui32CommandSize,
+					ui8FWCommandInt,
+					psRGXTDMSubmitTransferIN->ui32ExternalJobReference,
+					psRGXTDMSubmitTransferIN->ui32SyncPMRCount,
+					ui32SyncPMRFlagsInt,
+					psSyncPMRsInt);
+
+
+
+
+RGXTDMSubmitTransfer_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psTransferContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT);
+						}
+				}
+
+
+
+
+
+
+	if (hFenceUFOSyncPrimBlockInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32ClientFenceCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psFenceUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hFenceUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hUpdateUFOSyncPrimBlockInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32ClientUpdateCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psUpdateUFOSyncPrimBlockInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hUpdateUFOSyncPrimBlockInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hServerSyncInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+
+
+
+
+
+
+	if (hSyncPMRsInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXTDMSubmitTransferIN->ui32SyncPMRCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncPMRsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncPMRsInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXTDMSetTransferContextPriority(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXTDMSETTRANSFERCONTEXTPRIORITY *psRGXTDMSetTransferContextPriorityIN,
+					  PVRSRV_BRIDGE_OUT_RGXTDMSETTRANSFERCONTEXTPRIORITY *psRGXTDMSetTransferContextPriorityOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hTransferContext = psRGXTDMSetTransferContextPriorityIN->hTransferContext;
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContextInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
+		{
+			psRGXTDMSetTransferContextPriorityOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXTDMSetTransferContextPriority_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXTDMSetTransferContextPriorityOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psTransferContextInt,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
+											IMG_TRUE);
+					if(psRGXTDMSetTransferContextPriorityOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMSetTransferContextPriority_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXTDMSetTransferContextPriorityOUT->eError =
+		PVRSRVRGXTDMSetTransferContextPriorityKM(psConnection, OSGetDevData(psConnection),
+					psTransferContextInt,
+					psRGXTDMSetTransferContextPriorityIN->ui32Priority);
+
+
+
+
+RGXTDMSetTransferContextPriority_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psTransferContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeRGXTDMNotifyWriteOffsetUpdate(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_RGXTDMNOTIFYWRITEOFFSETUPDATE *psRGXTDMNotifyWriteOffsetUpdateIN,
+					  PVRSRV_BRIDGE_OUT_RGXTDMNOTIFYWRITEOFFSETUPDATE *psRGXTDMNotifyWriteOffsetUpdateOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hTransferContext = psRGXTDMNotifyWriteOffsetUpdateIN->hTransferContext;
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContextInt = NULL;
+
+
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevData(psConnection);
+
+		/* Check that device supports the required feature */
+		if ((psDeviceNode->pfnCheckDeviceFeature) &&
+			!psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
+		{
+			psRGXTDMNotifyWriteOffsetUpdateOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+
+			goto RGXTDMNotifyWriteOffsetUpdate_exit;
+		}
+	}
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psRGXTDMNotifyWriteOffsetUpdateOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &psTransferContextInt,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
+											IMG_TRUE);
+					if(psRGXTDMNotifyWriteOffsetUpdateOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto RGXTDMNotifyWriteOffsetUpdate_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psRGXTDMNotifyWriteOffsetUpdateOUT->eError =
+		PVRSRVRGXTDMNotifyWriteOffsetUpdateKM(
+					psTransferContextInt,
+					psRGXTDMNotifyWriteOffsetUpdateIN->ui32PDumpFlags);
+
+
+
+
+RGXTDMNotifyWriteOffsetUpdate_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psTransferContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+
+
+/* *************************************************************************** 
+ * Server bridge dispatch related glue 
+ */
+
+static IMG_BOOL bUseLock = IMG_TRUE;
+
+PVRSRV_ERROR InitRGXTQ2Bridge(void);
+PVRSRV_ERROR DeinitRGXTQ2Bridge(void);
+
+/*
+ * Register all RGXTQ2 functions with services
+ */
+PVRSRV_ERROR InitRGXTQ2Bridge(void)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2, PVRSRV_BRIDGE_RGXTQ2_RGXTDMCREATETRANSFERCONTEXT, PVRSRVBridgeRGXTDMCreateTransferContext,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2, PVRSRV_BRIDGE_RGXTQ2_RGXTDMDESTROYTRANSFERCONTEXT, PVRSRVBridgeRGXTDMDestroyTransferContext,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2, PVRSRV_BRIDGE_RGXTQ2_RGXTDMSUBMITTRANSFER, PVRSRVBridgeRGXTDMSubmitTransfer,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2, PVRSRV_BRIDGE_RGXTQ2_RGXTDMSETTRANSFERCONTEXTPRIORITY, PVRSRVBridgeRGXTDMSetTransferContextPriority,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2, PVRSRV_BRIDGE_RGXTQ2_RGXTDMNOTIFYWRITEOFFSETUPDATE, PVRSRVBridgeRGXTDMNotifyWriteOffsetUpdate,
+					NULL, bUseLock);
+
+
+	return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxtq2 functions with services
+ */
+PVRSRV_ERROR DeinitRGXTQ2Bridge(void)
+{
+	return PVRSRV_OK;
+}
diff --git a/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h b/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h
index e8dfde0..899d9b9 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for rgxtq
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for rgxtq
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for rgxtq
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,12 +45,13 @@
 #ifndef COMMON_RGXTQ_BRIDGE_H
 #define COMMON_RGXTQ_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "rgx_bridge.h"
-#include "sync_external.h"
-#include "rgx_fwif_shared.h"
+#include <powervr/sync_external.h>
 
 
 #define PVRSRV_BRIDGE_RGXTQ_CMD_FIRST			0
@@ -58,8 +59,7 @@
 #define PVRSRV_BRIDGE_RGXTQ_RGXDESTROYTRANSFERCONTEXT			PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+1
 #define PVRSRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER			PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+2
 #define PVRSRV_BRIDGE_RGXTQ_RGXSETTRANSFERCONTEXTPRIORITY			PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+3
-#define PVRSRV_BRIDGE_RGXTQ_RGXKICKSYNCTRANSFER			PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+4
-#define PVRSRV_BRIDGE_RGXTQ_CMD_LAST			(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RGXTQ_CMD_LAST			(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+3)
 
 
 /*******************************************
@@ -109,6 +109,7 @@
 typedef struct PVRSRV_BRIDGE_IN_RGXSUBMITTRANSFER_TAG
 {
 	IMG_HANDLE hTransferContext;
+	IMG_UINT32 ui32ClientCacheOpSeqNum;
 	IMG_UINT32 ui32PrepareCount;
 	IMG_UINT32 * pui32ClientFenceCount;
 	IMG_HANDLE* * phFenceUFOSyncPrimBlock;
@@ -128,7 +129,6 @@
 	IMG_UINT8* * pui8FWCommand;
 	IMG_UINT32 * pui32TQPrepareFlags;
 	IMG_UINT32 ui32ExtJobRef;
-	IMG_UINT32 ui32IntJobRef;
 	IMG_UINT32 ui32SyncPMRCount;
 	IMG_UINT32 * pui32SyncPMRFlags;
 	IMG_HANDLE * phSyncPMRs;
@@ -160,39 +160,4 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETTRANSFERCONTEXTPRIORITY;
 
 
-/*******************************************
-            RGXKickSyncTransfer          
- *******************************************/
-
-/* Bridge in structure for RGXKickSyncTransfer */
-typedef struct PVRSRV_BRIDGE_IN_RGXKICKSYNCTRANSFER_TAG
-{
-	IMG_HANDLE hTransferContext;
-	IMG_UINT32 ui32ClientFenceCount;
-	IMG_HANDLE * phClientFenceUFOSyncPrimBlock;
-	IMG_UINT32 * pui32ClientFenceSyncOffset;
-	IMG_UINT32 * pui32ClientFenceValue;
-	IMG_UINT32 ui32ClientUpdateCount;
-	IMG_HANDLE * phClientUpdateUFOSyncPrimBlock;
-	IMG_UINT32 * pui32ClientUpdateSyncOffset;
-	IMG_UINT32 * pui32ClientUpdateValue;
-	IMG_UINT32 ui32ServerSyncCount;
-	IMG_UINT32 * pui32ServerSyncFlags;
-	IMG_HANDLE * phServerSyncs;
-	IMG_INT32 i32CheckFenceFD;
-	IMG_INT32 i32UpdateTimelineFD;
-	IMG_CHAR * puiUpdateFenceName;
-	IMG_UINT32 ui32TQPrepareFlags;
-	IMG_UINT32 ui32ExtJobRef;
-	IMG_UINT32 ui32IntJobRef;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKSYNCTRANSFER;
-
-/* Bridge out structure for RGXKickSyncTransfer */
-typedef struct PVRSRV_BRIDGE_OUT_RGXKICKSYNCTRANSFER_TAG
-{
-	IMG_INT32 i32UpdateFenceFD;
-	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKSYNCTRANSFER;
-
-
 #endif /* COMMON_RGXTQ_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c b/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c
index 87b1554..f9d5370 100644
--- a/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -75,50 +77,91 @@
 					 CONNECTION_DATA *psConnection)
 {
 	IMG_BYTE *psFrameworkCmdInt = NULL;
+	IMG_HANDLE hPrivData = psRGXCreateTransferContextIN->hPrivData;
 	IMG_HANDLE hPrivDataInt = NULL;
 	RGX_SERVER_TQ_CONTEXT * psTransferContextInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) +
+			0;
 
 
 
-	if (psRGXCreateTransferContextIN->ui32FrameworkCmdize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		psFrameworkCmdInt = OSAllocMemNoStats(psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE));
-		if (!psFrameworkCmdInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXCreateTransferContextIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXCreateTransferContext_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXCreateTransferContextIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXCreateTransferContext_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXCreateTransferContextIN->psFrameworkCmd, psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE))
-				|| (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateTransferContextIN->psFrameworkCmd,
-				psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
-			{
-				psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psRGXCreateTransferContextIN->ui32FrameworkCmdize != 0)
+	{
+		psFrameworkCmdInt = (IMG_BYTE*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE);
+	}
 
-				goto RGXCreateTransferContext_exit;
+			/* Copy the data over */
+			if (psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateTransferContextIN->psFrameworkCmd, psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK )
+				{
+					psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXCreateTransferContext_exit;
+				}
 			}
 
-	PMRLock();
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXCreateTransferContextOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hPrivDataInt,
-											psRGXCreateTransferContextIN->hPrivData,
-											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+											IMG_TRUE);
 					if(psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXCreateTransferContext_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXCreateTransferContextOUT->eError =
 		PVRSRVRGXCreateTransferContextKM(psConnection, OSGetDevData(psConnection),
@@ -131,13 +174,18 @@
 	/* Exit early if bridged call fails */
 	if(psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto RGXCreateTransferContext_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psRGXCreateTransferContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psRGXCreateTransferContextOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRGXCreateTransferContextOUT->hTransferContext,
 							(void *) psTransferContextInt,
 							PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
@@ -145,13 +193,37 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVRGXDestroyTransferContextKM);
 	if (psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RGXCreateTransferContext_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RGXCreateTransferContext_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hPrivDataInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPrivData,
+											PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
 	{
 		if (psTransferContextInt)
@@ -160,12 +232,21 @@
 		}
 	}
 
-	if (psFrameworkCmdInt)
-		OSFreeMemNoStats(psFrameworkCmdInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXDestroyTransferContext(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXDESTROYTRANSFERCONTEXT *psRGXDestroyTransferContextIN,
@@ -177,36 +258,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psRGXDestroyTransferContextOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRGXDestroyTransferContextIN->hTransferContext,
 					PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
-	if ((psRGXDestroyTransferContextOUT->eError != PVRSRV_OK) && (psRGXDestroyTransferContextOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRGXDestroyTransferContextOUT->eError != PVRSRV_OK) &&
+	    (psRGXDestroyTransferContextOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRGXDestroyTransferContext: %s",
+		        PVRSRVGetErrorStringKM(psRGXDestroyTransferContextOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto RGXDestroyTransferContext_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RGXDestroyTransferContext_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXSubmitTransfer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXSUBMITTRANSFER *psRGXSubmitTransferIN,
 					  PVRSRV_BRIDGE_OUT_RGXSUBMITTRANSFER *psRGXSubmitTransferOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hTransferContext = psRGXSubmitTransferIN->hTransferContext;
 	RGX_SERVER_TQ_CONTEXT * psTransferContextInt = NULL;
 	IMG_UINT32 *ui32ClientFenceCountInt = NULL;
 	SYNC_PRIMITIVE_BLOCK * **psFenceUFOSyncPrimBlockInt = NULL;
@@ -230,91 +328,492 @@
 	PMR * *psSyncPMRsInt = NULL;
 	IMG_HANDLE *hSyncPMRsInt2 = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+	IMG_BYTE   *pArrayArgsBuffer2 = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
 
-
+	IMG_UINT32 ui32BufferSize = 
+			(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+			(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+			(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+			(32 * sizeof(IMG_CHAR)) +
+			(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+			(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+			(psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+			(psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(PMR *)) +
+			(psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) +
+			0;
+	IMG_UINT32 ui32BufferSize2 = 0;
+	IMG_UINT32 ui32NextOffset2 = 0;
 
 	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
 	{
-		ui32ClientFenceCountInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
-		if (!ui32ClientFenceCountInt)
+
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK **);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE **);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK **);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE **);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SERVER_SYNC_PRIMITIVE **);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE **);
+		ui32BufferSize += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT8*);
+	}
+
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRGXSubmitTransferIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRGXSubmitTransferIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RGXSubmitTransfer_exit;
+			}
+		}
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		ui32ClientFenceCountInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientFenceCountInt, psRGXSubmitTransferIN->pui32ClientFenceCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning psFenceUFOSyncPrimBlockInt to the right offset in the pool buffer for first dimension */
+		psFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK ***)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK **);
+		/* Assigning hFenceUFOSyncPrimBlockInt2 to the right offset in the pool buffer for first dimension */
+		hFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning ui32FenceSyncOffsetInt to the right offset in the pool buffer for first dimension */
+		ui32FenceSyncOffsetInt = (IMG_UINT32**)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning ui32FenceValueInt to the right offset in the pool buffer for first dimension */
+		ui32FenceValueInt = (IMG_UINT32**)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		ui32ClientUpdateCountInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ClientUpdateCountInt, psRGXSubmitTransferIN->pui32ClientUpdateCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning psUpdateUFOSyncPrimBlockInt to the right offset in the pool buffer for first dimension */
+		psUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK ***)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK **);
+		/* Assigning hUpdateUFOSyncPrimBlockInt2 to the right offset in the pool buffer for first dimension */
+		hUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning ui32UpdateSyncOffsetInt to the right offset in the pool buffer for first dimension */
+		ui32UpdateSyncOffsetInt = (IMG_UINT32**)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning ui32UpdateValueInt to the right offset in the pool buffer for first dimension */
+		ui32UpdateValueInt = (IMG_UINT32**)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		ui32ServerSyncCountInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32ServerSyncCountInt, psRGXSubmitTransferIN->pui32ServerSyncCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning ui32ServerSyncFlagsInt to the right offset in the pool buffer for first dimension */
+		ui32ServerSyncFlagsInt = (IMG_UINT32**)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32*);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning psServerSyncInt to the right offset in the pool buffer for first dimension */
+		psServerSyncInt = (SERVER_SYNC_PRIMITIVE ***)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SERVER_SYNC_PRIMITIVE **);
+		/* Assigning hServerSyncInt2 to the right offset in the pool buffer for first dimension */
+		hServerSyncInt2 = (IMG_HANDLE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE);
+	}
+
+	
+	{
+		uiUpdateFenceNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += 32 * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (32 * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXSubmitTransferIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		ui32CommandSizeInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32CommandSizeInt, psRGXSubmitTransferIN->pui32CommandSize, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		/* Assigning ui8FWCommandInt to the right offset in the pool buffer for first dimension */
+		ui8FWCommandInt = (IMG_UINT8**)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT8*);
+	}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		ui32TQPrepareFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32TQPrepareFlagsInt, psRGXSubmitTransferIN->pui32TQPrepareFlags, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32SyncPMRCount != 0)
+	{
+		ui32SyncPMRFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32SyncPMRFlagsInt, psRGXSubmitTransferIN->pui32SyncPMRFlags, psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+	if (psRGXSubmitTransferIN->ui32SyncPMRCount != 0)
+	{
+		psSyncPMRsInt = (PMR **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(PMR *);
+		hSyncPMRsInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
+	}
+
+			/* Copy the data over */
+			if (psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE) > 0)
+			{
+				if ( OSCopyFromUser(NULL, hSyncPMRsInt2, psRGXSubmitTransferIN->phSyncPMRs, psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i = 0; i < psRGXSubmitTransferIN->ui32PrepareCount; i++)
+		{
+			ui32BufferSize2 += ui32ClientFenceCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);
+			ui32BufferSize2 += ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE *);
+			ui32BufferSize2 += ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);
+			ui32BufferSize2 += ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);
+			ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);
+			ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE *);
+			ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+			ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+			ui32BufferSize2 += ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32);
+			ui32BufferSize2 += ui32ServerSyncCountInt[i] * sizeof(SERVER_SYNC_PRIMITIVE *);
+			ui32BufferSize2 += ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE *);
+			ui32BufferSize2 += ui32CommandSizeInt[i] * sizeof(IMG_UINT8);
+		}
+	}
+
+	if (ui32BufferSize2 != 0)
+	{
+		pArrayArgsBuffer2 = OSAllocMemNoStats(ui32BufferSize2);
+
+		if(!pArrayArgsBuffer2)
 		{
 			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
 			goto RGXSubmitTransfer_exit;
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->pui32ClientFenceCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientFenceCountInt, psRGXSubmitTransferIN->pui32ClientFenceCount,
-				psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each psFenceUFOSyncPrimBlockInt to the right offset in the pool buffer (this is the second dimension) */
+			psFenceUFOSyncPrimBlockInt[i] = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ClientFenceCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);
+			/* Assigning each hFenceUFOSyncPrimBlockInt2 to the right offset in the pool buffer (this is the second dimension) */
+			hFenceUFOSyncPrimBlockInt2[i] = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2); 
+			ui32NextOffset2 += ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each ui32FenceSyncOffsetInt to the right offset in the pool buffer (this is the second dimension) */
+			ui32FenceSyncOffsetInt[i] = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each ui32FenceValueInt to the right offset in the pool buffer (this is the second dimension) */
+			ui32FenceValueInt[i] = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each psUpdateUFOSyncPrimBlockInt to the right offset in the pool buffer (this is the second dimension) */
+			psUpdateUFOSyncPrimBlockInt[i] = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ClientUpdateCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);
+			/* Assigning each hUpdateUFOSyncPrimBlockInt2 to the right offset in the pool buffer (this is the second dimension) */
+			hUpdateUFOSyncPrimBlockInt2[i] = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2); 
+			ui32NextOffset2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each ui32UpdateSyncOffsetInt to the right offset in the pool buffer (this is the second dimension) */
+			ui32UpdateSyncOffsetInt[i] = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each ui32UpdateValueInt to the right offset in the pool buffer (this is the second dimension) */
+			ui32UpdateValueInt[i] = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each ui32ServerSyncFlagsInt to the right offset in the pool buffer (this is the second dimension) */
+			ui32ServerSyncFlagsInt[i] = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each psServerSyncInt to the right offset in the pool buffer (this is the second dimension) */
+			psServerSyncInt[i] = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32ServerSyncCountInt[i] * sizeof(SERVER_SYNC_PRIMITIVE *);
+			/* Assigning each hServerSyncInt2 to the right offset in the pool buffer (this is the second dimension) */
+			hServerSyncInt2[i] = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2); 
+			ui32NextOffset2 += ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE);
+		}
+	}
+	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+	{
+		IMG_UINT32 i;
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Assigning each ui8FWCommandInt to the right offset in the pool buffer (this is the second dimension) */
+			ui8FWCommandInt[i] = (IMG_UINT8*)(((IMG_UINT8 *)pArrayArgsBuffer2) + ui32NextOffset2);
+			ui32NextOffset2 += ui32CommandSizeInt[i] * sizeof(IMG_UINT8);
+		}
+	}
+
+	{
+		IMG_UINT32 i;
+		IMG_HANDLE **psPtr;
+
+		/* Loop over all the pointers in the array copying the data into the kernel */
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Copy the pointer over from the client side */
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phFenceUFOSyncPrimBlock[i],
+				sizeof(IMG_HANDLE **)) != PVRSRV_OK )
 			{
 				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
 				goto RGXSubmitTransfer_exit;
 			}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-		IMG_UINT32 ui32AllocSize2=0;
-		IMG_UINT32 ui32Size2;
-		IMG_UINT8 *pui8Ptr2 = NULL;
 
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+			/* Copy the data over */
+			if ((ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE)) > 0)
+			{
+				if ( OSCopyFromUser(NULL, (hFenceUFOSyncPrimBlockInt2[i]), psPtr, (ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
+			}
+		}
+	}
+
+	{
+		IMG_UINT32 i;
+		IMG_UINT32 **psPtr;
+
+		/* Loop over all the pointers in the array copying the data into the kernel */
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK * *);
-			ui32Size2 = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE *);
-			if (ui32Pass == 0)
+			/* Copy the pointer over from the client side */
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32FenceSyncOffset[i],
+				sizeof(IMG_UINT32 **)) != PVRSRV_OK )
 			{
-				ui32AllocSize += ui32Size;
-				ui32AllocSize2 += ui32Size2;
+				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+				goto RGXSubmitTransfer_exit;
 			}
-			else
+
+			/* Copy the data over */
+			if ((ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32)) > 0)
 			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
+				if ( OSCopyFromUser(NULL, (ui32FenceSyncOffsetInt[i]), psPtr, (ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK )
 				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
 					goto RGXSubmitTransfer_exit;
 				}
-				psFenceUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK * **) pui8Ptr;
-				pui8Ptr += ui32Size;
-				pui8Ptr2 = OSAllocMemNoStats(ui32AllocSize2);
-				if (pui8Ptr2 == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				hFenceUFOSyncPrimBlockInt2 = (IMG_HANDLE **) pui8Ptr2;
-				pui8Ptr2 += ui32Size2;
 			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		}
+	}
+
+	{
+		IMG_UINT32 i;
+		IMG_UINT32 **psPtr;
+
+		/* Loop over all the pointers in the array copying the data into the kernel */
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			/* Copy the pointer over from the client side */
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32FenceValue[i],
+				sizeof(IMG_UINT32 **)) != PVRSRV_OK )
 			{
-				ui32Size = ui32ClientFenceCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);		
-				ui32Size2 = ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE);		
-				if (ui32Size)
+				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+				goto RGXSubmitTransfer_exit;
+			}
+
+			/* Copy the data over */
+			if ((ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32)) > 0)
+			{
+				if ( OSCopyFromUser(NULL, (ui32FenceValueInt[i]), psPtr, (ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK )
 				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-						ui32AllocSize2 += ui32Size2;
-					}
-					else
-					{
-						psFenceUFOSyncPrimBlockInt[i] = (SYNC_PRIMITIVE_BLOCK * *) pui8Ptr;
-						pui8Ptr += ui32Size;
-						hFenceUFOSyncPrimBlockInt2[i] = (IMG_HANDLE *) pui8Ptr2;
-						pui8Ptr2 += ui32Size2;
-					}
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
 				}
 			}
 		}
@@ -328,71 +827,23 @@
 		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
 			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->phFenceUFOSyncPrimBlock[i], sizeof(IMG_HANDLE **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phFenceUFOSyncPrimBlock[i],
-				sizeof(IMG_HANDLE **)) != PVRSRV_OK) )
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phUpdateUFOSyncPrimBlock[i],
+				sizeof(IMG_HANDLE **)) != PVRSRV_OK )
 			{
 				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
 				goto RGXSubmitTransfer_exit;
 			}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE)))
-				|| (OSCopyFromUser(NULL, (hFenceUFOSyncPrimBlockInt2[i]), psPtr,
-				(ui32ClientFenceCountInt[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK) )
+			if ((ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE)) > 0)
 			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
+				if ( OSCopyFromUser(NULL, (hUpdateUFOSyncPrimBlockInt2[i]), psPtr, (ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK )
 				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
 					goto RGXSubmitTransfer_exit;
 				}
-				ui32FenceSyncOffsetInt = (IMG_UINT32 **) pui8Ptr;
-				pui8Ptr += ui32Size;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-					}
-					else
-					{
-						ui32FenceSyncOffsetInt[i] = (IMG_UINT32 *) pui8Ptr;
-						pui8Ptr += ui32Size;
-					}
-				}
 			}
 		}
 	}
@@ -405,71 +856,23 @@
 		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
 			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->pui32FenceSyncOffset[i], sizeof(IMG_UINT32 **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32FenceSyncOffset[i],
-				sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32UpdateSyncOffset[i],
+				sizeof(IMG_UINT32 **)) != PVRSRV_OK )
 			{
 				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
 				goto RGXSubmitTransfer_exit;
 			}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32)))
-				|| (OSCopyFromUser(NULL, (ui32FenceSyncOffsetInt[i]), psPtr,
-				(ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+			if ((ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32)) > 0)
 			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
+				if ( OSCopyFromUser(NULL, (ui32UpdateSyncOffsetInt[i]), psPtr, (ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK )
 				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
 					goto RGXSubmitTransfer_exit;
 				}
-				ui32FenceValueInt = (IMG_UINT32 **) pui8Ptr;
-				pui8Ptr += ui32Size;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-					}
-					else
-					{
-						ui32FenceValueInt[i] = (IMG_UINT32 *) pui8Ptr;
-						pui8Ptr += ui32Size;
-					}
-				}
 			}
 		}
 	}
@@ -482,108 +885,52 @@
 		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
 			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->pui32FenceValue[i], sizeof(IMG_UINT32 **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32FenceValue[i],
-				sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32UpdateValue[i],
+				sizeof(IMG_UINT32 **)) != PVRSRV_OK )
 			{
 				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
 				goto RGXSubmitTransfer_exit;
 			}
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32)))
-				|| (OSCopyFromUser(NULL, (ui32FenceValueInt[i]), psPtr,
-				(ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXSubmitTransfer_exit;
+			/* Copy the data over */
+			if ((ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32)) > 0)
+			{
+				if ( OSCopyFromUser(NULL, (ui32UpdateValueInt[i]), psPtr, (ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
 			}
 		}
 	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		ui32ClientUpdateCountInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
-		if (!ui32ClientUpdateCountInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->pui32ClientUpdateCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientUpdateCountInt, psRGXSubmitTransferIN->pui32ClientUpdateCount,
-				psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
 	{
-		IMG_UINT32 ui32Pass=0;
 		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-		IMG_UINT32 ui32AllocSize2=0;
-		IMG_UINT32 ui32Size2;
-		IMG_UINT8 *pui8Ptr2 = NULL;
+		IMG_UINT32 **psPtr;
 
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+		/* Loop over all the pointers in the array copying the data into the kernel */
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK * *);
-			ui32Size2 = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE *);
-			if (ui32Pass == 0)
+			/* Copy the pointer over from the client side */
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32ServerSyncFlags[i],
+				sizeof(IMG_UINT32 **)) != PVRSRV_OK )
 			{
-				ui32AllocSize += ui32Size;
-				ui32AllocSize2 += ui32Size2;
+				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+				goto RGXSubmitTransfer_exit;
 			}
-			else
+
+			/* Copy the data over */
+			if ((ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32)) > 0)
 			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
+				if ( OSCopyFromUser(NULL, (ui32ServerSyncFlagsInt[i]), psPtr, (ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK )
 				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
 					goto RGXSubmitTransfer_exit;
 				}
-				psUpdateUFOSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK * **) pui8Ptr;
-				pui8Ptr += ui32Size;
-				pui8Ptr2 = OSAllocMemNoStats(ui32AllocSize2);
-				if (pui8Ptr2 == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				hUpdateUFOSyncPrimBlockInt2 = (IMG_HANDLE **) pui8Ptr2;
-				pui8Ptr2 += ui32Size2;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ClientUpdateCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);		
-				ui32Size2 = ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-						ui32AllocSize2 += ui32Size2;
-					}
-					else
-					{
-						psUpdateUFOSyncPrimBlockInt[i] = (SYNC_PRIMITIVE_BLOCK * *) pui8Ptr;
-						pui8Ptr += ui32Size;
-						hUpdateUFOSyncPrimBlockInt2[i] = (IMG_HANDLE *) pui8Ptr2;
-						pui8Ptr2 += ui32Size2;
-					}
-				}
 			}
 		}
 	}
@@ -596,456 +943,23 @@
 		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
 			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->phUpdateUFOSyncPrimBlock[i], sizeof(IMG_HANDLE **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phUpdateUFOSyncPrimBlock[i],
-				sizeof(IMG_HANDLE **)) != PVRSRV_OK) )
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phServerSync[i],
+				sizeof(IMG_HANDLE **)) != PVRSRV_OK )
 			{
 				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
 				goto RGXSubmitTransfer_exit;
 			}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE)))
-				|| (OSCopyFromUser(NULL, (hUpdateUFOSyncPrimBlockInt2[i]), psPtr,
-				(ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK) )
+			if ((ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE)) > 0)
 			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
+				if ( OSCopyFromUser(NULL, (hServerSyncInt2[i]), psPtr, (ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK )
 				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
 					goto RGXSubmitTransfer_exit;
 				}
-				ui32UpdateSyncOffsetInt = (IMG_UINT32 **) pui8Ptr;
-				pui8Ptr += ui32Size;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-					}
-					else
-					{
-						ui32UpdateSyncOffsetInt[i] = (IMG_UINT32 *) pui8Ptr;
-						pui8Ptr += ui32Size;
-					}
-				}
-			}
-		}
-	}
-
-	{
-		IMG_UINT32 i;
-		IMG_UINT32 **psPtr;
-
-		/* Loop over all the pointers in the array copying the data into the kernel */
-		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-		{
-			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->pui32UpdateSyncOffset[i], sizeof(IMG_UINT32 **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32UpdateSyncOffset[i],
-				sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32)))
-				|| (OSCopyFromUser(NULL, (ui32UpdateSyncOffsetInt[i]), psPtr,
-				(ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				ui32UpdateValueInt = (IMG_UINT32 **) pui8Ptr;
-				pui8Ptr += ui32Size;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-					}
-					else
-					{
-						ui32UpdateValueInt[i] = (IMG_UINT32 *) pui8Ptr;
-						pui8Ptr += ui32Size;
-					}
-				}
-			}
-		}
-	}
-
-	{
-		IMG_UINT32 i;
-		IMG_UINT32 **psPtr;
-
-		/* Loop over all the pointers in the array copying the data into the kernel */
-		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-		{
-			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->pui32UpdateValue[i], sizeof(IMG_UINT32 **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32UpdateValue[i],
-				sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32)))
-				|| (OSCopyFromUser(NULL, (ui32UpdateValueInt[i]), psPtr,
-				(ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		ui32ServerSyncCountInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
-		if (!ui32ServerSyncCountInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->pui32ServerSyncCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ServerSyncCountInt, psRGXSubmitTransferIN->pui32ServerSyncCount,
-				psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				ui32ServerSyncFlagsInt = (IMG_UINT32 **) pui8Ptr;
-				pui8Ptr += ui32Size;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-					}
-					else
-					{
-						ui32ServerSyncFlagsInt[i] = (IMG_UINT32 *) pui8Ptr;
-						pui8Ptr += ui32Size;
-					}
-				}
-			}
-		}
-	}
-
-	{
-		IMG_UINT32 i;
-		IMG_UINT32 **psPtr;
-
-		/* Loop over all the pointers in the array copying the data into the kernel */
-		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-		{
-			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->pui32ServerSyncFlags[i], sizeof(IMG_UINT32 **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32ServerSyncFlags[i],
-				sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32)))
-				|| (OSCopyFromUser(NULL, (ui32ServerSyncFlagsInt[i]), psPtr,
-				(ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-		IMG_UINT32 ui32AllocSize2=0;
-		IMG_UINT32 ui32Size2;
-		IMG_UINT8 *pui8Ptr2 = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SERVER_SYNC_PRIMITIVE * *);
-			ui32Size2 = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-				ui32AllocSize2 += ui32Size2;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				psServerSyncInt = (SERVER_SYNC_PRIMITIVE * **) pui8Ptr;
-				pui8Ptr += ui32Size;
-				pui8Ptr2 = OSAllocMemNoStats(ui32AllocSize2);
-				if (pui8Ptr2 == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				hServerSyncInt2 = (IMG_HANDLE **) pui8Ptr2;
-				pui8Ptr2 += ui32Size2;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32ServerSyncCountInt[i] * sizeof(SERVER_SYNC_PRIMITIVE *);		
-				ui32Size2 = ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-						ui32AllocSize2 += ui32Size2;
-					}
-					else
-					{
-						psServerSyncInt[i] = (SERVER_SYNC_PRIMITIVE * *) pui8Ptr;
-						pui8Ptr += ui32Size;
-						hServerSyncInt2[i] = (IMG_HANDLE *) pui8Ptr2;
-						pui8Ptr2 += ui32Size2;
-					}
-				}
-			}
-		}
-	}
-
-	{
-		IMG_UINT32 i;
-		IMG_HANDLE **psPtr;
-
-		/* Loop over all the pointers in the array copying the data into the kernel */
-		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-		{
-			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->phServerSync[i], sizeof(IMG_HANDLE **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phServerSync[i],
-				sizeof(IMG_HANDLE **)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE)))
-				|| (OSCopyFromUser(NULL, (hServerSyncInt2[i]), psPtr,
-				(ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-		}
-	}
-	
-	{
-		uiUpdateFenceNameInt = OSAllocMemNoStats(32 * sizeof(IMG_CHAR));
-		if (!uiUpdateFenceNameInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXSubmitTransferIN->puiUpdateFenceName,
-				32 * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		ui32CommandSizeInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
-		if (!ui32CommandSizeInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->pui32CommandSize, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32CommandSizeInt, psRGXSubmitTransferIN->pui32CommandSize,
-				psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		IMG_UINT32 ui32Pass=0;
-		IMG_UINT32 i;
-		IMG_UINT32 ui32AllocSize=0;
-		IMG_UINT32 ui32Size;
-		IMG_UINT8 *pui8Ptr = NULL;
-
-		/*
-			Two pass loop, 1st find out the size and 2nd allocation and set offsets.
-			Keeps allocation cost down and simplifies the free path
-		*/
-		for (ui32Pass=0;ui32Pass<2;ui32Pass++)
-		{
-			ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT8 *);
-			if (ui32Pass == 0)
-			{
-				ui32AllocSize += ui32Size;
-			}
-			else
-			{
-				pui8Ptr = OSAllocMemNoStats(ui32AllocSize);
-				if (pui8Ptr == NULL)
-				{
-					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-					goto RGXSubmitTransfer_exit;
-				}
-				ui8FWCommandInt = (IMG_UINT8 **) pui8Ptr;
-				pui8Ptr += ui32Size;
-			}
-			
-			for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
-			{
-				ui32Size = ui32CommandSizeInt[i] * sizeof(IMG_UINT8);		
-				if (ui32Size)
-				{
-					if (ui32Pass == 0)
-					{
-						ui32AllocSize += ui32Size;
-					}
-					else
-					{
-						ui8FWCommandInt[i] = (IMG_UINT8 *) pui8Ptr;
-						pui8Ptr += ui32Size;
-					}
-				}
 			}
 		}
 	}
@@ -1058,111 +972,52 @@
 		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
 		{
 			/* Copy the pointer over from the client side */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) &psRGXSubmitTransferIN->pui8FWCommand[i], sizeof(IMG_UINT8 **))
-				|| (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui8FWCommand[i],
-				sizeof(IMG_UINT8 **)) != PVRSRV_OK) )
+			if ( OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui8FWCommand[i],
+				sizeof(IMG_UINT8 **)) != PVRSRV_OK )
 			{
 				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
 				goto RGXSubmitTransfer_exit;
 			}
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psPtr, (ui32CommandSizeInt[i] * sizeof(IMG_UINT8)))
-				|| (OSCopyFromUser(NULL, (ui8FWCommandInt[i]), psPtr,
-				(ui32CommandSizeInt[i] * sizeof(IMG_UINT8))) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXSubmitTransfer_exit;
+			/* Copy the data over */
+			if ((ui32CommandSizeInt[i] * sizeof(IMG_UINT8)) > 0)
+			{
+				if ( OSCopyFromUser(NULL, (ui8FWCommandInt[i]), psPtr, (ui32CommandSizeInt[i] * sizeof(IMG_UINT8))) != PVRSRV_OK )
+				{
+					psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RGXSubmitTransfer_exit;
+				}
 			}
 		}
 	}
-	if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
-	{
-		ui32TQPrepareFlagsInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
-		if (!ui32TQPrepareFlagsInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
+	/* Lock over handle lookup. */
+	LockHandle();
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->pui32TQPrepareFlags, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32TQPrepareFlagsInt, psRGXSubmitTransferIN->pui32TQPrepareFlags,
-				psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RGXSubmitTransfer_exit;
-			}
-	if (psRGXSubmitTransferIN->ui32SyncPMRCount != 0)
-	{
-		ui32SyncPMRFlagsInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32));
-		if (!ui32SyncPMRFlagsInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->pui32SyncPMRFlags, psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32SyncPMRFlagsInt, psRGXSubmitTransferIN->pui32SyncPMRFlags,
-				psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-	if (psRGXSubmitTransferIN->ui32SyncPMRCount != 0)
-	{
-		psSyncPMRsInt = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(PMR *));
-		if (!psSyncPMRsInt)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-		hSyncPMRsInt2 = OSAllocMemNoStats(psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE));
-		if (!hSyncPMRsInt2)
-		{
-			psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXSubmitTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXSubmitTransferIN->phSyncPMRs, psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hSyncPMRsInt2, psRGXSubmitTransferIN->phSyncPMRs,
-				psRGXSubmitTransferIN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
-			{
-				psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXSubmitTransfer_exit;
-			}
-
-	PMRLock();
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXSubmitTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psTransferContextInt,
-											psRGXSubmitTransferIN->hTransferContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
+											IMG_TRUE);
 					if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXSubmitTransfer_exit;
 					}
 				}
 
 
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1174,21 +1029,25 @@
 				{
 					/* Look up the address from the handle */
 					psRGXSubmitTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psFenceUFOSyncPrimBlockInt[i][j],
 											hFenceUFOSyncPrimBlockInt2[i][j],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXSubmitTransfer_exit;
 					}
 				}
-
 			}
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1200,21 +1059,25 @@
 				{
 					/* Look up the address from the handle */
 					psRGXSubmitTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psUpdateUFOSyncPrimBlockInt[i][j],
 											hUpdateUFOSyncPrimBlockInt2[i][j],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXSubmitTransfer_exit;
 					}
 				}
-
 			}
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1226,21 +1089,25 @@
 				{
 					/* Look up the address from the handle */
 					psRGXSubmitTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerSyncInt[i][j],
 											hServerSyncInt2[i][j],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXSubmitTransfer_exit;
 					}
 				}
-
 			}
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -1249,23 +1116,26 @@
 				{
 					/* Look up the address from the handle */
 					psRGXSubmitTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncPMRsInt[i],
 											hSyncPMRsInt2[i],
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto RGXSubmitTransfer_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXSubmitTransferOUT->eError =
 		PVRSRVRGXSubmitTransferKM(
 					psTransferContextInt,
+					psRGXSubmitTransferIN->ui32ClientCacheOpSeqNum,
 					psRGXSubmitTransferIN->ui32PrepareCount,
 					ui32ClientFenceCountInt,
 					psFenceUFOSyncPrimBlockInt,
@@ -1286,490 +1156,235 @@
 					ui8FWCommandInt,
 					ui32TQPrepareFlagsInt,
 					psRGXSubmitTransferIN->ui32ExtJobRef,
-					psRGXSubmitTransferIN->ui32IntJobRef,
 					psRGXSubmitTransferIN->ui32SyncPMRCount,
 					ui32SyncPMRFlagsInt,
 					psSyncPMRsInt);
-	PMRUnlock();
 
 
 
 
 RGXSubmitTransfer_exit:
-	if (ui32ClientFenceCountInt)
-		OSFreeMemNoStats(ui32ClientFenceCountInt);
-	if (psFenceUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psFenceUFOSyncPrimBlockInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psTransferContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+						}
+				}
+
+
+
+
+
+
 	if (hFenceUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hFenceUFOSyncPrimBlockInt2);
-	if (ui32FenceSyncOffsetInt)
-		OSFreeMemNoStats(ui32FenceSyncOffsetInt);
-	if (ui32FenceValueInt)
-		OSFreeMemNoStats(ui32FenceValueInt);
-	if (ui32ClientUpdateCountInt)
-		OSFreeMemNoStats(ui32ClientUpdateCountInt);
-	if (psUpdateUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psUpdateUFOSyncPrimBlockInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			IMG_UINT32 j;
+			for (j=0;j<ui32ClientFenceCountInt[i];j++)
+			{
+				{
+					/* Unreference the previously looked up handle */
+						if(psFenceUFOSyncPrimBlockInt[i][j])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hFenceUFOSyncPrimBlockInt2[i][j],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+			}
+		}
+	}
+
+
+
+
+
+
 	if (hUpdateUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hUpdateUFOSyncPrimBlockInt2);
-	if (ui32UpdateSyncOffsetInt)
-		OSFreeMemNoStats(ui32UpdateSyncOffsetInt);
-	if (ui32UpdateValueInt)
-		OSFreeMemNoStats(ui32UpdateValueInt);
-	if (ui32ServerSyncCountInt)
-		OSFreeMemNoStats(ui32ServerSyncCountInt);
-	if (ui32ServerSyncFlagsInt)
-		OSFreeMemNoStats(ui32ServerSyncFlagsInt);
-	if (psServerSyncInt)
-		OSFreeMemNoStats(psServerSyncInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			IMG_UINT32 j;
+			for (j=0;j<ui32ClientUpdateCountInt[i];j++)
+			{
+				{
+					/* Unreference the previously looked up handle */
+						if(psUpdateUFOSyncPrimBlockInt[i][j])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hUpdateUFOSyncPrimBlockInt2[i][j],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+			}
+		}
+	}
+
+
+
+
+
+
 	if (hServerSyncInt2)
-		OSFreeMemNoStats(hServerSyncInt2);
-	if (uiUpdateFenceNameInt)
-		OSFreeMemNoStats(uiUpdateFenceNameInt);
-	if (ui32CommandSizeInt)
-		OSFreeMemNoStats(ui32CommandSizeInt);
-	if (ui8FWCommandInt)
-		OSFreeMemNoStats(ui8FWCommandInt);
-	if (ui32TQPrepareFlagsInt)
-		OSFreeMemNoStats(ui32TQPrepareFlagsInt);
-	if (ui32SyncPMRFlagsInt)
-		OSFreeMemNoStats(ui32SyncPMRFlagsInt);
-	if (psSyncPMRsInt)
-		OSFreeMemNoStats(psSyncPMRsInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+		{
+			IMG_UINT32 j;
+			for (j=0;j<ui32ServerSyncCountInt[i];j++)
+			{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncInt[i][j])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncInt2[i][j],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+			}
+		}
+	}
+
+
+
+
+
+
 	if (hSyncPMRsInt2)
-		OSFreeMemNoStats(hSyncPMRsInt2);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psRGXSubmitTransferIN->ui32SyncPMRCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncPMRsInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncPMRsInt2[i],
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize2 == ui32NextOffset2);
+
+	if(pArrayArgsBuffer2)
+		OSFreeMemNoStats(pArrayArgsBuffer2);
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXSetTransferContextPriority(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXSETTRANSFERCONTEXTPRIORITY *psRGXSetTransferContextPriorityIN,
 					  PVRSRV_BRIDGE_OUT_RGXSETTRANSFERCONTEXTPRIORITY *psRGXSetTransferContextPriorityOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hTransferContext = psRGXSetTransferContextPriorityIN->hTransferContext;
 	RGX_SERVER_TQ_CONTEXT * psTransferContextInt = NULL;
 
 
 
 
 
-#if defined(PDUMP)
-	PMRLock();
-#endif
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRGXSetTransferContextPriorityOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psTransferContextInt,
-											psRGXSetTransferContextPriorityIN->hTransferContext,
-											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+											hTransferContext,
+											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
+											IMG_TRUE);
 					if(psRGXSetTransferContextPriorityOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto RGXSetTransferContextPriority_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRGXSetTransferContextPriorityOUT->eError =
 		PVRSRVRGXSetTransferContextPriorityKM(psConnection, OSGetDevData(psConnection),
 					psTransferContextInt,
 					psRGXSetTransferContextPriorityIN->ui32Priority);
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
 
 
 
 
 RGXSetTransferContextPriority_exit:
 
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeRGXKickSyncTransfer(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_RGXKICKSYNCTRANSFER *psRGXKickSyncTransferIN,
-					  PVRSRV_BRIDGE_OUT_RGXKICKSYNCTRANSFER *psRGXKickSyncTransferOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	RGX_SERVER_TQ_CONTEXT * psTransferContextInt = NULL;
-	SYNC_PRIMITIVE_BLOCK * *psClientFenceUFOSyncPrimBlockInt = NULL;
-	IMG_HANDLE *hClientFenceUFOSyncPrimBlockInt2 = NULL;
-	IMG_UINT32 *ui32ClientFenceSyncOffsetInt = NULL;
-	IMG_UINT32 *ui32ClientFenceValueInt = NULL;
-	SYNC_PRIMITIVE_BLOCK * *psClientUpdateUFOSyncPrimBlockInt = NULL;
-	IMG_HANDLE *hClientUpdateUFOSyncPrimBlockInt2 = NULL;
-	IMG_UINT32 *ui32ClientUpdateSyncOffsetInt = NULL;
-	IMG_UINT32 *ui32ClientUpdateValueInt = NULL;
-	IMG_UINT32 *ui32ServerSyncFlagsInt = NULL;
-	SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = NULL;
-	IMG_HANDLE *hServerSyncsInt2 = NULL;
-	IMG_CHAR *uiUpdateFenceNameInt = NULL;
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
 
 
 
 
-	if (psRGXKickSyncTransferIN->ui32ClientFenceCount != 0)
-	{
-		psClientFenceUFOSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClientFenceUFOSyncPrimBlockInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-		hClientFenceUFOSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE));
-		if (!hClientFenceUFOSyncPrimBlockInt2)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->phClientFenceUFOSyncPrimBlock, psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClientFenceUFOSyncPrimBlockInt2, psRGXKickSyncTransferIN->phClientFenceUFOSyncPrimBlock,
-				psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ClientFenceCount != 0)
-	{
-		ui32ClientFenceSyncOffsetInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
-		if (!ui32ClientFenceSyncOffsetInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->pui32ClientFenceSyncOffset, psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientFenceSyncOffsetInt, psRGXKickSyncTransferIN->pui32ClientFenceSyncOffset,
-				psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ClientFenceCount != 0)
-	{
-		ui32ClientFenceValueInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
-		if (!ui32ClientFenceValueInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->pui32ClientFenceValue, psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickSyncTransferIN->pui32ClientFenceValue,
-				psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ClientUpdateCount != 0)
-	{
-		psClientUpdateUFOSyncPrimBlockInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psClientUpdateUFOSyncPrimBlockInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-		hClientUpdateUFOSyncPrimBlockInt2 = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE));
-		if (!hClientUpdateUFOSyncPrimBlockInt2)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->phClientUpdateUFOSyncPrimBlock, psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hClientUpdateUFOSyncPrimBlockInt2, psRGXKickSyncTransferIN->phClientUpdateUFOSyncPrimBlock,
-				psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ClientUpdateCount != 0)
-	{
-		ui32ClientUpdateSyncOffsetInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32ClientUpdateSyncOffsetInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->pui32ClientUpdateSyncOffset, psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientUpdateSyncOffsetInt, psRGXKickSyncTransferIN->pui32ClientUpdateSyncOffset,
-				psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ClientUpdateCount != 0)
-	{
-		ui32ClientUpdateValueInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
-		if (!ui32ClientUpdateValueInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->pui32ClientUpdateValue, psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickSyncTransferIN->pui32ClientUpdateValue,
-				psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ServerSyncCount != 0)
-	{
-		ui32ServerSyncFlagsInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
-		if (!ui32ServerSyncFlagsInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->pui32ServerSyncFlags, psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickSyncTransferIN->pui32ServerSyncFlags,
-				psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	if (psRGXKickSyncTransferIN->ui32ServerSyncCount != 0)
-	{
-		psServerSyncsInt = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psServerSyncsInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-		hServerSyncsInt2 = OSAllocMemNoStats(psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
-		if (!hServerSyncsInt2)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->phServerSyncs, psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickSyncTransferIN->phServerSyncs,
-				psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-	
-	{
-		uiUpdateFenceNameInt = OSAllocMemNoStats(32 * sizeof(IMG_CHAR));
-		if (!uiUpdateFenceNameInt)
-		{
-			psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RGXKickSyncTransfer_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRGXKickSyncTransferIN->puiUpdateFenceName, 32 * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiUpdateFenceNameInt, psRGXKickSyncTransferIN->puiUpdateFenceName,
-				32 * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto RGXKickSyncTransfer_exit;
-			}
-
-#if defined(PDUMP)
-	PMRLock();
-#endif
 
 
 				{
-					/* Look up the address from the handle */
-					psRGXKickSyncTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psTransferContextInt,
-											psRGXKickSyncTransferIN->hTransferContext,
+					/* Unreference the previously looked up handle */
+						if(psTransferContextInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hTransferContext,
 											PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
-					if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
-					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
-						goto RGXKickSyncTransfer_exit;
-					}
+						}
 				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
 
 
-	{
-		IMG_UINT32 i;
-
-		for (i=0;i<psRGXKickSyncTransferIN->ui32ClientFenceCount;i++)
-		{
-				{
-					/* Look up the address from the handle */
-					psRGXKickSyncTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psClientFenceUFOSyncPrimBlockInt[i],
-											hClientFenceUFOSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
-					if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
-					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
-						goto RGXKickSyncTransfer_exit;
-					}
-				}
-
-		}
-	}
-
-	{
-		IMG_UINT32 i;
-
-		for (i=0;i<psRGXKickSyncTransferIN->ui32ClientUpdateCount;i++)
-		{
-				{
-					/* Look up the address from the handle */
-					psRGXKickSyncTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psClientUpdateUFOSyncPrimBlockInt[i],
-											hClientUpdateUFOSyncPrimBlockInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
-					if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
-					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
-						goto RGXKickSyncTransfer_exit;
-					}
-				}
-
-		}
-	}
-
-	{
-		IMG_UINT32 i;
-
-		for (i=0;i<psRGXKickSyncTransferIN->ui32ServerSyncCount;i++)
-		{
-				{
-					/* Look up the address from the handle */
-					psRGXKickSyncTransferOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &psServerSyncsInt[i],
-											hServerSyncsInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
-					if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
-					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
-						goto RGXKickSyncTransfer_exit;
-					}
-				}
-
-		}
-	}
-
-	psRGXKickSyncTransferOUT->eError =
-		PVRSRVRGXKickSyncTransferKM(
-					psTransferContextInt,
-					psRGXKickSyncTransferIN->ui32ClientFenceCount,
-					psClientFenceUFOSyncPrimBlockInt,
-					ui32ClientFenceSyncOffsetInt,
-					ui32ClientFenceValueInt,
-					psRGXKickSyncTransferIN->ui32ClientUpdateCount,
-					psClientUpdateUFOSyncPrimBlockInt,
-					ui32ClientUpdateSyncOffsetInt,
-					ui32ClientUpdateValueInt,
-					psRGXKickSyncTransferIN->ui32ServerSyncCount,
-					ui32ServerSyncFlagsInt,
-					psServerSyncsInt,
-					psRGXKickSyncTransferIN->i32CheckFenceFD,
-					psRGXKickSyncTransferIN->i32UpdateTimelineFD,
-					&psRGXKickSyncTransferOUT->i32UpdateFenceFD,
-					uiUpdateFenceNameInt,
-					psRGXKickSyncTransferIN->ui32TQPrepareFlags,
-					psRGXKickSyncTransferIN->ui32ExtJobRef,
-					psRGXKickSyncTransferIN->ui32IntJobRef);
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
-
-
-
-
-RGXKickSyncTransfer_exit:
-	if (psClientFenceUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psClientFenceUFOSyncPrimBlockInt);
-	if (hClientFenceUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClientFenceUFOSyncPrimBlockInt2);
-	if (ui32ClientFenceSyncOffsetInt)
-		OSFreeMemNoStats(ui32ClientFenceSyncOffsetInt);
-	if (ui32ClientFenceValueInt)
-		OSFreeMemNoStats(ui32ClientFenceValueInt);
-	if (psClientUpdateUFOSyncPrimBlockInt)
-		OSFreeMemNoStats(psClientUpdateUFOSyncPrimBlockInt);
-	if (hClientUpdateUFOSyncPrimBlockInt2)
-		OSFreeMemNoStats(hClientUpdateUFOSyncPrimBlockInt2);
-	if (ui32ClientUpdateSyncOffsetInt)
-		OSFreeMemNoStats(ui32ClientUpdateSyncOffsetInt);
-	if (ui32ClientUpdateValueInt)
-		OSFreeMemNoStats(ui32ClientUpdateValueInt);
-	if (ui32ServerSyncFlagsInt)
-		OSFreeMemNoStats(ui32ServerSyncFlagsInt);
-	if (psServerSyncsInt)
-		OSFreeMemNoStats(psServerSyncsInt);
-	if (hServerSyncsInt2)
-		OSFreeMemNoStats(hServerSyncsInt2);
-	if (uiUpdateFenceNameInt)
-		OSFreeMemNoStats(uiUpdateFenceNameInt);
-
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -1797,9 +1412,6 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ, PVRSRV_BRIDGE_RGXTQ_RGXSETTRANSFERCONTEXTPRIORITY, PVRSRVBridgeRGXSetTransferContextPriority,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ, PVRSRV_BRIDGE_RGXTQ_RGXKICKSYNCTRANSFER, PVRSRVBridgeRGXKickSyncTransfer,
-					NULL, bUseLock);
-
 
 	return PVRSRV_OK;
 }
@@ -1811,4 +1423,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/ri_bridge/common_ri_bridge.h b/drivers/staging/imgtec/rogue/generated/ri_bridge/common_ri_bridge.h
index 3c5fa89..71f2fba 100644
--- a/drivers/staging/imgtec/rogue/generated/ri_bridge/common_ri_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/ri_bridge/common_ri_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for ri
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for ri
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for ri
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_RI_BRIDGE_H
 #define COMMON_RI_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/ri_bridge/server_ri_bridge.c b/drivers/staging/imgtec/rogue/generated/ri_bridge/server_ri_bridge.c
index ed059c1..c1553c2 100644
--- a/drivers/staging/imgtec/rogue/generated/ri_bridge/server_ri_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/ri_bridge/server_ri_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -74,48 +76,91 @@
 					  PVRSRV_BRIDGE_OUT_RIWRITEPMRENTRY *psRIWritePMREntryOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMRHandle = psRIWritePMREntryIN->hPMRHandle;
 	PMR * psPMRHandleInt = NULL;
 	IMG_CHAR *uiTextAInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psRIWritePMREntryIN->ui32TextASize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiTextAInt = OSAllocMemNoStats(psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR));
-		if (!uiTextAInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRIWritePMREntryIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRIWritePMREntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RIWritePMREntry_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRIWritePMREntryIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRIWritePMREntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RIWritePMREntry_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRIWritePMREntryIN->puiTextA, psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiTextAInt, psRIWritePMREntryIN->puiTextA,
-				psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psRIWritePMREntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psRIWritePMREntryIN->ui32TextASize != 0)
+	{
+		uiTextAInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR);
+	}
 
-				goto RIWritePMREntry_exit;
+			/* Copy the data over */
+			if (psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextAInt, psRIWritePMREntryIN->puiTextA, psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRIWritePMREntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RIWritePMREntry_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRIWritePMREntryOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRHandleInt,
-											psRIWritePMREntryIN->hPMRHandle,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMRHandle,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRIWritePMREntryOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RIWritePMREntry_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRIWritePMREntryOUT->eError =
 		RIWritePMREntryKM(
@@ -128,61 +173,134 @@
 
 
 RIWritePMREntry_exit:
-	if (uiTextAInt)
-		OSFreeMemNoStats(uiTextAInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMRHandle,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIWriteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIWRITEMEMDESCENTRY *psRIWriteMEMDESCEntryIN,
 					  PVRSRV_BRIDGE_OUT_RIWRITEMEMDESCENTRY *psRIWriteMEMDESCEntryOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMRHandle = psRIWriteMEMDESCEntryIN->hPMRHandle;
 	PMR * psPMRHandleInt = NULL;
 	IMG_CHAR *uiTextBInt = NULL;
 	RI_HANDLE psRIHandleInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psRIWriteMEMDESCEntryIN->ui32TextBSize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiTextBInt = OSAllocMemNoStats(psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR));
-		if (!uiTextBInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRIWriteMEMDESCEntryIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RIWriteMEMDESCEntry_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRIWriteMEMDESCEntryIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RIWriteMEMDESCEntry_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRIWriteMEMDESCEntryIN->puiTextB, psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiTextBInt, psRIWriteMEMDESCEntryIN->puiTextB,
-				psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psRIWriteMEMDESCEntryIN->ui32TextBSize != 0)
+	{
+		uiTextBInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR);
+	}
 
-				goto RIWriteMEMDESCEntry_exit;
+			/* Copy the data over */
+			if (psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiTextBInt, psRIWriteMEMDESCEntryIN->puiTextB, psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto RIWriteMEMDESCEntry_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psRIWriteMEMDESCEntryOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRHandleInt,
-											psRIWriteMEMDESCEntryIN->hPMRHandle,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMRHandle,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RIWriteMEMDESCEntry_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRIWriteMEMDESCEntryOUT->eError =
 		RIWriteMEMDESCEntryKM(
@@ -201,8 +319,15 @@
 		goto RIWriteMEMDESCEntry_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psRIWriteMEMDESCEntryOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psRIWriteMEMDESCEntryOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRIWriteMEMDESCEntryOUT->hRIHandle,
 							(void *) psRIHandleInt,
 							PVRSRV_HANDLE_TYPE_RI_HANDLE,
@@ -210,13 +335,37 @@
 							,(PFN_HANDLE_RELEASE)&RIDeleteMEMDESCEntryKM);
 	if (psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RIWriteMEMDESCEntry_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RIWriteMEMDESCEntry_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMRHandle,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
 	{
 		if (psRIHandleInt)
@@ -225,12 +374,21 @@
 		}
 	}
 
-	if (uiTextBInt)
-		OSFreeMemNoStats(uiTextBInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIWriteProcListEntry(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIWRITEPROCLISTENTRY *psRIWriteProcListEntryIN,
@@ -240,32 +398,65 @@
 	IMG_CHAR *uiTextBInt = NULL;
 	RI_HANDLE psRIHandleInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psRIWriteProcListEntryIN->ui32TextBSize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiTextBInt = OSAllocMemNoStats(psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR));
-		if (!uiTextBInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psRIWriteProcListEntryIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psRIWriteProcListEntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto RIWriteProcListEntry_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psRIWriteProcListEntryIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psRIWriteProcListEntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto RIWriteProcListEntry_exit;
+			}
 		}
 	}
 
+	if (psRIWriteProcListEntryIN->ui32TextBSize != 0)
+	{
+		uiTextBInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psRIWriteProcListEntryIN->puiTextB, psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiTextBInt, psRIWriteProcListEntryIN->puiTextB,
-				psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR) > 0)
 			{
-				psRIWriteProcListEntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiTextBInt, psRIWriteProcListEntryIN->puiTextB, psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psRIWriteProcListEntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto RIWriteProcListEntry_exit;
+					goto RIWriteProcListEntry_exit;
+				}
 			}
 
 
-
 	psRIWriteProcListEntryOUT->eError =
 		RIWriteProcListEntryKM(
 					psRIWriteProcListEntryIN->ui32TextBSize,
@@ -280,8 +471,15 @@
 		goto RIWriteProcListEntry_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psRIWriteProcListEntryOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psRIWriteProcListEntryOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psRIWriteProcListEntryOUT->hRIHandle,
 							(void *) psRIHandleInt,
 							PVRSRV_HANDLE_TYPE_RI_HANDLE,
@@ -289,13 +487,19 @@
 							,(PFN_HANDLE_RELEASE)&RIDeleteMEMDESCEntryKM);
 	if (psRIWriteProcListEntryOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto RIWriteProcListEntry_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 RIWriteProcListEntry_exit:
+
+
+
 	if (psRIWriteProcListEntryOUT->eError != PVRSRV_OK)
 	{
 		if (psRIHandleInt)
@@ -304,18 +508,28 @@
 		}
 	}
 
-	if (uiTextBInt)
-		OSFreeMemNoStats(uiTextBInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIUpdateMEMDESCAddr(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIUPDATEMEMDESCADDR *psRIUpdateMEMDESCAddrIN,
 					  PVRSRV_BRIDGE_OUT_RIUPDATEMEMDESCADDR *psRIUpdateMEMDESCAddrOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hRIHandle = psRIUpdateMEMDESCAddrIN->hRIHandle;
 	RI_HANDLE psRIHandleInt = NULL;
 
 
@@ -324,19 +538,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRIUpdateMEMDESCAddrOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRIHandleInt,
-											psRIUpdateMEMDESCAddrIN->hRIHandle,
-											PVRSRV_HANDLE_TYPE_RI_HANDLE);
+											hRIHandle,
+											PVRSRV_HANDLE_TYPE_RI_HANDLE,
+											IMG_TRUE);
 					if(psRIUpdateMEMDESCAddrOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RIUpdateMEMDESCAddr_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRIUpdateMEMDESCAddrOUT->eError =
 		RIUpdateMEMDESCAddrKM(
@@ -348,15 +572,38 @@
 
 RIUpdateMEMDESCAddr_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRIHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRIHandle,
+											PVRSRV_HANDLE_TYPE_RI_HANDLE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIUpdateMEMDESCPinning(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIUPDATEMEMDESCPINNING *psRIUpdateMEMDESCPinningIN,
 					  PVRSRV_BRIDGE_OUT_RIUPDATEMEMDESCPINNING *psRIUpdateMEMDESCPinningOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hRIHandle = psRIUpdateMEMDESCPinningIN->hRIHandle;
 	RI_HANDLE psRIHandleInt = NULL;
 
 
@@ -365,19 +612,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRIUpdateMEMDESCPinningOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRIHandleInt,
-											psRIUpdateMEMDESCPinningIN->hRIHandle,
-											PVRSRV_HANDLE_TYPE_RI_HANDLE);
+											hRIHandle,
+											PVRSRV_HANDLE_TYPE_RI_HANDLE,
+											IMG_TRUE);
 					if(psRIUpdateMEMDESCPinningOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RIUpdateMEMDESCPinning_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRIUpdateMEMDESCPinningOUT->eError =
 		RIUpdateMEMDESCPinningKM(
@@ -389,15 +646,38 @@
 
 RIUpdateMEMDESCPinning_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRIHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRIHandle,
+											PVRSRV_HANDLE_TYPE_RI_HANDLE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIUpdateMEMDESCBacking(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIUPDATEMEMDESCBACKING *psRIUpdateMEMDESCBackingIN,
 					  PVRSRV_BRIDGE_OUT_RIUPDATEMEMDESCBACKING *psRIUpdateMEMDESCBackingOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hRIHandle = psRIUpdateMEMDESCBackingIN->hRIHandle;
 	RI_HANDLE psRIHandleInt = NULL;
 
 
@@ -406,19 +686,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRIUpdateMEMDESCBackingOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psRIHandleInt,
-											psRIUpdateMEMDESCBackingIN->hRIHandle,
-											PVRSRV_HANDLE_TYPE_RI_HANDLE);
+											hRIHandle,
+											PVRSRV_HANDLE_TYPE_RI_HANDLE,
+											IMG_TRUE);
 					if(psRIUpdateMEMDESCBackingOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RIUpdateMEMDESCBacking_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRIUpdateMEMDESCBackingOUT->eError =
 		RIUpdateMEMDESCBackingKM(
@@ -430,9 +720,31 @@
 
 RIUpdateMEMDESCBacking_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psRIHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hRIHandle,
+											PVRSRV_HANDLE_TYPE_RI_HANDLE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIDeleteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIDELETEMEMDESCENTRY *psRIDeleteMEMDESCEntryIN,
@@ -448,29 +760,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psRIDeleteMEMDESCEntryOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psRIDeleteMEMDESCEntryIN->hRIHandle,
 					PVRSRV_HANDLE_TYPE_RI_HANDLE);
-	if ((psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_OK) && (psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_OK) &&
+	    (psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeRIDeleteMEMDESCEntry: %s",
+		        PVRSRVGetErrorStringKM(psRIDeleteMEMDESCEntryOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto RIDeleteMEMDESCEntry_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 RIDeleteMEMDESCEntry_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIDumpList(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIDUMPLIST *psRIDumpListIN,
 					  PVRSRV_BRIDGE_OUT_RIDUMPLIST *psRIDumpListOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hPMRHandle = psRIDumpListIN->hPMRHandle;
 	PMR * psPMRHandleInt = NULL;
 
 
@@ -479,19 +811,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psRIDumpListOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psPMRHandleInt,
-											psRIDumpListIN->hPMRHandle,
-											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+											hPMRHandle,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+											IMG_TRUE);
 					if(psRIDumpListOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto RIDumpList_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psRIDumpListOUT->eError =
 		RIDumpListKM(
@@ -502,9 +844,31 @@
 
 RIDumpList_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psPMRHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hPMRHandle,
+											PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIDumpAll(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIDUMPALL *psRIDumpAllIN,
@@ -512,6 +876,8 @@
 					 CONNECTION_DATA *psConnection)
 {
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psRIDumpAllIN);
 
@@ -519,7 +885,6 @@
 
 
 
-
 	psRIDumpAllOUT->eError =
 		RIDumpAllKM(
 					);
@@ -528,9 +893,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRIDumpProcess(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RIDUMPPROCESS *psRIDumpProcessIN,
@@ -538,9 +907,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
 
 
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
 
 
 
@@ -553,11 +923,15 @@
 
 
 
+
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -614,4 +988,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/srvcore_bridge/common_srvcore_bridge.h b/drivers/staging/imgtec/rogue/generated/srvcore_bridge/common_srvcore_bridge.h
index aecf4c0..58bd2f8 100644
--- a/drivers/staging/imgtec/rogue/generated/srvcore_bridge/common_srvcore_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/srvcore_bridge/common_srvcore_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for srvcore
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for srvcore
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for srvcore
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,11 +45,13 @@
 #ifndef COMMON_SRVCORE_BRIDGE_H
 #define COMMON_SRVCORE_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
 #include "pvrsrv_device_types.h"
-#include "cache_external.h"
+#include "cache_ops.h"
 
 
 #define PVRSRV_BRIDGE_SRVCORE_CMD_FIRST			0
@@ -64,9 +66,9 @@
 #define PVRSRV_BRIDGE_SRVCORE_DUMPDEBUGINFO			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+8
 #define PVRSRV_BRIDGE_SRVCORE_GETDEVCLOCKSPEED			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+9
 #define PVRSRV_BRIDGE_SRVCORE_HWOPTIMEOUT			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+10
-#define PVRSRV_BRIDGE_SRVCORE_KICKDEVICES			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+11
-#define PVRSRV_BRIDGE_SRVCORE_RESETHWRLOGS			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+12
-#define PVRSRV_BRIDGE_SRVCORE_SOFTRESET			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+13
+#define PVRSRV_BRIDGE_SRVCORE_ALIGNMENTCHECK			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+11
+#define PVRSRV_BRIDGE_SRVCORE_GETDEVICESTATUS			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+12
+#define PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTWAITTIMEOUT			PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+13
 #define PVRSRV_BRIDGE_SRVCORE_CMD_LAST			(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+13)
 
 
@@ -87,7 +89,9 @@
 typedef struct PVRSRV_BRIDGE_OUT_CONNECT_TAG
 {
 	IMG_UINT8 ui8KernelArch;
-	IMG_UINT32 ui32Log2PageSize;
+	IMG_UINT32 ui32CapabilityFlags;
+	IMG_UINT32 ui32PVRBridges;
+	IMG_UINT32 ui32RGXBridges;
 	PVRSRV_ERROR eError;
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_CONNECT;
 
@@ -267,55 +271,57 @@
 
 
 /*******************************************
-            KickDevices          
+            AlignmentCheck          
  *******************************************/
 
-/* Bridge in structure for KickDevices */
-typedef struct PVRSRV_BRIDGE_IN_KICKDEVICES_TAG
+/* Bridge in structure for AlignmentCheck */
+typedef struct PVRSRV_BRIDGE_IN_ALIGNMENTCHECK_TAG
 {
-	 IMG_UINT32 ui32EmptyStructPlaceholder;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_KICKDEVICES;
+	IMG_UINT32 ui32AlignChecksSize;
+	IMG_UINT32 * pui32AlignChecks;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_ALIGNMENTCHECK;
 
-/* Bridge out structure for KickDevices */
-typedef struct PVRSRV_BRIDGE_OUT_KICKDEVICES_TAG
+/* Bridge out structure for AlignmentCheck */
+typedef struct PVRSRV_BRIDGE_OUT_ALIGNMENTCHECK_TAG
 {
 	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_KICKDEVICES;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_ALIGNMENTCHECK;
 
 
 /*******************************************
-            ResetHWRLogs          
+            GetDeviceStatus          
  *******************************************/
 
-/* Bridge in structure for ResetHWRLogs */
-typedef struct PVRSRV_BRIDGE_IN_RESETHWRLOGS_TAG
+/* Bridge in structure for GetDeviceStatus */
+typedef struct PVRSRV_BRIDGE_IN_GETDEVICESTATUS_TAG
 {
 	 IMG_UINT32 ui32EmptyStructPlaceholder;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_RESETHWRLOGS;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_GETDEVICESTATUS;
 
-/* Bridge out structure for ResetHWRLogs */
-typedef struct PVRSRV_BRIDGE_OUT_RESETHWRLOGS_TAG
+/* Bridge out structure for GetDeviceStatus */
+typedef struct PVRSRV_BRIDGE_OUT_GETDEVICESTATUS_TAG
 {
+	IMG_UINT32 ui32DeviceSatus;
 	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RESETHWRLOGS;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_GETDEVICESTATUS;
 
 
 /*******************************************
-            SoftReset          
+            EventObjectWaitTimeout          
  *******************************************/
 
-/* Bridge in structure for SoftReset */
-typedef struct PVRSRV_BRIDGE_IN_SOFTRESET_TAG
+/* Bridge in structure for EventObjectWaitTimeout */
+typedef struct PVRSRV_BRIDGE_IN_EVENTOBJECTWAITTIMEOUT_TAG
 {
-	IMG_UINT64 ui64ResetValue1;
-	IMG_UINT64 ui64ResetValue2;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_SOFTRESET;
+	IMG_HANDLE hOSEventKM;
+	IMG_UINT64 ui64uiTimeoutus;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_EVENTOBJECTWAITTIMEOUT;
 
-/* Bridge out structure for SoftReset */
-typedef struct PVRSRV_BRIDGE_OUT_SOFTRESET_TAG
+/* Bridge out structure for EventObjectWaitTimeout */
+typedef struct PVRSRV_BRIDGE_OUT_EVENTOBJECTWAITTIMEOUT_TAG
 {
 	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SOFTRESET;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_EVENTOBJECTWAITTIMEOUT;
 
 
 #endif /* COMMON_SRVCORE_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/srvcore_bridge/server_srvcore_bridge.c b/drivers/staging/imgtec/rogue/generated/srvcore_bridge/server_srvcore_bridge.c
index 596d549..eb9e2a2 100644
--- a/drivers/staging/imgtec/rogue/generated/srvcore_bridge/server_srvcore_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/srvcore_bridge/server_srvcore_bridge.c
@@ -47,7 +47,6 @@
 #include "img_defs.h"
 
 #include "srvcore.h"
-#include "pvrsrv.h"
 
 
 #include "common_srvcore_bridge.h"
@@ -65,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -82,6 +83,7 @@
 
 
 
+
 	psConnectOUT->eError =
 		PVRSRVConnectKM(psConnection, OSGetDevData(psConnection),
 					psConnectIN->ui32Flags,
@@ -89,7 +91,12 @@
 					psConnectIN->ui32ClientDDKVersion,
 					psConnectIN->ui32ClientDDKBuild,
 					&psConnectOUT->ui8KernelArch,
-					&psConnectOUT->ui32Log2PageSize);
+					&psConnectOUT->ui32CapabilityFlags,
+					&psConnectOUT->ui32PVRBridges,
+					&psConnectOUT->ui32RGXBridges);
+
+
+
 
 
 
@@ -98,6 +105,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDisconnect(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DISCONNECT *psDisconnectIN,
@@ -105,6 +113,8 @@
 					 CONNECTION_DATA *psConnection)
 {
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psDisconnectIN);
 
@@ -112,7 +122,6 @@
 
 
 
-
 	psDisconnectOUT->eError =
 		PVRSRVDisconnectKM(
 					);
@@ -121,9 +130,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeInitSrvDisconnect(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_INITSRVDISCONNECT *psInitSrvDisconnectIN,
@@ -135,14 +148,16 @@
 
 
 
-	PMRLock();
+
 
 
 	psInitSrvDisconnectOUT->eError =
 		PVRSRVInitSrvDisconnectKM(psConnection, OSGetDevData(psConnection),
 					psInitSrvDisconnectIN->bInitSuccesful,
 					psInitSrvDisconnectIN->ui32ClientBuildOptions);
-	PMRUnlock();
+
+
+
 
 
 
@@ -151,6 +166,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeAcquireGlobalEventObject(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_ACQUIREGLOBALEVENTOBJECT *psAcquireGlobalEventObjectIN,
@@ -159,15 +175,16 @@
 {
 	IMG_HANDLE hGlobalEventObjectInt = NULL;
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psAcquireGlobalEventObjectIN);
 
 
 
 
 
-
 	psAcquireGlobalEventObjectOUT->eError =
-		AcquireGlobalEventObjectServer(
+		PVRSRVAcquireGlobalEventObjectKM(
 					&hGlobalEventObjectInt);
 	/* Exit early if bridged call fails */
 	if(psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK)
@@ -175,27 +192,40 @@
 		goto AcquireGlobalEventObject_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psAcquireGlobalEventObjectOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psAcquireGlobalEventObjectOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psAcquireGlobalEventObjectOUT->hGlobalEventObject,
 							(void *) hGlobalEventObjectInt,
 							PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
 							PVRSRV_HANDLE_ALLOC_FLAG_MULTI
-							,(PFN_HANDLE_RELEASE)&ReleaseGlobalEventObjectServer);
+							,(PFN_HANDLE_RELEASE)&PVRSRVReleaseGlobalEventObjectKM);
 	if (psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto AcquireGlobalEventObject_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 AcquireGlobalEventObject_exit:
+
+
+
 	if (psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK)
 	{
 		if (hGlobalEventObjectInt)
 		{
-			ReleaseGlobalEventObjectServer(hGlobalEventObjectInt);
+			PVRSRVReleaseGlobalEventObjectKM(hGlobalEventObjectInt);
 		}
 	}
 
@@ -203,6 +233,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeReleaseGlobalEventObject(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RELEASEGLOBALEVENTOBJECT *psReleaseGlobalEventObjectIN,
@@ -218,29 +249,49 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psReleaseGlobalEventObjectOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psReleaseGlobalEventObjectIN->hGlobalEventObject,
 					PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
-	if ((psReleaseGlobalEventObjectOUT->eError != PVRSRV_OK) && (psReleaseGlobalEventObjectOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psReleaseGlobalEventObjectOUT->eError != PVRSRV_OK) &&
+	    (psReleaseGlobalEventObjectOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeReleaseGlobalEventObject: %s",
+		        PVRSRVGetErrorStringKM(psReleaseGlobalEventObjectOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto ReleaseGlobalEventObject_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 ReleaseGlobalEventObject_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeEventObjectOpen(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_EVENTOBJECTOPEN *psEventObjectOpenIN,
 					  PVRSRV_BRIDGE_OUT_EVENTOBJECTOPEN *psEventObjectOpenOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hEventObject = psEventObjectOpenIN->hEventObject;
 	IMG_HANDLE hEventObjectInt = NULL;
 	IMG_HANDLE hOSEventInt = NULL;
 
@@ -250,19 +301,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psEventObjectOpenOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hEventObjectInt,
-											psEventObjectOpenIN->hEventObject,
-											PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+											hEventObject,
+											PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+											IMG_TRUE);
 					if(psEventObjectOpenOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto EventObjectOpen_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psEventObjectOpenOUT->eError =
 		OSEventObjectOpen(
@@ -274,8 +335,15 @@
 		goto EventObjectOpen_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psEventObjectOpenOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psEventObjectOpenOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psEventObjectOpenOUT->hOSEvent,
 							(void *) hOSEventInt,
 							PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
@@ -283,13 +351,37 @@
 							,(PFN_HANDLE_RELEASE)&OSEventObjectClose);
 	if (psEventObjectOpenOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto EventObjectOpen_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 EventObjectOpen_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hEventObjectInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hEventObject,
+											PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psEventObjectOpenOUT->eError != PVRSRV_OK)
 	{
 		if (hOSEventInt)
@@ -302,12 +394,14 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeEventObjectWait(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_EVENTOBJECTWAIT *psEventObjectWaitIN,
 					  PVRSRV_BRIDGE_OUT_EVENTOBJECTWAIT *psEventObjectWaitOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hOSEventKM = psEventObjectWaitIN->hOSEventKM;
 	IMG_HANDLE hOSEventKMInt = NULL;
 
 
@@ -316,19 +410,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psEventObjectWaitOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &hOSEventKMInt,
-											psEventObjectWaitIN->hOSEventKM,
-											PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+											hOSEventKM,
+											PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+											IMG_TRUE);
 					if(psEventObjectWaitOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto EventObjectWait_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psEventObjectWaitOUT->eError =
 		OSEventObjectWait(
@@ -339,9 +443,31 @@
 
 EventObjectWait_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hOSEventKMInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hOSEventKM,
+											PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeEventObjectClose(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_EVENTOBJECTCLOSE *psEventObjectCloseIN,
@@ -357,23 +483,42 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psEventObjectCloseOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psEventObjectCloseIN->hOSEventKM,
 					PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
-	if ((psEventObjectCloseOUT->eError != PVRSRV_OK) && (psEventObjectCloseOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psEventObjectCloseOUT->eError != PVRSRV_OK) &&
+	    (psEventObjectCloseOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeEventObjectClose: %s",
+		        PVRSRVGetErrorStringKM(psEventObjectCloseOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto EventObjectClose_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 EventObjectClose_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeDumpDebugInfo(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_DUMPDEBUGINFO *psDumpDebugInfoIN,
@@ -381,7 +526,7 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
+
 
 
 
@@ -389,16 +534,20 @@
 
 
 	psDumpDebugInfoOUT->eError =
-		PVRSRVDumpDebugInfoKM(
+		PVRSRVDumpDebugInfoKM(psConnection, OSGetDevData(psConnection),
 					psDumpDebugInfoIN->ui32ui32VerbLevel);
 
 
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeGetDevClockSpeed(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_GETDEVCLOCKSPEED *psGetDevClockSpeedIN,
@@ -406,9 +555,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psGetDevClockSpeedIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psGetDevClockSpeedIN);
+
 
 
 
@@ -421,9 +571,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeHWOpTimeout(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_HWOPTIMEOUT *psHWOpTimeoutIN,
@@ -431,93 +585,148 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
 	PVR_UNREFERENCED_PARAMETER(psHWOpTimeoutIN);
 
 
 
 
 
-
 	psHWOpTimeoutOUT->eError =
-		PVRSRVHWOpTimeoutKM(
+		PVRSRVHWOpTimeoutKM(psConnection, OSGetDevData(psConnection)
 					);
 
 
 
 
 
+
+
+
 	return 0;
 }
 
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
 static IMG_INT
-PVRSRVBridgeKickDevices(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_KICKDEVICES *psKickDevicesIN,
-					  PVRSRV_BRIDGE_OUT_KICKDEVICES *psKickDevicesOUT,
+PVRSRVBridgeAlignmentCheck(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_ALIGNMENTCHECK *psAlignmentCheckIN,
+					  PVRSRV_BRIDGE_OUT_ALIGNMENTCHECK *psAlignmentCheckOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_UINT32 *ui32AlignChecksInt = NULL;
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
-	PVR_UNREFERENCED_PARAMETER(psKickDevicesIN);
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psAlignmentCheckIN->ui32AlignChecksSize * sizeof(IMG_UINT32)) +
+			0;
 
 
 
 
 
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psAlignmentCheckIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
 
-	psKickDevicesOUT->eError =
-		PVRSRVKickDevicesKM(
-					);
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psAlignmentCheckIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psAlignmentCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto AlignmentCheck_exit;
+			}
+		}
+	}
+
+	if (psAlignmentCheckIN->ui32AlignChecksSize != 0)
+	{
+		ui32AlignChecksInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psAlignmentCheckIN->ui32AlignChecksSize * sizeof(IMG_UINT32);
+	}
+
+			/* Copy the data over */
+			if (psAlignmentCheckIN->ui32AlignChecksSize * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32AlignChecksInt, psAlignmentCheckIN->pui32AlignChecks, psAlignmentCheckIN->ui32AlignChecksSize * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psAlignmentCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto AlignmentCheck_exit;
+				}
+			}
+
+
+	psAlignmentCheckOUT->eError =
+		PVRSRVAlignmentCheckKM(psConnection, OSGetDevData(psConnection),
+					psAlignmentCheckIN->ui32AlignChecksSize,
+					ui32AlignChecksInt);
 
 
 
 
+AlignmentCheck_exit:
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
-static IMG_INT
-PVRSRVBridgeResetHWRLogs(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_RESETHWRLOGS *psResetHWRLogsIN,
-					  PVRSRV_BRIDGE_OUT_RESETHWRLOGS *psResetHWRLogsOUT,
-					 CONNECTION_DATA *psConnection)
-{
-
-	PVR_UNREFERENCED_PARAMETER(psResetHWRLogsIN);
-
-
-
-
-
-
-	psResetHWRLogsOUT->eError =
-		PVRSRVResetHWRLogsKM(psConnection, OSGetDevData(psConnection)
-					);
-
-
-
-
-
-	return 0;
-}
+#else
+#define PVRSRVBridgeAlignmentCheck NULL
+#endif
 
 static IMG_INT
-PVRSRVBridgeSoftReset(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_SOFTRESET *psSoftResetIN,
-					  PVRSRV_BRIDGE_OUT_SOFTRESET *psSoftResetOUT,
+PVRSRVBridgeGetDeviceStatus(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_GETDEVICESTATUS *psGetDeviceStatusIN,
+					  PVRSRV_BRIDGE_OUT_GETDEVICESTATUS *psGetDeviceStatusOUT,
 					 CONNECTION_DATA *psConnection)
 {
 
 
 
+	PVR_UNREFERENCED_PARAMETER(psGetDeviceStatusIN);
 
 
 
 
-	psSoftResetOUT->eError =
-		PVRSRVSoftResetKM(psConnection, OSGetDevData(psConnection),
-					psSoftResetIN->ui64ResetValue1,
-					psSoftResetIN->ui64ResetValue2);
+
+	psGetDeviceStatusOUT->eError =
+		PVRSRVGetDeviceStatusKM(psConnection, OSGetDevData(psConnection),
+					&psGetDeviceStatusOUT->ui32DeviceSatus);
+
+
+
 
 
 
@@ -527,6 +736,81 @@
 }
 
 
+static IMG_INT
+PVRSRVBridgeEventObjectWaitTimeout(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_EVENTOBJECTWAITTIMEOUT *psEventObjectWaitTimeoutIN,
+					  PVRSRV_BRIDGE_OUT_EVENTOBJECTWAITTIMEOUT *psEventObjectWaitTimeoutOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_HANDLE hOSEventKM = psEventObjectWaitTimeoutIN->hOSEventKM;
+	IMG_HANDLE hOSEventKMInt = NULL;
+
+
+
+
+
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psEventObjectWaitTimeoutOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &hOSEventKMInt,
+											hOSEventKM,
+											PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+											IMG_TRUE);
+					if(psEventObjectWaitTimeoutOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto EventObjectWaitTimeout_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psEventObjectWaitTimeoutOUT->eError =
+		OSEventObjectWaitTimeout(
+					hOSEventKMInt,
+					psEventObjectWaitTimeoutIN->ui64uiTimeoutus);
+
+
+
+
+EventObjectWaitTimeout_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(hOSEventKMInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hOSEventKM,
+											PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
+	return 0;
+}
+
+
+
 
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
@@ -576,13 +860,13 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_HWOPTIMEOUT, PVRSRVBridgeHWOpTimeout,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_KICKDEVICES, PVRSRVBridgeKickDevices,
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_ALIGNMENTCHECK, PVRSRVBridgeAlignmentCheck,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_RESETHWRLOGS, PVRSRVBridgeResetHWRLogs,
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_GETDEVICESTATUS, PVRSRVBridgeGetDeviceStatus,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_SOFTRESET, PVRSRVBridgeSoftReset,
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTWAITTIMEOUT, PVRSRVBridgeEventObjectWaitTimeout,
 					NULL, bUseLock);
 
 
@@ -596,4 +880,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_bridge.h b/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_bridge.h
index 612ad05..b533be8 100644
--- a/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_bridge.h
@@ -72,18 +72,6 @@
 							       IMG_HANDLE hSyncHandle,
 							       IMG_UINT32 ui32Value);
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordRemoveByHandle(IMG_HANDLE hBridge,
-								      IMG_HANDLE hhRecord);
-
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordAdd(IMG_HANDLE hBridge,
-							   IMG_HANDLE *phhRecord,
-							   IMG_HANDLE hhServerSyncPrimBlock,
-							   IMG_UINT32 ui32ui32FwBlockAddr,
-							   IMG_UINT32 ui32ui32SyncOffset,
-							   IMG_BOOL bbServerSync,
-							   IMG_UINT32 ui32ClassNameSize,
-							   const IMG_CHAR *puiClassName);
-
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncAlloc(IMG_HANDLE hBridge,
 							     IMG_HANDLE *phSyncHandle,
 							     IMG_UINT32 *pui32SyncPrimVAddr,
@@ -165,5 +153,14 @@
 							      IMG_DEVMEM_SIZE_T uiPacketSize,
 							      IMG_DEVMEM_SIZE_T uiBufferSize);
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncAllocEvent(IMG_HANDLE hBridge,
+							    IMG_BOOL bServerSync,
+							    IMG_UINT32 ui32FWAddr,
+							    IMG_UINT32 ui32ClassNameSize,
+							    const IMG_CHAR *puiClassName);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncFreeEvent(IMG_HANDLE hBridge,
+							   IMG_UINT32 ui32FWAddr);
+
 
 #endif /* CLIENT_SYNC_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_direct_bridge.c
index edb4d51..7378dd5 100644
--- a/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/sync_bridge/client_sync_direct_bridge.c
@@ -48,6 +48,7 @@
 #include "pdumpdefs.h"
 #include "devicemem_typedefs.h"
 
+#include "sync.h"
 #include "sync_server.h"
 #include "pdump.h"
 
@@ -130,52 +131,6 @@
 	return eError;
 }
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordRemoveByHandle(IMG_HANDLE hBridge,
-								      IMG_HANDLE hhRecord)
-{
-	PVRSRV_ERROR eError;
-	SYNC_RECORD_HANDLE pshRecordInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
-
-	pshRecordInt = (SYNC_RECORD_HANDLE) hhRecord;
-
-	eError =
-		PVRSRVSyncRecordRemoveByHandleKM(
-					pshRecordInt);
-
-	return eError;
-}
-
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordAdd(IMG_HANDLE hBridge,
-							   IMG_HANDLE *phhRecord,
-							   IMG_HANDLE hhServerSyncPrimBlock,
-							   IMG_UINT32 ui32ui32FwBlockAddr,
-							   IMG_UINT32 ui32ui32SyncOffset,
-							   IMG_BOOL bbServerSync,
-							   IMG_UINT32 ui32ClassNameSize,
-							   const IMG_CHAR *puiClassName)
-{
-	PVRSRV_ERROR eError;
-	SYNC_RECORD_HANDLE pshRecordInt;
-	SYNC_PRIMITIVE_BLOCK * pshServerSyncPrimBlockInt;
-	PVR_UNREFERENCED_PARAMETER(hBridge);
-
-	pshServerSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK *) hhServerSyncPrimBlock;
-
-	eError =
-		PVRSRVSyncRecordAddKM(
-					&pshRecordInt,
-					pshServerSyncPrimBlockInt,
-					ui32ui32FwBlockAddr,
-					ui32ui32SyncOffset,
-					bbServerSync,
-					ui32ClassNameSize,
-					puiClassName);
-
-	*phhRecord = pshRecordInt;
-	return eError;
-}
-
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncAlloc(IMG_HANDLE hBridge,
 							     IMG_HANDLE *phSyncHandle,
 							     IMG_UINT32 *pui32SyncPrimVAddr,
@@ -378,6 +333,7 @@
 							   IMG_HANDLE hSyncHandle,
 							   IMG_UINT32 ui32Offset)
 {
+#if defined(PDUMP)
 	PVRSRV_ERROR eError;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
@@ -390,6 +346,13 @@
 					ui32Offset);
 
 	return eError;
+#else
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+	PVR_UNREFERENCED_PARAMETER(hSyncHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+	return PVRSRV_ERROR_NOT_IMPLEMENTED;
+#endif
 }
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpValue(IMG_HANDLE hBridge,
@@ -397,6 +360,7 @@
 								IMG_UINT32 ui32Offset,
 								IMG_UINT32 ui32Value)
 {
+#if defined(PDUMP)
 	PVRSRV_ERROR eError;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
@@ -410,6 +374,14 @@
 					ui32Value);
 
 	return eError;
+#else
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+	PVR_UNREFERENCED_PARAMETER(hSyncHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32Offset);
+	PVR_UNREFERENCED_PARAMETER(ui32Value);
+
+	return PVRSRV_ERROR_NOT_IMPLEMENTED;
+#endif
 }
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpPol(IMG_HANDLE hBridge,
@@ -420,6 +392,7 @@
 							      PDUMP_POLL_OPERATOR eOperator,
 							      PDUMP_FLAGS_T uiPDumpFlags)
 {
+#if defined(PDUMP)
 	PVRSRV_ERROR eError;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
@@ -436,6 +409,17 @@
 					uiPDumpFlags);
 
 	return eError;
+#else
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+	PVR_UNREFERENCED_PARAMETER(hSyncHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32Offset);
+	PVR_UNREFERENCED_PARAMETER(ui32Value);
+	PVR_UNREFERENCED_PARAMETER(ui32Mask);
+	PVR_UNREFERENCED_PARAMETER(eOperator);
+	PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+
+	return PVRSRV_ERROR_NOT_IMPLEMENTED;
+#endif
 }
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpPDumpPol(IMG_HANDLE hBridge,
@@ -443,6 +427,7 @@
 								PDUMP_POLL_OPERATOR eOperator,
 								PDUMP_FLAGS_T uiPDumpFlags)
 {
+#if defined(PDUMP)
 	PVRSRV_ERROR eError;
 	SERVER_OP_COOKIE * psServerCookieInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
@@ -456,6 +441,14 @@
 					uiPDumpFlags);
 
 	return eError;
+#else
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+	PVR_UNREFERENCED_PARAMETER(hServerCookie);
+	PVR_UNREFERENCED_PARAMETER(eOperator);
+	PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+
+	return PVRSRV_ERROR_NOT_IMPLEMENTED;
+#endif
 }
 
 IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpCBP(IMG_HANDLE hBridge,
@@ -465,6 +458,7 @@
 							      IMG_DEVMEM_SIZE_T uiPacketSize,
 							      IMG_DEVMEM_SIZE_T uiBufferSize)
 {
+#if defined(PDUMP)
 	PVRSRV_ERROR eError;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
@@ -480,5 +474,49 @@
 					uiBufferSize);
 
 	return eError;
+#else
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+	PVR_UNREFERENCED_PARAMETER(hSyncHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32Offset);
+	PVR_UNREFERENCED_PARAMETER(uiWriteOffset);
+	PVR_UNREFERENCED_PARAMETER(uiPacketSize);
+	PVR_UNREFERENCED_PARAMETER(uiBufferSize);
+
+	return PVRSRV_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncAllocEvent(IMG_HANDLE hBridge,
+							    IMG_BOOL bServerSync,
+							    IMG_UINT32 ui32FWAddr,
+							    IMG_UINT32 ui32ClassNameSize,
+							    const IMG_CHAR *puiClassName)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		PVRSRVSyncAllocEventKM(
+					bServerSync,
+					ui32FWAddr,
+					ui32ClassNameSize,
+					puiClassName);
+
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncFreeEvent(IMG_HANDLE hBridge,
+							   IMG_UINT32 ui32FWAddr)
+{
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+	eError =
+		PVRSRVSyncFreeEventKM(
+					ui32FWAddr);
+
+	return eError;
 }
 
diff --git a/drivers/staging/imgtec/rogue/generated/sync_bridge/common_sync_bridge.h b/drivers/staging/imgtec/rogue/generated/sync_bridge/common_sync_bridge.h
index 8c43e4bf..6003b42 100644
--- a/drivers/staging/imgtec/rogue/generated/sync_bridge/common_sync_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/sync_bridge/common_sync_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for sync
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for sync
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for sync
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_SYNC_BRIDGE_H
 #define COMMON_SYNC_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -58,22 +60,22 @@
 #define PVRSRV_BRIDGE_SYNC_FREESYNCPRIMITIVEBLOCK			PVRSRV_BRIDGE_SYNC_CMD_FIRST+1
 #define PVRSRV_BRIDGE_SYNC_SYNCPRIMSET			PVRSRV_BRIDGE_SYNC_CMD_FIRST+2
 #define PVRSRV_BRIDGE_SYNC_SERVERSYNCPRIMSET			PVRSRV_BRIDGE_SYNC_CMD_FIRST+3
-#define PVRSRV_BRIDGE_SYNC_SYNCRECORDREMOVEBYHANDLE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+4
-#define PVRSRV_BRIDGE_SYNC_SYNCRECORDADD			PVRSRV_BRIDGE_SYNC_CMD_FIRST+5
-#define PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC			PVRSRV_BRIDGE_SYNC_CMD_FIRST+6
-#define PVRSRV_BRIDGE_SYNC_SERVERSYNCFREE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+7
-#define PVRSRV_BRIDGE_SYNC_SERVERSYNCQUEUEHWOP			PVRSRV_BRIDGE_SYNC_CMD_FIRST+8
-#define PVRSRV_BRIDGE_SYNC_SERVERSYNCGETSTATUS			PVRSRV_BRIDGE_SYNC_CMD_FIRST+9
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCREATE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+10
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPTAKE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+11
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPREADY			PVRSRV_BRIDGE_SYNC_CMD_FIRST+12
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCOMPLETE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+13
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPDESTROY			PVRSRV_BRIDGE_SYNC_CMD_FIRST+14
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMP			PVRSRV_BRIDGE_SYNC_CMD_FIRST+15
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPVALUE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+16
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPPOL			PVRSRV_BRIDGE_SYNC_CMD_FIRST+17
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPPDUMPPOL			PVRSRV_BRIDGE_SYNC_CMD_FIRST+18
-#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPCBP			PVRSRV_BRIDGE_SYNC_CMD_FIRST+19
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC			PVRSRV_BRIDGE_SYNC_CMD_FIRST+4
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCFREE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+5
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCQUEUEHWOP			PVRSRV_BRIDGE_SYNC_CMD_FIRST+6
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCGETSTATUS			PVRSRV_BRIDGE_SYNC_CMD_FIRST+7
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCREATE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+8
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPTAKE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+9
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPREADY			PVRSRV_BRIDGE_SYNC_CMD_FIRST+10
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCOMPLETE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+11
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPDESTROY			PVRSRV_BRIDGE_SYNC_CMD_FIRST+12
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMP			PVRSRV_BRIDGE_SYNC_CMD_FIRST+13
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPVALUE			PVRSRV_BRIDGE_SYNC_CMD_FIRST+14
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPPOL			PVRSRV_BRIDGE_SYNC_CMD_FIRST+15
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPPDUMPPOL			PVRSRV_BRIDGE_SYNC_CMD_FIRST+16
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPCBP			PVRSRV_BRIDGE_SYNC_CMD_FIRST+17
+#define PVRSRV_BRIDGE_SYNC_SYNCALLOCEVENT			PVRSRV_BRIDGE_SYNC_CMD_FIRST+18
+#define PVRSRV_BRIDGE_SYNC_SYNCFREEEVENT			PVRSRV_BRIDGE_SYNC_CMD_FIRST+19
 #define PVRSRV_BRIDGE_SYNC_CMD_LAST			(PVRSRV_BRIDGE_SYNC_CMD_FIRST+19)
 
 
@@ -153,46 +155,6 @@
 
 
 /*******************************************
-            SyncRecordRemoveByHandle          
- *******************************************/
-
-/* Bridge in structure for SyncRecordRemoveByHandle */
-typedef struct PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE_TAG
-{
-	IMG_HANDLE hhRecord;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE;
-
-/* Bridge out structure for SyncRecordRemoveByHandle */
-typedef struct PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE_TAG
-{
-	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE;
-
-
-/*******************************************
-            SyncRecordAdd          
- *******************************************/
-
-/* Bridge in structure for SyncRecordAdd */
-typedef struct PVRSRV_BRIDGE_IN_SYNCRECORDADD_TAG
-{
-	IMG_HANDLE hhServerSyncPrimBlock;
-	IMG_UINT32 ui32ui32FwBlockAddr;
-	IMG_UINT32 ui32ui32SyncOffset;
-	IMG_BOOL bbServerSync;
-	IMG_UINT32 ui32ClassNameSize;
-	const IMG_CHAR * puiClassName;
-} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCRECORDADD;
-
-/* Bridge out structure for SyncRecordAdd */
-typedef struct PVRSRV_BRIDGE_OUT_SYNCRECORDADD_TAG
-{
-	IMG_HANDLE hhRecord;
-	PVRSRV_ERROR eError;
-} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCRECORDADD;
-
-
-/*******************************************
             ServerSyncAlloc          
  *******************************************/
 
@@ -477,4 +439,41 @@
 } __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPCBP;
 
 
+/*******************************************
+            SyncAllocEvent          
+ *******************************************/
+
+/* Bridge in structure for SyncAllocEvent */
+typedef struct PVRSRV_BRIDGE_IN_SYNCALLOCEVENT_TAG
+{
+	IMG_BOOL bServerSync;
+	IMG_UINT32 ui32FWAddr;
+	IMG_UINT32 ui32ClassNameSize;
+	const IMG_CHAR * puiClassName;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCALLOCEVENT;
+
+/* Bridge out structure for SyncAllocEvent */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCALLOCEVENT_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCALLOCEVENT;
+
+
+/*******************************************
+            SyncFreeEvent          
+ *******************************************/
+
+/* Bridge in structure for SyncFreeEvent */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFREEEVENT_TAG
+{
+	IMG_UINT32 ui32FWAddr;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCFREEEVENT;
+
+/* Bridge out structure for SyncFreeEvent */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFREEEVENT_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCFREEEVENT;
+
+
 #endif /* COMMON_SYNC_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/sync_bridge/server_sync_bridge.c b/drivers/staging/imgtec/rogue/generated/sync_bridge/server_sync_bridge.c
index da6176a..746c4a2 100644
--- a/drivers/staging/imgtec/rogue/generated/sync_bridge/server_sync_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/sync_bridge/server_sync_bridge.c
@@ -46,6 +46,7 @@
 
 #include "img_defs.h"
 
+#include "sync.h"
 #include "sync_server.h"
 #include "pdump.h"
 
@@ -65,6 +66,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -78,14 +81,14 @@
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = NULL;
 	PMR * pshSyncPMRInt = NULL;
 
+
+
 	PVR_UNREFERENCED_PARAMETER(psAllocSyncPrimitiveBlockIN);
 
 
 	psAllocSyncPrimitiveBlockOUT->hSyncHandle = NULL;
 
 
-	PMRLock();
-
 
 	psAllocSyncPrimitiveBlockOUT->eError =
 		PVRSRVAllocSyncPrimitiveBlockKM(psConnection, OSGetDevData(psConnection),
@@ -96,13 +99,18 @@
 	/* Exit early if bridged call fails */
 	if(psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
 	{
-		PMRUnlock();
 		goto AllocSyncPrimitiveBlock_exit;
 	}
-	PMRUnlock();
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psAllocSyncPrimitiveBlockOUT->hSyncHandle,
 							(void *) psSyncHandleInt,
 							PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
@@ -110,11 +118,17 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVFreeSyncPrimitiveBlockKM);
 	if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto AllocSyncPrimitiveBlock_exit;
 	}
 
 
-	psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+
+
+
+
+	psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocSubHandleUnlocked(psConnection->psHandleBase,
+
 							&psAllocSyncPrimitiveBlockOUT->hhSyncPMR,
 							(void *) pshSyncPMRInt,
 							PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
@@ -122,22 +136,38 @@
 							,psAllocSyncPrimitiveBlockOUT->hSyncHandle);
 	if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto AllocSyncPrimitiveBlock_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 AllocSyncPrimitiveBlock_exit:
+
+
+
 	if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
 	{
+		/* Lock over handle creation cleanup. */
+		LockHandle();
 		if (psAllocSyncPrimitiveBlockOUT->hSyncHandle)
 		{
-			PVRSRV_ERROR eError = PVRSRVReleaseHandle(psConnection->psHandleBase,
+
+
+			PVRSRV_ERROR eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 						(IMG_HANDLE) psAllocSyncPrimitiveBlockOUT->hSyncHandle,
 						PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
-
-			/* Releasing the handle should free/destroy/release the resource. This should never fail... */
+			if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+				        "PVRSRVBridgeAllocSyncPrimitiveBlock: %s",
+				        PVRSRVGetErrorStringKM(eError)));
+			}
+			/* Releasing the handle should free/destroy/release the resource.
+			 * This should never fail... */
 			PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
 
 			/* Avoid freeing/destroying/releasing the resource a second time below */
@@ -145,6 +175,8 @@
 		}
 
 
+		/* Release now we have cleaned up creation handles. */
+		UnlockHandle();
 		if (psSyncHandleInt)
 		{
 			PVRSRVFreeSyncPrimitiveBlockKM(psSyncHandleInt);
@@ -155,6 +187,7 @@
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeFreeSyncPrimitiveBlock(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_FREESYNCPRIMITIVEBLOCK *psFreeSyncPrimitiveBlockIN,
@@ -166,36 +199,53 @@
 
 
 
-	PMRLock();
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
 
 
 
 
 	psFreeSyncPrimitiveBlockOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psFreeSyncPrimitiveBlockIN->hSyncHandle,
 					PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
-	if ((psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_OK) && (psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_OK) &&
+	    (psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeFreeSyncPrimitiveBlock: %s",
+		        PVRSRVGetErrorStringKM(psFreeSyncPrimitiveBlockOUT->eError)));
 		PVR_ASSERT(0);
-		PMRUnlock();
+		UnlockHandle();
 		goto FreeSyncPrimitiveBlock_exit;
 	}
 
-	PMRUnlock();
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 FreeSyncPrimitiveBlock_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeSyncPrimSet(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMSET *psSyncPrimSetIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMSET *psSyncPrimSetOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psSyncPrimSetIN->hSyncHandle;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = NULL;
 
 
@@ -204,19 +254,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psSyncPrimSetOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psSyncPrimSetIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psSyncPrimSetOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimSet_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimSetOUT->eError =
 		PVRSRVSyncPrimSetKM(
@@ -229,15 +289,38 @@
 
 SyncPrimSet_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeServerSyncPrimSet(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SERVERSYNCPRIMSET *psServerSyncPrimSetIN,
 					  PVRSRV_BRIDGE_OUT_SERVERSYNCPRIMSET *psServerSyncPrimSetOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psServerSyncPrimSetIN->hSyncHandle;
 	SERVER_SYNC_PRIMITIVE * psSyncHandleInt = NULL;
 
 
@@ -246,19 +329,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psServerSyncPrimSetOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psServerSyncPrimSetIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psServerSyncPrimSetOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto ServerSyncPrimSet_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psServerSyncPrimSetOUT->eError =
 		PVRSRVServerSyncPrimSetKM(
@@ -270,136 +363,31 @@
 
 ServerSyncPrimSet_exit:
 
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeSyncRecordRemoveByHandle(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE *psSyncRecordRemoveByHandleIN,
-					  PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE *psSyncRecordRemoveByHandleOUT,
-					 CONNECTION_DATA *psConnection)
-{
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
 
 
 
 
 
 
-
-
-
-	psSyncRecordRemoveByHandleOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
-					(IMG_HANDLE) psSyncRecordRemoveByHandleIN->hhRecord,
-					PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE);
-	if ((psSyncRecordRemoveByHandleOUT->eError != PVRSRV_OK) && (psSyncRecordRemoveByHandleOUT->eError != PVRSRV_ERROR_RETRY))
-	{
-		PVR_ASSERT(0);
-		goto SyncRecordRemoveByHandle_exit;
-	}
-
-
-
-SyncRecordRemoveByHandle_exit:
-
-	return 0;
-}
-
-static IMG_INT
-PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32DispatchTableEntry,
-					  PVRSRV_BRIDGE_IN_SYNCRECORDADD *psSyncRecordAddIN,
-					  PVRSRV_BRIDGE_OUT_SYNCRECORDADD *psSyncRecordAddOUT,
-					 CONNECTION_DATA *psConnection)
-{
-	SYNC_RECORD_HANDLE pshRecordInt = NULL;
-	SYNC_PRIMITIVE_BLOCK * pshServerSyncPrimBlockInt = NULL;
-	IMG_CHAR *uiClassNameInt = NULL;
-
-
-
-
-	if (psSyncRecordAddIN->ui32ClassNameSize != 0)
-	{
-		uiClassNameInt = OSAllocMemNoStats(psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR));
-		if (!uiClassNameInt)
-		{
-			psSyncRecordAddOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncRecordAdd_exit;
-		}
-	}
-
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncRecordAddIN->puiClassName, psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiClassNameInt, psSyncRecordAddIN->puiClassName,
-				psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
-			{
-				psSyncRecordAddOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-				goto SyncRecordAdd_exit;
-			}
-
-
-
 				{
-					/* Look up the address from the handle */
-					psSyncRecordAddOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
-											(void **) &pshServerSyncPrimBlockInt,
-											psSyncRecordAddIN->hhServerSyncPrimBlock,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
-					if(psSyncRecordAddOUT->eError != PVRSRV_OK)
-					{
-						goto SyncRecordAdd_exit;
-					}
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
 				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
 
 
-	psSyncRecordAddOUT->eError =
-		PVRSRVSyncRecordAddKM(
-					&pshRecordInt,
-					pshServerSyncPrimBlockInt,
-					psSyncRecordAddIN->ui32ui32FwBlockAddr,
-					psSyncRecordAddIN->ui32ui32SyncOffset,
-					psSyncRecordAddIN->bbServerSync,
-					psSyncRecordAddIN->ui32ClassNameSize,
-					uiClassNameInt);
-	/* Exit early if bridged call fails */
-	if(psSyncRecordAddOUT->eError != PVRSRV_OK)
-	{
-		goto SyncRecordAdd_exit;
-	}
-
-
-	psSyncRecordAddOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
-							&psSyncRecordAddOUT->hhRecord,
-							(void *) pshRecordInt,
-							PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE,
-							PVRSRV_HANDLE_ALLOC_FLAG_NONE
-							,(PFN_HANDLE_RELEASE)&PVRSRVSyncRecordRemoveByHandleKM);
-	if (psSyncRecordAddOUT->eError != PVRSRV_OK)
-	{
-		goto SyncRecordAdd_exit;
-	}
-
-
-
-
-SyncRecordAdd_exit:
-	if (psSyncRecordAddOUT->eError != PVRSRV_OK)
-	{
-		if (pshRecordInt)
-		{
-			PVRSRVSyncRecordRemoveByHandleKM(pshRecordInt);
-		}
-	}
-
-	if (uiClassNameInt)
-		OSFreeMemNoStats(uiClassNameInt);
-
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeServerSyncAlloc(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SERVERSYNCALLOC *psServerSyncAllocIN,
@@ -409,34 +397,64 @@
 	SERVER_SYNC_PRIMITIVE * psSyncHandleInt = NULL;
 	IMG_CHAR *uiClassNameInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR)) +
+			0;
 
 
 
-	if (psServerSyncAllocIN->ui32ClassNameSize != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		uiClassNameInt = OSAllocMemNoStats(psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR));
-		if (!uiClassNameInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psServerSyncAllocIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psServerSyncAllocOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncAlloc_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psServerSyncAllocIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psServerSyncAllocOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto ServerSyncAlloc_exit;
+			}
 		}
 	}
 
+	if (psServerSyncAllocIN->ui32ClassNameSize != 0)
+	{
+		uiClassNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR);
+	}
+
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psServerSyncAllocIN->puiClassName, psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR))
-				|| (OSCopyFromUser(NULL, uiClassNameInt, psServerSyncAllocIN->puiClassName,
-				psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+			if (psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR) > 0)
 			{
-				psServerSyncAllocOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, uiClassNameInt, psServerSyncAllocIN->puiClassName, psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psServerSyncAllocOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto ServerSyncAlloc_exit;
+					goto ServerSyncAlloc_exit;
+				}
 			}
 
-#if defined(PDUMP)
-	PMRLock();
-#endif
-
 
 	psServerSyncAllocOUT->eError =
 		PVRSRVServerSyncAllocKM(psConnection, OSGetDevData(psConnection),
@@ -447,17 +465,18 @@
 	/* Exit early if bridged call fails */
 	if(psServerSyncAllocOUT->eError != PVRSRV_OK)
 	{
-#if defined(PDUMP)
-		PMRUnlock();
-#endif
 		goto ServerSyncAlloc_exit;
 	}
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
+
+	/* Lock over handle creation. */
+	LockHandle();
 
 
-	psServerSyncAllocOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+	psServerSyncAllocOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psServerSyncAllocOUT->hSyncHandle,
 							(void *) psSyncHandleInt,
 							PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
@@ -465,13 +484,19 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVServerSyncFreeKM);
 	if (psServerSyncAllocOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto ServerSyncAlloc_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
 
 
 
 ServerSyncAlloc_exit:
+
+
+
 	if (psServerSyncAllocOUT->eError != PVRSRV_OK)
 	{
 		if (psSyncHandleInt)
@@ -480,12 +505,21 @@
 		}
 	}
 
-	if (uiClassNameInt)
-		OSFreeMemNoStats(uiClassNameInt);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeServerSyncFree(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SERVERSYNCFREE *psServerSyncFreeIN,
@@ -501,56 +535,80 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psServerSyncFreeOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psServerSyncFreeIN->hSyncHandle,
 					PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
-	if ((psServerSyncFreeOUT->eError != PVRSRV_OK) && (psServerSyncFreeOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psServerSyncFreeOUT->eError != PVRSRV_OK) &&
+	    (psServerSyncFreeOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeServerSyncFree: %s",
+		        PVRSRVGetErrorStringKM(psServerSyncFreeOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto ServerSyncFree_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 ServerSyncFree_exit:
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeServerSyncQueueHWOp(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SERVERSYNCQUEUEHWOP *psServerSyncQueueHWOpIN,
 					  PVRSRV_BRIDGE_OUT_SERVERSYNCQUEUEHWOP *psServerSyncQueueHWOpOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psServerSyncQueueHWOpIN->hSyncHandle;
 	SERVER_SYNC_PRIMITIVE * psSyncHandleInt = NULL;
 
 
 
 
 
-#if defined(PDUMP)
-	PMRLock();
-#endif
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psServerSyncQueueHWOpOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psServerSyncQueueHWOpIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psServerSyncQueueHWOpOUT->eError != PVRSRV_OK)
 					{
-#if defined(PDUMP)
-						PMRUnlock();
-#endif
+						UnlockHandle();
 						goto ServerSyncQueueHWOp_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psServerSyncQueueHWOpOUT->eError =
 		PVRSRVServerSyncQueueHWOpKM(
@@ -558,18 +616,37 @@
 					psServerSyncQueueHWOpIN->bbUpdate,
 					&psServerSyncQueueHWOpOUT->ui32FenceValue,
 					&psServerSyncQueueHWOpOUT->ui32UpdateValue);
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
 
 
 
 
 ServerSyncQueueHWOp_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeServerSyncGetStatus(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SERVERSYNCGETSTATUS *psServerSyncGetStatusIN,
@@ -583,6 +660,22 @@
 	IMG_UINT32 *pui32CurrentOpInt = NULL;
 	IMG_UINT32 *pui32NextOpInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE)) +
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) +
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) +
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) +
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) +
+			0;
+
+
 
 	psServerSyncGetStatusOUT->pui32UID = psServerSyncGetStatusIN->pui32UID;
 	psServerSyncGetStatusOUT->pui32FWAddr = psServerSyncGetStatusIN->pui32FWAddr;
@@ -590,78 +683,81 @@
 	psServerSyncGetStatusOUT->pui32NextOp = psServerSyncGetStatusIN->pui32NextOp;
 
 
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psServerSyncGetStatusIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psServerSyncGetStatusIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto ServerSyncGetStatus_exit;
+			}
+		}
+	}
+
 	if (psServerSyncGetStatusIN->ui32SyncCount != 0)
 	{
-		psSyncHandleInt = OSAllocMemNoStats(psServerSyncGetStatusIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psSyncHandleInt)
-		{
-			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncGetStatus_exit;
-		}
-		hSyncHandleInt2 = OSAllocMemNoStats(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE));
-		if (!hSyncHandleInt2)
-		{
-			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncGetStatus_exit;
-		}
+		psSyncHandleInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psServerSyncGetStatusIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hSyncHandleInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psServerSyncGetStatusIN->phSyncHandle, psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hSyncHandleInt2, psServerSyncGetStatusIN->phSyncHandle,
-				psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hSyncHandleInt2, psServerSyncGetStatusIN->phSyncHandle, psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto ServerSyncGetStatus_exit;
+					goto ServerSyncGetStatus_exit;
+				}
 			}
 	if (psServerSyncGetStatusIN->ui32SyncCount != 0)
 	{
-		pui32UIDInt = OSAllocMemNoStats(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
-		if (!pui32UIDInt)
-		{
-			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncGetStatus_exit;
-		}
+		pui32UIDInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32);
 	}
 
 	if (psServerSyncGetStatusIN->ui32SyncCount != 0)
 	{
-		pui32FWAddrInt = OSAllocMemNoStats(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
-		if (!pui32FWAddrInt)
-		{
-			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncGetStatus_exit;
-		}
+		pui32FWAddrInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32);
 	}
 
 	if (psServerSyncGetStatusIN->ui32SyncCount != 0)
 	{
-		pui32CurrentOpInt = OSAllocMemNoStats(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
-		if (!pui32CurrentOpInt)
-		{
-			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncGetStatus_exit;
-		}
+		pui32CurrentOpInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32);
 	}
 
 	if (psServerSyncGetStatusIN->ui32SyncCount != 0)
 	{
-		pui32NextOpInt = OSAllocMemNoStats(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
-		if (!pui32NextOpInt)
-		{
-			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto ServerSyncGetStatus_exit;
-		}
+		pui32NextOpInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32);
 	}
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 	{
@@ -672,18 +768,21 @@
 				{
 					/* Look up the address from the handle */
 					psServerSyncGetStatusOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt[i],
 											hSyncHandleInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psServerSyncGetStatusOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto ServerSyncGetStatus_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psServerSyncGetStatusOUT->eError =
 		PVRSRVServerSyncGetStatusKM(
@@ -696,60 +795,97 @@
 
 
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psServerSyncGetStatusOUT->pui32UID, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32UID, pui32UIDInt,
-		(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) > 0)
 	{
-		psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32UID, pui32UIDInt,
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto ServerSyncGetStatus_exit;
+			goto ServerSyncGetStatus_exit;
+		}
 	}
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psServerSyncGetStatusOUT->pui32FWAddr, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32FWAddr, pui32FWAddrInt,
-		(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) > 0)
 	{
-		psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32FWAddr, pui32FWAddrInt,
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto ServerSyncGetStatus_exit;
+			goto ServerSyncGetStatus_exit;
+		}
 	}
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psServerSyncGetStatusOUT->pui32CurrentOp, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32CurrentOp, pui32CurrentOpInt,
-		(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) > 0)
 	{
-		psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32CurrentOp, pui32CurrentOpInt,
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto ServerSyncGetStatus_exit;
+			goto ServerSyncGetStatus_exit;
+		}
 	}
 
-	if ( !OSAccessOK(PVR_VERIFY_WRITE, (void*) psServerSyncGetStatusOUT->pui32NextOp, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
-		|| (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32NextOp, pui32NextOpInt,
-		(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+	if ((psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)) > 0)
 	{
-		psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		if ( OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32NextOp, pui32NextOpInt,
+			(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK )
+		{
+			psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-		goto ServerSyncGetStatus_exit;
+			goto ServerSyncGetStatus_exit;
+		}
 	}
 
 
 ServerSyncGetStatus_exit:
-	if (psSyncHandleInt)
-		OSFreeMemNoStats(psSyncHandleInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+
 	if (hSyncHandleInt2)
-		OSFreeMemNoStats(hSyncHandleInt2);
-	if (pui32UIDInt)
-		OSFreeMemNoStats(pui32UIDInt);
-	if (pui32FWAddrInt)
-		OSFreeMemNoStats(pui32FWAddrInt);
-	if (pui32CurrentOpInt)
-		OSFreeMemNoStats(pui32CurrentOpInt);
-	if (pui32NextOpInt)
-		OSFreeMemNoStats(pui32NextOpInt);
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psServerSyncGetStatusIN->ui32SyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandleInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeSyncPrimOpCreate(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMOPCREATE *psSyncPrimOpCreateIN,
@@ -764,104 +900,126 @@
 	IMG_HANDLE *hServerSyncInt2 = NULL;
 	SERVER_OP_COOKIE * psServerCookieInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+			(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)) +
+			(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) +
+			(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) +
+			(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)) +
+			(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) +
+			0;
 
 
 
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psSyncPrimOpCreateIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psSyncPrimOpCreateIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto SyncPrimOpCreate_exit;
+			}
+		}
+	}
+
 	if (psSyncPrimOpCreateIN->ui32SyncBlockCount != 0)
 	{
-		psBlockListInt = OSAllocMemNoStats(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
-		if (!psBlockListInt)
-		{
-			psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpCreate_exit;
-		}
-		hBlockListInt2 = OSAllocMemNoStats(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE));
-		if (!hBlockListInt2)
-		{
-			psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpCreate_exit;
-		}
+		psBlockListInt = (SYNC_PRIMITIVE_BLOCK **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
+		hBlockListInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpCreateIN->phBlockList, psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hBlockListInt2, psSyncPrimOpCreateIN->phBlockList,
-				psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hBlockListInt2, psSyncPrimOpCreateIN->phBlockList, psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpCreate_exit;
+					goto SyncPrimOpCreate_exit;
+				}
 			}
 	if (psSyncPrimOpCreateIN->ui32ClientSyncCount != 0)
 	{
-		ui32SyncBlockIndexInt = OSAllocMemNoStats(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
-		if (!ui32SyncBlockIndexInt)
-		{
-			psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpCreate_exit;
-		}
+		ui32SyncBlockIndexInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpCreateIN->pui32SyncBlockIndex, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32SyncBlockIndexInt, psSyncPrimOpCreateIN->pui32SyncBlockIndex,
-				psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32SyncBlockIndexInt, psSyncPrimOpCreateIN->pui32SyncBlockIndex, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpCreate_exit;
+					goto SyncPrimOpCreate_exit;
+				}
 			}
 	if (psSyncPrimOpCreateIN->ui32ClientSyncCount != 0)
 	{
-		ui32IndexInt = OSAllocMemNoStats(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
-		if (!ui32IndexInt)
-		{
-			psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpCreate_exit;
-		}
+		ui32IndexInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpCreateIN->pui32Index, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32IndexInt, psSyncPrimOpCreateIN->pui32Index,
-				psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32IndexInt, psSyncPrimOpCreateIN->pui32Index, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpCreate_exit;
+					goto SyncPrimOpCreate_exit;
+				}
 			}
 	if (psSyncPrimOpCreateIN->ui32ServerSyncCount != 0)
 	{
-		psServerSyncInt = OSAllocMemNoStats(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
-		if (!psServerSyncInt)
-		{
-			psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpCreate_exit;
-		}
-		hServerSyncInt2 = OSAllocMemNoStats(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
-		if (!hServerSyncInt2)
-		{
-			psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpCreate_exit;
-		}
+		psServerSyncInt = (SERVER_SYNC_PRIMITIVE **)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *);
+		hServerSyncInt2 = (IMG_HANDLE *)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset); 
+		ui32NextOffset += psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpCreateIN->phServerSync, psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
-				|| (OSCopyFromUser(NULL, hServerSyncInt2, psSyncPrimOpCreateIN->phServerSync,
-				psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+			if (psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE) > 0)
 			{
-				psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, hServerSyncInt2, psSyncPrimOpCreateIN->phServerSync, psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK )
+				{
+					psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpCreate_exit;
+					goto SyncPrimOpCreate_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 	{
@@ -872,19 +1030,24 @@
 				{
 					/* Look up the address from the handle */
 					psSyncPrimOpCreateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psBlockListInt[i],
 											hBlockListInt2[i],
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimOpCreate_exit;
 					}
 				}
-
 		}
 	}
 
+
+
+
+
 	{
 		IMG_UINT32 i;
 
@@ -893,18 +1056,21 @@
 				{
 					/* Look up the address from the handle */
 					psSyncPrimOpCreateOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerSyncInt[i],
 											hServerSyncInt2[i],
-											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+											IMG_TRUE);
 					if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimOpCreate_exit;
 					}
 				}
-
 		}
 	}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimOpCreateOUT->eError =
 		PVRSRVSyncPrimOpCreateKM(
@@ -922,8 +1088,15 @@
 		goto SyncPrimOpCreate_exit;
 	}
 
+	/* Lock over handle creation. */
+	LockHandle();
 
-	psSyncPrimOpCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+
+
+
+
+	psSyncPrimOpCreateOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
 							&psSyncPrimOpCreateOUT->hServerCookie,
 							(void *) psServerCookieInt,
 							PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
@@ -931,13 +1104,69 @@
 							,(PFN_HANDLE_RELEASE)&PVRSRVSyncPrimOpDestroyKM);
 	if (psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
 	{
+		UnlockHandle();
 		goto SyncPrimOpCreate_exit;
 	}
 
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+SyncPrimOpCreate_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+
+	if (hBlockListInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psSyncPrimOpCreateIN->ui32SyncBlockCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psBlockListInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hBlockListInt2[i],
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+		}
+	}
+
 
 
 
-SyncPrimOpCreate_exit:
+
+
+	if (hServerSyncInt2)
+	{
+		IMG_UINT32 i;
+
+		for (i=0;i<psSyncPrimOpCreateIN->ui32ServerSyncCount;i++)
+		{
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerSyncInt[i])
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerSyncInt2[i],
+											PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+						}
+				}
+		}
+	}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
 	if (psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
 	{
 		if (psServerCookieInt)
@@ -946,133 +1175,166 @@
 		}
 	}
 
-	if (psBlockListInt)
-		OSFreeMemNoStats(psBlockListInt);
-	if (hBlockListInt2)
-		OSFreeMemNoStats(hBlockListInt2);
-	if (ui32SyncBlockIndexInt)
-		OSFreeMemNoStats(ui32SyncBlockIndexInt);
-	if (ui32IndexInt)
-		OSFreeMemNoStats(ui32IndexInt);
-	if (psServerSyncInt)
-		OSFreeMemNoStats(psServerSyncInt);
-	if (hServerSyncInt2)
-		OSFreeMemNoStats(hServerSyncInt2);
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeSyncPrimOpTake(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMOPTAKE *psSyncPrimOpTakeIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMOPTAKE *psSyncPrimOpTakeOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hServerCookie = psSyncPrimOpTakeIN->hServerCookie;
 	SERVER_OP_COOKIE * psServerCookieInt = NULL;
 	IMG_UINT32 *ui32FlagsInt = NULL;
 	IMG_UINT32 *ui32FenceValueInt = NULL;
 	IMG_UINT32 *ui32UpdateValueInt = NULL;
 	IMG_UINT32 *ui32ServerFlagsInt = NULL;
 
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) +
+			(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) +
+			(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) +
+			(psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) +
+			0;
 
 
 
-	if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
+
+
+	if (ui32BufferSize != 0)
 	{
-		ui32FlagsInt = OSAllocMemNoStats(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
-		if (!ui32FlagsInt)
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psSyncPrimOpTakeIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
 		{
-			psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpTake_exit;
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psSyncPrimOpTakeIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto SyncPrimOpTake_exit;
+			}
 		}
 	}
 
-			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpTakeIN->pui32Flags, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32FlagsInt, psSyncPrimOpTakeIN->pui32Flags,
-				psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
-			{
-				psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+	if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
+	{
+		ui32FlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32);
+	}
 
-				goto SyncPrimOpTake_exit;
+			/* Copy the data over */
+			if (psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32) > 0)
+			{
+				if ( OSCopyFromUser(NULL, ui32FlagsInt, psSyncPrimOpTakeIN->pui32Flags, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto SyncPrimOpTake_exit;
+				}
 			}
 	if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
 	{
-		ui32FenceValueInt = OSAllocMemNoStats(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
-		if (!ui32FenceValueInt)
-		{
-			psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpTake_exit;
-		}
+		ui32FenceValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpTakeIN->pui32FenceValue, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32FenceValueInt, psSyncPrimOpTakeIN->pui32FenceValue,
-				psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32FenceValueInt, psSyncPrimOpTakeIN->pui32FenceValue, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpTake_exit;
+					goto SyncPrimOpTake_exit;
+				}
 			}
 	if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
 	{
-		ui32UpdateValueInt = OSAllocMemNoStats(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
-		if (!ui32UpdateValueInt)
-		{
-			psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpTake_exit;
-		}
+		ui32UpdateValueInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpTakeIN->pui32UpdateValue, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32UpdateValueInt, psSyncPrimOpTakeIN->pui32UpdateValue,
-				psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32UpdateValueInt, psSyncPrimOpTakeIN->pui32UpdateValue, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpTake_exit;
+					goto SyncPrimOpTake_exit;
+				}
 			}
 	if (psSyncPrimOpTakeIN->ui32ServerSyncCount != 0)
 	{
-		ui32ServerFlagsInt = OSAllocMemNoStats(psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
-		if (!ui32ServerFlagsInt)
-		{
-			psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	
-			goto SyncPrimOpTake_exit;
-		}
+		ui32ServerFlagsInt = (IMG_UINT32*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32);
 	}
 
 			/* Copy the data over */
-			if ( !OSAccessOK(PVR_VERIFY_READ, (void*) psSyncPrimOpTakeIN->pui32ServerFlags, psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
-				|| (OSCopyFromUser(NULL, ui32ServerFlagsInt, psSyncPrimOpTakeIN->pui32ServerFlags,
-				psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+			if (psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32) > 0)
 			{
-				psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+				if ( OSCopyFromUser(NULL, ui32ServerFlagsInt, psSyncPrimOpTakeIN->pui32ServerFlags, psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK )
+				{
+					psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-				goto SyncPrimOpTake_exit;
+					goto SyncPrimOpTake_exit;
+				}
 			}
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psSyncPrimOpTakeOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerCookieInt,
-											psSyncPrimOpTakeIN->hServerCookie,
-											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
+											IMG_TRUE);
 					if(psSyncPrimOpTakeOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimOpTake_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimOpTakeOUT->eError =
 		PVRSRVSyncPrimOpTakeKM(
@@ -1088,24 +1350,49 @@
 
 
 SyncPrimOpTake_exit:
-	if (ui32FlagsInt)
-		OSFreeMemNoStats(ui32FlagsInt);
-	if (ui32FenceValueInt)
-		OSFreeMemNoStats(ui32FenceValueInt);
-	if (ui32UpdateValueInt)
-		OSFreeMemNoStats(ui32UpdateValueInt);
-	if (ui32ServerFlagsInt)
-		OSFreeMemNoStats(ui32ServerFlagsInt);
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerCookieInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
 
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeSyncPrimOpReady(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMOPREADY *psSyncPrimOpReadyIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMOPREADY *psSyncPrimOpReadyOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hServerCookie = psSyncPrimOpReadyIN->hServerCookie;
 	SERVER_OP_COOKIE * psServerCookieInt = NULL;
 
 
@@ -1114,19 +1401,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psSyncPrimOpReadyOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerCookieInt,
-											psSyncPrimOpReadyIN->hServerCookie,
-											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
+											IMG_TRUE);
 					if(psSyncPrimOpReadyOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimOpReady_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimOpReadyOUT->eError =
 		PVRSRVSyncPrimOpReadyKM(
@@ -1138,15 +1435,38 @@
 
 SyncPrimOpReady_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerCookieInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeSyncPrimOpComplete(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMOPCOMPLETE *psSyncPrimOpCompleteIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMOPCOMPLETE *psSyncPrimOpCompleteOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hServerCookie = psSyncPrimOpCompleteIN->hServerCookie;
 	SERVER_OP_COOKIE * psServerCookieInt = NULL;
 
 
@@ -1155,19 +1475,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psSyncPrimOpCompleteOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerCookieInt,
-											psSyncPrimOpCompleteIN->hServerCookie,
-											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
+											IMG_TRUE);
 					if(psSyncPrimOpCompleteOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimOpComplete_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimOpCompleteOUT->eError =
 		PVRSRVSyncPrimOpCompleteKM(
@@ -1178,9 +1508,31 @@
 
 SyncPrimOpComplete_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerCookieInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeSyncPrimOpDestroy(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMOPDESTROY *psSyncPrimOpDestroyIN,
@@ -1196,118 +1548,207 @@
 
 
 
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
 	psSyncPrimOpDestroyOUT->eError =
-		PVRSRVReleaseHandle(psConnection->psHandleBase,
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
 					(IMG_HANDLE) psSyncPrimOpDestroyIN->hServerCookie,
 					PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
-	if ((psSyncPrimOpDestroyOUT->eError != PVRSRV_OK) && (psSyncPrimOpDestroyOUT->eError != PVRSRV_ERROR_RETRY))
+	if ((psSyncPrimOpDestroyOUT->eError != PVRSRV_OK) &&
+	    (psSyncPrimOpDestroyOUT->eError != PVRSRV_ERROR_RETRY))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeSyncPrimOpDestroy: %s",
+		        PVRSRVGetErrorStringKM(psSyncPrimOpDestroyOUT->eError)));
 		PVR_ASSERT(0);
+		UnlockHandle();
 		goto SyncPrimOpDestroy_exit;
 	}
 
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
 
 
 SyncPrimOpDestroy_exit:
 
+
+
+
 	return 0;
 }
 
+
+#if defined(PDUMP)
 static IMG_INT
 PVRSRVBridgeSyncPrimPDump(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMPDUMP *psSyncPrimPDumpIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMP *psSyncPrimPDumpOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psSyncPrimPDumpIN->hSyncHandle;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psSyncPrimPDumpOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psSyncPrimPDumpIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psSyncPrimPDumpOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto SyncPrimPDump_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimPDumpOUT->eError =
 		PVRSRVSyncPrimPDumpKM(
 					psSyncHandleInt,
 					psSyncPrimPDumpIN->ui32Offset);
-	PMRUnlock();
 
 
 
 
 SyncPrimPDump_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+#else
+#define PVRSRVBridgeSyncPrimPDump NULL
+#endif
+
+#if defined(PDUMP)
 static IMG_INT
 PVRSRVBridgeSyncPrimPDumpValue(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPVALUE *psSyncPrimPDumpValueIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPVALUE *psSyncPrimPDumpValueOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psSyncPrimPDumpValueIN->hSyncHandle;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = NULL;
 
 
 
 
 
-	PMRLock();
+
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
 
 
 				{
 					/* Look up the address from the handle */
 					psSyncPrimPDumpValueOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psSyncPrimPDumpValueIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psSyncPrimPDumpValueOUT->eError != PVRSRV_OK)
 					{
-						PMRUnlock();
+						UnlockHandle();
 						goto SyncPrimPDumpValue_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimPDumpValueOUT->eError =
 		PVRSRVSyncPrimPDumpValueKM(
 					psSyncHandleInt,
 					psSyncPrimPDumpValueIN->ui32Offset,
 					psSyncPrimPDumpValueIN->ui32Value);
-	PMRUnlock();
 
 
 
 
 SyncPrimPDumpValue_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+#else
+#define PVRSRVBridgeSyncPrimPDumpValue NULL
+#endif
+
+#if defined(PDUMP)
 static IMG_INT
 PVRSRVBridgeSyncPrimPDumpPol(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPPOL *psSyncPrimPDumpPolIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPPOL *psSyncPrimPDumpPolOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psSyncPrimPDumpPolIN->hSyncHandle;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = NULL;
 
 
@@ -1316,19 +1757,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psSyncPrimPDumpPolOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psSyncPrimPDumpPolIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psSyncPrimPDumpPolOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimPDumpPol_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimPDumpPolOUT->eError =
 		PVRSRVSyncPrimPDumpPolKM(
@@ -1344,15 +1795,42 @@
 
 SyncPrimPDumpPol_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+#else
+#define PVRSRVBridgeSyncPrimPDumpPol NULL
+#endif
+
+#if defined(PDUMP)
 static IMG_INT
 PVRSRVBridgeSyncPrimOpPDumpPol(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMOPPDUMPPOL *psSyncPrimOpPDumpPolIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMOPPDUMPPOL *psSyncPrimOpPDumpPolOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hServerCookie = psSyncPrimOpPDumpPolIN->hServerCookie;
 	SERVER_OP_COOKIE * psServerCookieInt = NULL;
 
 
@@ -1361,19 +1839,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psSyncPrimOpPDumpPolOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psServerCookieInt,
-											psSyncPrimOpPDumpPolIN->hServerCookie,
-											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
+											IMG_TRUE);
 					if(psSyncPrimOpPDumpPolOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimOpPDumpPol_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimOpPDumpPolOUT->eError =
 		PVRSRVSyncPrimOpPDumpPolKM(
@@ -1386,15 +1874,42 @@
 
 SyncPrimOpPDumpPol_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psServerCookieInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hServerCookie,
+											PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+#else
+#define PVRSRVBridgeSyncPrimOpPDumpPol NULL
+#endif
+
+#if defined(PDUMP)
 static IMG_INT
 PVRSRVBridgeSyncPrimPDumpCBP(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPCBP *psSyncPrimPDumpCBPIN,
 					  PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPCBP *psSyncPrimPDumpCBPOUT,
 					 CONNECTION_DATA *psConnection)
 {
+	IMG_HANDLE hSyncHandle = psSyncPrimPDumpCBPIN->hSyncHandle;
 	SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = NULL;
 
 
@@ -1403,19 +1918,29 @@
 
 
 
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
 				{
 					/* Look up the address from the handle */
 					psSyncPrimPDumpCBPOUT->eError =
-						PVRSRVLookupHandle(psConnection->psHandleBase,
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
 											(void **) &psSyncHandleInt,
-											psSyncPrimPDumpCBPIN->hSyncHandle,
-											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
 					if(psSyncPrimPDumpCBPOUT->eError != PVRSRV_OK)
 					{
+						UnlockHandle();
 						goto SyncPrimPDumpCBP_exit;
 					}
 				}
-
+	/* Release now we have looked up handles. */
+	UnlockHandle();
 
 	psSyncPrimPDumpCBPOUT->eError =
 		PVRSRVSyncPrimPDumpCBPKM(
@@ -1430,9 +1955,161 @@
 
 SyncPrimPDumpCBP_exit:
 
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(psSyncHandleInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hSyncHandle,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+
 	return 0;
 }
 
+#else
+#define PVRSRVBridgeSyncPrimPDumpCBP NULL
+#endif
+
+static IMG_INT
+PVRSRVBridgeSyncAllocEvent(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_SYNCALLOCEVENT *psSyncAllocEventIN,
+					  PVRSRV_BRIDGE_OUT_SYNCALLOCEVENT *psSyncAllocEventOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	IMG_CHAR *uiClassNameInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psSyncAllocEventIN->ui32ClassNameSize * sizeof(IMG_CHAR)) +
+			0;
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psSyncAllocEventIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psSyncAllocEventIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psSyncAllocEventOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto SyncAllocEvent_exit;
+			}
+		}
+	}
+
+	if (psSyncAllocEventIN->ui32ClassNameSize != 0)
+	{
+		uiClassNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncAllocEventIN->ui32ClassNameSize * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (psSyncAllocEventIN->ui32ClassNameSize * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiClassNameInt, psSyncAllocEventIN->puiClassName, psSyncAllocEventIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psSyncAllocEventOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto SyncAllocEvent_exit;
+				}
+			}
+
+
+	psSyncAllocEventOUT->eError =
+		PVRSRVSyncAllocEventKM(
+					psSyncAllocEventIN->bServerSync,
+					psSyncAllocEventIN->ui32FWAddr,
+					psSyncAllocEventIN->ui32ClassNameSize,
+					uiClassNameInt);
+
+
+
+
+SyncAllocEvent_exit:
+
+
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeSyncFreeEvent(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_SYNCFREEEVENT *psSyncFreeEventIN,
+					  PVRSRV_BRIDGE_OUT_SYNCFREEEVENT *psSyncFreeEventOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+
+	psSyncFreeEventOUT->eError =
+		PVRSRVSyncFreeEventKM(
+					psSyncFreeEventIN->ui32FWAddr);
+
+
+
+
+
+
+
+
+	return 0;
+}
+
+
 
 
 /* *************************************************************************** 
@@ -1462,12 +2139,6 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SERVERSYNCPRIMSET, PVRSRVBridgeServerSyncPrimSet,
 					NULL, bUseLock);
 
-	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SYNCRECORDREMOVEBYHANDLE, PVRSRVBridgeSyncRecordRemoveByHandle,
-					NULL, bUseLock);
-
-	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SYNCRECORDADD, PVRSRVBridgeSyncRecordAdd,
-					NULL, bUseLock);
-
 	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC, PVRSRVBridgeServerSyncAlloc,
 					NULL, bUseLock);
 
@@ -1510,6 +2181,12 @@
 	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPCBP, PVRSRVBridgeSyncPrimPDumpCBP,
 					NULL, bUseLock);
 
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SYNCALLOCEVENT, PVRSRVBridgeSyncAllocEvent,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_SYNCFREEEVENT, PVRSRVBridgeSyncFreeEvent,
+					NULL, bUseLock);
+
 
 	return PVRSRV_OK;
 }
@@ -1521,4 +2198,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/client_synctracking_bridge.h
similarity index 75%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
copy to drivers/staging/imgtec/rogue/generated/synctracking_bridge/client_synctracking_bridge.h
index 839a17a..ce11130 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/client_synctracking_bridge.h
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          Client bridge header for cachegeneric
+@Title          Client bridge header for synctracking
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Exports the client bridge functions for cachegeneric
+@Description    Exports the client bridge functions for synctracking
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,8 +41,8 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef CLIENT_CACHEGENERIC_BRIDGE_H
-#define CLIENT_CACHEGENERIC_BRIDGE_H
+#ifndef CLIENT_SYNCTRACKING_BRIDGE_H
+#define CLIENT_SYNCTRACKING_BRIDGE_H
 
 #include "img_defs.h"
 #include "pvrsrv_error.h"
@@ -52,13 +52,19 @@
 #include "pvr_bridge.h"
 #endif
 
-#include "common_cachegeneric_bridge.h"
+#include "common_synctracking_bridge.h"
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp);
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordRemoveByHandle(IMG_HANDLE hBridge,
+								      IMG_HANDLE hhRecord);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordAdd(IMG_HANDLE hBridge,
+							   IMG_HANDLE *phhRecord,
+							   IMG_HANDLE hhServerSyncPrimBlock,
+							   IMG_UINT32 ui32ui32FwBlockAddr,
+							   IMG_UINT32 ui32ui32SyncOffset,
+							   IMG_BOOL bbServerSync,
+							   IMG_UINT32 ui32ClassNameSize,
+							   const IMG_CHAR *puiClassName);
 
 
-#endif /* CLIENT_CACHEGENERIC_BRIDGE_H */
+#endif /* CLIENT_SYNCTRACKING_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/client_synctracking_direct_bridge.c
similarity index 65%
copy from drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
copy to drivers/staging/imgtec/rogue/generated/synctracking_bridge/client_synctracking_direct_bridge.c
index d0cdf5a..3568038 100644
--- a/drivers/staging/imgtec/rogue/generated/cachegeneric_bridge/client_cachegeneric_direct_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/client_synctracking_direct_bridge.c
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          Direct client bridge for cachegeneric
+@Title          Direct client bridge for synctracking
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,35 +39,59 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include "client_cachegeneric_bridge.h"
+#include "client_synctracking_bridge.h"
 #include "img_defs.h"
 #include "pvr_debug.h"
 
 /* Module specific includes */
-#include "cache_external.h"
 
-#include "cache_generic.h"
+#include "sync.h"
+#include "sync_server.h"
 
 
-IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeCacheOpQueue(IMG_HANDLE hBridge,
-							  IMG_HANDLE hPMR,
-							  IMG_DEVMEM_OFFSET_T uiOffset,
-							  IMG_DEVMEM_SIZE_T uiSize,
-							  PVRSRV_CACHE_OP iuCacheOp)
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordRemoveByHandle(IMG_HANDLE hBridge,
+								      IMG_HANDLE hhRecord)
 {
 	PVRSRV_ERROR eError;
-	PMR * psPMRInt;
+	SYNC_RECORD_HANDLE pshRecordInt;
 	PVR_UNREFERENCED_PARAMETER(hBridge);
 
-	psPMRInt = (PMR *) hPMR;
+	pshRecordInt = (SYNC_RECORD_HANDLE) hhRecord;
 
 	eError =
-		CacheOpQueue(
-					psPMRInt,
-					uiOffset,
-					uiSize,
-					iuCacheOp);
+		PVRSRVSyncRecordRemoveByHandleKM(
+					pshRecordInt);
 
 	return eError;
 }
 
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordAdd(IMG_HANDLE hBridge,
+							   IMG_HANDLE *phhRecord,
+							   IMG_HANDLE hhServerSyncPrimBlock,
+							   IMG_UINT32 ui32ui32FwBlockAddr,
+							   IMG_UINT32 ui32ui32SyncOffset,
+							   IMG_BOOL bbServerSync,
+							   IMG_UINT32 ui32ClassNameSize,
+							   const IMG_CHAR *puiClassName)
+{
+	PVRSRV_ERROR eError;
+	SYNC_RECORD_HANDLE pshRecordInt;
+	SYNC_PRIMITIVE_BLOCK * pshServerSyncPrimBlockInt;
+
+	pshServerSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK *) hhServerSyncPrimBlock;
+
+	eError =
+		PVRSRVSyncRecordAddKM(NULL, (PVRSRV_DEVICE_NODE *)((void*) hBridge)
+		,
+					&pshRecordInt,
+					pshServerSyncPrimBlockInt,
+					ui32ui32FwBlockAddr,
+					ui32ui32SyncOffset,
+					bbServerSync,
+					ui32ClassNameSize,
+					puiClassName);
+
+	*phhRecord = pshRecordInt;
+	return eError;
+}
+
diff --git a/drivers/staging/imgtec/rogue/generated/synctracking_bridge/common_synctracking_bridge.h b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/common_synctracking_bridge.h
new file mode 100644
index 0000000..edc856f
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/common_synctracking_bridge.h
@@ -0,0 +1,101 @@
+/*************************************************************************/ /*!
+@File
+@Title          Common bridge header for synctracking
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for synctracking
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef COMMON_SYNCTRACKING_BRIDGE_H
+#define COMMON_SYNCTRACKING_BRIDGE_H
+
+#include <powervr/mem_types.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+
+
+#define PVRSRV_BRIDGE_SYNCTRACKING_CMD_FIRST			0
+#define PVRSRV_BRIDGE_SYNCTRACKING_SYNCRECORDREMOVEBYHANDLE			PVRSRV_BRIDGE_SYNCTRACKING_CMD_FIRST+0
+#define PVRSRV_BRIDGE_SYNCTRACKING_SYNCRECORDADD			PVRSRV_BRIDGE_SYNCTRACKING_CMD_FIRST+1
+#define PVRSRV_BRIDGE_SYNCTRACKING_CMD_LAST			(PVRSRV_BRIDGE_SYNCTRACKING_CMD_FIRST+1)
+
+
+/*******************************************
+            SyncRecordRemoveByHandle          
+ *******************************************/
+
+/* Bridge in structure for SyncRecordRemoveByHandle */
+typedef struct PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE_TAG
+{
+	IMG_HANDLE hhRecord;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE;
+
+/* Bridge out structure for SyncRecordRemoveByHandle */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE_TAG
+{
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE;
+
+
+/*******************************************
+            SyncRecordAdd          
+ *******************************************/
+
+/* Bridge in structure for SyncRecordAdd */
+typedef struct PVRSRV_BRIDGE_IN_SYNCRECORDADD_TAG
+{
+	IMG_HANDLE hhServerSyncPrimBlock;
+	IMG_UINT32 ui32ui32FwBlockAddr;
+	IMG_UINT32 ui32ui32SyncOffset;
+	IMG_BOOL bbServerSync;
+	IMG_UINT32 ui32ClassNameSize;
+	const IMG_CHAR * puiClassName;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCRECORDADD;
+
+/* Bridge out structure for SyncRecordAdd */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCRECORDADD_TAG
+{
+	IMG_HANDLE hhRecord;
+	PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCRECORDADD;
+
+
+#endif /* COMMON_SYNCTRACKING_BRIDGE_H */
diff --git a/drivers/staging/imgtec/rogue/generated/synctracking_bridge/server_synctracking_bridge.c b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/server_synctracking_bridge.c
new file mode 100644
index 0000000..9c9508d
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/generated/synctracking_bridge/server_synctracking_bridge.c
@@ -0,0 +1,336 @@
+/*************************************************************************/ /*!
+@File
+@Title          Server bridge for synctracking
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements the server side of the bridge for synctracking
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "sync.h"
+#include "sync_server.h"
+
+
+#include "common_synctracking_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#include <linux/slab.h>
+
+
+
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+ 
+static IMG_INT
+PVRSRVBridgeSyncRecordRemoveByHandle(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE *psSyncRecordRemoveByHandleIN,
+					  PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE *psSyncRecordRemoveByHandleOUT,
+					 CONNECTION_DATA *psConnection)
+{
+
+
+
+
+
+
+
+
+
+	/* Lock over handle destruction. */
+	LockHandle();
+
+
+
+
+
+	psSyncRecordRemoveByHandleOUT->eError =
+		PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+					(IMG_HANDLE) psSyncRecordRemoveByHandleIN->hhRecord,
+					PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE);
+	if ((psSyncRecordRemoveByHandleOUT->eError != PVRSRV_OK) &&
+	    (psSyncRecordRemoveByHandleOUT->eError != PVRSRV_ERROR_RETRY))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "PVRSRVBridgeSyncRecordRemoveByHandle: %s",
+		        PVRSRVGetErrorStringKM(psSyncRecordRemoveByHandleOUT->eError)));
+		PVR_ASSERT(0);
+		UnlockHandle();
+		goto SyncRecordRemoveByHandle_exit;
+	}
+
+	/* Release now we have destroyed handles. */
+	UnlockHandle();
+
+
+
+SyncRecordRemoveByHandle_exit:
+
+
+
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32DispatchTableEntry,
+					  PVRSRV_BRIDGE_IN_SYNCRECORDADD *psSyncRecordAddIN,
+					  PVRSRV_BRIDGE_OUT_SYNCRECORDADD *psSyncRecordAddOUT,
+					 CONNECTION_DATA *psConnection)
+{
+	SYNC_RECORD_HANDLE pshRecordInt = NULL;
+	IMG_HANDLE hhServerSyncPrimBlock = psSyncRecordAddIN->hhServerSyncPrimBlock;
+	SYNC_PRIMITIVE_BLOCK * pshServerSyncPrimBlockInt = NULL;
+	IMG_CHAR *uiClassNameInt = NULL;
+
+	IMG_UINT32 ui32NextOffset = 0;
+	IMG_BYTE   *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+	IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+	IMG_UINT32 ui32BufferSize = 
+			(psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR)) +
+			0;
+
+
+
+
+
+	if (ui32BufferSize != 0)
+	{
+#if !defined(INTEGRITY_OS)
+		/* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+		IMG_UINT32 ui32InBufferOffset = PVR_ALIGN(sizeof(*psSyncRecordAddIN), sizeof(unsigned long));
+		IMG_UINT32 ui32InBufferExcessSize = ui32InBufferOffset >= PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 :
+			PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+		bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+		if (bHaveEnoughSpace)
+		{
+			IMG_BYTE *pInputBuffer = (IMG_BYTE *)psSyncRecordAddIN;
+
+			pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];		}
+		else
+#endif
+		{
+			pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+			if(!pArrayArgsBuffer)
+			{
+				psSyncRecordAddOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto SyncRecordAdd_exit;
+			}
+		}
+	}
+
+	if (psSyncRecordAddIN->ui32ClassNameSize != 0)
+	{
+		uiClassNameInt = (IMG_CHAR*)(((IMG_UINT8 *)pArrayArgsBuffer) + ui32NextOffset);
+		ui32NextOffset += psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR);
+	}
+
+			/* Copy the data over */
+			if (psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR) > 0)
+			{
+				if ( OSCopyFromUser(NULL, uiClassNameInt, psSyncRecordAddIN->puiClassName, psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK )
+				{
+					psSyncRecordAddOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+					goto SyncRecordAdd_exit;
+				}
+			}
+
+	/* Lock over handle lookup. */
+	LockHandle();
+
+
+
+
+
+				{
+					/* Look up the address from the handle */
+					psSyncRecordAddOUT->eError =
+						PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
+											(void **) &pshServerSyncPrimBlockInt,
+											hhServerSyncPrimBlock,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+											IMG_TRUE);
+					if(psSyncRecordAddOUT->eError != PVRSRV_OK)
+					{
+						UnlockHandle();
+						goto SyncRecordAdd_exit;
+					}
+				}
+	/* Release now we have looked up handles. */
+	UnlockHandle();
+
+	psSyncRecordAddOUT->eError =
+		PVRSRVSyncRecordAddKM(psConnection, OSGetDevData(psConnection),
+					&pshRecordInt,
+					pshServerSyncPrimBlockInt,
+					psSyncRecordAddIN->ui32ui32FwBlockAddr,
+					psSyncRecordAddIN->ui32ui32SyncOffset,
+					psSyncRecordAddIN->bbServerSync,
+					psSyncRecordAddIN->ui32ClassNameSize,
+					uiClassNameInt);
+	/* Exit early if bridged call fails */
+	if(psSyncRecordAddOUT->eError != PVRSRV_OK)
+	{
+		goto SyncRecordAdd_exit;
+	}
+
+	/* Lock over handle creation. */
+	LockHandle();
+
+
+
+
+
+	psSyncRecordAddOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+
+							&psSyncRecordAddOUT->hhRecord,
+							(void *) pshRecordInt,
+							PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE,
+							PVRSRV_HANDLE_ALLOC_FLAG_NONE
+							,(PFN_HANDLE_RELEASE)&PVRSRVSyncRecordRemoveByHandleKM);
+	if (psSyncRecordAddOUT->eError != PVRSRV_OK)
+	{
+		UnlockHandle();
+		goto SyncRecordAdd_exit;
+	}
+
+	/* Release now we have created handles. */
+	UnlockHandle();
+
+
+
+SyncRecordAdd_exit:
+
+	/* Lock over handle lookup cleanup. */
+	LockHandle();
+
+
+
+
+
+
+				{
+					/* Unreference the previously looked up handle */
+						if(pshServerSyncPrimBlockInt)
+						{
+							PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+											hhServerSyncPrimBlock,
+											PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+						}
+				}
+	/* Release now we have cleaned up look up handles. */
+	UnlockHandle();
+
+	if (psSyncRecordAddOUT->eError != PVRSRV_OK)
+	{
+		if (pshRecordInt)
+		{
+			PVRSRVSyncRecordRemoveByHandleKM(pshRecordInt);
+		}
+	}
+
+	/* Allocated space should be equal to the last updated offset */
+	PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+
+#if defined(INTEGRITY_OS)
+	if(pArrayArgsBuffer)
+#else
+	if(!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+		OSFreeMemNoStats(pArrayArgsBuffer);
+
+
+	return 0;
+}
+
+
+
+
+/* *************************************************************************** 
+ * Server bridge dispatch related glue 
+ */
+
+static IMG_BOOL bUseLock = IMG_TRUE;
+
+PVRSRV_ERROR InitSYNCTRACKINGBridge(void);
+PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void);
+
+/*
+ * Register all SYNCTRACKING functions with services
+ */
+PVRSRV_ERROR InitSYNCTRACKINGBridge(void)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCTRACKING, PVRSRV_BRIDGE_SYNCTRACKING_SYNCRECORDREMOVEBYHANDLE, PVRSRVBridgeSyncRecordRemoveByHandle,
+					NULL, bUseLock);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCTRACKING, PVRSRV_BRIDGE_SYNCTRACKING_SYNCRECORDADD, PVRSRVBridgeSyncRecordAdd,
+					NULL, bUseLock);
+
+
+	return PVRSRV_OK;
+}
+
+/*
+ * Unregister all synctracking functions with services
+ */
+PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void)
+{
+	return PVRSRV_OK;
+}
diff --git a/drivers/staging/imgtec/rogue/generated/timerquery_bridge/common_timerquery_bridge.h b/drivers/staging/imgtec/rogue/generated/timerquery_bridge/common_timerquery_bridge.h
index a79d9ea1..ed544f2 100644
--- a/drivers/staging/imgtec/rogue/generated/timerquery_bridge/common_timerquery_bridge.h
+++ b/drivers/staging/imgtec/rogue/generated/timerquery_bridge/common_timerquery_bridge.h
@@ -2,8 +2,8 @@
 @File
 @Title          Common bridge header for timerquery
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures that are used by both
-                the client and sever side of the bridge for timerquery
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for timerquery
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -45,6 +45,8 @@
 #ifndef COMMON_TIMERQUERY_BRIDGE_H
 #define COMMON_TIMERQUERY_BRIDGE_H
 
+#include <powervr/mem_types.h>
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
diff --git a/drivers/staging/imgtec/rogue/generated/timerquery_bridge/server_timerquery_bridge.c b/drivers/staging/imgtec/rogue/generated/timerquery_bridge/server_timerquery_bridge.c
index 51e5de7..fbd7c10 100644
--- a/drivers/staging/imgtec/rogue/generated/timerquery_bridge/server_timerquery_bridge.c
+++ b/drivers/staging/imgtec/rogue/generated/timerquery_bridge/server_timerquery_bridge.c
@@ -64,6 +64,8 @@
 
 
 
+
+
 /* ***************************************************************************
  * Server-side bridge entry points
  */
@@ -81,6 +83,7 @@
 
 
 
+
 	psRGXBeginTimerQueryOUT->eError =
 		PVRSRVRGXBeginTimerQueryKM(psConnection, OSGetDevData(psConnection),
 					psRGXBeginTimerQueryIN->ui32QueryId);
@@ -89,9 +92,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXEndTimerQuery(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXENDTIMERQUERY *psRGXEndTimerQueryIN,
@@ -99,9 +106,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psRGXEndTimerQueryIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psRGXEndTimerQueryIN);
+
 
 
 
@@ -114,9 +122,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXQueryTimer(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXQUERYTIMER *psRGXQueryTimerIN,
@@ -130,6 +142,7 @@
 
 
 
+
 	psRGXQueryTimerOUT->eError =
 		PVRSRVRGXQueryTimerKM(psConnection, OSGetDevData(psConnection),
 					psRGXQueryTimerIN->ui32QueryId,
@@ -140,9 +153,13 @@
 
 
 
+
+
+
 	return 0;
 }
 
+
 static IMG_INT
 PVRSRVBridgeRGXCurrentTime(IMG_UINT32 ui32DispatchTableEntry,
 					  PVRSRV_BRIDGE_IN_RGXCURRENTTIME *psRGXCurrentTimeIN,
@@ -150,9 +167,10 @@
 					 CONNECTION_DATA *psConnection)
 {
 
-	PVR_UNREFERENCED_PARAMETER(psRGXCurrentTimeIN);
 
 
+	PVR_UNREFERENCED_PARAMETER(psRGXCurrentTimeIN);
+
 
 
 
@@ -165,11 +183,15 @@
 
 
 
+
+
+
 	return 0;
 }
 
 
 
+
 /* *************************************************************************** 
  * Server bridge dispatch related glue 
  */
@@ -208,4 +230,3 @@
 {
 	return PVRSRV_OK;
 }
-
diff --git a/drivers/staging/imgtec/rogue/handle.c b/drivers/staging/imgtec/rogue/handle.c
index be0d688..d0f8aae 100644
--- a/drivers/staging/imgtec/rogue/handle.c
+++ b/drivers/staging/imgtec/rogue/handle.c
@@ -108,8 +108,10 @@
 	/* List entry for sibling subhandles */
 	HANDLE_LIST sSiblings;
 
-	/* Reference count, always 1 unless handle is shared */
-	IMG_UINT32 ui32Refs;
+	/* Reference count. The pfnReleaseData callback gets called when the
+	 * reference count hits zero
+	 */
+	IMG_UINT32 ui32RefCount;
 } HANDLE_DATA;
 
 struct _HANDLE_BASE_
@@ -123,6 +125,9 @@
 	 * pointers to handles.
 	 */
 	HASH_TABLE *psHashTab;
+
+	/* Can be connection, process, global */
+	PVRSRV_HANDLE_BASE_TYPE eType;
 };
 
 /*
@@ -168,6 +173,42 @@
  */
 PVRSRV_HANDLE_BASE *gpsKernelHandleBase = NULL;
 
+/* Increase the reference count on the given handle.
+ * The handle lock must already be acquired.
+ * Returns: the reference count after the increment
+ */
+static inline IMG_UINT32 _HandleRef(HANDLE_DATA *psHandleData)
+{
+#if defined PVRSRV_DEBUG_HANDLE_LOCK
+	if(!OSLockIsLocked(gHandleLock))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Handle lock is not locked", __func__));
+		OSDumpStack();
+	}
+#endif
+	psHandleData->ui32RefCount++;
+	return psHandleData->ui32RefCount;
+}
+
+/* Decrease the reference count on the given handle.
+ * The handle lock must already be acquired.
+ * Returns: the reference count after the decrement
+ */
+static inline IMG_UINT32 _HandleUnref(HANDLE_DATA *psHandleData)
+{
+#if defined PVRSRV_DEBUG_HANDLE_LOCK
+	if(!OSLockIsLocked(gHandleLock))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Handle lock is not locked", __func__));
+		OSDumpStack();
+	}
+#endif
+	PVR_ASSERT(psHandleData->ui32RefCount > 0);
+	psHandleData->ui32RefCount--;
+
+	return psHandleData->ui32RefCount;
+}
+
 /*!
 ******************************************************************************
 
@@ -842,7 +883,13 @@
 		return eError;
 	}
 
-	PVR_ASSERT(psHandleData->ui32Refs > 0);
+	if(_HandleUnref(psHandleData) > 0)
+	{
+		/* this handle still has references so do not destroy it
+		 * or the underlying object yet
+		 */
+		return PVRSRV_OK;
+	}
 
 	/* Call the release data callback for each reference on the handle */
 	if (psHandleData->pfnReleaseData != NULL)
@@ -856,6 +903,9 @@
 				 hHandle,
 				 (IMG_UINT32)psHandleData->eType));
 
+			/* the caller should retry, so retain a reference on the handle */
+			_HandleRef(psHandleData);
+
 			return eError;
 		}
 		else if (eError != PVRSRV_OK)
@@ -864,14 +914,6 @@
 		}
 	}
 
-	psHandleData->ui32Refs--;
-	if (psHandleData->ui32Refs > 0)
-	{
-		/* Reference count still positive, only possible for shared handles */
-		PVR_ASSERT(TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_SHARED));
-		return PVRSRV_OK;
-	}
-
 	if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
 	{
 		HAND_KEY aKey;
@@ -1042,7 +1084,7 @@
 	psNewHandleData->eFlag = eFlag;
 	psNewHandleData->pvData = pvData;
 	psNewHandleData->pfnReleaseData = pfnReleaseData;
-	psNewHandleData->ui32Refs = 1;
+	psNewHandleData->ui32RefCount = 1;
 
 	InitParentList(psNewHandleData);
 #if defined(DEBUG)
@@ -1093,7 +1135,41 @@
 			       PVRSRV_HANDLE_ALLOC_FLAG eFlag,
 			       PFN_HANDLE_RELEASE pfnReleaseData)
 {
-	IMG_HANDLE hHandle;
+	PVRSRV_ERROR eError;
+
+	LockHandle();
+	eError = PVRSRVAllocHandleUnlocked(psBase, phHandle, pvData, eType, eFlag, pfnReleaseData);
+	UnlockHandle();
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocHandleUnlocked
+
+ @Description	Allocate a handle without acquiring/releasing the handle
+		lock. The function assumes you hold the lock when called.
+
+ @Input		phHandle - location for new handle
+		pvData - pointer to resource to be associated with the handle
+		eType - the type of resource
+		pfnReleaseData - Function to release resource at handle release
+		                 time
+
+ @Output	phHandle - points to new handle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+			       IMG_HANDLE *phHandle,
+			       void *pvData,
+			       PVRSRV_HANDLE_TYPE eType,
+			       PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+			       PFN_HANDLE_RELEASE pfnReleaseData)
+{
 	PVRSRV_ERROR eError;
 
 	*phHandle = NULL;
@@ -1102,65 +1178,23 @@
 	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
 	PVR_ASSERT(gpsHandleFuncs);
 
-	LockHandle();
 	if (psBase == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing handle base"));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	if (pfnReleaseData == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing release function"));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto ExitUnlock;
-	}
-
-	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
-	{
-		/* See if there is already a handle for this data pointer */
-		hHandle = FindHandle(psBase, pvData, eType, NULL);
-		if (hHandle != NULL)
-		{
-			HANDLE_DATA *psHandleData = NULL;
-
-			eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,
-					 "PVRSRVAllocHandle: Lookup of existing handle failed (%s)",
-					 PVRSRVGetErrorStringKM(eError)));
-				goto ExitUnlock;
-			}
-
-			/*
-			 * If the client is willing to share a handle, and the
-			 * existing handle is marked as shareable, return the
-			 * existing handle.
-			 */
-			if (TEST_FLAG(psHandleData->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
-			{
-				/* The same release function should be used for shared handles */
-				PVR_ASSERT(psHandleData->pfnReleaseData == pfnReleaseData);
-
-				psHandleData->ui32Refs++;
-				*phHandle = hHandle;
-
-				eError = PVRSRV_OK;
-				goto ExitUnlock;
-			}
-
-			eError = PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
-			goto ExitUnlock;
-		}
+		goto Exit;
 	}
 
 	eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, NULL, pfnReleaseData);
 
-ExitUnlock:
-	UnlockHandle();
-
+Exit:
 	return eError;
 }
 
@@ -1188,6 +1222,40 @@
 				  PVRSRV_HANDLE_ALLOC_FLAG eFlag,
 				  IMG_HANDLE hParent)
 {
+	PVRSRV_ERROR eError;
+
+	LockHandle();
+	eError = PVRSRVAllocSubHandleUnlocked(psBase, phHandle, pvData, eType, eFlag, hParent);
+	UnlockHandle();
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocSubHandleUnlocked
+
+ @Description	Allocate a subhandle without acquiring/releasing the
+		handle lock. The function assumes you hold the lock when called.
+
+ @Input		phHandle - location for new subhandle
+		pvData - pointer to resource to be associated with the subhandle
+		eType - the type of resource
+		hParent - parent handle
+
+ @Output	phHandle - points to new subhandle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocSubHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+				  IMG_HANDLE *phHandle,
+				  void *pvData,
+				  PVRSRV_HANDLE_TYPE eType,
+				  PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+				  IMG_HANDLE hParent)
+{
 	HANDLE_DATA *psPHandleData = NULL;
 	HANDLE_DATA *psCHandleData = NULL;
 	IMG_HANDLE hParentKey;
@@ -1200,13 +1268,11 @@
 	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
 	PVR_ASSERT(gpsHandleFuncs);
 
-	LockHandle();
-
 	if (psBase == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Missing handle base"));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ? hParent : NULL;
@@ -1216,49 +1282,13 @@
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
-		goto ExitUnlock;
-	}
-
-	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
-	{
-		/* See if there is already a handle for this data pointer */
-		hHandle = FindHandle(psBase, pvData, eType, hParentKey);
-		if (hHandle != NULL)
-		{
-			eError = GetHandleData(psBase, &psCHandleData, hHandle, eType);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
-				goto ExitUnlock;
-			}
-
-			PVR_ASSERT(hParentKey != NULL && ParentHandle(psCHandleData) == hParent);
-
-			/*
-			 * If the client is willing to share a handle, the
-			 * existing handle is marked as shareable, and the
-			 * existing handle has the same parent, return the
-			 * existing handle.
-			 */
-			if (TEST_FLAG(psCHandleData->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && 
-			    ParentHandle(psCHandleData) == hParent)
-			{
-				psCHandleData->ui32Refs++;
-				*phHandle = hHandle;
-
-				eError = PVRSRV_OK;
-				goto ExitUnlock;
-			}
-
-			eError = PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
-			goto ExitUnlock;
-		}
+		goto Exit;
 	}
 
 	eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey, NULL);
 	if (eError != PVRSRV_OK)
 	{
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	eError = GetHandleData(psBase, &psCHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
@@ -1270,7 +1300,7 @@
 		   can't also get it's handle structure. Otherwise something has gone badly wrong. */
 		PVR_ASSERT(eError == PVRSRV_OK);
 
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	/*
@@ -1284,7 +1314,7 @@
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
 
 		(void)FreeHandle(psBase, hHandle, eType, NULL);
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	eError = AdoptChild(psBase, psPHandleData, psCHandleData);
@@ -1293,16 +1323,14 @@
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Parent handle failed to adopt subhandle"));
 
 		(void)FreeHandle(psBase, hHandle, eType, NULL);
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	*phHandle = hHandle;
 
 	eError = PVRSRV_OK;
 
-ExitUnlock:
-	UnlockHandle();
-
+Exit:
 	return eError;
 }
 
@@ -1327,6 +1355,38 @@
 			      void *pvData,
 			      PVRSRV_HANDLE_TYPE eType)
 {
+	PVRSRV_ERROR eError;
+
+	LockHandle();
+	eError = PVRSRVFindHandleUnlocked(psBase, phHandle, pvData, eType);
+	UnlockHandle();
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVFindHandleUnlocked
+
+ @Description	Find handle corresponding to a resource pointer without
+		acquiring/releasing the handle lock. The function assumes you hold
+		the lock when called.
+
+ @Input		phHandle - location for returned handle
+		pvData - pointer to resource to be associated with the handle
+		eType - the type of resource
+
+ @Output	phHandle - points to handle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVFindHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+			      IMG_HANDLE *phHandle,
+			      void *pvData,
+			      PVRSRV_HANDLE_TYPE eType)
+{
 	IMG_HANDLE hHandle;
 	PVRSRV_ERROR eError;
 
@@ -1334,30 +1394,30 @@
 	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
 	PVR_ASSERT(gpsHandleFuncs);
 
-	LockHandle();
-
 	if (psBase == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVFindHandle: Missing handle base"));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	/* See if there is a handle for this data pointer */
 	hHandle = FindHandle(psBase, pvData, eType, NULL);
 	if (hHandle == NULL)
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+			 "PVRSRVFindHandle: Error finding handle. Type %u",
+			 eType));
+
 		eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	*phHandle = hHandle;
 
 	eError = PVRSRV_OK;
 
-ExitUnlock:
-	UnlockHandle();
-
+Exit:
 	return eError;
 
 }
@@ -1372,6 +1432,8 @@
  @Input		ppvData - location to return data pointer
 		hHandle - handle from client
 		eType - handle type
+		bRef - If TRUE, a reference will be added on the handle if the
+		       lookup is successful.
 
  @Output	ppvData - points to the data pointer
 
@@ -1381,7 +1443,43 @@
 PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
 				void **ppvData,
 				IMG_HANDLE hHandle,
-				PVRSRV_HANDLE_TYPE eType)
+				PVRSRV_HANDLE_TYPE eType,
+				IMG_BOOL bRef)
+{
+	PVRSRV_ERROR eError;
+
+	LockHandle();
+	eError = PVRSRVLookupHandleUnlocked(psBase, ppvData, hHandle, eType, bRef);
+	UnlockHandle();
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVLookupHandleUnlocked
+
+ @Description	Lookup the data pointer corresponding to a handle without
+ 		acquiring/releasing the handle lock. The function assumes you
+		hold the lock when called.
+
+ @Input		ppvData - location to return data pointer
+		hHandle - handle from client
+		eType - handle type
+		bRef - If TRUE, a reference will be added on the handle if the
+		       lookup is successful.
+
+ @Output	ppvData - points to the data pointer
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+				void **ppvData,
+				IMG_HANDLE hHandle,
+				PVRSRV_HANDLE_TYPE eType,
+				IMG_BOOL bRef)
 {
 	HANDLE_DATA *psHandleData = NULL;
 	PVRSRV_ERROR eError;
@@ -1390,33 +1488,37 @@
 	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
 	PVR_ASSERT(gpsHandleFuncs);
 
-	LockHandle();
-
 	if (psBase == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Missing handle base"));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
-			 "PVRSRVLookupHandle: Error looking up handle (%s)",
-			 PVRSRVGetErrorStringKM(eError)));
+			 "PVRSRVLookupHandle: Error looking up handle (%s). Handle %p, type %u",
+			 PVRSRVGetErrorStringKM(eError),
+			 (void*) hHandle,
+			 eType));
 #if defined(DEBUG) || defined(PVRSRV_NEED_PVR_DPF)
 		OSDumpStack();
 #endif
-		goto ExitUnlock;
+		goto Exit;
+	}
+
+	if(bRef)
+	{
+		_HandleRef(psHandleData);
 	}
 
 	*ppvData = psHandleData->pvData;
 
 	eError = PVRSRV_OK;
 
-ExitUnlock:
-	UnlockHandle();
+Exit:
 
 	return eError;
 }
@@ -1465,8 +1567,10 @@
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
-			 "PVRSRVLookupSubHandle: Error looking up subhandle (%s)",
-			 PVRSRVGetErrorStringKM(eError)));
+			 "PVRSRVLookupSubHandle: Error looking up subhandle (%s). Handle %p, type %u",
+			 PVRSRVGetErrorStringKM(eError),
+			 (void*) hHandle,
+			 eType));
 		OSDumpStack();
 		goto ExitUnlock;
 	}
@@ -1536,8 +1640,9 @@
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
-			 "PVRSRVGetParentHandle: Error looking up subhandle (%s)",
-			 PVRSRVGetErrorStringKM(eError)));
+			 "PVRSRVGetParentHandle: Error looking up subhandle (%s). Type %u",
+			 PVRSRVGetErrorStringKM(eError),
+			 eType));
 		OSDumpStack();
 		goto ExitUnlock;
 	}
@@ -1571,23 +1676,49 @@
 {
 	PVRSRV_ERROR eError;
 
+	LockHandle();
+	eError = PVRSRVReleaseHandleUnlocked(psBase, hHandle, eType);
+	UnlockHandle();
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVReleaseHandleUnlocked
+
+ @Description	Release a handle that is no longer needed without
+ 		acquiring/releasing the handle lock. The function assumes you
+		hold the lock when called.
+
+ @Input 	hHandle - handle from client
+		eType - handle type
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+				 IMG_HANDLE hHandle,
+				 PVRSRV_HANDLE_TYPE eType)
+{
+	PVRSRV_ERROR eError;
+
 	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
 	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
 	PVR_ASSERT(gpsHandleFuncs);
 
-	LockHandle();
-
 	if (psBase == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Missing handle base"));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto ExitUnlock;
+		goto Exit;
 	}
 
 	eError = FreeHandle(psBase, hHandle, eType, NULL);
 
-ExitUnlock:
-	UnlockHandle();
+Exit:
 
 	return eError;
 }
@@ -1641,7 +1772,8 @@
  @Return	Error code or PVRSRV_OK
 
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase,
+                                   PVRSRV_HANDLE_BASE_TYPE eType)
 {
 	PVRSRV_HANDLE_BASE *psBase;
 	PVRSRV_ERROR eError;
@@ -1668,6 +1800,8 @@
 		goto ErrorUnlock;
 	}
 
+	psBase->eType = eType;
+
 	eError = gpsHandleFuncs->pfnCreateHandleBase(&psBase->psImplBase);
 	if (eError != PVRSRV_OK)
 	{
@@ -1743,6 +1877,46 @@
 
 	return PVRSRV_OK;
 }
+
+/* Print a handle in the handle base. Used with the iterator callback. */
+static PVRSRV_ERROR ListHandlesInBase(IMG_HANDLE hHandle, void *pvData)
+{
+	PVRSRV_HANDLE_BASE *psBase = (PVRSRV_HANDLE_BASE*) pvData;
+	HANDLE_DATA *psHandleData = NULL;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(gpsHandleFuncs);
+
+	if (psBase == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Missing base", __func__));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = GetHandleData(psBase,
+			       &psHandleData,
+			       hHandle,
+			       PVRSRV_HANDLE_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't get handle data for handle", __func__));
+		return eError;
+	}
+
+	if (psHandleData != NULL)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "    Handle: %6u, Type: %3u, Refs: %3u",
+				(IMG_UINT32) (uintptr_t) psHandleData->hHandle,
+				psHandleData->eType,
+				psHandleData->ui32RefCount));
+
+	}
+
+	return PVRSRV_OK;
+}
+
+
+
 #endif /* defined(DEBUG) */
 
 typedef struct FREE_HANDLE_DATA_TAG
@@ -1803,9 +1977,9 @@
 		return PVRSRV_OK;
 	}
 
-	PVR_ASSERT(psHandleData->ui32Refs > 0);
+	PVR_ASSERT(psHandleData->ui32RefCount > 0);
 
-	while (psHandleData->ui32Refs != 0)
+	while (psHandleData->ui32RefCount != 0)
 	{
 		if (psHandleData->pfnReleaseData != NULL)
 		{
@@ -1826,7 +2000,7 @@
 			}
 		}
 
-		psHandleData->ui32Refs--;
+		_HandleUnref(psHandleData);
 	}
 
 	if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
@@ -1862,12 +2036,10 @@
 		PVR_DPF((PVR_DBG_MESSAGE, "FreeResourceByCriteria: Lock timeout (timeout: %llu)",
 								            psData->ui64MaxBridgeTime));
 		UnlockHandle();
-		PMRUnlock();
 		OSReleaseBridgeLock();
 		/* Invoke the scheduler to check if other processes are waiting for the lock */
 		OSReleaseThreadQuanta();
 		OSAcquireBridgeLock();
-		PMRLock();
 		LockHandle();
 		/* Set again lock timeout and reset the counter */
 		psData->ui64TimeStart = OSClockns64();
@@ -1884,14 +2056,15 @@
 	PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
 	PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
 	PVRSRV_HANDLE_TYPE_RGX_FREELIST,
-	PVRSRV_HANDLE_TYPE_RGX_RPM_CONTEXT_CLEANUP,
 	PVRSRV_HANDLE_TYPE_RGX_RPM_FREELIST,
+	PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_MEMORY_BLOCK,
 	PVRSRV_HANDLE_TYPE_RGX_POPULATION,
 	PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
 	PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
+	PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT,
@@ -1918,7 +2091,6 @@
 	PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
 	PVRSRV_HANDLE_TYPE_DC_DEVICE,
 	PVRSRV_HANDLE_TYPE_PVR_TL_SD,
-	PVRSRV_HANDLE_TYPE_DEV_NODE,
 	PVRSRV_HANDLE_TYPE_MM_PLAT_CLEANUP
 };
 
@@ -1951,26 +2123,9 @@
 	sHandleData.ui64TimeStart = OSClockns64();
 	sHandleData.ui64MaxBridgeTime = ui64MaxBridgeTime;
 
-	for (i = 0; i < ARRAY_SIZE(g_aeOrderedFreeList); i++)
-	{
-		sHandleData.eHandleFreeType = g_aeOrderedFreeList[i];
-
-		/* Make sure all handles have been freed before destroying the handle base */
-		eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
-							       &FreeHandleDataWrapper,
-							       (void *)&sHandleData);
-		if (eError != PVRSRV_OK)
-		{
-			goto ExitUnlock;
-		}
-	}
 
 #if defined(DEBUG)
-	/*
-	 * As we're freeing handles based on type, make sure all
-	 * handles have actually had their data freed to avoid
-	 * resources being leaked
-	 */
+
 	sCountData.psBase = psBase;
 
 	eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
@@ -1986,14 +2141,50 @@
 
 	if (sCountData.uiHandleDataCount != 0)
 	{
-		PVR_DPF((PVR_DBG_ERROR,
-			 "PVRSRVFreeHandleBase: Found %u handles that need freeing for handle base %p",
+		IMG_BOOL bList = sCountData.uiHandleDataCount < HANDLE_DEBUG_LISTING_MAX_NUM;
+
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: %u remaining handles in handle base 0x%p "
+			 "(PVRSRV_HANDLE_BASE_TYPE %u). %s",
+			 __func__,
 			 sCountData.uiHandleDataCount,
-			 psBase));
-		PVR_ASSERT(0);
+			 psBase,
+			 psBase->eType,
+			 bList ? "Check handle.h for a type reference":
+					 "Skipping details, too many items..."));
+
+		if (bList)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "-------- Listing Handles --------"));
+			eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
+										   &ListHandlesInBase,
+										   psBase);
+			PVR_DPF((PVR_DBG_WARNING, "-------- Done Listing    --------"));
+		}
 	}
+
 #endif /* defined(DEBUG) */
 
+	/*
+	 * As we're freeing handles based on type, make sure all
+	 * handles have actually had their data freed to avoid
+	 * resources being leaked
+	 */
+	for (i = 0; i < ARRAY_SIZE(g_aeOrderedFreeList); i++)
+	{
+		sHandleData.eHandleFreeType = g_aeOrderedFreeList[i];
+
+		/* Make sure all handles have been freed before destroying the handle base */
+		eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
+							       &FreeHandleDataWrapper,
+							       (void *)&sHandleData);
+		if (eError != PVRSRV_OK)
+		{
+			goto ExitUnlock;
+		}
+	}
+
+
 	if (psBase->psHashTab != NULL)
 	{
 		HASH_Delete(psBase->psHashTab);
@@ -2052,7 +2243,8 @@
 		goto ErrorHandleDeinit;
 	}
 
-	eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+	eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase,
+	                               PVRSRV_HANDLE_BASE_TYPE_GLOBAL);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
diff --git a/drivers/staging/imgtec/rogue/handle.h b/drivers/staging/imgtec/rogue/handle.h
index 5da9417..fd90d8a 100644
--- a/drivers/staging/imgtec/rogue/handle.h
+++ b/drivers/staging/imgtec/rogue/handle.h
@@ -67,11 +67,6 @@
  * For handles that have a definite lifetime, where the corresponding
  * resource is explicitly created and destroyed, eFlag should be zero.
  *
- * If the resource is not explicitly created and destroyed, eFlag should be
- * set to PVRSRV_HANDLE_ALLOC_FLAG_SHARED.  For a given process, the same
- * handle will be returned each time a handle for the resource is allocated
- * with the PVRSRV_HANDLE_ALLOC_FLAG_SHARED flag.
- *
  * If a particular resource may be referenced multiple times by a
  * given process, setting eFlag to PVRSRV_HANDLE_ALLOC_FLAG_MULTI
  * will allow multiple handles to be allocated for the resource.
@@ -128,7 +123,6 @@
 typedef enum
 {
 	PVRSRV_HANDLE_TYPE_NONE = 0,
-	PVRSRV_HANDLE_TYPE_DEV_NODE,
 	PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
 	PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
 	PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
@@ -143,11 +137,12 @@
 	PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
 	PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
 	PVRSRV_HANDLE_TYPE_RGX_FREELIST,
-	PVRSRV_HANDLE_TYPE_RGX_RPM_CONTEXT_CLEANUP,
+	PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_RPM_FREELIST,
 	PVRSRV_HANDLE_TYPE_RGX_MEMORY_BLOCK,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
+	PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
 	PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT,
@@ -168,45 +163,67 @@
 	PVRSRV_HANDLE_TYPE_PVR_TL_SD,
 	PVRSRV_HANDLE_TYPE_RI_HANDLE,
 	PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
-	PVRSRV_HANDLE_TYPE_MM_PLAT_CLEANUP
+	PVRSRV_HANDLE_TYPE_MM_PLAT_CLEANUP,
+	PVRSRV_HANDLE_TYPE_WORKEST_RETURN_DATA
 } PVRSRV_HANDLE_TYPE;
 
 typedef enum
 {
+	PVRSRV_HANDLE_BASE_TYPE_CONNECTION,
+	PVRSRV_HANDLE_BASE_TYPE_PROCESS,
+	PVRSRV_HANDLE_BASE_TYPE_GLOBAL
+} PVRSRV_HANDLE_BASE_TYPE;
+
+
+typedef enum
+{
 	/* No flags */
 	PVRSRV_HANDLE_ALLOC_FLAG_NONE = 		0,
-	/* Share a handle that already exists for a given data pointer */
-	PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 		0x01,
 	/* Muliple handles can point at the given data pointer */
-	PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 		0x02,
+	PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 		0x01,
 	/* Subhandles are allocated in a private handle space */
-	PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 		0x04
+	PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 		0x02
 } PVRSRV_HANDLE_ALLOC_FLAG;
 
 typedef struct _HANDLE_BASE_ PVRSRV_HANDLE_BASE;
 
+typedef struct _PROCESS_HANDLE_BASE_
+{
+	PVRSRV_HANDLE_BASE *psHandleBase;
+	ATOMIC_T iRefCount;
+
+} PROCESS_HANDLE_BASE;
+
 extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
 #define	KERNEL_HANDLE_BASE (gpsKernelHandleBase)
 
+#define HANDLE_DEBUG_LISTING_MAX_NUM 20
+
 typedef PVRSRV_ERROR (*PFN_HANDLE_RELEASE)(void *pvData);
 
 PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, void *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, PFN_HANDLE_RELEASE pfnReleaseData);
+PVRSRV_ERROR PVRSRVAllocHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, void *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, PFN_HANDLE_RELEASE pfnReleaseData);
 
 PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, void *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+PVRSRV_ERROR PVRSRVAllocSubHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, void *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
 
 PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, void *pvData, PVRSRV_HANDLE_TYPE eType);
+PVRSRV_ERROR PVRSRVFindHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, void *pvData, PVRSRV_HANDLE_TYPE eType);
 
-PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, void **ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, void **ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_BOOL bRef);
+PVRSRV_ERROR PVRSRVLookupHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, void **ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_BOOL bRef);
 
 PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, void **ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
 
 PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
 
 PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+PVRSRV_ERROR PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
 
 PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
 
-PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase,
+                                   PVRSRV_HANDLE_BASE_TYPE eType);
 
 PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase, IMG_UINT64 ui64MaxBridgeTime);
 
diff --git a/drivers/staging/imgtec/rogue/handle_idr.c b/drivers/staging/imgtec/rogue/handle_idr.c
index d18df75..a203ebd 100644
--- a/drivers/staging/imgtec/rogue/handle_idr.c
+++ b/drivers/staging/imgtec/rogue/handle_idr.c
@@ -389,12 +389,6 @@
 {
 	PVR_ASSERT(psBase);
 
-	if (psBase->ui32TotalHandCount != 0)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "%s: Handles still exist (%u found)", 
-			 __FUNCTION__, psBase->ui32TotalHandCount));
-	}
-
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
 	idr_remove_all(&psBase->sIdr);
 #endif
diff --git a/drivers/staging/imgtec/rogue/hash.c b/drivers/staging/imgtec/rogue/hash.c
index 9444bcf..b098dfe 100644
--- a/drivers/staging/imgtec/rogue/hash.c
+++ b/drivers/staging/imgtec/rogue/hash.c
@@ -187,6 +187,7 @@
 @Input          pBucket       The bucket
 @Input          ppBucketTable The hash table
 @Input          uSize         The size of the hash table
+@Return         PVRSRV_ERROR
 */ /**************************************************************************/
 static void
 _ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
@@ -211,6 +212,7 @@
 @Input          uOldSize     The size of the old hash table
 @Input          ppNewTable   The new hash table
 @Input          uNewSize     The size of the new hash table
+@Return         None
 */ /**************************************************************************/
 static void
 _Rehash (HASH_TABLE *pHash,
@@ -384,6 +386,12 @@
 			bDoCheck = IMG_FALSE;
 		}
 	}
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	else
+	{
+		bDoCheck = IMG_FALSE;
+	}
+#endif
 #endif
 	if (pHash != NULL)
     {
@@ -395,8 +403,20 @@
 		}
 		if(pHash->uCount != 0)
 		{
-			PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
-			PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+			IMG_UINT32 uiEntriesLeft = pHash->uCount;
+			IMG_UINT32 i;
+			PVR_DPF ((PVR_DBG_ERROR, "%s: Leak detected in hash table!", __func__));
+			PVR_DPF ((PVR_DBG_ERROR, "%s: Likely Cause: client drivers not freeing allocations before destroying devmemcontext", __func__));
+			PVR_DPF ((PVR_DBG_ERROR, "%s: Removing remaining %u hash entries.", __func__, uiEntriesLeft));
+
+			for (i = 0; i < uiEntriesLeft; i++)
+			{
+#if defined(__linux__) && defined(__KERNEL__)
+				OSFreeMemNoStats(pHash->ppBucketTable[i]);
+#else
+				OSFreeMem(pHash->ppBucketTable[i]);
+#endif
+			}
 		}
 #if defined(__linux__) && defined(__KERNEL__)
 		OSFreeMemNoStats(pHash->ppBucketTable);
@@ -642,7 +662,6 @@
     return PVRSRV_OK;
 }
 
-
 #ifdef HASH_TRACE
 /*************************************************************************/ /*!
 @Function       HASH_Dump
diff --git a/drivers/staging/imgtec/rogue/hostfunc.c b/drivers/staging/imgtec/rogue/hostfunc.c
index 00628f4..b0bf414 100644
--- a/drivers/staging/imgtec/rogue/hostfunc.c
+++ b/drivers/staging/imgtec/rogue/hostfunc.c
@@ -39,7 +39,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -49,11 +48,7 @@
 #include <linux/string.h>
 #include <asm/page.h>
 #include <linux/vmalloc.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
 #include <linux/mutex.h>
-#else
-#include <asm/semaphore.h>
-#endif
 #include <linux/hardirq.h>
 
 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
@@ -70,113 +65,6 @@
 #include "hostfunc.h"
 #include "dbgdriv.h"
 
-#if defined(PVRSRV_NEED_PVR_DPF) && !defined(SUPPORT_DRM)
-IMG_UINT32	gPVRDebugLevel = (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING |
-		DBGPRIV_CALLTRACE); /* Added call trace level to support PVR_LOGging of state in debug driver */
-
-#define PVR_STRING_TERMINATOR		'\0'
-#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
-
-/******************************************************************************/
-
-
-/*----------------------------------------------------------------------------
-<function>
-	FUNCTION   : PVRSRVDebugPrintf
-	PURPOSE    : To output a debug message to the user
-	PARAMETERS : In : uDebugLevel - The current debug level
-	             In : pszFile - The source file generating the message
-	             In : uLine - The line of the source file
-	             In : pszFormat - The message format string
-	             In : ... - Zero or more arguments for use by the format string
-	RETURNS    : None
-</function>
-------------------------------------------------------------------------------*/
-void PVRSRVDebugPrintf	(
-						IMG_UINT32	ui32DebugLevel,
-						const IMG_CHAR*	pszFileName,
-						IMG_UINT32	ui32Line,
-						const IMG_CHAR*	pszFormat,
-						...
-					)
-{
-	IMG_BOOL bTrace;
-	IMG_CHAR *pszLeafName;
-
-	pszLeafName = (char *)strrchr (pszFileName, '/');
-
-	if (pszLeafName)
-	{
-		pszFileName = pszLeafName;
-	}
-
-	bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
-
-	if (gPVRDebugLevel & ui32DebugLevel)
-	{
-		va_list vaArgs;
-		static char szBuffer[512];
-
-		va_start (vaArgs, pszFormat);
-
-		/* Add in the level of warning */
-		if (bTrace == IMG_FALSE)
-		{
-			switch(ui32DebugLevel)
-			{
-				case DBGPRIV_FATAL:
-				{
-					strcpy (szBuffer, "PVR_K:(Fatal): ");
-					break;
-				}
-				case DBGPRIV_ERROR:
-				{
-					strcpy (szBuffer, "PVR_K:(Error): ");
-					break;
-				}
-				case DBGPRIV_WARNING:
-				{
-					strcpy (szBuffer, "PVR_K:(Warning): ");
-					break;
-				}
-				case DBGPRIV_MESSAGE:
-				{
-					strcpy (szBuffer, "PVR_K:(Message): ");
-					break;
-				}
-				case DBGPRIV_VERBOSE:
-				{
-					strcpy (szBuffer, "PVR_K:(Verbose): ");
-					break;
-				}
-				default:
-				{
-					strcpy (szBuffer, "PVR_K:()");
-					break;
-				}
-			}
-		}
-		else
-		{
-			strcpy (szBuffer, "PVR_K: ");
-		}
-
-		vsprintf (&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
-
- 		/*
- 		 * Metrics and Traces don't need a location
- 		 */
- 		if (bTrace == IMG_FALSE)
-		{
-			sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName);
-		}
-
-		printk(KERN_INFO "%s\n", szBuffer);
-
-		va_end (vaArgs);
-	}
-}
-#endif	/* defined(PVRSRV_NEED_PVR_DPF) && !defined(SUPPORT_DRM) */
 
 /*!
 ******************************************************************************
diff --git a/drivers/staging/imgtec/rogue/htbinit.c b/drivers/staging/imgtec/rogue/htbinit.c
deleted file mode 100644
index 4764c2c..0000000
--- a/drivers/staging/imgtec/rogue/htbinit.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Host trace buffer initialisation routines
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include "img_defs.h"
-#include "pvr_debug.h"
-#include "srvinit.h"
-#include "srvinit_param.h"
-#include "htbuffer_types.h"
-#include "htbuffer_init.h"
-
-/* apphint map of name vs. enable flag */
-static SRV_INIT_PARAM_UINT32_LOOKUP asLogGroupTable[] = {
-#define X(a, b) { #b, HTB_LOG_GROUP_FLAG_NAME(b) },
-	HTB_LOG_SFGROUPLIST
-#undef X
-};
-/* apphint map of arg vs. OpMode */
-static SRV_INIT_PARAM_UINT32_LOOKUP asOpModeTable[] = {
-	{ "droplatest", HTB_OPMODE_DROPLATEST},
-	{ "dropoldest", HTB_OPMODE_DROPOLDEST},
-	/* HTB should never be started in HTB_OPMODE_BLOCK
-	 * as this can lead to deadlocks
-	 */
-};
-/* apphint map of arg vs. LogMode */
-static SRV_INIT_PARAM_UINT32_LOOKUP asLogModeTable[] = {
-	{ "all", HTB_LOGMODE_ALLPID},
-	{ "restricted", HTB_LOGMODE_RESTRICTEDPID}
-};
-
-
-/* setup apphint root and associated data from the apphint maps */
-/* Future improvements: AppHint parsing will need to be reworked to support more than 32 Log Groups */
-SrvInitParamInitUINT32BitField( EnableHTBLogGroup,     0,                       asLogGroupTable);
-SrvInitParamInitUINT32List(     HTBOperationMode,      HTB_OPMODE_DROPLATEST,   asOpModeTable);
-SrvInitParamInitUINT32List(     HTBLogMode,            HTB_LOGMODE_ALLPID,      asLogModeTable);
-SrvInitParamInitUINT32(         HTBufferSize,          0x1000 );
-
-/* Future improvements: */
-SrvInitParamInitBOOL(           EnableHTBPID,          0);
-SrvInitParamInitUINT32(         HTBLogLevel,           0);
-
-IMG_INTERNAL void
-_ParseHTBAppHints(SHARED_DEV_CONNECTION hServices)
-{
-	PVRSRV_ERROR eError;
-	void * pvParamState = NULL;
-	IMG_UINT32 ui32LogType;
-	IMG_BOOL bAnyLogGroupConfigured;
-	HTB_LOGMODE_CTRL eLogMode;
-
-	IMG_CHAR * szBufferName = "PVRHTBuffer";
-	IMG_UINT32 ui32BufferSize;
-	HTB_OPMODE_CTRL eOpMode;
-
-	/* Services initialisation parameters */
-	pvParamState = SrvInitParamOpen();
-
-	bAnyLogGroupConfigured = SrvInitParamGetUINT32BitField(pvParamState, EnableHTBLogGroup, ui32LogType);
-	SrvInitParamGetUINT32List(pvParamState, HTBOperationMode, eOpMode);
-	SrvInitParamGetUINT32(pvParamState, HTBufferSize, ui32BufferSize);
-	SrvInitParamGetUINT32List(pvParamState, HTBLogMode, eLogMode);
-
-	/* future improvements:
-	 * PID should be enabled against a process name
-	 * LogLevel requires SF change
-	 */
-	{
-	IMG_BOOL bEnablePID;
-	IMG_UINT32 ui32LogLevel;
-	SrvInitParamGetBOOL(pvParamState, EnableHTBPID, bEnablePID);
-	SrvInitParamGetUINT32(pvParamState, HTBLogLevel, ui32LogLevel);
-	}
-
-	eError = HTBConfigure(hServices, szBufferName, ui32BufferSize);
-	PVR_LOGG_IF_ERROR(eError, "PVRSRVHTBConfigure", cleanup);
-
-	if (bAnyLogGroupConfigured)
-	{
-		eError = HTBControl(hServices, 1, &ui32LogType, 0, 0, eLogMode, eOpMode);
-		PVR_LOGG_IF_ERROR(eError, "PVRSRVHTBControl", cleanup);
-	}
-
-cleanup:
-	SrvInitParamClose(pvParamState);
-}
-
-/******************************************************************************
- End of file (htbinit.c)
-*****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/htbserver.c b/drivers/staging/imgtec/rogue/htbserver.c
index 2eff4ab..a4cc3c4 100644
--- a/drivers/staging/imgtec/rogue/htbserver.c
+++ b/drivers/staging/imgtec/rogue/htbserver.c
@@ -47,12 +47,16 @@
 
 #include "htbserver.h"
 #include "htbuffer.h"
+#include "htbuffer_types.h"
 #include "tlstream.h"
-#include "pvr_tlcommon.h"
+#include "pvrsrv_tlcommon.h"
 #include "img_types.h"
 #include "pvrsrv_error.h"
 #include "osfunc.h"
 #include "allocmem.h"
+#include "pvr_notifier.h"
+#include "pvrsrv.h"
+#include "pvrsrv_apphint.h"
 
 /* size of circular buffer controlling the maximum number of concurrent PIDs logged */
 #define HTB_MAX_NUM_PID 8
@@ -147,8 +151,102 @@
 
 
 /************************************************************************/ /*!
+ @Function      _HTBLogDebugInfo
+ @Description   Debug dump handler used to dump the state of the HTB module.
+                Called for each verbosity level during a debug dump. Function
+                only prints state when called for High verbosity.
+
+ @Input         hDebugRequestHandle See PFN_DBGREQ_NOTIFY
+
+ @Input         ui32VerbLevel       See PFN_DBGREQ_NOTIFY
+
+ @Input         pfnDumpDebugPrintf  See PFN_DBGREQ_NOTIFY
+
+ @Input         pvDumpDebugFile     See PFN_DBGREQ_NOTIFY
+
+*/ /**************************************************************************/
+static void _HTBLogDebugInfo(
+		PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
+		IMG_UINT32 ui32VerbLevel,
+		DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+		void *pvDumpDebugFile
+)
+{
+	PVR_UNREFERENCED_PARAMETER(hDebugRequestHandle);
+
+	if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
+	{
+
+		if (g_bConfigured)
+		{
+			IMG_INT i;
+
+			PVR_DUMPDEBUG_LOG("------[ HTB Log state: On ]------");
+
+			PVR_DUMPDEBUG_LOG("HTB Log mode: %d", g_sCtrl.eLogMode);
+			PVR_DUMPDEBUG_LOG("HTB Log level: %d", g_sCtrl.ui32LogLevel);
+			PVR_DUMPDEBUG_LOG("HTB Buffer Opmode: %d", g_sCtrl.eOpMode);
+
+			for (i=0; i < HTB_FLAG_NUM_EL; i++)
+			{
+				PVR_DUMPDEBUG_LOG("HTB Log group %d: %x", i, g_auiHTBGroupEnable[i]);
+			}
+		}
+		else
+		{
+			PVR_DUMPDEBUG_LOG("------[ HTB Log state: Off ]------");
+		}
+	}
+}
+
+/************************************************************************/ /*!
+ @Function      HTBDeviceCreate
+ @Description   Initialisation actions for HTB at device creation.
+
+ @Input         psDeviceNode    Reference to the device node in context
+
+ @Return        eError          Internal services call returned eError error
+                                number
+*/ /**************************************************************************/
+PVRSRV_ERROR
+HTBDeviceCreate(
+		PVRSRV_DEVICE_NODE *psDeviceNode
+)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	eError = PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hHtbDbgReqNotify,
+			psDeviceNode, &_HTBLogDebugInfo, DEBUG_REQUEST_HTB, NULL);
+	PVR_LOG_IF_ERROR(eError, "PVRSRVRegisterDbgRequestNotify");
+
+	return eError;
+}
+
+/************************************************************************/ /*!
+ @Function      HTBIDeviceDestroy
+ @Description   De-initialisation actions for HTB at device destruction.
+
+ @Input         psDeviceNode    Reference to the device node in context
+
+*/ /**************************************************************************/
+void
+HTBDeviceDestroy(
+		PVRSRV_DEVICE_NODE *psDeviceNode
+)
+{
+	if (psDeviceNode->hHtbDbgReqNotify)
+	{
+		/* No much we can do if it fails, driver unloading */
+		(void)PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hHtbDbgReqNotify);
+		psDeviceNode->hHtbDbgReqNotify = NULL;
+	}
+}
+
+
+/************************************************************************/ /*!
  @Function      HTBDeInit
- @Description   Close the Host Trace Buffer and free all resources
+ @Description   Close the Host Trace Buffer and free all resources. Must
+                perform a no-op if already de-initialised.
 
  @Return        eError          Internal services call returned eError error
                                 number
@@ -173,6 +271,56 @@
 
 
 /*************************************************************************/ /*!
+ AppHint interface functions
+*/ /**************************************************************************/
+static
+PVRSRV_ERROR _HTBSetLogGroup(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                             const void *psPrivate,
+                             IMG_UINT32 ui32Value)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	return HTBControlKM(1, &ui32Value, 0, 0,
+	                    HTB_LOGMODE_UNDEF, HTB_OPMODE_UNDEF);
+}
+
+static
+PVRSRV_ERROR _HTBReadLogGroup(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const void *psPrivate,
+                              IMG_UINT32 *pui32Value)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	*pui32Value = g_auiHTBGroupEnable[0];
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR _HTBSetOpMode(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                           const void *psPrivate,
+                           IMG_UINT32 ui32Value)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	return HTBControlKM(0, NULL, 0, 0, HTB_LOGMODE_UNDEF, ui32Value);
+}
+
+static
+PVRSRV_ERROR _HTBReadOpMode(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                            const void *psPrivate,
+                            IMG_UINT32 *pui32Value)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	*pui32Value = (IMG_UINT32)g_sCtrl.eOpMode;
+	return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
  @Function      HTBConfigureKM
  @Description   Configure or update the configuration of the Host Trace Buffer
 
@@ -207,6 +355,17 @@
 		g_sCtrl.ui32PIDHead = 0;
 		g_sCtrl.eLogMode = HTB_LOGMODE_ALLPID;
 		g_sCtrl.bLogDropSignalled = IMG_FALSE;
+
+		PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableHTBLogGroup,
+		                                    _HTBReadLogGroup,
+		                                    _HTBSetLogGroup,
+		                                    NULL,
+		                                    NULL);
+		PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_HTBOperationMode,
+		                                    _HTBReadOpMode,
+		                                    _HTBSetOpMode,
+		                                    NULL,
+		                                    NULL);
 	}
 	else
 	{
@@ -309,7 +468,7 @@
 	/* HTB_LOGMODE_ALLPID overrides ui32EnablePID */
 	if ( HTB_LOGMODE_ALLPID == eLogMode )
 	{
-		OSMemSet(g_sCtrl.aui32EnablePID, 0, sizeof(g_sCtrl.aui32EnablePID));
+		OSCachedMemSet(g_sCtrl.aui32EnablePID, 0, sizeof(g_sCtrl.aui32EnablePID));
 		g_sCtrl.ui32PIDCount = 0;
 		g_sCtrl.ui32PIDHead = 0;
 	}
@@ -365,7 +524,6 @@
 	return eError;
 }
 
-
 /*************************************************************************/ /*!
 */ /**************************************************************************/
 static IMG_BOOL
diff --git a/drivers/staging/imgtec/rogue/htbserver.h b/drivers/staging/imgtec/rogue/htbserver.h
index 1411f4f..670e83a 100644
--- a/drivers/staging/imgtec/rogue/htbserver.h
+++ b/drivers/staging/imgtec/rogue/htbserver.h
@@ -71,10 +71,39 @@
 
 #include "img_types.h"
 #include "pvrsrv_error.h"
+#include "pvrsrv.h"
 #include "htbuffer.h"
 
 
 /************************************************************************/ /*!
+ @Function      HTBIDeviceCreate
+ @Description   Initialisation actions for HTB at device creation.
+
+ @Input         psDeviceNode    Reference to the device node in context
+
+ @Return        eError          Internal services call returned eError error
+                                number
+*/ /**************************************************************************/
+PVRSRV_ERROR
+HTBDeviceCreate(
+		PVRSRV_DEVICE_NODE *psDeviceNode
+);
+
+
+/************************************************************************/ /*!
+ @Function      HTBIDeviceDestroy
+ @Description   De-initialisation actions for HTB at device destruction.
+
+ @Input         psDeviceNode    Reference to the device node in context
+
+*/ /**************************************************************************/
+void
+HTBDeviceDestroy(
+		PVRSRV_DEVICE_NODE *psDeviceNode
+);
+
+
+/************************************************************************/ /*!
  @Function      HTBDeInit
  @Description   Close the Host Trace Buffer and free all resources
 
diff --git a/drivers/staging/imgtec/rogue/htbuffer.c b/drivers/staging/imgtec/rogue/htbuffer.c
index dfe078d..b2f2006 100644
--- a/drivers/staging/imgtec/rogue/htbuffer.c
+++ b/drivers/staging/imgtec/rogue/htbuffer.c
@@ -140,15 +140,11 @@
 static PVRSRV_ERROR
 _HTBLog(IMG_HANDLE hSrvHandle, IMG_UINT32 PID, IMG_UINT32 ui32TimeStampus, HTB_LOG_SFids SF, va_list args)
 {
+#if defined(__KERNEL__)
 	IMG_UINT32 i;
 	IMG_UINT32 ui32NumArgs = HTB_SF_PARAMNUM(SF);
 	IMG_UINT32 aui32Args[HTB_LOG_MAX_PARAMS];
 
-#if !defined(__KERNEL__)
-	PVR_ASSERT(0=="HTB Logging in UM is not yet supported");
-	return PVRSRV_ERROR_NOT_SUPPORTED;
-#endif
-
 	PVR_ASSERT(ui32NumArgs <= HTB_LOG_MAX_PARAMS);
 	ui32NumArgs = (ui32NumArgs>HTB_LOG_MAX_PARAMS)? HTB_LOG_MAX_PARAMS: ui32NumArgs;
 
@@ -159,6 +155,16 @@
 	}
 
 	return BridgeHTBLog(hSrvHandle, PID, ui32TimeStampus, SF, ui32NumArgs, aui32Args);
+#else
+	PVR_UNREFERENCED_PARAMETER(hSrvHandle);
+	PVR_UNREFERENCED_PARAMETER(PID);
+	PVR_UNREFERENCED_PARAMETER(ui32TimeStampus);
+	PVR_UNREFERENCED_PARAMETER(SF);
+	PVR_UNREFERENCED_PARAMETER(args);
+
+	PVR_ASSERT(0=="HTB Logging in UM is not yet supported");
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
 }
 
 
@@ -182,7 +188,7 @@
 
 */ /**************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR
-HTBLog(IMG_HANDLE hSrvHandle, IMG_UINT32 PID, IMG_UINT32 ui32TimeStampus, HTB_LOG_SFids SF, ...)
+HTBLog(IMG_HANDLE hSrvHandle, IMG_UINT32 PID, IMG_UINT32 ui32TimeStampus, IMG_UINT32 SF, ...)
 {
 	PVRSRV_ERROR eError;
 	va_list args;
@@ -205,7 +211,7 @@
 
 */ /**************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR
-HTBLogSimple(IMG_HANDLE hSrvHandle, HTB_LOG_SFids SF, ...)
+HTBLogSimple(IMG_HANDLE hSrvHandle, IMG_UINT32 SF, ...)
 {
 	PVRSRV_ERROR eError;
 	va_list args;
diff --git a/drivers/staging/imgtec/rogue/htbuffer.h b/drivers/staging/imgtec/rogue/htbuffer.h
index f95c1dd..888a041 100644
--- a/drivers/staging/imgtec/rogue/htbuffer.h
+++ b/drivers/staging/imgtec/rogue/htbuffer.h
@@ -91,7 +91,7 @@
 
 */ /**************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR
-HTBLog(IMG_HANDLE hSrvHandle, IMG_UINT32 PID, IMG_UINT32 ui32TimeStampus, HTB_LOG_SFids SF, ...);
+HTBLog(IMG_HANDLE hSrvHandle, IMG_UINT32 PID, IMG_UINT32 ui32TimeStampus, IMG_UINT32 SF, ...);
 
 
 /*************************************************************************/ /*!
@@ -106,7 +106,7 @@
 
 */ /**************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR
-HTBLogSimple(IMG_HANDLE hSrvHandle, HTB_LOG_SFids SF, ...);
+HTBLogSimple(IMG_HANDLE hSrvHandle, IMG_UINT32 SF, ...);
 
 
 
diff --git a/drivers/staging/imgtec/rogue/htbuffer_sf.h b/drivers/staging/imgtec/rogue/htbuffer_sf.h
index 8c1935e..517c384 100644
--- a/drivers/staging/imgtec/rogue/htbuffer_sf.h
+++ b/drivers/staging/imgtec/rogue/htbuffer_sf.h
@@ -60,10 +60,10 @@
 
 
 /* String used in pvrdebug -h output */
-#define HTB_LOG_GROUPS_STRING_LIST   "ctrl,mmu,sync,main"
+#define HTB_LOG_GROUPS_STRING_LIST   "ctrl,mmu,sync,main,brg"
 
 /* Used in print statements to display log group state, one %s per group defined */
-#define HTB_LOG_ENABLED_GROUPS_LIST_PFSPEC  "%s%s%s%s"
+#define HTB_LOG_ENABLED_GROUPS_LIST_PFSPEC  "%s%s%s%s%s"
 
 /* Available log groups - Master template
  *
@@ -82,6 +82,7 @@
 	X( HTB_GROUP_MMU,      MMU   )                        \
 	X( HTB_GROUP_SYNC,     SYNC  )                        \
 	X( HTB_GROUP_MAIN,     MAIN  )                        \
+	X( HTB_GROUP_BRG,      BRG  )                         \
 /* Debug group HTB_GROUP_DBG must always be last */       \
 	X( HTB_GROUP_DBG,      DBG   )
 
@@ -133,6 +134,9 @@
 X( 7,  HTB_GROUP_MAIN,  HTB_SF_MAIN_KICK_UNCOUNTED,     "Kick (uncounted) for all DMs\n", 0) \
 X( 8,  HTB_GROUP_MAIN,  HTB_SF_MAIN_FWCCB_CMD,          "FW CCB Cmd: %d\n", 1) \
 \
+X( 1,  HTB_GROUP_BRG,   HTB_SF_BRG_BRIDGE_CALL,         "Bridge call: start: %010u: bid %03d fid %d\n", 3) \
+X( 2,  HTB_GROUP_BRG,   HTB_SF_BRG_BRIDGE_CALL_ERR,     "Bridge call: start: %010u: bid %03d fid %d error %d\n", 4) \
+\
 X( 1,  HTB_GROUP_DBG,   HTB_SF_DBG_INTPAIR,             "0x%8.8x 0x%8.8x\n", 2) \
 \
 X( 65535, HTB_GROUP_NONE, HTB_SF_LAST,                  "You should not use this string\n", 15)
diff --git a/drivers/staging/imgtec/rogue/htbuffer_types.h b/drivers/staging/imgtec/rogue/htbuffer_types.h
index 92a824e..c4f19b3 100644
--- a/drivers/staging/imgtec/rogue/htbuffer_types.h
+++ b/drivers/staging/imgtec/rogue/htbuffer_types.h
@@ -60,35 +60,6 @@
 
 #define HTB_GROUP_ENABLED(SF) (g_auiHTBGroupEnable[HTB_LOG_GROUP_FLAG_GROUP(HTB_SF_GID(SF))] & HTB_LOG_GROUP_FLAG(HTB_SF_GID(SF)))
 
-
-
-/**************************************************************************
-from log_helper.h for later
- **************************************************************************/
-#if 0
-#include "htbuffer_sf.h"
-
-static IMG_CHAR *groups[]= {
-#define X(A,B) #B,
-	HTB_LOG_SFGROUPLIST
-#undef X
-};
-
-typedef struct {
-	IMG_UINT32 id;
-	IMG_CHAR *name;
-} tuple; /*  pair of string format id and string formats */
-
-/*  The tuple pairs that will be generated using XMacros will be stored here.
- *   This macro definition must match the definition of SFids in htb_sf.h */
-tuple SFs[]= {
-#define X(a, b, c, d, e) { HTB_LOG_CREATESFID(a,b,e) , d },
-	HTB_LOG_SFIDLIST
-#undef X
-};
-#endif
-
-
 /*************************************************************************/ /*!
  Host Trace Buffer operation mode
  Care must be taken if changing this enum to ensure the MapFlags[] array
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_10.V.2.26.h
similarity index 69%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_10.V.2.26.h
index 0462d6f..89c2e94 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_10.V.2.26.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 10.V.2.26
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,60 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_10_V_2_26_H_
+#define _RGXCONFIG_KM_10_V_2_26_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (11/04/2017 07:00:42): Do not edit manually ********************/
+/***** Timestamp:  (11/04/2017 07:00:42)************************************************************/
 
-#define RGX_BNC_KM_B 4
+#define RGX_BNC_KM_B 10
 #define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_C 26
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
-#define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
-#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
-#define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
+#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
 #define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
+#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
+#define RGX_FEATURE_SCALABLE_VDM_GPP 
+#define RGX_FEATURE_VDM_DRAWINDIRECT 
+#define RGX_FEATURE_SLC_VIVT 
+#define RGX_FEATURE_VDM_OBJECT_LEVEL_LLS 
+#define RGX_FEATURE_PDS_PER_DUST 
+#define RGX_FEATURE_META (MTP219)
+#define RGX_FEATURE_COMPUTE_OVERLAP_WITH_BARRIERS 
+#define RGX_FEATURE_TESSELLATION 
+#define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS 
+#define RGX_FEATURE_PDS_TEMPSIZE8 
+#define RGX_FEATURE_META_DMA 
+#define RGX_FEATURE_META_DMA_CHANNEL_COUNT (4)
+#define RGX_FEATURE_META_COREMEM_BANKS (8)
+#define RGX_FEATURE_META_COREMEM_SIZE (256)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (3)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_GPU_VIRTUALISATION 
+#define RGX_FEATURE_SLC_HYBRID_CACHELINE_64_128 
+#define RGX_FEATURE_FASTRENDER_DM 
+#define RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT (2)
+#define RGX_FEATURE_SIGNAL_SNOOPING 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
+#define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128)
+#define RGX_FEATURE_SLC_BANKS (2)
+#define RGX_FEATURE_SCALABLE_TE_ARCH (1)
+#define RGX_FEATURE_SCALABLE_VCE (1)
+#define RGX_FEATURE_S7_CACHE_HIERARCHY 
+#define RGX_FEATURE_S7_TOP_INFRASTRUCTURE 
+#define RGX_FEATURE_CLUSTER_GROUPING 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_10_V_2_26_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_10.V.4.25.h
similarity index 68%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_10.V.4.25.h
index 0462d6f..dd86af6 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_10.V.4.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 10.V.4.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,60 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_10_V_4_25_H_
+#define _RGXCONFIG_KM_10_V_4_25_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (11/04/2017 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (11/04/2017 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 10
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 25
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
-#define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
-#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
-#define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
+#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
 #define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
+#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
+#define RGX_FEATURE_SCALABLE_VDM_GPP 
+#define RGX_FEATURE_VDM_DRAWINDIRECT 
+#define RGX_FEATURE_SLC_VIVT 
+#define RGX_FEATURE_VDM_OBJECT_LEVEL_LLS 
+#define RGX_FEATURE_PDS_PER_DUST 
+#define RGX_FEATURE_META (MTP219)
+#define RGX_FEATURE_COMPUTE_OVERLAP_WITH_BARRIERS 
+#define RGX_FEATURE_TESSELLATION 
+#define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS 
+#define RGX_FEATURE_PDS_TEMPSIZE8 
+#define RGX_FEATURE_META_DMA 
+#define RGX_FEATURE_META_DMA_CHANNEL_COUNT (4)
+#define RGX_FEATURE_META_COREMEM_BANKS (8)
+#define RGX_FEATURE_META_COREMEM_SIZE (256)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (3)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_GPU_VIRTUALISATION 
+#define RGX_FEATURE_SLC_HYBRID_CACHELINE_64_128 
+#define RGX_FEATURE_FASTRENDER_DM 
+#define RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT (2)
+#define RGX_FEATURE_SIGNAL_SNOOPING 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
+#define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (512)
+#define RGX_FEATURE_SLC_BANKS (4)
+#define RGX_FEATURE_SCALABLE_TE_ARCH (1)
+#define RGX_FEATURE_SCALABLE_VCE (1)
+#define RGX_FEATURE_S7_CACHE_HIERARCHY 
+#define RGX_FEATURE_S7_TOP_INFRASTRUCTURE 
+#define RGX_FEATURE_CLUSTER_GROUPING 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_10_V_4_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h
index 1e18cab..5566126 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCONFIG_KM_12_V_1_20_H_
 #define _RGXCONFIG_KM_12_V_1_20_H_
 
-/***** Automatically generated file (5/12/2015 8:14:27 AM): Do not edit manually ********************/
-/***** Timestamp:  (5/12/2015 8:14:27 AM)************************************************************/
+/***** Automatically generated file (24/08/2016 07:01:08): Do not edit manually ********************/
+/***** Timestamp:  (24/08/2016 07:01:08)************************************************************/
 
 #define RGX_BNC_KM_B 12
 #define RGX_BNC_KM_N 1
@@ -62,6 +62,7 @@
 #define RGX_FEATURE_SLC_SIZE_IN_BYTES (0*1024)
 #define RGX_FEATURE_META_COREMEM_SIZE (0)
 #define RGX_FEATURE_COMPUTE 
+#define RGX_FEATURE_ROGUEXE 
 
 
 #endif /* _RGXCONFIG_12_V_1_20_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.48.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.48.h
index 3853bff..375f8f6 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.48.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.48.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCONFIG_KM_12_V_1_48_H_
 #define _RGXCONFIG_KM_12_V_1_48_H_
 
-/***** Automatically generated file (5/12/2015 8:14:26 AM): Do not edit manually ********************/
-/***** Timestamp:  (5/12/2015 8:14:26 AM)************************************************************/
+/***** Automatically generated file (24/08/2016 07:01:08): Do not edit manually ********************/
+/***** Timestamp:  (24/08/2016 07:01:08)************************************************************/
 
 #define RGX_BNC_KM_B 12
 #define RGX_BNC_KM_N 1
@@ -63,6 +63,7 @@
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1)
 #define RGX_FEATURE_META_COREMEM_SIZE (0)
 #define RGX_FEATURE_COMPUTE 
+#define RGX_FEATURE_ROGUEXE 
 
 
 #endif /* _RGXCONFIG_12_V_1_48_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_15.V.1.64.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_15.V.1.64.h
index 5685f72..2846583 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_15.V.1.64.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_15.V.1.64.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCONFIG_KM_15_V_1_64_H_
 #define _RGXCONFIG_KM_15_V_1_64_H_
 
-/***** Automatically generated file (23/07/2015 12:44:38): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 12:44:38)************************************************************/
+/***** Automatically generated file (24/08/2016 07:01:09): Do not edit manually ********************/
+/***** Timestamp:  (24/08/2016 07:01:09)************************************************************/
 
 #define RGX_BNC_KM_B 15
 #define RGX_BNC_KM_N 1
@@ -68,6 +68,7 @@
 #define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_META_COREMEM_SIZE (0)
 #define RGX_FEATURE_COMPUTE 
+#define RGX_FEATURE_ROGUEXE 
 
 
 #endif /* _RGXCONFIG_15_V_1_64_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.208.312.h
similarity index 74%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.208.312.h
index 0462d6f..6ca1c46 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.208.312.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.208.312
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_208_312_H_
+#define _RGXCONFIG_KM_22_V_208_312_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:44): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:44)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 208
+#define RGX_BNC_KM_C 312
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
 #define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (4)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_208_312_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.208.316.h
similarity index 74%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.208.316.h
index 0462d6f..2150e11 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.208.316.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.208.316
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_208_316_H_
+#define _RGXCONFIG_KM_22_V_208_316_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (17/01/2017 07:00:49): Do not edit manually ********************/
+/***** Timestamp:  (17/01/2017 07:00:49)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 208
+#define RGX_BNC_KM_C 316
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
 #define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (12)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_208_316_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.21.11.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.21.11.h
index 0462d6f..b8ad5c3c 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.21.11.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.21.11
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_21_11_H_
+#define _RGXCONFIG_KM_22_V_21_11_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (14/11/2016 07:00:35): Do not edit manually ********************/
+/***** Timestamp:  (14/11/2016 07:00:35)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 21
+#define RGX_BNC_KM_C 11
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_SLCSIZE8 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_21_11_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.21.16.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.21.16.h
index 0462d6f..5292f59 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.21.16.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.21.16
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_21_16_H_
+#define _RGXCONFIG_KM_22_V_21_16_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (08/02/2017 07:00:50): Do not edit manually ********************/
+/***** Timestamp:  (08/02/2017 07:00:50)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 21
+#define RGX_BNC_KM_C 16
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (2)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_SLCSIZE8 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_21_16_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.22.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.22.h
index 0462d6f..655b096 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.22.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.22.22
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,36 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_22_22_H_
+#define _RGXCONFIG_KM_22_V_22_22_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 22
+#define RGX_BNC_KM_C 22
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_22_22_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.23.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.23.h
index 0462d6f..da162f6 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.23.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.22.23
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_22_23_H_
+#define _RGXCONFIG_KM_22_V_22_23_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 22
+#define RGX_BNC_KM_C 23
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_22_23_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.25.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.25.h
index 0462d6f..7355335 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.22.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_22_25_H_
+#define _RGXCONFIG_KM_22_V_22_25_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (08/02/2017 07:00:50): Do not edit manually ********************/
+/***** Timestamp:  (08/02/2017 07:00:50)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 22
+#define RGX_BNC_KM_C 25
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (2)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_22_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.27.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.27.h
index 0462d6f..f639123 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.27.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.22.27
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_22_27_H_
+#define _RGXCONFIG_KM_22_V_22_27_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 22
+#define RGX_BNC_KM_C 27
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_22_27_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.29.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.29.h
index 0462d6f..0462945 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.22.29.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.22.29
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_22_29_H_
+#define _RGXCONFIG_KM_22_V_22_29_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (08/02/2017 07:00:49): Do not edit manually ********************/
+/***** Timestamp:  (08/02/2017 07:00:49)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 22
+#define RGX_BNC_KM_C 29
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (2)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_22_29_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.24.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.24.h
index 0462d6f..75a238f 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.24.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.54.24
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,36 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_54_24_H_
+#define _RGXCONFIG_KM_22_V_54_24_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 54
+#define RGX_BNC_KM_C 24
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_54_24_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.25.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.25.h
index 0462d6f..2eeea71 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.54.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_54_25_H_
+#define _RGXCONFIG_KM_22_V_54_25_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 54
+#define RGX_BNC_KM_C 25
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_54_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.30.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.30.h
index 0462d6f..fc506af 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,37 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_54_30_H_
+#define _RGXCONFIG_KM_22_V_54_30_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 54
+#define RGX_BNC_KM_C 30
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (4)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.328.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.328.h
index 0462d6f..84540cd 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.328.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.54.328
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,38 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_54_328_H_
+#define _RGXCONFIG_KM_22_V_54_328_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 54
+#define RGX_BNC_KM_C 328
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (4)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_54_328_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.330.h
similarity index 73%
copy from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.330.h
index 0462d6f..47615d9 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_22.V.54.330.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 22.V.54.330
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,41 +39,38 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_22_V_54_330_H_
+#define _RGXCONFIG_KM_22_V_54_330_H_
 
-/***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
-/***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
+/***** Automatically generated file (26/08/2016 07:00:43): Do not edit manually ********************/
+/***** Timestamp:  (26/08/2016 07:00:43)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 22
+#define RGX_BNC_KM_N 54
+#define RGX_BNC_KM_C 330
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
-#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
-#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (32)
 #define RGX_FEATURE_PERFBUS 
 #define RGX_FEATURE_AXI_ACELITE 
-#define RGX_FEATURE_CLUSTER_GROUPING 
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
-#define RGX_FEATURE_DYNAMIC_DUST_POWER 
+#define RGX_FEATURE_NUM_CLUSTERS (1)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
-#define RGX_FEATURE_TLA 
+#define RGX_FEATURE_SLC_BANKS (1)
 #define RGX_FEATURE_GS_RTA_SUPPORT 
-#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
-#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
-#define RGX_FEATURE_META (LTP218)
-#define RGX_FEATURE_TPU_FILTERING_MODE_CONTROL 
-#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
-#define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
-#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (4)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (1)
 #define RGX_FEATURE_GPU_VIRTUALISATION 
-#define RGX_FEATURE_META_COREMEM_SIZE (32)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (64*1024)
 #define RGX_FEATURE_COMPUTE 
-#define RGX_FEATURE_COMPUTE_OVERLAP 
+#define RGX_FEATURE_SINGLE_BIF 
+#define RGX_FEATURE_PBE2_IN_XE 
+#define RGX_FEATURE_MIPS 
+#define RGX_FEATURE_PBVNC_COREID_REG 
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET 
+#define RGX_FEATURE_ROGUEXE 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_22_V_54_330_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h
index 2added3..c633fda 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCONFIG_KM_5_V_1_46_H_
 #define _RGXCONFIG_KM_5_V_1_46_H_
 
-/***** Automatically generated file (23/07/2015 12:44:37): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 12:44:37)************************************************************/
+/***** Automatically generated file (24/08/2016 07:01:08): Do not edit manually ********************/
+/***** Timestamp:  (24/08/2016 07:01:08)************************************************************/
 
 #define RGX_BNC_KM_B 5
 #define RGX_BNC_KM_N 1
@@ -67,6 +67,7 @@
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1)
 #define RGX_FEATURE_META_COREMEM_SIZE (0)
 #define RGX_FEATURE_COMPUTE 
+#define RGX_FEATURE_ROGUEXE 
 
 
 #endif /* _RGXCONFIG_5_V_1_46_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_6.V.4.35.h
similarity index 91%
rename from drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
rename to drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_6.V.4.35.h
index 0462d6f..0a7925d 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/configs/rgxconfig_km_6.V.4.35.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Config BVNC 4.V.2.52
+@Title          RGX Config BVNC 6.V.4.35
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,20 +39,20 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCONFIG_KM_4_V_2_52_H_
-#define _RGXCONFIG_KM_4_V_2_52_H_
+#ifndef _RGXCONFIG_KM_6_V_4_35_H_
+#define _RGXCONFIG_KM_6_V_4_35_H_
 
 /***** Automatically generated file (22/02/2016 07:00:34): Do not edit manually ********************/
 /***** Timestamp:  (22/02/2016 07:00:34)************************************************************/
 
-#define RGX_BNC_KM_B 4
-#define RGX_BNC_KM_N 2
-#define RGX_BNC_KM_C 52
+#define RGX_BNC_KM_B 6
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 35
 
 /******************************************************************************
  * DDK Defines
  *****************************************************************************/
-#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_NUM_CLUSTERS (4)
 #define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
 #define RGX_FEATURE_PHYS_BUS_WIDTH (40)
 #define RGX_FEATURE_PERFBUS 
@@ -61,6 +61,7 @@
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
 #define RGX_FEATURE_DYNAMIC_DUST_POWER 
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_RAY_TRACING 
 #define RGX_FEATURE_TLA 
 #define RGX_FEATURE_GS_RTA_SUPPORT 
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS 
@@ -70,10 +71,9 @@
 #define RGX_FEATURE_XT_TOP_INFRASTRUCTURE 
 #define RGX_FEATURE_COMPUTE_MORTON_CAPABLE 
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
-#define RGX_FEATURE_GPU_VIRTUALISATION 
 #define RGX_FEATURE_META_COREMEM_SIZE (32)
 #define RGX_FEATURE_COMPUTE 
 #define RGX_FEATURE_COMPUTE_OVERLAP 
 
 
-#endif /* _RGXCONFIG_4_V_2_52_H_ */
+#endif /* _RGXCONFIG_6_V_4_35_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h
index f94f194..8b40dd0 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_33_2_5_H_
 #define _RGXCORE_KM_1_33_2_5_H_
 
-/***** Automatically generated file (26/08/2015 09:15:02): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:02)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2106753 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h
index 7678e0a..e718bee 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_39_4_19_H_
 #define _RGXCORE_KM_1_39_4_19_H_
 
-/***** Automatically generated file (26/08/2015 09:15:02): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:02)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2784771 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h
index 7df2b7b..a88ec7a 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_48_2_0_H_
 #define _RGXCORE_KM_1_48_2_0_H_
 
-/***** Automatically generated file (26/08/2015 09:15:02): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:02)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2523218 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h
index 550b8e0..3bc0581 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_72_4_12_H_
 #define _RGXCORE_KM_1_72_4_12_H_
 
-/***** Automatically generated file (23/07/2015 09:37:59): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 09:37:59)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2646650 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h
index 9dc9f31..5835ad0 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_75_2_20_H_
 #define _RGXCORE_KM_1_75_2_20_H_
 
-/***** Automatically generated file (26/08/2015 09:15:07): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:07)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2309075 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h
index 0a3f0ae..17369b9 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_75_2_30_H_
 #define _RGXCORE_KM_1_75_2_30_H_
 
-/***** Automatically generated file (26/08/2015 09:15:07): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:07)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2309075 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h
index c7e04ed..b1127c8 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_76_4_6_H_
 #define _RGXCORE_KM_1_76_4_6_H_
 
-/***** Automatically generated file (23/07/2015 09:37:59): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 09:37:59)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2318404 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h
index 923c480..d27bf7f 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_81_4_15_H_
 #define _RGXCORE_KM_1_81_4_15_H_
 
-/***** Automatically generated file (26/08/2015 09:15:07): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:07)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2373516 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h
index 94632e3..8257262 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_1_82_4_5_H_
 #define _RGXCORE_KM_1_82_4_5_H_
 
-/***** Automatically generated file (23/07/2015 09:37:59): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 09:37:59)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
 /***** CS: @2503111 ******************************************************************/
 
 
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.22.4.25.h
similarity index 83%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.22.4.25.h
index 8455edc..fb30e17 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.22.4.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 10.22.4.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,27 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_10_22_4_25_H_
+#define _RGXCORE_KM_10_22_4_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (29/11/2016 07:01:41): Do not edit manually ********************/
+/***** Timestamp:  (29/11/2016 07:01:41)************************************************************/
+/***** CS: @3943572 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 10.22.4.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 10
+#define RGX_BVNC_KM_V 22
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_62204
 
 
  
@@ -71,7 +69,11 @@
 #define HW_ERN_36400
 #define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_45914
+#define HW_ERN_46066
+#define HW_ERN_47025
+#define HW_ERN_50539
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_10_22_4_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.30.2.26.h
similarity index 84%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.30.2.26.h
index 8455edc..792da6d 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.30.2.26.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 10.30.2.26
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,27 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_10_30_2_26_H_
+#define _RGXCORE_KM_10_30_2_26_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (23/02/2017 15:15:18): Do not edit manually ********************/
+/***** Timestamp:  (23/02/2017 15:15:18)************************************************************/
+/***** CS: @3943572 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 10.30.2.26 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
+#define RGX_BVNC_KM_B 10
+#define RGX_BVNC_KM_V 30
 #define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_C 26
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_62204
 
 
  
@@ -71,7 +69,11 @@
 #define HW_ERN_36400
 #define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_45914
+#define HW_ERN_46066
+#define HW_ERN_47025
+#define HW_ERN_50539
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_10_30_2_26_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.32.4.25.h
similarity index 84%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.32.4.25.h
index 8455edc..1e2e194 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.32.4.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 10.32.4.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,27 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_10_32_4_25_H_
+#define _RGXCORE_KM_10_32_4_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (29/11/2016 07:01:41): Do not edit manually ********************/
+/***** Timestamp:  (29/11/2016 07:01:41)************************************************************/
+/***** CS: @3976602 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 10.32.4.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
+#define RGX_BVNC_KM_B 10
 #define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_62204
 
 
  
@@ -71,7 +69,11 @@
 #define HW_ERN_36400
 #define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_45914
+#define HW_ERN_46066
+#define HW_ERN_47025
+#define HW_ERN_50539
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_10_32_4_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.33.4.25.h
similarity index 83%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.33.4.25.h
index 8455edc..dc8198a 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_10.33.4.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 10.33.4.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,27 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_10_33_4_25_H_
+#define _RGXCORE_KM_10_33_4_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (23/02/2017 15:15:18): Do not edit manually ********************/
+/***** Timestamp:  (23/02/2017 15:15:18)************************************************************/
+/***** CS: @4036299 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 10.33.4.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 10
+#define RGX_BVNC_KM_V 33
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_62204
 
 
  
@@ -71,7 +69,11 @@
 #define HW_ERN_36400
 #define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_45914
+#define HW_ERN_46066
+#define HW_ERN_47025
+#define HW_ERN_50539
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_10_33_4_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.48.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.48.h
index c1e7ada..0bf4b61 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.48.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.48.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_12_4_1_48_H_
 #define _RGXCORE_KM_12_4_1_48_H_
 
-/***** Automatically generated file (26/08/2015 09:15:07): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:07)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:18): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:18)************************************************************/
 /***** CS: @2989295 ******************************************************************/
 
 
@@ -60,6 +60,8 @@
  *****************************************************************************/
 
 #define FIX_HW_BRN_38344
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.5.1.20.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.5.1.20.h
index f7a02a8..33c05fd 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.5.1.20.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_12.5.1.20.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_12_5_1_20_H_
 #define _RGXCORE_KM_12_5_1_20_H_
 
-/***** Automatically generated file (23/07/2015 09:38:00): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 09:38:00)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @3146507 ******************************************************************/
 
 
@@ -59,6 +59,8 @@
  * Errata 
  *****************************************************************************/
 
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_15.5.1.64.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_15.5.1.64.h
index f906923..c77946c 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_15.5.1.64.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_15.5.1.64.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_15_5_1_64_H_
 #define _RGXCORE_KM_15_5_1_64_H_
 
-/***** Automatically generated file (11/12/2015 08:48:34): Do not edit manually ********************/
-/***** Timestamp:  (11/12/2015 08:48:34)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
 /***** CS: @3846532 ******************************************************************/
 
 
@@ -59,6 +59,8 @@
  * Errata 
  *****************************************************************************/
 
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.18.22.22.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.18.22.22.h
index 8455edc..0558361 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.18.22.22.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.18.22.22
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_18_22_22_H_
+#define _RGXCORE_KM_22_18_22_22_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @3872583 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.18.22.22 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 18
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 22
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,8 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_18_22_22_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.26.54.24.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.26.54.24.h
index 8455edc..297215e 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.26.54.24.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.26.54.24
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_26_54_24_H_
+#define _RGXCORE_KM_22_26_54_24_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @3943204 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.26.54.24 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 26
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 24
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_26_54_24_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.28.22.23.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.28.22.23.h
index 8455edc..8601045 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.28.22.23.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.28.22.23
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_28_22_23_H_
+#define _RGXCORE_KM_22_28_22_23_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @3969181 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.28.22.23 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 28
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 23
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_28_22_23_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.29.22.27.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.29.22.27.h
index 8455edc..604b0c7 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.29.22.27.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.29.22.27
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_29_22_27_H_
+#define _RGXCORE_KM_22_29_22_27_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @3976753 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.29.22.27 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 29
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 27
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_29_22_27_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.30.54.25.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.30.54.25.h
index 8455edc..9ffffd6 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.30.54.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.30.54.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_30_54_25_H_
+#define _RGXCORE_KM_22_30_54_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4086500 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.30.54.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 30
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_30_54_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.32.54.328.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.32.54.328.h
index 8455edc..0b88fd9 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.32.54.328.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.32.54.328
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_32_54_328_H_
+#define _RGXCORE_KM_22_32_54_328_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4048608 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.32.54.328 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
+#define RGX_BVNC_KM_B 22
 #define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 328
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -74,4 +77,4 @@
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_32_54_328_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.33.21.11.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.33.21.11.h
index 8455edc..e89e8966 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.33.21.11.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.33.21.11
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_33_21_11_H_
+#define _RGXCORE_KM_22_33_21_11_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4048565 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.33.21.11 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 33
+#define RGX_BVNC_KM_N 21
+#define RGX_BVNC_KM_C 11
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_33_21_11_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.35.22.27.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.35.22.27.h
index 8455edc..de7022c 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.35.22.27.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.35.22.27
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_35_22_27_H_
+#define _RGXCORE_KM_22_35_22_27_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4005275 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.35.22.27 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 35
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 27
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_35_22_27_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.40.54.30.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.40.54.30.h
index 8455edc..ac55756 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.40.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.40.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_40_54_30_H_
+#define _RGXCORE_KM_22_40_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4094817 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.40.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 40
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_40_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.41.54.330.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.41.54.330.h
index 8455edc..09f71a5 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.41.54.330.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.41.54.330
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_41_54_330_H_
+#define _RGXCORE_KM_22_41_54_330_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4075207 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.41.54.330 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 41
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 330
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -74,4 +77,4 @@
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_41_54_330_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.44.22.25.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.44.22.25.h
index 8455edc..4a727f3 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.44.22.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.44.22.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_44_22_25_H_
+#define _RGXCORE_KM_22_44_22_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4137146 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.44.22.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 44
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_44_22_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.45.22.29.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.45.22.29.h
index 8455edc..af23862 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.45.22.29.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.45.22.29
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_45_22_29_H_
+#define _RGXCORE_KM_22_45_22_29_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4127311 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.45.22.29 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 45
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 29
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_45_22_29_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.46.54.330.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.46.54.330.h
index 8455edc..5899f5b 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.46.54.330.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.46.54.330
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_46_54_330_H_
+#define _RGXCORE_KM_22_46_54_330_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4136505 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.46.54.330 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 46
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 330
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -74,4 +77,4 @@
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_46_54_330_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.47.208.312.h
similarity index 83%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.47.208.312.h
index 8455edc..8053060 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.47.208.312.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.47.208.312
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,29 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_47_208_312_H_
+#define _RGXCORE_KM_22_47_208_312_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4202467 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.47.208.312 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 47
+#define RGX_BVNC_KM_N 208
+#define RGX_BVNC_KM_C 312
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -74,4 +74,4 @@
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_47_208_312_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.48.54.30.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.48.54.30.h
index 8455edc..809ba6e 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.48.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.48.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_48_54_30_H_
+#define _RGXCORE_KM_22_48_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:18): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:18)************************************************************/
+/***** CS: @4158661 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.48.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 48
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_48_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.49.21.16.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.49.21.16.h
index 8455edc..f4b7d04 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.49.21.16.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.49.21.16
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,30 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_49_21_16_H_
+#define _RGXCORE_KM_22_49_21_16_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4158766 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.49.21.16 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 49
+#define RGX_BVNC_KM_N 21
+#define RGX_BVNC_KM_C 16
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +70,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_49_21_16_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.50.22.29.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.50.22.29.h
index 8455edc..d6ee92b 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.50.22.29.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.50.22.29
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_50_22_29_H_
+#define _RGXCORE_KM_22_50_22_29_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4156423 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.50.22.29 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 50
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 29
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_61450
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +72,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_50_22_29_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.55.54.30.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.55.54.30.h
index 8455edc..8afd36f 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.55.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.55.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,31 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_55_54_30_H_
+#define _RGXCORE_KM_22_55_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4230075 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.55.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 55
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +71,9 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_55_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.57.54.30.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.57.54.30.h
index 8455edc..55d979f 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.57.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.57.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,31 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_57_54_30_H_
+#define _RGXCORE_KM_22_57_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4279085 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.57.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 57
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +71,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_57_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.58.22.25.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.58.22.25.h
index 8455edc..167a279 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.58.22.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.58.22.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,30 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_58_22_25_H_
+#define _RGXCORE_KM_22_58_22_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4279077 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.58.22.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 58
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +70,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_58_22_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.59.54.30.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.59.54.30.h
index 8455edc..4324248 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.59.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.59.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,30 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_59_54_30_H_
+#define _RGXCORE_KM_22_59_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
+/***** CS: @4317182 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.59.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 59
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +70,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_59_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.62.21.16.h
similarity index 83%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.62.21.16.h
index 8455edc..1387449 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.62.21.16.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.62.21.16
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,28 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_62_21_16_H_
+#define _RGXCORE_KM_22_62_21_16_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4339985 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.62.21.16 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 62
+#define RGX_BVNC_KM_N 21
+#define RGX_BVNC_KM_C 16
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +68,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_62_21_16_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.63.54.330.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.63.54.330.h
index 8455edc..0c09802 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.63.54.330.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.63.54.330
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,30 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_63_54_330_H_
+#define _RGXCORE_KM_22_63_54_330_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4400526 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.63.54.330 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 63
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 330
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -71,7 +72,8 @@
 #define HW_ERN_36400
 #define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_63_54_330_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.67.54.30.h
similarity index 81%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.67.54.30.h
index 8455edc..d2d9e1c 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.67.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.67.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,31 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_67_54_30_H_
+#define _RGXCORE_KM_22_67_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:18): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:18)************************************************************/
+/***** CS: @4339986 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.67.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 67
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_60084
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +71,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_67_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.68.54.30.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.68.54.30.h
index 8455edc..2fc5275 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.68.54.30.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.68.54.30
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,30 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_68_54_30_H_
+#define _RGXCORE_KM_22_68_54_30_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4339984 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.68.54.30 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 68
+#define RGX_BVNC_KM_N 54
+#define RGX_BVNC_KM_C 30
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +70,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_68_54_30_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.69.22.25.h
similarity index 82%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.69.22.25.h
index 8455edc..35b4fdb 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.69.22.25.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.69.22.25
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,30 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_69_22_25_H_
+#define _RGXCORE_KM_22_69_22_25_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4339983 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.69.22.25 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 69
+#define RGX_BVNC_KM_N 22
+#define RGX_BVNC_KM_C 25
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -69,9 +70,10 @@
  * Enhancements 
  *****************************************************************************/
 #define HW_ERN_36400
-#define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_57596
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_69_22_25_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.70.208.316.h
similarity index 83%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.70.208.316.h
index 8455edc..7d1dd70 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_22.70.208.316.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 22.70.208.316
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,28 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_22_70_208_316_H_
+#define _RGXCORE_KM_22_70_208_316_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
+/***** CS: @4476117 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 22.70.208.316 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 22
+#define RGX_BVNC_KM_V 70
+#define RGX_BVNC_KM_N 208
+#define RGX_BVNC_KM_C 316
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
-#define FIX_HW_BRN_57193
+#define FIX_HW_BRN_55091
+#define FIX_HW_BRN_63027
 
 
  
@@ -71,7 +70,8 @@
 #define HW_ERN_36400
 #define HW_ERN_42290
 #define HW_ERN_42606
+#define HW_ERN_61389
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_22_70_208_316_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h
index 80e6fb7..49e10f5 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_29_2_51_H_
 #define _RGXCORE_KM_4_29_2_51_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:06): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:06)************************************************************/
 /***** CS: @2944502 ******************************************************************/
 
 
@@ -62,6 +62,7 @@
 #define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.31.4.55.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.31.4.55.h
index 2f98874..57f8e2d 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.31.4.55.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.31.4.55.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_31_4_55_H_
 #define _RGXCORE_KM_4_31_4_55_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:06): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:06)************************************************************/
 /***** CS: @2919104 ******************************************************************/
 
 
@@ -62,6 +62,7 @@
 #define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.40.2.51.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.40.2.51.h
index 677c121..a85ac35 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.40.2.51.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.40.2.51.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_40_2_51_H_
 #define _RGXCORE_KM_4_40_2_51_H_
 
-/***** Automatically generated file (07/09/2015 09:24:25): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:25)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:06): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:06)************************************************************/
 /***** CS: @3254374 ******************************************************************/
 
 
@@ -62,6 +62,7 @@
 #define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.41.2.57.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.41.2.57.h
index 285635c..ea14d9e 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.41.2.57.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.41.2.57.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_41_2_57_H_
 #define _RGXCORE_KM_4_41_2_57_H_
 
-/***** Automatically generated file (07/09/2015 09:24:25): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:25)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:05): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:05)************************************************************/
 /***** CS: @3254338 ******************************************************************/
 
 
@@ -62,6 +62,7 @@
 #define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.42.4.53.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.42.4.53.h
index f177e88..e95381c 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.42.4.53.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.42.4.53.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_42_4_53_H_
 #define _RGXCORE_KM_4_42_4_53_H_
 
-/***** Automatically generated file (07/09/2015 09:24:25): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:25)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:06): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:06)************************************************************/
 /***** CS: @3250390 ******************************************************************/
 
 
@@ -62,6 +62,7 @@
 #define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.43.6.62.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.43.6.62.h
index 3eea043..3c55e1c 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.43.6.62.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.43.6.62.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_43_6_62_H_
 #define _RGXCORE_KM_4_43_6_62_H_
 
-/***** Automatically generated file (07/09/2015 09:24:25): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:25)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:06): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:06)************************************************************/
 /***** CS: @3253129 ******************************************************************/
 
 
@@ -62,6 +62,7 @@
 #define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.45.2.58.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.45.2.58.h
index 2588258..0001e9b 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.45.2.58.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.45.2.58.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_4_45_2_58_H_
 #define _RGXCORE_KM_4_45_2_58_H_
 
-/***** Automatically generated file (27/08/2015 09:09:26): Do not edit manually ********************/
-/***** Timestamp:  (27/08/2015 09:09:26)************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:06): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:06)************************************************************/
 /***** CS: @3547765 ******************************************************************/
 
 
@@ -61,6 +61,7 @@
 
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.46.6.62.h
similarity index 86%
rename from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
rename to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.46.6.62.h
index 8455edc..d196dd0 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.46.6.62.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 4.46.6.62
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,29 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_4_46_6_62_H_
+#define _RGXCORE_KM_4_46_6_62_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:05): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:05)************************************************************/
+/***** CS: @4015666 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 4.46.6.62 
  *****************************************************************************/
 #define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_V 46
+#define RGX_BVNC_KM_N 6
+#define RGX_BVNC_KM_C 62
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
 #define FIX_HW_BRN_50767
-#define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
@@ -74,4 +74,4 @@
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_4_46_6_62_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.11.1.46.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.11.1.46.h
index 8e7ca99..0f426ca 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.11.1.46.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.11.1.46.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_5_11_1_46_H_
 #define _RGXCORE_KM_5_11_1_46_H_
 
-/***** Automatically generated file (26/08/2015 09:15:10): Do not edit manually ********************/
-/***** Timestamp:  (26/08/2015 09:15:10)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:20): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:20)************************************************************/
 /***** CS: @3485232 ******************************************************************/
 
 
@@ -60,6 +60,8 @@
  *****************************************************************************/
 
 #define FIX_HW_BRN_42321
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h
index 72b7e52..ac693ff 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_5_9_1_46_H_
 #define _RGXCORE_KM_5_9_1_46_H_
 
-/***** Automatically generated file (23/07/2015 09:38:00): Do not edit manually ********************/
-/***** Timestamp:  (23/07/2015 09:38:00)************************************************************/
+/***** Automatically generated file (20/02/2017 07:01:19): Do not edit manually ********************/
+/***** Timestamp:  (20/02/2017 07:01:19)************************************************************/
 /***** CS: @2967148 ******************************************************************/
 
 
@@ -60,6 +60,8 @@
  *****************************************************************************/
 
 #define FIX_HW_BRN_38344
+#define FIX_HW_BRN_43276
+#define FIX_HW_BRN_44871
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_6.34.4.35.h
similarity index 85%
copy from drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
copy to drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_6.34.4.35.h
index 8455edc..7e4f836 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_4.32.2.52.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_6.34.4.35.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 4.32.2.52
+@Title          RGX Core BVNC 6.34.4.35
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,29 +39,29 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _RGXCORE_KM_4_32_2_52_H_
-#define _RGXCORE_KM_4_32_2_52_H_
+#ifndef _RGXCORE_KM_6_34_4_35_H_
+#define _RGXCORE_KM_6_34_4_35_H_
 
-/***** Automatically generated file (07/09/2015 09:24:24): Do not edit manually ********************/
-/***** Timestamp:  (07/09/2015 09:24:24)************************************************************/
-/***** CS: @2966609 ******************************************************************/
+/***** Automatically generated file (06/02/2017 07:01:05): Do not edit manually ********************/
+/***** Timestamp:  (06/02/2017 07:01:05)************************************************************/
+/***** CS: @3533654 ******************************************************************/
 
 
 /******************************************************************************
- * BVNC = 4.32.2.52 
+ * BVNC = 6.34.4.35 
  *****************************************************************************/
-#define RGX_BVNC_KM_B 4
-#define RGX_BVNC_KM_V 32
-#define RGX_BVNC_KM_N 2
-#define RGX_BVNC_KM_C 52
+#define RGX_BVNC_KM_B 6
+#define RGX_BVNC_KM_V 34
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 35
 
 /******************************************************************************
  * Errata 
  *****************************************************************************/
 
-#define FIX_HW_BRN_50767
 #define FIX_HW_BRN_54441
 #define FIX_HW_BRN_57193
+#define FIX_HW_BRN_63142
 
 
  
@@ -74,4 +74,4 @@
 
 
 
-#endif /* _RGXCORE_KM_4_32_2_52_H_ */
+#endif /* _RGXCORE_KM_6_34_4_35_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.47.2.39.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.47.2.39.h
index 690c435..923614e 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.47.2.39.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.47.2.39.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_8_47_2_39_H_
 #define _RGXCORE_KM_8_47_2_39_H_
 
-/***** Automatically generated file (20/08/2015 16:40:24): Do not edit manually ********************/
-/***** Timestamp:  (20/08/2015 16:40:24)************************************************************/
+/***** Automatically generated file (23/02/2017 15:15:18): Do not edit manually ********************/
+/***** Timestamp:  (23/02/2017 15:15:18)************************************************************/
 /***** CS: @3673034 ******************************************************************/
 
 
@@ -59,6 +59,8 @@
  * Errata 
  *****************************************************************************/
 
+#define FIX_HW_BRN_52563
+#define FIX_HW_BRN_62204
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.48.2.39.h b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.48.2.39.h
index 5d2e495..0e4e85e 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.48.2.39.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/cores/rgxcore_km_8.48.2.39.h
@@ -42,8 +42,8 @@
 #ifndef _RGXCORE_KM_8_48_2_39_H_
 #define _RGXCORE_KM_8_48_2_39_H_
 
-/***** Automatically generated file (16/10/2015 06:53:38): Do not edit manually ********************/
-/***** Timestamp:  (16/10/2015 06:53:38)************************************************************/
+/***** Automatically generated file (23/02/2017 15:15:18): Do not edit manually ********************/
+/***** Timestamp:  (23/02/2017 15:15:18)************************************************************/
 /***** CS: @3753485 ******************************************************************/
 
 
@@ -59,6 +59,8 @@
  * Errata 
  *****************************************************************************/
 
+#define FIX_HW_BRN_52563
+#define FIX_HW_BRN_62204
 
 
  
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/rgx_bvnc_defs_km.h b/drivers/staging/imgtec/rogue/hwdefs/km/rgx_bvnc_defs_km.h
new file mode 100644
index 0000000..e49d3dd
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/rgx_bvnc_defs_km.h
@@ -0,0 +1,320 @@
+/*************************************************************************/ /*!
+@Title          Hardware definition file rgx_bvnc_defs_km.h
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/**************************************************
+*       Auto generated file by BVNCTableGen.py    *
+*       This file should not be edited manually   *
+**************************************************/
+
+#ifndef _RGX_BVNC_DEFS_KM_H_
+#define _RGX_BVNC_DEFS_KM_H_
+
+#include "img_types.h"
+
+#define   BVNC_FIELD_WIDTH  (16U)
+
+#define	RGX_FEATURE_AXI_ACELITE_POS                                 	(0U)
+#define	RGX_FEATURE_AXI_ACELITE_BIT_MASK                            	(IMG_UINT64_C(0x0000000000000001))
+
+#define	RGX_FEATURE_CLUSTER_GROUPING_POS                            	(1U)
+#define	RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK                       	(IMG_UINT64_C(0x0000000000000002))
+
+#define	RGX_FEATURE_COMPUTE_POS                                     	(2U)
+#define	RGX_FEATURE_COMPUTE_BIT_MASK                                	(IMG_UINT64_C(0x0000000000000004))
+
+#define	RGX_FEATURE_COMPUTE_MORTON_CAPABLE_POS                      	(3U)
+#define	RGX_FEATURE_COMPUTE_MORTON_CAPABLE_BIT_MASK                 	(IMG_UINT64_C(0x0000000000000008))
+
+#define	RGX_FEATURE_COMPUTE_OVERLAP_POS                             	(4U)
+#define	RGX_FEATURE_COMPUTE_OVERLAP_BIT_MASK                        	(IMG_UINT64_C(0x0000000000000010))
+
+#define	RGX_FEATURE_COMPUTE_OVERLAP_WITH_BARRIERS_POS               	(5U)
+#define	RGX_FEATURE_COMPUTE_OVERLAP_WITH_BARRIERS_BIT_MASK          	(IMG_UINT64_C(0x0000000000000020))
+
+#define	RGX_FEATURE_DYNAMIC_DUST_POWER_POS                          	(6U)
+#define	RGX_FEATURE_DYNAMIC_DUST_POWER_BIT_MASK                     	(IMG_UINT64_C(0x0000000000000040))
+
+#define	RGX_FEATURE_FASTRENDER_DM_POS                               	(7U)
+#define	RGX_FEATURE_FASTRENDER_DM_BIT_MASK                          	(IMG_UINT64_C(0x0000000000000080))
+
+#define	RGX_FEATURE_GPU_CPU_COHERENCY_POS                           	(8U)
+#define	RGX_FEATURE_GPU_CPU_COHERENCY_BIT_MASK                      	(IMG_UINT64_C(0x0000000000000100))
+
+#define	RGX_FEATURE_GPU_VIRTUALISATION_POS                          	(9U)
+#define	RGX_FEATURE_GPU_VIRTUALISATION_BIT_MASK                     	(IMG_UINT64_C(0x0000000000000200))
+
+#define	RGX_FEATURE_GS_RTA_SUPPORT_POS                              	(10U)
+#define	RGX_FEATURE_GS_RTA_SUPPORT_BIT_MASK                         	(IMG_UINT64_C(0x0000000000000400))
+
+#define	RGX_FEATURE_META_DMA_POS                                    	(11U)
+#define	RGX_FEATURE_META_DMA_BIT_MASK                               	(IMG_UINT64_C(0x0000000000000800))
+
+#define	RGX_FEATURE_MIPS_POS                                        	(12U)
+#define	RGX_FEATURE_MIPS_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000001000))
+
+#define	RGX_FEATURE_PBE2_IN_XE_POS                                  	(13U)
+#define	RGX_FEATURE_PBE2_IN_XE_BIT_MASK                             	(IMG_UINT64_C(0x0000000000002000))
+
+#define	RGX_FEATURE_PBVNC_COREID_REG_POS                            	(14U)
+#define	RGX_FEATURE_PBVNC_COREID_REG_BIT_MASK                       	(IMG_UINT64_C(0x0000000000004000))
+
+#define	RGX_FEATURE_PDS_PER_DUST_POS                                	(15U)
+#define	RGX_FEATURE_PDS_PER_DUST_BIT_MASK                           	(IMG_UINT64_C(0x0000000000008000))
+
+#define	RGX_FEATURE_PDS_TEMPSIZE8_POS                               	(16U)
+#define	RGX_FEATURE_PDS_TEMPSIZE8_BIT_MASK                          	(IMG_UINT64_C(0x0000000000010000))
+
+#define	RGX_FEATURE_PERFBUS_POS                                     	(17U)
+#define	RGX_FEATURE_PERFBUS_BIT_MASK                                	(IMG_UINT64_C(0x0000000000020000))
+
+#define	RGX_FEATURE_RAY_TRACING_POS                                 	(18U)
+#define	RGX_FEATURE_RAY_TRACING_BIT_MASK                            	(IMG_UINT64_C(0x0000000000040000))
+
+#define	RGX_FEATURE_ROGUEXE_POS                                     	(19U)
+#define	RGX_FEATURE_ROGUEXE_BIT_MASK                                	(IMG_UINT64_C(0x0000000000080000))
+
+#define	RGX_FEATURE_S7_CACHE_HIERARCHY_POS                          	(20U)
+#define	RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK                     	(IMG_UINT64_C(0x0000000000100000))
+
+#define	RGX_FEATURE_S7_TOP_INFRASTRUCTURE_POS                       	(21U)
+#define	RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK                  	(IMG_UINT64_C(0x0000000000200000))
+
+#define	RGX_FEATURE_SCALABLE_VDM_GPP_POS                            	(22U)
+#define	RGX_FEATURE_SCALABLE_VDM_GPP_BIT_MASK                       	(IMG_UINT64_C(0x0000000000400000))
+
+#define	RGX_FEATURE_SIGNAL_SNOOPING_POS                             	(23U)
+#define	RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK                        	(IMG_UINT64_C(0x0000000000800000))
+
+#define	RGX_FEATURE_SINGLE_BIF_POS                                  	(24U)
+#define	RGX_FEATURE_SINGLE_BIF_BIT_MASK                             	(IMG_UINT64_C(0x0000000001000000))
+
+#define	RGX_FEATURE_SLCSIZE8_POS                                    	(25U)
+#define	RGX_FEATURE_SLCSIZE8_BIT_MASK                               	(IMG_UINT64_C(0x0000000002000000))
+
+#define	RGX_FEATURE_SLC_HYBRID_CACHELINE_64_128_POS                 	(26U)
+#define	RGX_FEATURE_SLC_HYBRID_CACHELINE_64_128_BIT_MASK            	(IMG_UINT64_C(0x0000000004000000))
+
+#define	RGX_FEATURE_SLC_VIVT_POS                                    	(27U)
+#define	RGX_FEATURE_SLC_VIVT_BIT_MASK                               	(IMG_UINT64_C(0x0000000008000000))
+
+#define	RGX_FEATURE_SYS_BUS_SECURE_RESET_POS                        	(28U)
+#define	RGX_FEATURE_SYS_BUS_SECURE_RESET_BIT_MASK                   	(IMG_UINT64_C(0x0000000010000000))
+
+#define	RGX_FEATURE_TESSELLATION_POS                                	(29U)
+#define	RGX_FEATURE_TESSELLATION_BIT_MASK                           	(IMG_UINT64_C(0x0000000020000000))
+
+#define	RGX_FEATURE_TLA_POS                                         	(30U)
+#define	RGX_FEATURE_TLA_BIT_MASK                                    	(IMG_UINT64_C(0x0000000040000000))
+
+#define	RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_POS         	(31U)
+#define	RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_BIT_MASK    	(IMG_UINT64_C(0x0000000080000000))
+
+#define	RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_POS                     	(32U)
+#define	RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_BIT_MASK                	(IMG_UINT64_C(0x0000000100000000))
+
+#define	RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_POS                  	(33U)
+#define	RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_BIT_MASK             	(IMG_UINT64_C(0x0000000200000000))
+
+#define	RGX_FEATURE_VDM_DRAWINDIRECT_POS                            	(34U)
+#define	RGX_FEATURE_VDM_DRAWINDIRECT_BIT_MASK                       	(IMG_UINT64_C(0x0000000400000000))
+
+#define	RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_POS                        	(35U)
+#define	RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_BIT_MASK                   	(IMG_UINT64_C(0x0000000800000000))
+
+#define	RGX_FEATURE_XT_TOP_INFRASTRUCTURE_POS                       	(36U)
+#define	RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK                  	(IMG_UINT64_C(0x0000001000000000))
+
+#define	RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_POS                   	(0U)
+#define	RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_BIT_MASK              	(IMG_UINT64_C(0x0000000000000003))
+
+#define	RGX_FEATURE_FBCDC_ARCHITECTURE_POS                          	(2U)
+#define	RGX_FEATURE_FBCDC_ARCHITECTURE_BIT_MASK                     	(IMG_UINT64_C(0x000000000000000C))
+
+#define	RGX_FEATURE_META_POS                                        	(4U)
+#define	RGX_FEATURE_META_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000030))
+
+#define	RGX_FEATURE_META_COREMEM_BANKS_POS                          	(6U)
+#define	RGX_FEATURE_META_COREMEM_BANKS_BIT_MASK                     	(IMG_UINT64_C(0x00000000000001C0))
+
+#define	RGX_FEATURE_META_COREMEM_SIZE_POS                           	(9U)
+#define	RGX_FEATURE_META_COREMEM_SIZE_BIT_MASK                      	(IMG_UINT64_C(0x0000000000000E00))
+
+#define	RGX_FEATURE_META_DMA_CHANNEL_COUNT_POS                      	(12U)
+#define	RGX_FEATURE_META_DMA_CHANNEL_COUNT_BIT_MASK                 	(IMG_UINT64_C(0x0000000000003000))
+
+#define	RGX_FEATURE_NUM_CLUSTERS_POS                                	(14U)
+#define	RGX_FEATURE_NUM_CLUSTERS_BIT_MASK                           	(IMG_UINT64_C(0x000000000003C000))
+
+#define	RGX_FEATURE_NUM_ISP_IPP_PIPES_POS                           	(18U)
+#define	RGX_FEATURE_NUM_ISP_IPP_PIPES_BIT_MASK                      	(IMG_UINT64_C(0x00000000003C0000))
+
+#define	RGX_FEATURE_PHYS_BUS_WIDTH_POS                              	(22U)
+#define	RGX_FEATURE_PHYS_BUS_WIDTH_BIT_MASK                         	(IMG_UINT64_C(0x0000000000C00000))
+
+#define	RGX_FEATURE_SCALABLE_TE_ARCH_POS                            	(24U)
+#define	RGX_FEATURE_SCALABLE_TE_ARCH_BIT_MASK                       	(IMG_UINT64_C(0x0000000003000000))
+
+#define	RGX_FEATURE_SCALABLE_VCE_POS                                	(26U)
+#define	RGX_FEATURE_SCALABLE_VCE_BIT_MASK                           	(IMG_UINT64_C(0x000000000C000000))
+
+#define	RGX_FEATURE_SLC_BANKS_POS                                   	(28U)
+#define	RGX_FEATURE_SLC_BANKS_BIT_MASK                              	(IMG_UINT64_C(0x0000000030000000))
+
+#define	RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_POS                    	(30U)
+#define	RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_BIT_MASK               	(IMG_UINT64_C(0x0000000040000000))
+
+#define	RGX_FEATURE_SLC_SIZE_IN_BYTES_POS                           	(31U)
+#define	RGX_FEATURE_SLC_SIZE_IN_BYTES_BIT_MASK                      	(IMG_UINT64_C(0x0000000380000000))
+
+#define	RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_POS                       	(31U)
+#define	RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_BIT_MASK                  	(IMG_UINT64_C(0x0000000380000000))
+
+#define	RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_POS                  	(36U)
+#define	RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_BIT_MASK             	(IMG_UINT64_C(0x0000001000000000))
+
+#define	HW_ERN_36400_POS                                            	(0U)
+#define	HW_ERN_36400_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000000001))
+
+#define	FIX_HW_BRN_37200_POS                                        	(1U)
+#define	FIX_HW_BRN_37200_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000002))
+
+#define	FIX_HW_BRN_37918_POS                                        	(2U)
+#define	FIX_HW_BRN_37918_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000004))
+
+#define	FIX_HW_BRN_38344_POS                                        	(3U)
+#define	FIX_HW_BRN_38344_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000008))
+
+#define	HW_ERN_41805_POS                                            	(4U)
+#define	HW_ERN_41805_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000000010))
+
+#define	HW_ERN_42290_POS                                            	(5U)
+#define	HW_ERN_42290_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000000020))
+
+#define	FIX_HW_BRN_42321_POS                                        	(6U)
+#define	FIX_HW_BRN_42321_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000040))
+
+#define	FIX_HW_BRN_42480_POS                                        	(7U)
+#define	FIX_HW_BRN_42480_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000080))
+
+#define	HW_ERN_42606_POS                                            	(8U)
+#define	HW_ERN_42606_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000000100))
+
+#define	FIX_HW_BRN_43276_POS                                        	(9U)
+#define	FIX_HW_BRN_43276_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000200))
+
+#define	FIX_HW_BRN_44455_POS                                        	(10U)
+#define	FIX_HW_BRN_44455_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000400))
+
+#define	FIX_HW_BRN_44871_POS                                        	(11U)
+#define	FIX_HW_BRN_44871_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000000800))
+
+#define	HW_ERN_44885_POS                                            	(12U)
+#define	HW_ERN_44885_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000001000))
+
+#define	HW_ERN_45914_POS                                            	(13U)
+#define	HW_ERN_45914_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000002000))
+
+#define	HW_ERN_46066_POS                                            	(14U)
+#define	HW_ERN_46066_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000004000))
+
+#define	HW_ERN_47025_POS                                            	(15U)
+#define	HW_ERN_47025_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000008000))
+
+#define	HW_ERN_49144_POS                                            	(16U)
+#define	HW_ERN_49144_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000010000))
+
+#define	HW_ERN_50539_POS                                            	(17U)
+#define	HW_ERN_50539_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000020000))
+
+#define	FIX_HW_BRN_50767_POS                                        	(18U)
+#define	FIX_HW_BRN_50767_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000040000))
+
+#define	FIX_HW_BRN_51281_POS                                        	(19U)
+#define	FIX_HW_BRN_51281_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000080000))
+
+#define	HW_ERN_51468_POS                                            	(20U)
+#define	HW_ERN_51468_BIT_MASK                                       	(IMG_UINT64_C(0x0000000000100000))
+
+#define	FIX_HW_BRN_52402_POS                                        	(21U)
+#define	FIX_HW_BRN_52402_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000200000))
+
+#define	FIX_HW_BRN_52563_POS                                        	(22U)
+#define	FIX_HW_BRN_52563_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000400000))
+
+#define	FIX_HW_BRN_54141_POS                                        	(23U)
+#define	FIX_HW_BRN_54141_BIT_MASK                                   	(IMG_UINT64_C(0x0000000000800000))
+
+#define	FIX_HW_BRN_54441_POS                                        	(24U)
+#define	FIX_HW_BRN_54441_BIT_MASK                                   	(IMG_UINT64_C(0x0000000001000000))
+
+#define	FIX_HW_BRN_55091_POS                                        	(25U)
+#define	FIX_HW_BRN_55091_BIT_MASK                                   	(IMG_UINT64_C(0x0000000002000000))
+
+#define	FIX_HW_BRN_57193_POS                                        	(26U)
+#define	FIX_HW_BRN_57193_BIT_MASK                                   	(IMG_UINT64_C(0x0000000004000000))
+
+#define	HW_ERN_57596_POS                                            	(27U)
+#define	HW_ERN_57596_BIT_MASK                                       	(IMG_UINT64_C(0x0000000008000000))
+
+#define	FIX_HW_BRN_60084_POS                                        	(28U)
+#define	FIX_HW_BRN_60084_BIT_MASK                                   	(IMG_UINT64_C(0x0000000010000000))
+
+#define	HW_ERN_61389_POS                                            	(29U)
+#define	HW_ERN_61389_BIT_MASK                                       	(IMG_UINT64_C(0x0000000020000000))
+
+#define	FIX_HW_BRN_61450_POS                                        	(30U)
+#define	FIX_HW_BRN_61450_BIT_MASK                                   	(IMG_UINT64_C(0x0000000040000000))
+
+#define	FIX_HW_BRN_62204_POS                                        	(31U)
+#define	FIX_HW_BRN_62204_BIT_MASK                                   	(IMG_UINT64_C(0x0000000080000000))
+
+#define	FIX_HW_BRN_63027_POS                                        	(32U)
+#define	FIX_HW_BRN_63027_BIT_MASK                                   	(IMG_UINT64_C(0x0000000100000000))
+
+#define	FIX_HW_BRN_63142_POS                                        	(33U)
+#define	FIX_HW_BRN_63142_BIT_MASK                                   	(IMG_UINT64_C(0x0000000200000000))
+
+
+
+#endif /*_RGX_BVNC_DEFS_KM_H_ */
+
+
+
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/rgx_bvnc_table_km.h b/drivers/staging/imgtec/rogue/hwdefs/km/rgx_bvnc_table_km.h
new file mode 100644
index 0000000..c2db819
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/rgx_bvnc_table_km.h
@@ -0,0 +1,207 @@
+/*************************************************************************/ /*!
+@Title          Hardware definition file rgx_bvnc_table_km.h
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/**************************************************
+*       Auto generated file by BVNCTableGen.py    *
+*       This file should not be edited manually   *
+**************************************************/
+
+#ifndef _RGX_BVNC_TABLE_KM_H_
+#define _RGX_BVNC_TABLE_KM_H_
+
+#include "img_types.h"
+#include "rgxdefs_km.h"
+
+#define	CSF_MAX_VALUE	(1)
+static IMG_UINT32 CSF[] = {2, };
+
+#define	FBCDCArch_MAX_VALUE	(3)
+static IMG_UINT32 FBCDCArch[] = {1, 2, 3, };
+
+#define	MCRMB_MAX_VALUE	(2)
+static IMG_UINT32 MCRMB[] = {3, 8, };
+
+#define	MCRMS_MAX_VALUE	(5)
+static IMG_UINT32 MCRMS[] = {0, 32, 48, 64, 256, };
+
+#define	MDCC_MAX_VALUE	(1)
+static IMG_UINT32 MDCC[] = {4, };
+
+#define	NC_MAX_VALUE	(7)
+static IMG_UINT32 NC[] = {1, 2, 4, 6, 8, 12, 16, };
+
+#define	NIIP_MAX_VALUE	(11)
+static IMG_UINT32 NIIP[] = {1, 2, 3, 4, 6, 7, 8, 12, 16, 24, 32, };
+
+#define	PBW_MAX_VALUE	(3)
+static IMG_UINT32 PBW[] = {32, 38, 40, };
+
+#define	STEA_MAX_VALUE	(3)
+static IMG_UINT32 STEA[] = {1, 2, 4, };
+
+#define	SVCEA_MAX_VALUE	(4)
+static IMG_UINT32 SVCEA[] = {1, 2, 3, 4, };
+
+#define	SLCB_MAX_VALUE	(3)
+static IMG_UINT32 SLCB[] = {1, 2, 4, };
+
+#define	SLCCLSb_MAX_VALUE	(2)
+static IMG_UINT32 SLCCLSb[] = {512, 1024, };
+
+#define	SLCSKB_MAX_VALUE	(7)
+static IMG_UINT32 SLCSKB[] = {0, 16, 32, 64, 128, 256, 512, };
+
+#define	VASB_MAX_VALUE	(1)
+static IMG_UINT32 VASB[] = {40, };
+
+#define	META_MAX_VALUE	(4)
+static IMG_UINT32 META[] = {LTP217, LTP218, MTP218, MTP219, };
+
+
+IMG_UINT64    gaFeatures[][3]=
+{
+	{ 0x0001000000020000, 0x0000000040020415, 0x0000000200884020, },
+	{ 0x0001000000020005, 0x0000000040020415, 0x0000000200884020, },
+	{ 0x0001000000020014, 0x0000000040020415, 0x0000000200884020, },
+	{ 0x000100000002001e, 0x0000000040020415, 0x0000000200884020, },
+	{ 0x0001000000040005, 0x0000000040020414, 0x0000000200888020, },
+	{ 0x0001000000040006, 0x0000000040020414, 0x0000000200888020, },
+	{ 0x000100000004000c, 0x0000000040020414, 0x0000000280888020, },
+	{ 0x000100000004000f, 0x0000000040020415, 0x0000000280888020, },
+	{ 0x0001000000040013, 0x0000000040020415, 0x0000000200888020, },
+	{ 0x0004000000020033, 0x00000012c002045f, 0x0000000200984214, },
+	{ 0x0004000000020039, 0x00000012c002065f, 0x0000000200984214, },
+	{ 0x000400000002003a, 0x00000012c002065f, 0x0000000200984214, },
+	{ 0x0004000000040035, 0x00000012c002045f, 0x0000000200988214, },
+	{ 0x0004000000040037, 0x00000012c002045e, 0x0000000200988214, },
+	{ 0x000400000006003e, 0x00000012c002065f, 0x000000022098c214, },
+	{ 0x000500000001002e, 0x00000000000a0445, 0x0000000080800000, },
+	{ 0x0006000000040023, 0x00000012c006045f, 0x0000000200988214, },
+	{ 0x0008000000020027, 0x0000000fa8738e3f, 0x00000002108c4658, },
+	{ 0x000a00000002001a, 0x0000000fbcf38ebf, 0x0000000210984878, },
+	{ 0x000a000000040019, 0x0000000fbcf38ebf, 0x0000000320988878, },
+	{ 0x000c000000010014, 0x0000000000080005, 0x0000000000800000, },
+	{ 0x000c000000010030, 0x0000000000080005, 0x0000000000800000, },
+	{ 0x000f000000010040, 0x00000000000a0645, 0x0000000180840000, },
+	{ 0x001600000015000b, 0x00000000130a7605, 0x0000000000000000, },
+	{ 0x0016000000150010, 0x00000000130a7605, 0x0000000000040000, },
+	{ 0x0016000000160016, 0x00000000010a7605, 0x0000000080000000, },
+	{ 0x0016000000160017, 0x00000000110a7605, 0x0000000080000000, },
+	{ 0x0016000000160019, 0x00000000110a7605, 0x0000000080040000, },
+	{ 0x001600000016001b, 0x00000000110a7605, 0x0000000080000000, },
+	{ 0x001600000016001d, 0x00000000110a7605, 0x0000000080040000, },
+	{ 0x0016000000360018, 0x00000000010a7605, 0x0000000180080000, },
+	{ 0x0016000000360019, 0x00000000110a7605, 0x0000000180080000, },
+	{ 0x001600000036001e, 0x00000000110a7605, 0x00000001800c0000, },
+	{ 0x0016000000360148, 0x00000000110a7605, 0x00000001800c0000, },
+	{ 0x001600000036014a, 0x00000000110a7605, 0x00000001800c0000, },
+	{ 0x0016000000d00138, 0x00000000110a7605, 0x00000001800c4000, },
+	{ 0x0016000000d0013c, 0x00000000110a7605, 0x00000001801c4000, },
+};
+
+IMG_UINT64    gaErnsBrns[][2]=
+{
+	{ 0x0001002100020005, 0x000000000100044c, },
+	{ 0x0001002700040013, 0x0000000001000449, },
+	{ 0x0001003000020000, 0x0000000001000449, },
+	{ 0x000100480004000c, 0x0000000001000401, },
+	{ 0x0001004b00020014, 0x0000000001000441, },
+	{ 0x0001004b0002001e, 0x0000000001000441, },
+	{ 0x0001004c00040006, 0x0000000001000489, },
+	{ 0x000100510004000f, 0x0000000001000449, },
+	{ 0x0001005200040005, 0x0000000001000401, },
+	{ 0x0004001d00020033, 0x0000000205040121, },
+	{ 0x0004001f00040037, 0x0000000205040121, },
+	{ 0x0004002800020033, 0x0000000205040121, },
+	{ 0x0004002900020039, 0x0000000205040121, },
+	{ 0x0004002a00040035, 0x0000000205040121, },
+	{ 0x0004002b0006003e, 0x0000000205040121, },
+	{ 0x0004002d0002003a, 0x0000000205000121, },
+	{ 0x0004002e0006003e, 0x0000000204040121, },
+	{ 0x000500090001002e, 0x0000000000000a09, },
+	{ 0x0005000b0001002e, 0x0000000000000a41, },
+	{ 0x0006002200040023, 0x0000000205000121, },
+	{ 0x0008002f00020027, 0x000000008040e121, },
+	{ 0x0008003000020027, 0x000000008040e121, },
+	{ 0x000a001600040019, 0x000000008002e121, },
+	{ 0x000a001e0002001a, 0x000000008002e121, },
+	{ 0x000a002000040019, 0x000000008002e121, },
+	{ 0x000a002100040019, 0x000000008002e121, },
+	{ 0x000c000400010030, 0x0000000000000a09, },
+	{ 0x000c000500010014, 0x0000000000000a01, },
+	{ 0x000f000500010040, 0x0000000000000a01, },
+	{ 0x0016001200160016, 0x0000000152000b01, },
+	{ 0x0016001a00360018, 0x000000015a000b01, },
+	{ 0x0016001c00160017, 0x000000015a000b01, },
+	{ 0x0016001d0016001b, 0x000000015a000b01, },
+	{ 0x0016001e00360019, 0x000000015a000b01, },
+	{ 0x0016002000360148, 0x0000000152000b21, },
+	{ 0x001600210015000b, 0x000000015a000b01, },
+	{ 0x001600230016001b, 0x000000015a000b01, },
+	{ 0x001600280036001e, 0x000000015a000b01, },
+	{ 0x001600290036014a, 0x0000000152000b21, },
+	{ 0x0016002c00160019, 0x000000015a000b01, },
+	{ 0x0016002d0016001d, 0x000000015a000b01, },
+	{ 0x0016002e0036014a, 0x0000000152000b21, },
+	{ 0x0016002f00d00138, 0x0000000142000121, },
+	{ 0x001600300036001e, 0x000000015a000b01, },
+	{ 0x0016003100150010, 0x000000015a000101, },
+	{ 0x001600320016001d, 0x000000015a000b01, },
+	{ 0x001600370036001e, 0x000000011a000b01, },
+	{ 0x001600390036001e, 0x000000013a000b01, },
+	{ 0x0016003a00160019, 0x000000012a000b01, },
+	{ 0x0016003b0036001e, 0x0000000008000101, },
+	{ 0x0016003b0036001e, 0x000000012a000b01, },
+	{ 0x0016003e00150010, 0x000000012a000101, },
+	{ 0x0016003e00150010, 0x0000000028000101, },
+	{ 0x0016003f0036014a, 0x0000000122000b21, },
+	{ 0x0016003f0036014a, 0x0000000022000b21, },
+	{ 0x001600430036001e, 0x000000013a000b01, },
+	{ 0x001600440036001e, 0x000000012a000b01, },
+	{ 0x0016004500160019, 0x000000012a000b01, },
+	{ 0x0016004600d0013c, 0x0000000122000121, },
+};
+
+
+#endif /*_RGX_BVNC_TABLE_KM_H_ */
+
+
+
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/rgx_cr_defs_km.h b/drivers/staging/imgtec/rogue/hwdefs/km/rgx_cr_defs_km.h
index bab7c02..31814f8 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/rgx_cr_defs_km.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/rgx_cr_defs_km.h
@@ -42,8 +42,6 @@
 /*               ****   Autogenerated C -- do not edit    ****               */
 
 /*
- * Generated by regconv version MAIN@3328745
- *   from files:
  */
 
 #if !defined(__IMG_EXPLICIT_INCLUDE_HWDEFS)
@@ -55,6 +53,18 @@
 
 #include "img_types.h"
 
+
+#define RGX_CR_DEFS_KM_REVISION 1
+
+/*
+    Register RGX_CR_PBE_INDIRECT
+*/
+#define RGX_CR_PBE_INDIRECT                               (0x83E0U)
+#define RGX_CR_PBE_INDIRECT_MASKFULL                      (IMG_UINT64_C(0x000000000000000F))
+#define RGX_CR_PBE_INDIRECT_ADDRESS_SHIFT                 (0U)
+#define RGX_CR_PBE_INDIRECT_ADDRESS_CLRMSK                (0XFFFFFFF0U)
+
+
 /*
     Register RGX_CR_PBE_PERF_INDIRECT
 */
@@ -73,7 +83,6 @@
 #define RGX_CR_TPU_PERF_INDIRECT_ADDRESS_CLRMSK           (0XFFFFFFF8U)
 
 
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 /*
     Register RGX_CR_RASTERISATION_PERF_INDIRECT
 */
@@ -83,8 +92,6 @@
 #define RGX_CR_RASTERISATION_PERF_INDIRECT_ADDRESS_CLRMSK (0XFFFFFFF0U)
 
 
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
 /*
     Register RGX_CR_TPU_MCU_L0_PERF_INDIRECT
 */
@@ -104,6 +111,15 @@
 
 
 /*
+    Register RGX_CR_BLACKPEARL_INDIRECT
+*/
+#define RGX_CR_BLACKPEARL_INDIRECT                        (0x8388U)
+#define RGX_CR_BLACKPEARL_INDIRECT_MASKFULL               (IMG_UINT64_C(0x0000000000000003))
+#define RGX_CR_BLACKPEARL_INDIRECT_ADDRESS_SHIFT          (0U)
+#define RGX_CR_BLACKPEARL_INDIRECT_ADDRESS_CLRMSK         (0XFFFFFFFCU)
+
+
+/*
     Register RGX_CR_BLACKPEARL_PERF_INDIRECT
 */
 #define RGX_CR_BLACKPEARL_PERF_INDIRECT                   (0x83F8U)
@@ -121,7 +137,6 @@
 #define RGX_CR_TEXAS3_PERF_INDIRECT_ADDRESS_CLRMSK        (0XFFFFFFF8U)
 
 
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 /*
     Register RGX_CR_TEXAS_PERF_INDIRECT
 */
@@ -131,712 +146,284 @@
 #define RGX_CR_TEXAS_PERF_INDIRECT_ADDRESS_CLRMSK         (0XFFFFFFFCU)
 
 
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+/*
+    Register RGX_CR_BX_TU_PERF_INDIRECT
+*/
+#define RGX_CR_BX_TU_PERF_INDIRECT                        (0xC900U)
+#define RGX_CR_BX_TU_PERF_INDIRECT_MASKFULL               (IMG_UINT64_C(0x0000000000000003))
+#define RGX_CR_BX_TU_PERF_INDIRECT_ADDRESS_SHIFT          (0U)
+#define RGX_CR_BX_TU_PERF_INDIRECT_ADDRESS_CLRMSK         (0XFFFFFFFCU)
 
-#if defined(RGX_FEATURE_PBE2_IN_XE)
+
 /*
     Register RGX_CR_CLK_CTRL
 */
 #define RGX_CR_CLK_CTRL                                   (0x0000U)
+#define RGX_CR_CLK_CTRL__PBE2_XE__MASKFULL                (IMG_UINT64_C(0xFFFFFF003F3FFFFF))
+#define RGX_CR_CLK_CTRL__S7_TOP__MASKFULL                 (IMG_UINT64_C(0xCFCF03000F3F3F0F))
 #define RGX_CR_CLK_CTRL_MASKFULL                          (IMG_UINT64_C(0xFFFFFF003F3FFFFF))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 #define RGX_CR_CLK_CTRL_BIF_TEXAS_SHIFT                   (62U)
 #define RGX_CR_CLK_CTRL_BIF_TEXAS_CLRMSK                  (IMG_UINT64_C(0X3FFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_OFF                     (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_ON                      (IMG_UINT64_C(0x4000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_AUTO                    (IMG_UINT64_C(0x8000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_OFF                     (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_ON                      (IMG_UINT64_C(0x4000000000000000))  
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_AUTO                    (IMG_UINT64_C(0x8000000000000000))  
 #define RGX_CR_CLK_CTRL_IPP_SHIFT                         (60U)
 #define RGX_CR_CLK_CTRL_IPP_CLRMSK                        (IMG_UINT64_C(0XCFFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_IPP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_IPP_ON                            (IMG_UINT64_C(0x1000000000000000))
-#define RGX_CR_CLK_CTRL_IPP_AUTO                          (IMG_UINT64_C(0x2000000000000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
+#define RGX_CR_CLK_CTRL_IPP_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_IPP_ON                            (IMG_UINT64_C(0x1000000000000000))  
+#define RGX_CR_CLK_CTRL_IPP_AUTO                          (IMG_UINT64_C(0x2000000000000000))  
 #define RGX_CR_CLK_CTRL_FBC_SHIFT                         (58U)
 #define RGX_CR_CLK_CTRL_FBC_CLRMSK                        (IMG_UINT64_C(0XF3FFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FBC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FBC_ON                            (IMG_UINT64_C(0x0400000000000000))
-#define RGX_CR_CLK_CTRL_FBC_AUTO                          (IMG_UINT64_C(0x0800000000000000))
+#define RGX_CR_CLK_CTRL_FBC_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_FBC_ON                            (IMG_UINT64_C(0x0400000000000000))  
+#define RGX_CR_CLK_CTRL_FBC_AUTO                          (IMG_UINT64_C(0x0800000000000000))  
 #define RGX_CR_CLK_CTRL_FBDC_SHIFT                        (56U)
 #define RGX_CR_CLK_CTRL_FBDC_CLRMSK                       (IMG_UINT64_C(0XFCFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FBDC_OFF                          (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_ON                           (IMG_UINT64_C(0x0100000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_AUTO                         (IMG_UINT64_C(0x0200000000000000))
+#define RGX_CR_CLK_CTRL_FBDC_OFF                          (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_FBDC_ON                           (IMG_UINT64_C(0x0100000000000000))  
+#define RGX_CR_CLK_CTRL_FBDC_AUTO                         (IMG_UINT64_C(0x0200000000000000))  
 #define RGX_CR_CLK_CTRL_FB_TLCACHE_SHIFT                  (54U)
 #define RGX_CR_CLK_CTRL_FB_TLCACHE_CLRMSK                 (IMG_UINT64_C(0XFF3FFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_OFF                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_ON                     (IMG_UINT64_C(0x0040000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_AUTO                   (IMG_UINT64_C(0x0080000000000000))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_OFF                    (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_ON                     (IMG_UINT64_C(0x0040000000000000))  
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_AUTO                   (IMG_UINT64_C(0x0080000000000000))  
 #define RGX_CR_CLK_CTRL_USCS_SHIFT                        (52U)
 #define RGX_CR_CLK_CTRL_USCS_CLRMSK                       (IMG_UINT64_C(0XFFCFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_USCS_OFF                          (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_USCS_ON                           (IMG_UINT64_C(0x0010000000000000))
-#define RGX_CR_CLK_CTRL_USCS_AUTO                         (IMG_UINT64_C(0x0020000000000000))
+#define RGX_CR_CLK_CTRL_USCS_OFF                          (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_USCS_ON                           (IMG_UINT64_C(0x0010000000000000))  
+#define RGX_CR_CLK_CTRL_USCS_AUTO                         (IMG_UINT64_C(0x0020000000000000))  
 #define RGX_CR_CLK_CTRL_PBE_SHIFT                         (50U)
 #define RGX_CR_CLK_CTRL_PBE_CLRMSK                        (IMG_UINT64_C(0XFFF3FFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_PBE_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PBE_ON                            (IMG_UINT64_C(0x0004000000000000))
-#define RGX_CR_CLK_CTRL_PBE_AUTO                          (IMG_UINT64_C(0x0008000000000000))
+#define RGX_CR_CLK_CTRL_PBE_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_PBE_ON                            (IMG_UINT64_C(0x0004000000000000))  
+#define RGX_CR_CLK_CTRL_PBE_AUTO                          (IMG_UINT64_C(0x0008000000000000))  
 #define RGX_CR_CLK_CTRL_MCU_L1_SHIFT                      (48U)
 #define RGX_CR_CLK_CTRL_MCU_L1_CLRMSK                     (IMG_UINT64_C(0XFFFCFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_MCU_L1_OFF                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_ON                         (IMG_UINT64_C(0x0001000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_AUTO                       (IMG_UINT64_C(0x0002000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L1_OFF                        (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_MCU_L1_ON                         (IMG_UINT64_C(0x0001000000000000))  
+#define RGX_CR_CLK_CTRL_MCU_L1_AUTO                       (IMG_UINT64_C(0x0002000000000000))  
 #define RGX_CR_CLK_CTRL_CDM_SHIFT                         (46U)
 #define RGX_CR_CLK_CTRL_CDM_CLRMSK                        (IMG_UINT64_C(0XFFFF3FFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_CDM_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_CDM_ON                            (IMG_UINT64_C(0x0000400000000000))
-#define RGX_CR_CLK_CTRL_CDM_AUTO                          (IMG_UINT64_C(0x0000800000000000))
+#define RGX_CR_CLK_CTRL_CDM_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_CDM_ON                            (IMG_UINT64_C(0x0000400000000000))  
+#define RGX_CR_CLK_CTRL_CDM_AUTO                          (IMG_UINT64_C(0x0000800000000000))  
 #define RGX_CR_CLK_CTRL_SIDEKICK_SHIFT                    (44U)
 #define RGX_CR_CLK_CTRL_SIDEKICK_CLRMSK                   (IMG_UINT64_C(0XFFFFCFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_SIDEKICK_OFF                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_SIDEKICK_ON                       (IMG_UINT64_C(0x0000100000000000))
-#define RGX_CR_CLK_CTRL_SIDEKICK_AUTO                     (IMG_UINT64_C(0x0000200000000000))
+#define RGX_CR_CLK_CTRL_SIDEKICK_OFF                      (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_SIDEKICK_ON                       (IMG_UINT64_C(0x0000100000000000))  
+#define RGX_CR_CLK_CTRL_SIDEKICK_AUTO                     (IMG_UINT64_C(0x0000200000000000))  
 #define RGX_CR_CLK_CTRL_BIF_SIDEKICK_SHIFT                (42U)
 #define RGX_CR_CLK_CTRL_BIF_SIDEKICK_CLRMSK               (IMG_UINT64_C(0XFFFFF3FFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_OFF                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_ON                   (IMG_UINT64_C(0x0000040000000000))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_AUTO                 (IMG_UINT64_C(0x0000080000000000))
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_OFF                  (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_ON                   (IMG_UINT64_C(0x0000040000000000))  
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_AUTO                 (IMG_UINT64_C(0x0000080000000000))  
 #define RGX_CR_CLK_CTRL_BIF_SHIFT                         (40U)
 #define RGX_CR_CLK_CTRL_BIF_CLRMSK                        (IMG_UINT64_C(0XFFFFFCFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_ON                            (IMG_UINT64_C(0x0000010000000000))
-#define RGX_CR_CLK_CTRL_BIF_AUTO                          (IMG_UINT64_C(0x0000020000000000))
+#define RGX_CR_CLK_CTRL_BIF_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_BIF_ON                            (IMG_UINT64_C(0x0000010000000000))  
+#define RGX_CR_CLK_CTRL_BIF_AUTO                          (IMG_UINT64_C(0x0000020000000000))  
 #define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_SHIFT               (28U)
 #define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFCFFFFFFF))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_OFF                 (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_ON                  (IMG_UINT64_C(0x0000000010000000))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_AUTO                (IMG_UINT64_C(0x0000000020000000))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_OFF                 (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_ON                  (IMG_UINT64_C(0x0000000010000000))  
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_AUTO                (IMG_UINT64_C(0x0000000020000000))  
 #define RGX_CR_CLK_CTRL_MCU_L0_SHIFT                      (26U)
 #define RGX_CR_CLK_CTRL_MCU_L0_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
-#define RGX_CR_CLK_CTRL_MCU_L0_OFF                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_ON                         (IMG_UINT64_C(0x0000000004000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_AUTO                       (IMG_UINT64_C(0x0000000008000000))
+#define RGX_CR_CLK_CTRL_MCU_L0_OFF                        (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_MCU_L0_ON                         (IMG_UINT64_C(0x0000000004000000))  
+#define RGX_CR_CLK_CTRL_MCU_L0_AUTO                       (IMG_UINT64_C(0x0000000008000000))  
 #define RGX_CR_CLK_CTRL_TPU_SHIFT                         (24U)
 #define RGX_CR_CLK_CTRL_TPU_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
-#define RGX_CR_CLK_CTRL_TPU_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TPU_ON                            (IMG_UINT64_C(0x0000000001000000))
-#define RGX_CR_CLK_CTRL_TPU_AUTO                          (IMG_UINT64_C(0x0000000002000000))
+#define RGX_CR_CLK_CTRL_TPU_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_TPU_ON                            (IMG_UINT64_C(0x0000000001000000))  
+#define RGX_CR_CLK_CTRL_TPU_AUTO                          (IMG_UINT64_C(0x0000000002000000))  
 #define RGX_CR_CLK_CTRL_USC_SHIFT                         (20U)
 #define RGX_CR_CLK_CTRL_USC_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
-#define RGX_CR_CLK_CTRL_USC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_USC_ON                            (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_CLK_CTRL_USC_AUTO                          (IMG_UINT64_C(0x0000000000200000))
+#define RGX_CR_CLK_CTRL_USC_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_USC_ON                            (IMG_UINT64_C(0x0000000000100000))  
+#define RGX_CR_CLK_CTRL_USC_AUTO                          (IMG_UINT64_C(0x0000000000200000))  
 #define RGX_CR_CLK_CTRL_TLA_SHIFT                         (18U)
 #define RGX_CR_CLK_CTRL_TLA_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
-#define RGX_CR_CLK_CTRL_TLA_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TLA_ON                            (IMG_UINT64_C(0x0000000000040000))
-#define RGX_CR_CLK_CTRL_TLA_AUTO                          (IMG_UINT64_C(0x0000000000080000))
+#define RGX_CR_CLK_CTRL_TLA_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_TLA_ON                            (IMG_UINT64_C(0x0000000000040000))  
+#define RGX_CR_CLK_CTRL_TLA_AUTO                          (IMG_UINT64_C(0x0000000000080000))  
 #define RGX_CR_CLK_CTRL_SLC_SHIFT                         (16U)
 #define RGX_CR_CLK_CTRL_SLC_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
-#define RGX_CR_CLK_CTRL_SLC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_SLC_ON                            (IMG_UINT64_C(0x0000000000010000))
-#define RGX_CR_CLK_CTRL_SLC_AUTO                          (IMG_UINT64_C(0x0000000000020000))
+#define RGX_CR_CLK_CTRL_SLC_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_SLC_ON                            (IMG_UINT64_C(0x0000000000010000))  
+#define RGX_CR_CLK_CTRL_SLC_AUTO                          (IMG_UINT64_C(0x0000000000020000))  
 #define RGX_CR_CLK_CTRL_UVS_SHIFT                         (14U)
 #define RGX_CR_CLK_CTRL_UVS_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFF3FFF))
-#define RGX_CR_CLK_CTRL_UVS_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_UVS_ON                            (IMG_UINT64_C(0x0000000000004000))
-#define RGX_CR_CLK_CTRL_UVS_AUTO                          (IMG_UINT64_C(0x0000000000008000))
+#define RGX_CR_CLK_CTRL_UVS_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_UVS_ON                            (IMG_UINT64_C(0x0000000000004000))  
+#define RGX_CR_CLK_CTRL_UVS_AUTO                          (IMG_UINT64_C(0x0000000000008000))  
 #define RGX_CR_CLK_CTRL_PDS_SHIFT                         (12U)
 #define RGX_CR_CLK_CTRL_PDS_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
-#define RGX_CR_CLK_CTRL_PDS_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PDS_ON                            (IMG_UINT64_C(0x0000000000001000))
-#define RGX_CR_CLK_CTRL_PDS_AUTO                          (IMG_UINT64_C(0x0000000000002000))
+#define RGX_CR_CLK_CTRL_PDS_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_PDS_ON                            (IMG_UINT64_C(0x0000000000001000))  
+#define RGX_CR_CLK_CTRL_PDS_AUTO                          (IMG_UINT64_C(0x0000000000002000))  
 #define RGX_CR_CLK_CTRL_VDM_SHIFT                         (10U)
 #define RGX_CR_CLK_CTRL_VDM_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
-#define RGX_CR_CLK_CTRL_VDM_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_VDM_ON                            (IMG_UINT64_C(0x0000000000000400))
-#define RGX_CR_CLK_CTRL_VDM_AUTO                          (IMG_UINT64_C(0x0000000000000800))
+#define RGX_CR_CLK_CTRL_VDM_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_VDM_ON                            (IMG_UINT64_C(0x0000000000000400))  
+#define RGX_CR_CLK_CTRL_VDM_AUTO                          (IMG_UINT64_C(0x0000000000000800))  
 #define RGX_CR_CLK_CTRL_PM_SHIFT                          (8U)
 #define RGX_CR_CLK_CTRL_PM_CLRMSK                         (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
-#define RGX_CR_CLK_CTRL_PM_OFF                            (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PM_ON                             (IMG_UINT64_C(0x0000000000000100))
-#define RGX_CR_CLK_CTRL_PM_AUTO                           (IMG_UINT64_C(0x0000000000000200))
+#define RGX_CR_CLK_CTRL_PM_OFF                            (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_PM_ON                             (IMG_UINT64_C(0x0000000000000100))  
+#define RGX_CR_CLK_CTRL_PM_AUTO                           (IMG_UINT64_C(0x0000000000000200))  
 #define RGX_CR_CLK_CTRL_GPP_SHIFT                         (6U)
 #define RGX_CR_CLK_CTRL_GPP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFF3F))
-#define RGX_CR_CLK_CTRL_GPP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_GPP_ON                            (IMG_UINT64_C(0x0000000000000040))
-#define RGX_CR_CLK_CTRL_GPP_AUTO                          (IMG_UINT64_C(0x0000000000000080))
+#define RGX_CR_CLK_CTRL_GPP_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_GPP_ON                            (IMG_UINT64_C(0x0000000000000040))  
+#define RGX_CR_CLK_CTRL_GPP_AUTO                          (IMG_UINT64_C(0x0000000000000080))  
 #define RGX_CR_CLK_CTRL_TE_SHIFT                          (4U)
 #define RGX_CR_CLK_CTRL_TE_CLRMSK                         (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
-#define RGX_CR_CLK_CTRL_TE_OFF                            (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TE_ON                             (IMG_UINT64_C(0x0000000000000010))
-#define RGX_CR_CLK_CTRL_TE_AUTO                           (IMG_UINT64_C(0x0000000000000020))
+#define RGX_CR_CLK_CTRL_TE_OFF                            (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_TE_ON                             (IMG_UINT64_C(0x0000000000000010))  
+#define RGX_CR_CLK_CTRL_TE_AUTO                           (IMG_UINT64_C(0x0000000000000020))  
 #define RGX_CR_CLK_CTRL_TSP_SHIFT                         (2U)
 #define RGX_CR_CLK_CTRL_TSP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFF3))
-#define RGX_CR_CLK_CTRL_TSP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TSP_ON                            (IMG_UINT64_C(0x0000000000000004))
-#define RGX_CR_CLK_CTRL_TSP_AUTO                          (IMG_UINT64_C(0x0000000000000008))
+#define RGX_CR_CLK_CTRL_TSP_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_TSP_ON                            (IMG_UINT64_C(0x0000000000000004))  
+#define RGX_CR_CLK_CTRL_TSP_AUTO                          (IMG_UINT64_C(0x0000000000000008))  
 #define RGX_CR_CLK_CTRL_ISP_SHIFT                         (0U)
 #define RGX_CR_CLK_CTRL_ISP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
-#define RGX_CR_CLK_CTRL_ISP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_ISP_ON                            (IMG_UINT64_C(0x0000000000000001))
-#define RGX_CR_CLK_CTRL_ISP_AUTO                          (IMG_UINT64_C(0x0000000000000002))
-#endif /* RGX_FEATURE_PBE2_IN_XE */ 
+#define RGX_CR_CLK_CTRL_ISP_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL_ISP_ON                            (IMG_UINT64_C(0x0000000000000001))  
+#define RGX_CR_CLK_CTRL_ISP_AUTO                          (IMG_UINT64_C(0x0000000000000002))  
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-/*
-    Register RGX_CR_CLK_CTRL
-*/
-#define RGX_CR_CLK_CTRL                                   (0x0000U)
-#define RGX_CR_CLK_CTRL_MASKFULL                          (IMG_UINT64_C(0xCFCF03000F3F3F0F))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_SHIFT                   (62U)
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_CLRMSK                  (IMG_UINT64_C(0X3FFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_OFF                     (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_ON                      (IMG_UINT64_C(0x4000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_AUTO                    (IMG_UINT64_C(0x8000000000000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
-#define RGX_CR_CLK_CTRL_FBC_SHIFT                         (58U)
-#define RGX_CR_CLK_CTRL_FBC_CLRMSK                        (IMG_UINT64_C(0XF3FFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FBC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FBC_ON                            (IMG_UINT64_C(0x0400000000000000))
-#define RGX_CR_CLK_CTRL_FBC_AUTO                          (IMG_UINT64_C(0x0800000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_SHIFT                        (56U)
-#define RGX_CR_CLK_CTRL_FBDC_CLRMSK                       (IMG_UINT64_C(0XFCFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FBDC_OFF                          (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_ON                           (IMG_UINT64_C(0x0100000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_AUTO                         (IMG_UINT64_C(0x0200000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_SHIFT                  (54U)
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_CLRMSK                 (IMG_UINT64_C(0XFF3FFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_OFF                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_ON                     (IMG_UINT64_C(0x0040000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_AUTO                   (IMG_UINT64_C(0x0080000000000000))
-#define RGX_CR_CLK_CTRL_PBE_SHIFT                         (50U)
-#define RGX_CR_CLK_CTRL_PBE_CLRMSK                        (IMG_UINT64_C(0XFFF3FFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_PBE_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PBE_ON                            (IMG_UINT64_C(0x0004000000000000))
-#define RGX_CR_CLK_CTRL_PBE_AUTO                          (IMG_UINT64_C(0x0008000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_SHIFT                      (48U)
-#define RGX_CR_CLK_CTRL_MCU_L1_CLRMSK                     (IMG_UINT64_C(0XFFFCFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_MCU_L1_OFF                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_ON                         (IMG_UINT64_C(0x0001000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_AUTO                       (IMG_UINT64_C(0x0002000000000000))
-#define RGX_CR_CLK_CTRL_BIF_SHIFT                         (40U)
-#define RGX_CR_CLK_CTRL_BIF_CLRMSK                        (IMG_UINT64_C(0XFFFFFCFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_ON                            (IMG_UINT64_C(0x0000010000000000))
-#define RGX_CR_CLK_CTRL_BIF_AUTO                          (IMG_UINT64_C(0x0000020000000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_SHIFT                      (26U)
-#define RGX_CR_CLK_CTRL_MCU_L0_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
-#define RGX_CR_CLK_CTRL_MCU_L0_OFF                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_ON                         (IMG_UINT64_C(0x0000000004000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_AUTO                       (IMG_UINT64_C(0x0000000008000000))
-#define RGX_CR_CLK_CTRL_TPU_SHIFT                         (24U)
-#define RGX_CR_CLK_CTRL_TPU_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
-#define RGX_CR_CLK_CTRL_TPU_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TPU_ON                            (IMG_UINT64_C(0x0000000001000000))
-#define RGX_CR_CLK_CTRL_TPU_AUTO                          (IMG_UINT64_C(0x0000000002000000))
-#define RGX_CR_CLK_CTRL_USC_SHIFT                         (20U)
-#define RGX_CR_CLK_CTRL_USC_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
-#define RGX_CR_CLK_CTRL_USC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_USC_ON                            (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_CLK_CTRL_USC_AUTO                          (IMG_UINT64_C(0x0000000000200000))
-#define RGX_CR_CLK_CTRL_TLA_SHIFT                         (18U)
-#define RGX_CR_CLK_CTRL_TLA_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
-#define RGX_CR_CLK_CTRL_TLA_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TLA_ON                            (IMG_UINT64_C(0x0000000000040000))
-#define RGX_CR_CLK_CTRL_TLA_AUTO                          (IMG_UINT64_C(0x0000000000080000))
-#define RGX_CR_CLK_CTRL_SLC_SHIFT                         (16U)
-#define RGX_CR_CLK_CTRL_SLC_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
-#define RGX_CR_CLK_CTRL_SLC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_SLC_ON                            (IMG_UINT64_C(0x0000000000010000))
-#define RGX_CR_CLK_CTRL_SLC_AUTO                          (IMG_UINT64_C(0x0000000000020000))
-#define RGX_CR_CLK_CTRL_PDS_SHIFT                         (12U)
-#define RGX_CR_CLK_CTRL_PDS_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
-#define RGX_CR_CLK_CTRL_PDS_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PDS_ON                            (IMG_UINT64_C(0x0000000000001000))
-#define RGX_CR_CLK_CTRL_PDS_AUTO                          (IMG_UINT64_C(0x0000000000002000))
-#define RGX_CR_CLK_CTRL_VDM_SHIFT                         (10U)
-#define RGX_CR_CLK_CTRL_VDM_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
-#define RGX_CR_CLK_CTRL_VDM_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_VDM_ON                            (IMG_UINT64_C(0x0000000000000400))
-#define RGX_CR_CLK_CTRL_VDM_AUTO                          (IMG_UINT64_C(0x0000000000000800))
-#define RGX_CR_CLK_CTRL_PM_SHIFT                          (8U)
-#define RGX_CR_CLK_CTRL_PM_CLRMSK                         (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
-#define RGX_CR_CLK_CTRL_PM_OFF                            (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PM_ON                             (IMG_UINT64_C(0x0000000000000100))
-#define RGX_CR_CLK_CTRL_PM_AUTO                           (IMG_UINT64_C(0x0000000000000200))
-#define RGX_CR_CLK_CTRL_TSP_SHIFT                         (2U)
-#define RGX_CR_CLK_CTRL_TSP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFF3))
-#define RGX_CR_CLK_CTRL_TSP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TSP_ON                            (IMG_UINT64_C(0x0000000000000004))
-#define RGX_CR_CLK_CTRL_TSP_AUTO                          (IMG_UINT64_C(0x0000000000000008))
-#define RGX_CR_CLK_CTRL_ISP_SHIFT                         (0U)
-#define RGX_CR_CLK_CTRL_ISP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
-#define RGX_CR_CLK_CTRL_ISP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_ISP_ON                            (IMG_UINT64_C(0x0000000000000001))
-#define RGX_CR_CLK_CTRL_ISP_AUTO                          (IMG_UINT64_C(0x0000000000000002))
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */ 
-
-
-#if !defined(RGX_FEATURE_PBE2_IN_XE) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-/*
-    Register RGX_CR_CLK_CTRL
-*/
-#define RGX_CR_CLK_CTRL                                   (0x0000U)
-#define RGX_CR_CLK_CTRL_MASKFULL                          (IMG_UINT64_C(0xFFFFFF003F3FFFFF))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_SHIFT                   (62U)
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_CLRMSK                  (IMG_UINT64_C(0X3FFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_OFF                     (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_ON                      (IMG_UINT64_C(0x4000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_TEXAS_AUTO                    (IMG_UINT64_C(0x8000000000000000))
-#define RGX_CR_CLK_CTRL_IPP_SHIFT                         (60U)
-#define RGX_CR_CLK_CTRL_IPP_CLRMSK                        (IMG_UINT64_C(0XCFFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_IPP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_IPP_ON                            (IMG_UINT64_C(0x1000000000000000))
-#define RGX_CR_CLK_CTRL_IPP_AUTO                          (IMG_UINT64_C(0x2000000000000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
-#define RGX_CR_CLK_CTRL_FBC_SHIFT                         (58U)
-#define RGX_CR_CLK_CTRL_FBC_CLRMSK                        (IMG_UINT64_C(0XF3FFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FBC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FBC_ON                            (IMG_UINT64_C(0x0400000000000000))
-#define RGX_CR_CLK_CTRL_FBC_AUTO                          (IMG_UINT64_C(0x0800000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_SHIFT                        (56U)
-#define RGX_CR_CLK_CTRL_FBDC_CLRMSK                       (IMG_UINT64_C(0XFCFFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FBDC_OFF                          (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_ON                           (IMG_UINT64_C(0x0100000000000000))
-#define RGX_CR_CLK_CTRL_FBDC_AUTO                         (IMG_UINT64_C(0x0200000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_SHIFT                  (54U)
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_CLRMSK                 (IMG_UINT64_C(0XFF3FFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_OFF                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_ON                     (IMG_UINT64_C(0x0040000000000000))
-#define RGX_CR_CLK_CTRL_FB_TLCACHE_AUTO                   (IMG_UINT64_C(0x0080000000000000))
-#define RGX_CR_CLK_CTRL_USCS_SHIFT                        (52U)
-#define RGX_CR_CLK_CTRL_USCS_CLRMSK                       (IMG_UINT64_C(0XFFCFFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_USCS_OFF                          (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_USCS_ON                           (IMG_UINT64_C(0x0010000000000000))
-#define RGX_CR_CLK_CTRL_USCS_AUTO                         (IMG_UINT64_C(0x0020000000000000))
-#define RGX_CR_CLK_CTRL_PBE_SHIFT                         (50U)
-#define RGX_CR_CLK_CTRL_PBE_CLRMSK                        (IMG_UINT64_C(0XFFF3FFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_PBE_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PBE_ON                            (IMG_UINT64_C(0x0004000000000000))
-#define RGX_CR_CLK_CTRL_PBE_AUTO                          (IMG_UINT64_C(0x0008000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_SHIFT                      (48U)
-#define RGX_CR_CLK_CTRL_MCU_L1_CLRMSK                     (IMG_UINT64_C(0XFFFCFFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_MCU_L1_OFF                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_ON                         (IMG_UINT64_C(0x0001000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L1_AUTO                       (IMG_UINT64_C(0x0002000000000000))
-#if defined(RGX_FEATURE_COMPUTE)
-#define RGX_CR_CLK_CTRL_CDM_SHIFT                         (46U)
-#define RGX_CR_CLK_CTRL_CDM_CLRMSK                        (IMG_UINT64_C(0XFFFF3FFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_CDM_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_CDM_ON                            (IMG_UINT64_C(0x0000400000000000))
-#define RGX_CR_CLK_CTRL_CDM_AUTO                          (IMG_UINT64_C(0x0000800000000000))
-#endif /* RGX_FEATURE_COMPUTE */
-
-#define RGX_CR_CLK_CTRL_SIDEKICK_SHIFT                    (44U)
-#define RGX_CR_CLK_CTRL_SIDEKICK_CLRMSK                   (IMG_UINT64_C(0XFFFFCFFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_SIDEKICK_OFF                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_SIDEKICK_ON                       (IMG_UINT64_C(0x0000100000000000))
-#define RGX_CR_CLK_CTRL_SIDEKICK_AUTO                     (IMG_UINT64_C(0x0000200000000000))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_SHIFT                (42U)
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_CLRMSK               (IMG_UINT64_C(0XFFFFF3FFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_OFF                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_ON                   (IMG_UINT64_C(0x0000040000000000))
-#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_AUTO                 (IMG_UINT64_C(0x0000080000000000))
-#define RGX_CR_CLK_CTRL_BIF_SHIFT                         (40U)
-#define RGX_CR_CLK_CTRL_BIF_CLRMSK                        (IMG_UINT64_C(0XFFFFFCFFFFFFFFFF))
-#define RGX_CR_CLK_CTRL_BIF_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_BIF_ON                            (IMG_UINT64_C(0x0000010000000000))
-#define RGX_CR_CLK_CTRL_BIF_AUTO                          (IMG_UINT64_C(0x0000020000000000))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_SHIFT               (28U)
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFCFFFFFFF))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_OFF                 (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_ON                  (IMG_UINT64_C(0x0000000010000000))
-#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_AUTO                (IMG_UINT64_C(0x0000000020000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_SHIFT                      (26U)
-#define RGX_CR_CLK_CTRL_MCU_L0_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
-#define RGX_CR_CLK_CTRL_MCU_L0_OFF                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_ON                         (IMG_UINT64_C(0x0000000004000000))
-#define RGX_CR_CLK_CTRL_MCU_L0_AUTO                       (IMG_UINT64_C(0x0000000008000000))
-#define RGX_CR_CLK_CTRL_TPU_SHIFT                         (24U)
-#define RGX_CR_CLK_CTRL_TPU_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
-#define RGX_CR_CLK_CTRL_TPU_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TPU_ON                            (IMG_UINT64_C(0x0000000001000000))
-#define RGX_CR_CLK_CTRL_TPU_AUTO                          (IMG_UINT64_C(0x0000000002000000))
-#define RGX_CR_CLK_CTRL_USC_SHIFT                         (20U)
-#define RGX_CR_CLK_CTRL_USC_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
-#define RGX_CR_CLK_CTRL_USC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_USC_ON                            (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_CLK_CTRL_USC_AUTO                          (IMG_UINT64_C(0x0000000000200000))
-#define RGX_CR_CLK_CTRL_TLA_SHIFT                         (18U)
-#define RGX_CR_CLK_CTRL_TLA_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
-#define RGX_CR_CLK_CTRL_TLA_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TLA_ON                            (IMG_UINT64_C(0x0000000000040000))
-#define RGX_CR_CLK_CTRL_TLA_AUTO                          (IMG_UINT64_C(0x0000000000080000))
-#define RGX_CR_CLK_CTRL_SLC_SHIFT                         (16U)
-#define RGX_CR_CLK_CTRL_SLC_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
-#define RGX_CR_CLK_CTRL_SLC_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_SLC_ON                            (IMG_UINT64_C(0x0000000000010000))
-#define RGX_CR_CLK_CTRL_SLC_AUTO                          (IMG_UINT64_C(0x0000000000020000))
-#define RGX_CR_CLK_CTRL_UVS_SHIFT                         (14U)
-#define RGX_CR_CLK_CTRL_UVS_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFF3FFF))
-#define RGX_CR_CLK_CTRL_UVS_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_UVS_ON                            (IMG_UINT64_C(0x0000000000004000))
-#define RGX_CR_CLK_CTRL_UVS_AUTO                          (IMG_UINT64_C(0x0000000000008000))
-#define RGX_CR_CLK_CTRL_PDS_SHIFT                         (12U)
-#define RGX_CR_CLK_CTRL_PDS_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
-#define RGX_CR_CLK_CTRL_PDS_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PDS_ON                            (IMG_UINT64_C(0x0000000000001000))
-#define RGX_CR_CLK_CTRL_PDS_AUTO                          (IMG_UINT64_C(0x0000000000002000))
-#define RGX_CR_CLK_CTRL_VDM_SHIFT                         (10U)
-#define RGX_CR_CLK_CTRL_VDM_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
-#define RGX_CR_CLK_CTRL_VDM_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_VDM_ON                            (IMG_UINT64_C(0x0000000000000400))
-#define RGX_CR_CLK_CTRL_VDM_AUTO                          (IMG_UINT64_C(0x0000000000000800))
-#define RGX_CR_CLK_CTRL_PM_SHIFT                          (8U)
-#define RGX_CR_CLK_CTRL_PM_CLRMSK                         (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
-#define RGX_CR_CLK_CTRL_PM_OFF                            (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_PM_ON                             (IMG_UINT64_C(0x0000000000000100))
-#define RGX_CR_CLK_CTRL_PM_AUTO                           (IMG_UINT64_C(0x0000000000000200))
-#define RGX_CR_CLK_CTRL_GPP_SHIFT                         (6U)
-#define RGX_CR_CLK_CTRL_GPP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFF3F))
-#define RGX_CR_CLK_CTRL_GPP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_GPP_ON                            (IMG_UINT64_C(0x0000000000000040))
-#define RGX_CR_CLK_CTRL_GPP_AUTO                          (IMG_UINT64_C(0x0000000000000080))
-#define RGX_CR_CLK_CTRL_TE_SHIFT                          (4U)
-#define RGX_CR_CLK_CTRL_TE_CLRMSK                         (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
-#define RGX_CR_CLK_CTRL_TE_OFF                            (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TE_ON                             (IMG_UINT64_C(0x0000000000000010))
-#define RGX_CR_CLK_CTRL_TE_AUTO                           (IMG_UINT64_C(0x0000000000000020))
-#define RGX_CR_CLK_CTRL_TSP_SHIFT                         (2U)
-#define RGX_CR_CLK_CTRL_TSP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFF3))
-#define RGX_CR_CLK_CTRL_TSP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_TSP_ON                            (IMG_UINT64_C(0x0000000000000004))
-#define RGX_CR_CLK_CTRL_TSP_AUTO                          (IMG_UINT64_C(0x0000000000000008))
-#define RGX_CR_CLK_CTRL_ISP_SHIFT                         (0U)
-#define RGX_CR_CLK_CTRL_ISP_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
-#define RGX_CR_CLK_CTRL_ISP_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL_ISP_ON                            (IMG_UINT64_C(0x0000000000000001))
-#define RGX_CR_CLK_CTRL_ISP_AUTO                          (IMG_UINT64_C(0x0000000000000002))
-#endif /* !defined(RGX_FEATURE_PBE2_IN_XE) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
-
-
-#if defined(RGX_FEATURE_PBE2_IN_XE)
 /*
     Register RGX_CR_CLK_STATUS
 */
 #define RGX_CR_CLK_STATUS                                 (0x0008U)
+#define RGX_CR_CLK_STATUS__PBE2_XE__MASKFULL              (IMG_UINT64_C(0x00000001FFF077FF))
+#define RGX_CR_CLK_STATUS__S7_TOP__MASKFULL               (IMG_UINT64_C(0x00000001B3101773))
 #define RGX_CR_CLK_STATUS_MASKFULL                        (IMG_UINT64_C(0x00000001FFF077FF))
 #define RGX_CR_CLK_STATUS_MCU_FBTC_SHIFT                  (32U)
 #define RGX_CR_CLK_STATUS_MCU_FBTC_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_GATED                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_RUNNING                (IMG_UINT64_C(0x0000000100000000))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+#define RGX_CR_CLK_STATUS_MCU_FBTC_GATED                  (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_MCU_FBTC_RUNNING                (IMG_UINT64_C(0x0000000100000000))  
 #define RGX_CR_CLK_STATUS_BIF_TEXAS_SHIFT                 (31U)
 #define RGX_CR_CLK_STATUS_BIF_TEXAS_CLRMSK                (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_GATED                 (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_RUNNING               (IMG_UINT64_C(0x0000000080000000))
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_GATED                 (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_RUNNING               (IMG_UINT64_C(0x0000000080000000))  
 #define RGX_CR_CLK_STATUS_IPP_SHIFT                       (30U)
 #define RGX_CR_CLK_STATUS_IPP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
-#define RGX_CR_CLK_STATUS_IPP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_IPP_RUNNING                     (IMG_UINT64_C(0x0000000040000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
+#define RGX_CR_CLK_STATUS_IPP_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_IPP_RUNNING                     (IMG_UINT64_C(0x0000000040000000))  
 #define RGX_CR_CLK_STATUS_FBC_SHIFT                       (29U)
 #define RGX_CR_CLK_STATUS_FBC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
-#define RGX_CR_CLK_STATUS_FBC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FBC_RUNNING                     (IMG_UINT64_C(0x0000000020000000))
+#define RGX_CR_CLK_STATUS_FBC_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_FBC_RUNNING                     (IMG_UINT64_C(0x0000000020000000))  
 #define RGX_CR_CLK_STATUS_FBDC_SHIFT                      (28U)
 #define RGX_CR_CLK_STATUS_FBDC_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
-#define RGX_CR_CLK_STATUS_FBDC_GATED                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FBDC_RUNNING                    (IMG_UINT64_C(0x0000000010000000))
+#define RGX_CR_CLK_STATUS_FBDC_GATED                      (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_FBDC_RUNNING                    (IMG_UINT64_C(0x0000000010000000))  
 #define RGX_CR_CLK_STATUS_FB_TLCACHE_SHIFT                (27U)
 #define RGX_CR_CLK_STATUS_FB_TLCACHE_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFF7FFFFFF))
-#define RGX_CR_CLK_STATUS_FB_TLCACHE_GATED                (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FB_TLCACHE_RUNNING              (IMG_UINT64_C(0x0000000008000000))
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_GATED                (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_RUNNING              (IMG_UINT64_C(0x0000000008000000))  
 #define RGX_CR_CLK_STATUS_USCS_SHIFT                      (26U)
 #define RGX_CR_CLK_STATUS_USCS_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
-#define RGX_CR_CLK_STATUS_USCS_GATED                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_USCS_RUNNING                    (IMG_UINT64_C(0x0000000004000000))
+#define RGX_CR_CLK_STATUS_USCS_GATED                      (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_USCS_RUNNING                    (IMG_UINT64_C(0x0000000004000000))  
 #define RGX_CR_CLK_STATUS_PBE_SHIFT                       (25U)
 #define RGX_CR_CLK_STATUS_PBE_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
-#define RGX_CR_CLK_STATUS_PBE_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PBE_RUNNING                     (IMG_UINT64_C(0x0000000002000000))
+#define RGX_CR_CLK_STATUS_PBE_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_PBE_RUNNING                     (IMG_UINT64_C(0x0000000002000000))  
 #define RGX_CR_CLK_STATUS_MCU_L1_SHIFT                    (24U)
 #define RGX_CR_CLK_STATUS_MCU_L1_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
-#define RGX_CR_CLK_STATUS_MCU_L1_GATED                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_L1_RUNNING                  (IMG_UINT64_C(0x0000000001000000))
-#if defined(RGX_FEATURE_COMPUTE)
+#define RGX_CR_CLK_STATUS_MCU_L1_GATED                    (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_MCU_L1_RUNNING                  (IMG_UINT64_C(0x0000000001000000))  
 #define RGX_CR_CLK_STATUS_CDM_SHIFT                       (23U)
 #define RGX_CR_CLK_STATUS_CDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
-#define RGX_CR_CLK_STATUS_CDM_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_CDM_RUNNING                     (IMG_UINT64_C(0x0000000000800000))
-#endif /* RGX_FEATURE_COMPUTE */
-
+#define RGX_CR_CLK_STATUS_CDM_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_CDM_RUNNING                     (IMG_UINT64_C(0x0000000000800000))  
 #define RGX_CR_CLK_STATUS_SIDEKICK_SHIFT                  (22U)
 #define RGX_CR_CLK_STATUS_SIDEKICK_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFFFFBFFFFF))
-#define RGX_CR_CLK_STATUS_SIDEKICK_GATED                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_SIDEKICK_RUNNING                (IMG_UINT64_C(0x0000000000400000))
+#define RGX_CR_CLK_STATUS_SIDEKICK_GATED                  (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_SIDEKICK_RUNNING                (IMG_UINT64_C(0x0000000000400000))  
 #define RGX_CR_CLK_STATUS_BIF_SIDEKICK_SHIFT              (21U)
 #define RGX_CR_CLK_STATUS_BIF_SIDEKICK_CLRMSK             (IMG_UINT64_C(0XFFFFFFFFFFDFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_GATED              (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_RUNNING            (IMG_UINT64_C(0x0000000000200000))
+#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_GATED              (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_RUNNING            (IMG_UINT64_C(0x0000000000200000))  
 #define RGX_CR_CLK_STATUS_BIF_SHIFT                       (20U)
 #define RGX_CR_CLK_STATUS_BIF_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_RUNNING                     (IMG_UINT64_C(0x0000000000100000))
+#define RGX_CR_CLK_STATUS_BIF_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_BIF_RUNNING                     (IMG_UINT64_C(0x0000000000100000))  
 #define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_SHIFT             (14U)
 #define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_CLRMSK            (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
-#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_GATED             (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_RUNNING           (IMG_UINT64_C(0x0000000000004000))
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_GATED             (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_RUNNING           (IMG_UINT64_C(0x0000000000004000))  
 #define RGX_CR_CLK_STATUS_MCU_L0_SHIFT                    (13U)
 #define RGX_CR_CLK_STATUS_MCU_L0_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
-#define RGX_CR_CLK_STATUS_MCU_L0_GATED                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_L0_RUNNING                  (IMG_UINT64_C(0x0000000000002000))
+#define RGX_CR_CLK_STATUS_MCU_L0_GATED                    (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_MCU_L0_RUNNING                  (IMG_UINT64_C(0x0000000000002000))  
 #define RGX_CR_CLK_STATUS_TPU_SHIFT                       (12U)
 #define RGX_CR_CLK_STATUS_TPU_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
-#define RGX_CR_CLK_STATUS_TPU_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TPU_RUNNING                     (IMG_UINT64_C(0x0000000000001000))
+#define RGX_CR_CLK_STATUS_TPU_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_TPU_RUNNING                     (IMG_UINT64_C(0x0000000000001000))  
 #define RGX_CR_CLK_STATUS_USC_SHIFT                       (10U)
 #define RGX_CR_CLK_STATUS_USC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
-#define RGX_CR_CLK_STATUS_USC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_USC_RUNNING                     (IMG_UINT64_C(0x0000000000000400))
+#define RGX_CR_CLK_STATUS_USC_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_USC_RUNNING                     (IMG_UINT64_C(0x0000000000000400))  
 #define RGX_CR_CLK_STATUS_TLA_SHIFT                       (9U)
 #define RGX_CR_CLK_STATUS_TLA_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
-#define RGX_CR_CLK_STATUS_TLA_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TLA_RUNNING                     (IMG_UINT64_C(0x0000000000000200))
+#define RGX_CR_CLK_STATUS_TLA_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_TLA_RUNNING                     (IMG_UINT64_C(0x0000000000000200))  
 #define RGX_CR_CLK_STATUS_SLC_SHIFT                       (8U)
 #define RGX_CR_CLK_STATUS_SLC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
-#define RGX_CR_CLK_STATUS_SLC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_SLC_RUNNING                     (IMG_UINT64_C(0x0000000000000100))
+#define RGX_CR_CLK_STATUS_SLC_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_SLC_RUNNING                     (IMG_UINT64_C(0x0000000000000100))  
 #define RGX_CR_CLK_STATUS_UVS_SHIFT                       (7U)
 #define RGX_CR_CLK_STATUS_UVS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFF7F))
-#define RGX_CR_CLK_STATUS_UVS_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_UVS_RUNNING                     (IMG_UINT64_C(0x0000000000000080))
+#define RGX_CR_CLK_STATUS_UVS_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_UVS_RUNNING                     (IMG_UINT64_C(0x0000000000000080))  
 #define RGX_CR_CLK_STATUS_PDS_SHIFT                       (6U)
 #define RGX_CR_CLK_STATUS_PDS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
-#define RGX_CR_CLK_STATUS_PDS_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PDS_RUNNING                     (IMG_UINT64_C(0x0000000000000040))
+#define RGX_CR_CLK_STATUS_PDS_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_PDS_RUNNING                     (IMG_UINT64_C(0x0000000000000040))  
 #define RGX_CR_CLK_STATUS_VDM_SHIFT                       (5U)
 #define RGX_CR_CLK_STATUS_VDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
-#define RGX_CR_CLK_STATUS_VDM_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_VDM_RUNNING                     (IMG_UINT64_C(0x0000000000000020))
+#define RGX_CR_CLK_STATUS_VDM_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_VDM_RUNNING                     (IMG_UINT64_C(0x0000000000000020))  
 #define RGX_CR_CLK_STATUS_PM_SHIFT                        (4U)
 #define RGX_CR_CLK_STATUS_PM_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
-#define RGX_CR_CLK_STATUS_PM_GATED                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PM_RUNNING                      (IMG_UINT64_C(0x0000000000000010))
+#define RGX_CR_CLK_STATUS_PM_GATED                        (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_PM_RUNNING                      (IMG_UINT64_C(0x0000000000000010))  
 #define RGX_CR_CLK_STATUS_GPP_SHIFT                       (3U)
 #define RGX_CR_CLK_STATUS_GPP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
-#define RGX_CR_CLK_STATUS_GPP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_GPP_RUNNING                     (IMG_UINT64_C(0x0000000000000008))
+#define RGX_CR_CLK_STATUS_GPP_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_GPP_RUNNING                     (IMG_UINT64_C(0x0000000000000008))  
 #define RGX_CR_CLK_STATUS_TE_SHIFT                        (2U)
 #define RGX_CR_CLK_STATUS_TE_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
-#define RGX_CR_CLK_STATUS_TE_GATED                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TE_RUNNING                      (IMG_UINT64_C(0x0000000000000004))
+#define RGX_CR_CLK_STATUS_TE_GATED                        (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_TE_RUNNING                      (IMG_UINT64_C(0x0000000000000004))  
 #define RGX_CR_CLK_STATUS_TSP_SHIFT                       (1U)
 #define RGX_CR_CLK_STATUS_TSP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
-#define RGX_CR_CLK_STATUS_TSP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TSP_RUNNING                     (IMG_UINT64_C(0x0000000000000002))
+#define RGX_CR_CLK_STATUS_TSP_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_TSP_RUNNING                     (IMG_UINT64_C(0x0000000000000002))  
 #define RGX_CR_CLK_STATUS_ISP_SHIFT                       (0U)
 #define RGX_CR_CLK_STATUS_ISP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_CLK_STATUS_ISP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_ISP_RUNNING                     (IMG_UINT64_C(0x0000000000000001))
-#endif /* RGX_FEATURE_PBE2_IN_XE */ 
+#define RGX_CR_CLK_STATUS_ISP_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS_ISP_RUNNING                     (IMG_UINT64_C(0x0000000000000001))  
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 /*
-    Register RGX_CR_CLK_STATUS
+    Register RGX_CR_CORE_ID
 */
-#define RGX_CR_CLK_STATUS                                 (0x0008U)
-#define RGX_CR_CLK_STATUS_MASKFULL                        (IMG_UINT64_C(0x00000001B3101773))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_SHIFT                  (32U)
-#define RGX_CR_CLK_STATUS_MCU_FBTC_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_GATED                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_RUNNING                (IMG_UINT64_C(0x0000000100000000))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_SHIFT                 (31U)
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_CLRMSK                (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_GATED                 (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_RUNNING               (IMG_UINT64_C(0x0000000080000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
-#define RGX_CR_CLK_STATUS_FBC_SHIFT                       (29U)
-#define RGX_CR_CLK_STATUS_FBC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
-#define RGX_CR_CLK_STATUS_FBC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FBC_RUNNING                     (IMG_UINT64_C(0x0000000020000000))
-#define RGX_CR_CLK_STATUS_FBDC_SHIFT                      (28U)
-#define RGX_CR_CLK_STATUS_FBDC_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
-#define RGX_CR_CLK_STATUS_FBDC_GATED                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FBDC_RUNNING                    (IMG_UINT64_C(0x0000000010000000))
-#define RGX_CR_CLK_STATUS_PBE_SHIFT                       (25U)
-#define RGX_CR_CLK_STATUS_PBE_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
-#define RGX_CR_CLK_STATUS_PBE_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PBE_RUNNING                     (IMG_UINT64_C(0x0000000002000000))
-#define RGX_CR_CLK_STATUS_MCU_L1_SHIFT                    (24U)
-#define RGX_CR_CLK_STATUS_MCU_L1_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
-#define RGX_CR_CLK_STATUS_MCU_L1_GATED                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_L1_RUNNING                  (IMG_UINT64_C(0x0000000001000000))
-#define RGX_CR_CLK_STATUS_BIF_SHIFT                       (20U)
-#define RGX_CR_CLK_STATUS_BIF_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_RUNNING                     (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_CLK_STATUS_TPU_SHIFT                       (12U)
-#define RGX_CR_CLK_STATUS_TPU_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
-#define RGX_CR_CLK_STATUS_TPU_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TPU_RUNNING                     (IMG_UINT64_C(0x0000000000001000))
-#define RGX_CR_CLK_STATUS_USC_SHIFT                       (10U)
-#define RGX_CR_CLK_STATUS_USC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
-#define RGX_CR_CLK_STATUS_USC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_USC_RUNNING                     (IMG_UINT64_C(0x0000000000000400))
-#define RGX_CR_CLK_STATUS_TLA_SHIFT                       (9U)
-#define RGX_CR_CLK_STATUS_TLA_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
-#define RGX_CR_CLK_STATUS_TLA_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TLA_RUNNING                     (IMG_UINT64_C(0x0000000000000200))
-#define RGX_CR_CLK_STATUS_SLC_SHIFT                       (8U)
-#define RGX_CR_CLK_STATUS_SLC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
-#define RGX_CR_CLK_STATUS_SLC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_SLC_RUNNING                     (IMG_UINT64_C(0x0000000000000100))
-#define RGX_CR_CLK_STATUS_PDS_SHIFT                       (6U)
-#define RGX_CR_CLK_STATUS_PDS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
-#define RGX_CR_CLK_STATUS_PDS_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PDS_RUNNING                     (IMG_UINT64_C(0x0000000000000040))
-#define RGX_CR_CLK_STATUS_VDM_SHIFT                       (5U)
-#define RGX_CR_CLK_STATUS_VDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
-#define RGX_CR_CLK_STATUS_VDM_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_VDM_RUNNING                     (IMG_UINT64_C(0x0000000000000020))
-#define RGX_CR_CLK_STATUS_PM_SHIFT                        (4U)
-#define RGX_CR_CLK_STATUS_PM_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
-#define RGX_CR_CLK_STATUS_PM_GATED                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PM_RUNNING                      (IMG_UINT64_C(0x0000000000000010))
-#define RGX_CR_CLK_STATUS_TSP_SHIFT                       (1U)
-#define RGX_CR_CLK_STATUS_TSP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
-#define RGX_CR_CLK_STATUS_TSP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TSP_RUNNING                     (IMG_UINT64_C(0x0000000000000002))
-#define RGX_CR_CLK_STATUS_ISP_SHIFT                       (0U)
-#define RGX_CR_CLK_STATUS_ISP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_CLK_STATUS_ISP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_ISP_RUNNING                     (IMG_UINT64_C(0x0000000000000001))
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */ 
-
-
-#if !defined(RGX_FEATURE_PBE2_IN_XE) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-/*
-    Register RGX_CR_CLK_STATUS
-*/
-#define RGX_CR_CLK_STATUS                                 (0x0008U)
-#define RGX_CR_CLK_STATUS_MASKFULL                        (IMG_UINT64_C(0x00000001FFF077FF))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_SHIFT                  (32U)
-#define RGX_CR_CLK_STATUS_MCU_FBTC_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_GATED                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_FBTC_RUNNING                (IMG_UINT64_C(0x0000000100000000))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_SHIFT                 (31U)
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_CLRMSK                (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_GATED                 (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_TEXAS_RUNNING               (IMG_UINT64_C(0x0000000080000000))
-#define RGX_CR_CLK_STATUS_IPP_SHIFT                       (30U)
-#define RGX_CR_CLK_STATUS_IPP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
-#define RGX_CR_CLK_STATUS_IPP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_IPP_RUNNING                     (IMG_UINT64_C(0x0000000040000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
-#define RGX_CR_CLK_STATUS_FBC_SHIFT                       (29U)
-#define RGX_CR_CLK_STATUS_FBC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
-#define RGX_CR_CLK_STATUS_FBC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FBC_RUNNING                     (IMG_UINT64_C(0x0000000020000000))
-#define RGX_CR_CLK_STATUS_FBDC_SHIFT                      (28U)
-#define RGX_CR_CLK_STATUS_FBDC_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
-#define RGX_CR_CLK_STATUS_FBDC_GATED                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FBDC_RUNNING                    (IMG_UINT64_C(0x0000000010000000))
-#define RGX_CR_CLK_STATUS_FB_TLCACHE_SHIFT                (27U)
-#define RGX_CR_CLK_STATUS_FB_TLCACHE_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFF7FFFFFF))
-#define RGX_CR_CLK_STATUS_FB_TLCACHE_GATED                (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_FB_TLCACHE_RUNNING              (IMG_UINT64_C(0x0000000008000000))
-#define RGX_CR_CLK_STATUS_USCS_SHIFT                      (26U)
-#define RGX_CR_CLK_STATUS_USCS_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
-#define RGX_CR_CLK_STATUS_USCS_GATED                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_USCS_RUNNING                    (IMG_UINT64_C(0x0000000004000000))
-#define RGX_CR_CLK_STATUS_PBE_SHIFT                       (25U)
-#define RGX_CR_CLK_STATUS_PBE_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
-#define RGX_CR_CLK_STATUS_PBE_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PBE_RUNNING                     (IMG_UINT64_C(0x0000000002000000))
-#define RGX_CR_CLK_STATUS_MCU_L1_SHIFT                    (24U)
-#define RGX_CR_CLK_STATUS_MCU_L1_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
-#define RGX_CR_CLK_STATUS_MCU_L1_GATED                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_L1_RUNNING                  (IMG_UINT64_C(0x0000000001000000))
-#if defined(RGX_FEATURE_COMPUTE)
-#define RGX_CR_CLK_STATUS_CDM_SHIFT                       (23U)
-#define RGX_CR_CLK_STATUS_CDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
-#define RGX_CR_CLK_STATUS_CDM_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_CDM_RUNNING                     (IMG_UINT64_C(0x0000000000800000))
-#endif /* RGX_FEATURE_COMPUTE */
-
-#define RGX_CR_CLK_STATUS_SIDEKICK_SHIFT                  (22U)
-#define RGX_CR_CLK_STATUS_SIDEKICK_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFFFFBFFFFF))
-#define RGX_CR_CLK_STATUS_SIDEKICK_GATED                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_SIDEKICK_RUNNING                (IMG_UINT64_C(0x0000000000400000))
-#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_SHIFT              (21U)
-#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_CLRMSK             (IMG_UINT64_C(0XFFFFFFFFFFDFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_GATED              (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_RUNNING            (IMG_UINT64_C(0x0000000000200000))
-#define RGX_CR_CLK_STATUS_BIF_SHIFT                       (20U)
-#define RGX_CR_CLK_STATUS_BIF_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
-#define RGX_CR_CLK_STATUS_BIF_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_BIF_RUNNING                     (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_SHIFT             (14U)
-#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_CLRMSK            (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
-#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_GATED             (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_RUNNING           (IMG_UINT64_C(0x0000000000004000))
-#define RGX_CR_CLK_STATUS_MCU_L0_SHIFT                    (13U)
-#define RGX_CR_CLK_STATUS_MCU_L0_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
-#define RGX_CR_CLK_STATUS_MCU_L0_GATED                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_MCU_L0_RUNNING                  (IMG_UINT64_C(0x0000000000002000))
-#define RGX_CR_CLK_STATUS_TPU_SHIFT                       (12U)
-#define RGX_CR_CLK_STATUS_TPU_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
-#define RGX_CR_CLK_STATUS_TPU_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TPU_RUNNING                     (IMG_UINT64_C(0x0000000000001000))
-#define RGX_CR_CLK_STATUS_USC_SHIFT                       (10U)
-#define RGX_CR_CLK_STATUS_USC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
-#define RGX_CR_CLK_STATUS_USC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_USC_RUNNING                     (IMG_UINT64_C(0x0000000000000400))
-#define RGX_CR_CLK_STATUS_TLA_SHIFT                       (9U)
-#define RGX_CR_CLK_STATUS_TLA_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
-#define RGX_CR_CLK_STATUS_TLA_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TLA_RUNNING                     (IMG_UINT64_C(0x0000000000000200))
-#define RGX_CR_CLK_STATUS_SLC_SHIFT                       (8U)
-#define RGX_CR_CLK_STATUS_SLC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
-#define RGX_CR_CLK_STATUS_SLC_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_SLC_RUNNING                     (IMG_UINT64_C(0x0000000000000100))
-#define RGX_CR_CLK_STATUS_UVS_SHIFT                       (7U)
-#define RGX_CR_CLK_STATUS_UVS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFF7F))
-#define RGX_CR_CLK_STATUS_UVS_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_UVS_RUNNING                     (IMG_UINT64_C(0x0000000000000080))
-#define RGX_CR_CLK_STATUS_PDS_SHIFT                       (6U)
-#define RGX_CR_CLK_STATUS_PDS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
-#define RGX_CR_CLK_STATUS_PDS_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PDS_RUNNING                     (IMG_UINT64_C(0x0000000000000040))
-#define RGX_CR_CLK_STATUS_VDM_SHIFT                       (5U)
-#define RGX_CR_CLK_STATUS_VDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
-#define RGX_CR_CLK_STATUS_VDM_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_VDM_RUNNING                     (IMG_UINT64_C(0x0000000000000020))
-#define RGX_CR_CLK_STATUS_PM_SHIFT                        (4U)
-#define RGX_CR_CLK_STATUS_PM_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
-#define RGX_CR_CLK_STATUS_PM_GATED                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_PM_RUNNING                      (IMG_UINT64_C(0x0000000000000010))
-#define RGX_CR_CLK_STATUS_GPP_SHIFT                       (3U)
-#define RGX_CR_CLK_STATUS_GPP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
-#define RGX_CR_CLK_STATUS_GPP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_GPP_RUNNING                     (IMG_UINT64_C(0x0000000000000008))
-#define RGX_CR_CLK_STATUS_TE_SHIFT                        (2U)
-#define RGX_CR_CLK_STATUS_TE_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
-#define RGX_CR_CLK_STATUS_TE_GATED                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TE_RUNNING                      (IMG_UINT64_C(0x0000000000000004))
-#define RGX_CR_CLK_STATUS_TSP_SHIFT                       (1U)
-#define RGX_CR_CLK_STATUS_TSP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
-#define RGX_CR_CLK_STATUS_TSP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_TSP_RUNNING                     (IMG_UINT64_C(0x0000000000000002))
-#define RGX_CR_CLK_STATUS_ISP_SHIFT                       (0U)
-#define RGX_CR_CLK_STATUS_ISP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_CLK_STATUS_ISP_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS_ISP_RUNNING                     (IMG_UINT64_C(0x0000000000000001))
-#endif /* !defined(RGX_FEATURE_PBE2_IN_XE) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
+#define RGX_CR_CORE_ID__PBVNC                             (0x0020U)
+#define RGX_CR_CORE_ID__PBVNC__MASKFULL                   (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+#define RGX_CR_CORE_ID__PBVNC__BRANCH_ID_SHIFT            (48U)
+#define RGX_CR_CORE_ID__PBVNC__BRANCH_ID_CLRMSK           (IMG_UINT64_C(0X0000FFFFFFFFFFFF))
+#define RGX_CR_CORE_ID__PBVNC__VERSION_ID_SHIFT           (32U)
+#define RGX_CR_CORE_ID__PBVNC__VERSION_ID_CLRMSK          (IMG_UINT64_C(0XFFFF0000FFFFFFFF))
+#define RGX_CR_CORE_ID__PBVNC__NUMBER_OF_SCALABLE_UNITS_SHIFT (16U)
+#define RGX_CR_CORE_ID__PBVNC__NUMBER_OF_SCALABLE_UNITS_CLRMSK (IMG_UINT64_C(0XFFFFFFFF0000FFFF))
+#define RGX_CR_CORE_ID__PBVNC__CONFIG_ID_SHIFT            (0U)
+#define RGX_CR_CORE_ID__PBVNC__CONFIG_ID_CLRMSK           (IMG_UINT64_C(0XFFFFFFFFFFFF0000))
 
 
 /*
@@ -897,64 +484,61 @@
 */
 #define RGX_CR_CLK_XTPLUS_CTRL                            (0x0080U)
 #define RGX_CR_CLK_XTPLUS_CTRL_MASKFULL                   (IMG_UINT64_C(0x0000003FFFFF0000))
-#if defined(RGX_FEATURE_FASTRENDER_DM)
 #define RGX_CR_CLK_XTPLUS_CTRL_TDM_SHIFT                  (36U)
 #define RGX_CR_CLK_XTPLUS_CTRL_TDM_CLRMSK                 (IMG_UINT64_C(0XFFFFFFCFFFFFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_TDM_OFF                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_TDM_ON                     (IMG_UINT64_C(0x0000001000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_TDM_AUTO                   (IMG_UINT64_C(0x0000002000000000))
-#endif /* RGX_FEATURE_FASTRENDER_DM */
-
+#define RGX_CR_CLK_XTPLUS_CTRL_TDM_OFF                    (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_TDM_ON                     (IMG_UINT64_C(0x0000001000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_TDM_AUTO                   (IMG_UINT64_C(0x0000002000000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_ASTC_SHIFT                 (34U)
 #define RGX_CR_CLK_XTPLUS_CTRL_ASTC_CLRMSK                (IMG_UINT64_C(0XFFFFFFF3FFFFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_ASTC_OFF                   (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_ASTC_ON                    (IMG_UINT64_C(0x0000000400000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_ASTC_AUTO                  (IMG_UINT64_C(0x0000000800000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_ASTC_OFF                   (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_ASTC_ON                    (IMG_UINT64_C(0x0000000400000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_ASTC_AUTO                  (IMG_UINT64_C(0x0000000800000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_IPF_SHIFT                  (32U)
 #define RGX_CR_CLK_XTPLUS_CTRL_IPF_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFCFFFFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_IPF_OFF                    (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_IPF_ON                     (IMG_UINT64_C(0x0000000100000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_IPF_AUTO                   (IMG_UINT64_C(0x0000000200000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_OFF                    (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_ON                     (IMG_UINT64_C(0x0000000100000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_AUTO                   (IMG_UINT64_C(0x0000000200000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_SHIFT              (30U)
 #define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_CLRMSK             (IMG_UINT64_C(0XFFFFFFFF3FFFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_OFF                (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_ON                 (IMG_UINT64_C(0x0000000040000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_AUTO               (IMG_UINT64_C(0x0000000080000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_OFF                (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_ON                 (IMG_UINT64_C(0x0000000040000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_AUTO               (IMG_UINT64_C(0x0000000080000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_SHIFT                (28U)
 #define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFCFFFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_OFF                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_ON                   (IMG_UINT64_C(0x0000000010000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_AUTO                 (IMG_UINT64_C(0x0000000020000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_OFF                  (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_ON                   (IMG_UINT64_C(0x0000000010000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_AUTO                 (IMG_UINT64_C(0x0000000020000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_SHIFT               (26U)
 #define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_OFF                 (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_ON                  (IMG_UINT64_C(0x0000000004000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_AUTO                (IMG_UINT64_C(0x0000000008000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_OFF                 (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_ON                  (IMG_UINT64_C(0x0000000004000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_AUTO                (IMG_UINT64_C(0x0000000008000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_USCPS_SHIFT                (24U)
 #define RGX_CR_CLK_XTPLUS_CTRL_USCPS_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_OFF                  (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_ON                   (IMG_UINT64_C(0x0000000001000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_AUTO                 (IMG_UINT64_C(0x0000000002000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_OFF                  (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_ON                   (IMG_UINT64_C(0x0000000001000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_AUTO                 (IMG_UINT64_C(0x0000000002000000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_SHIFT           (22U)
 #define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_CLRMSK          (IMG_UINT64_C(0XFFFFFFFFFF3FFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_OFF             (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_ON              (IMG_UINT64_C(0x0000000000400000))
-#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_AUTO            (IMG_UINT64_C(0x0000000000800000))
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_OFF             (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_ON              (IMG_UINT64_C(0x0000000000400000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_AUTO            (IMG_UINT64_C(0x0000000000800000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_SHIFT       (20U)
 #define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_OFF         (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_ON          (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_AUTO        (IMG_UINT64_C(0x0000000000200000))
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_OFF         (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_ON          (IMG_UINT64_C(0x0000000000100000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_AUTO        (IMG_UINT64_C(0x0000000000200000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_SHIFT           (18U)
 #define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_CLRMSK          (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_OFF             (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_ON              (IMG_UINT64_C(0x0000000000040000))
-#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_AUTO            (IMG_UINT64_C(0x0000000000080000))
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_OFF             (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_ON              (IMG_UINT64_C(0x0000000000040000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_AUTO            (IMG_UINT64_C(0x0000000000080000))  
 #define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_SHIFT             (16U)
 #define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_CLRMSK            (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
-#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_OFF               (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_ON                (IMG_UINT64_C(0x0000000000010000))
-#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_AUTO              (IMG_UINT64_C(0x0000000000020000))
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_OFF               (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_ON                (IMG_UINT64_C(0x0000000000010000))  
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_AUTO              (IMG_UINT64_C(0x0000000000020000))  
 
 
 /*
@@ -962,254 +546,82 @@
 */
 #define RGX_CR_CLK_XTPLUS_STATUS                          (0x0088U)
 #define RGX_CR_CLK_XTPLUS_STATUS_MASKFULL                 (IMG_UINT64_C(0x00000000000007FF))
-#if defined(RGX_FEATURE_FASTRENDER_DM)
 #define RGX_CR_CLK_XTPLUS_STATUS_TDM_SHIFT                (10U)
 #define RGX_CR_CLK_XTPLUS_STATUS_TDM_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
-#define RGX_CR_CLK_XTPLUS_STATUS_TDM_GATED                (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_TDM_RUNNING              (IMG_UINT64_C(0x0000000000000400))
-#endif /* RGX_FEATURE_FASTRENDER_DM */
-
+#define RGX_CR_CLK_XTPLUS_STATUS_TDM_GATED                (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_TDM_RUNNING              (IMG_UINT64_C(0x0000000000000400))  
 #define RGX_CR_CLK_XTPLUS_STATUS_IPF_SHIFT                (9U)
 #define RGX_CR_CLK_XTPLUS_STATUS_IPF_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
-#define RGX_CR_CLK_XTPLUS_STATUS_IPF_GATED                (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_IPF_RUNNING              (IMG_UINT64_C(0x0000000000000200))
+#define RGX_CR_CLK_XTPLUS_STATUS_IPF_GATED                (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_IPF_RUNNING              (IMG_UINT64_C(0x0000000000000200))  
 #define RGX_CR_CLK_XTPLUS_STATUS_COMPUTE_SHIFT            (8U)
 #define RGX_CR_CLK_XTPLUS_STATUS_COMPUTE_CLRMSK           (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
-#define RGX_CR_CLK_XTPLUS_STATUS_COMPUTE_GATED            (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_COMPUTE_RUNNING          (IMG_UINT64_C(0x0000000000000100))
+#define RGX_CR_CLK_XTPLUS_STATUS_COMPUTE_GATED            (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_COMPUTE_RUNNING          (IMG_UINT64_C(0x0000000000000100))  
 #define RGX_CR_CLK_XTPLUS_STATUS_ASTC_SHIFT               (7U)
 #define RGX_CR_CLK_XTPLUS_STATUS_ASTC_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFFFFFFF7F))
-#define RGX_CR_CLK_XTPLUS_STATUS_ASTC_GATED               (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_ASTC_RUNNING             (IMG_UINT64_C(0x0000000000000080))
+#define RGX_CR_CLK_XTPLUS_STATUS_ASTC_GATED               (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_ASTC_RUNNING             (IMG_UINT64_C(0x0000000000000080))  
 #define RGX_CR_CLK_XTPLUS_STATUS_PIXEL_SHIFT              (6U)
 #define RGX_CR_CLK_XTPLUS_STATUS_PIXEL_CLRMSK             (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
-#define RGX_CR_CLK_XTPLUS_STATUS_PIXEL_GATED              (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_PIXEL_RUNNING            (IMG_UINT64_C(0x0000000000000040))
+#define RGX_CR_CLK_XTPLUS_STATUS_PIXEL_GATED              (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_PIXEL_RUNNING            (IMG_UINT64_C(0x0000000000000040))  
 #define RGX_CR_CLK_XTPLUS_STATUS_VERTEX_SHIFT             (5U)
 #define RGX_CR_CLK_XTPLUS_STATUS_VERTEX_CLRMSK            (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
-#define RGX_CR_CLK_XTPLUS_STATUS_VERTEX_GATED             (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_VERTEX_RUNNING           (IMG_UINT64_C(0x0000000000000020))
+#define RGX_CR_CLK_XTPLUS_STATUS_VERTEX_GATED             (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_VERTEX_RUNNING           (IMG_UINT64_C(0x0000000000000020))  
 #define RGX_CR_CLK_XTPLUS_STATUS_USCPS_SHIFT              (4U)
 #define RGX_CR_CLK_XTPLUS_STATUS_USCPS_CLRMSK             (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
-#define RGX_CR_CLK_XTPLUS_STATUS_USCPS_GATED              (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_USCPS_RUNNING            (IMG_UINT64_C(0x0000000000000010))
+#define RGX_CR_CLK_XTPLUS_STATUS_USCPS_GATED              (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_USCPS_RUNNING            (IMG_UINT64_C(0x0000000000000010))  
 #define RGX_CR_CLK_XTPLUS_STATUS_PDS_SHARED_SHIFT         (3U)
 #define RGX_CR_CLK_XTPLUS_STATUS_PDS_SHARED_CLRMSK        (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
-#define RGX_CR_CLK_XTPLUS_STATUS_PDS_SHARED_GATED         (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_PDS_SHARED_RUNNING       (IMG_UINT64_C(0x0000000000000008))
+#define RGX_CR_CLK_XTPLUS_STATUS_PDS_SHARED_GATED         (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_PDS_SHARED_RUNNING       (IMG_UINT64_C(0x0000000000000008))  
 #define RGX_CR_CLK_XTPLUS_STATUS_BIF_BLACKPEARL_SHIFT     (2U)
 #define RGX_CR_CLK_XTPLUS_STATUS_BIF_BLACKPEARL_CLRMSK    (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
-#define RGX_CR_CLK_XTPLUS_STATUS_BIF_BLACKPEARL_GATED     (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_BIF_BLACKPEARL_RUNNING   (IMG_UINT64_C(0x0000000000000004))
+#define RGX_CR_CLK_XTPLUS_STATUS_BIF_BLACKPEARL_GATED     (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_BIF_BLACKPEARL_RUNNING   (IMG_UINT64_C(0x0000000000000004))  
 #define RGX_CR_CLK_XTPLUS_STATUS_USC_SHARED_SHIFT         (1U)
 #define RGX_CR_CLK_XTPLUS_STATUS_USC_SHARED_CLRMSK        (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
-#define RGX_CR_CLK_XTPLUS_STATUS_USC_SHARED_GATED         (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_USC_SHARED_RUNNING       (IMG_UINT64_C(0x0000000000000002))
+#define RGX_CR_CLK_XTPLUS_STATUS_USC_SHARED_GATED         (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_USC_SHARED_RUNNING       (IMG_UINT64_C(0x0000000000000002))  
 #define RGX_CR_CLK_XTPLUS_STATUS_GEOMETRY_SHIFT           (0U)
 #define RGX_CR_CLK_XTPLUS_STATUS_GEOMETRY_CLRMSK          (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_CLK_XTPLUS_STATUS_GEOMETRY_GATED           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_XTPLUS_STATUS_GEOMETRY_RUNNING         (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_CLK_XTPLUS_STATUS_GEOMETRY_GATED           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_XTPLUS_STATUS_GEOMETRY_RUNNING         (IMG_UINT64_C(0x0000000000000001))  
 
 
-#if defined(RGX_FEATURE_PBE2_IN_XE)
 /*
     Register RGX_CR_SOFT_RESET
 */
 #define RGX_CR_SOFT_RESET                                 (0x0100U)
-#define RGX_CR_SOFT_RESET_MASKFULL                        (IMG_UINT64_C(0xFFE7FFFFFFFFFC1D))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_CR_SOFT_RESET_PHANTOM3_CORE_SHIFT             (63U)
-#define RGX_CR_SOFT_RESET_PHANTOM3_CORE_CLRMSK            (IMG_UINT64_C(0X7FFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_PHANTOM3_CORE_EN                (IMG_UINT64_C(0X8000000000000000))
-#define RGX_CR_SOFT_RESET_PHANTOM2_CORE_SHIFT             (62U)
-#define RGX_CR_SOFT_RESET_PHANTOM2_CORE_CLRMSK            (IMG_UINT64_C(0XBFFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_PHANTOM2_CORE_EN                (IMG_UINT64_C(0X4000000000000000))
-#define RGX_CR_SOFT_RESET_BERNADO2_CORE_SHIFT             (61U)
-#define RGX_CR_SOFT_RESET_BERNADO2_CORE_CLRMSK            (IMG_UINT64_C(0XDFFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_BERNADO2_CORE_EN                (IMG_UINT64_C(0X2000000000000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
-#define RGX_CR_SOFT_RESET_JONES_CORE_SHIFT                (60U)
-#define RGX_CR_SOFT_RESET_JONES_CORE_CLRMSK               (IMG_UINT64_C(0XEFFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_JONES_CORE_EN                   (IMG_UINT64_C(0X1000000000000000))
-#define RGX_CR_SOFT_RESET_TILING_CORE_SHIFT               (59U)
-#define RGX_CR_SOFT_RESET_TILING_CORE_CLRMSK              (IMG_UINT64_C(0XF7FFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_TILING_CORE_EN                  (IMG_UINT64_C(0X0800000000000000))
-#define RGX_CR_SOFT_RESET_TE3_SHIFT                       (58U)
-#define RGX_CR_SOFT_RESET_TE3_CLRMSK                      (IMG_UINT64_C(0XFBFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_TE3_EN                          (IMG_UINT64_C(0X0400000000000000))
-#define RGX_CR_SOFT_RESET_VCE_SHIFT                       (57U)
-#define RGX_CR_SOFT_RESET_VCE_CLRMSK                      (IMG_UINT64_C(0XFDFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_VCE_EN                          (IMG_UINT64_C(0X0200000000000000))
-#define RGX_CR_SOFT_RESET_VBS_SHIFT                       (56U)
-#define RGX_CR_SOFT_RESET_VBS_CLRMSK                      (IMG_UINT64_C(0XFEFFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_VBS_EN                          (IMG_UINT64_C(0X0100000000000000))
-#if defined(RGX_FEATURE_RAY_TRACING)
-#define RGX_CR_SOFT_RESET_DPX1_CORE_SHIFT                 (55U)
-#define RGX_CR_SOFT_RESET_DPX1_CORE_CLRMSK                (IMG_UINT64_C(0XFF7FFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DPX1_CORE_EN                    (IMG_UINT64_C(0X0080000000000000))
-#define RGX_CR_SOFT_RESET_DPX0_CORE_SHIFT                 (54U)
-#define RGX_CR_SOFT_RESET_DPX0_CORE_CLRMSK                (IMG_UINT64_C(0XFFBFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DPX0_CORE_EN                    (IMG_UINT64_C(0X0040000000000000))
-#define RGX_CR_SOFT_RESET_FBA_SHIFT                       (53U)
-#define RGX_CR_SOFT_RESET_FBA_CLRMSK                      (IMG_UINT64_C(0XFFDFFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_FBA_EN                          (IMG_UINT64_C(0X0020000000000000))
-#define RGX_CR_SOFT_RESET_SH_SHIFT                        (50U)
-#define RGX_CR_SOFT_RESET_SH_CLRMSK                       (IMG_UINT64_C(0XFFFBFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_SH_EN                           (IMG_UINT64_C(0X0004000000000000))
-#define RGX_CR_SOFT_RESET_VRDM_SHIFT                      (49U)
-#define RGX_CR_SOFT_RESET_VRDM_CLRMSK                     (IMG_UINT64_C(0XFFFDFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_VRDM_EN                         (IMG_UINT64_C(0X0002000000000000))
-#endif /* RGX_FEATURE_RAY_TRACING */
-
-#define RGX_CR_SOFT_RESET_MCU_FBTC_SHIFT                  (48U)
-#define RGX_CR_SOFT_RESET_MCU_FBTC_CLRMSK                 (IMG_UINT64_C(0XFFFEFFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_MCU_FBTC_EN                     (IMG_UINT64_C(0X0001000000000000))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_CR_SOFT_RESET_PHANTOM1_CORE_SHIFT             (47U)
-#define RGX_CR_SOFT_RESET_PHANTOM1_CORE_CLRMSK            (IMG_UINT64_C(0XFFFF7FFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_PHANTOM1_CORE_EN                (IMG_UINT64_C(0X0000800000000000))
-#define RGX_CR_SOFT_RESET_PHANTOM0_CORE_SHIFT             (46U)
-#define RGX_CR_SOFT_RESET_PHANTOM0_CORE_CLRMSK            (IMG_UINT64_C(0XFFFFBFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_PHANTOM0_CORE_EN                (IMG_UINT64_C(0X0000400000000000))
-#define RGX_CR_SOFT_RESET_BERNADO1_CORE_SHIFT             (45U)
-#define RGX_CR_SOFT_RESET_BERNADO1_CORE_CLRMSK            (IMG_UINT64_C(0XFFFFDFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_BERNADO1_CORE_EN                (IMG_UINT64_C(0X0000200000000000))
-#define RGX_CR_SOFT_RESET_BERNADO0_CORE_SHIFT             (44U)
-#define RGX_CR_SOFT_RESET_BERNADO0_CORE_CLRMSK            (IMG_UINT64_C(0XFFFFEFFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_BERNADO0_CORE_EN                (IMG_UINT64_C(0X0000100000000000))
-#define RGX_CR_SOFT_RESET_IPP_SHIFT                       (43U)
-#define RGX_CR_SOFT_RESET_IPP_CLRMSK                      (IMG_UINT64_C(0XFFFFF7FFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_IPP_EN                          (IMG_UINT64_C(0X0000080000000000))
-#define RGX_CR_SOFT_RESET_BIF_TEXAS_SHIFT                 (42U)
-#define RGX_CR_SOFT_RESET_BIF_TEXAS_CLRMSK                (IMG_UINT64_C(0XFFFFFBFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_BIF_TEXAS_EN                    (IMG_UINT64_C(0X0000040000000000))
-#define RGX_CR_SOFT_RESET_TORNADO_CORE_SHIFT              (41U)
-#define RGX_CR_SOFT_RESET_TORNADO_CORE_CLRMSK             (IMG_UINT64_C(0XFFFFFDFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_TORNADO_CORE_EN                 (IMG_UINT64_C(0X0000020000000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
-#define RGX_CR_SOFT_RESET_DUST_H_CORE_SHIFT               (40U)
-#define RGX_CR_SOFT_RESET_DUST_H_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFEFFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_H_CORE_EN                  (IMG_UINT64_C(0X0000010000000000))
-#define RGX_CR_SOFT_RESET_DUST_G_CORE_SHIFT               (39U)
-#define RGX_CR_SOFT_RESET_DUST_G_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFF7FFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_G_CORE_EN                  (IMG_UINT64_C(0X0000008000000000))
-#define RGX_CR_SOFT_RESET_DUST_F_CORE_SHIFT               (38U)
-#define RGX_CR_SOFT_RESET_DUST_F_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFBFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_F_CORE_EN                  (IMG_UINT64_C(0X0000004000000000))
-#define RGX_CR_SOFT_RESET_DUST_E_CORE_SHIFT               (37U)
-#define RGX_CR_SOFT_RESET_DUST_E_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFDFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_E_CORE_EN                  (IMG_UINT64_C(0X0000002000000000))
-#define RGX_CR_SOFT_RESET_DUST_D_CORE_SHIFT               (36U)
-#define RGX_CR_SOFT_RESET_DUST_D_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFEFFFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_D_CORE_EN                  (IMG_UINT64_C(0X0000001000000000))
-#define RGX_CR_SOFT_RESET_DUST_C_CORE_SHIFT               (35U)
-#define RGX_CR_SOFT_RESET_DUST_C_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFF7FFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_C_CORE_EN                  (IMG_UINT64_C(0X0000000800000000))
-#define RGX_CR_SOFT_RESET_MMU_SHIFT                       (34U)
-#define RGX_CR_SOFT_RESET_MMU_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFBFFFFFFFF))
-#define RGX_CR_SOFT_RESET_MMU_EN                          (IMG_UINT64_C(0X0000000400000000))
-#define RGX_CR_SOFT_RESET_BIF1_SHIFT                      (33U)
-#define RGX_CR_SOFT_RESET_BIF1_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFDFFFFFFFF))
-#define RGX_CR_SOFT_RESET_BIF1_EN                         (IMG_UINT64_C(0X0000000200000000))
-#define RGX_CR_SOFT_RESET_GARTEN_SHIFT                    (32U)
-#define RGX_CR_SOFT_RESET_GARTEN_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
-#define RGX_CR_SOFT_RESET_GARTEN_EN                       (IMG_UINT64_C(0X0000000100000000))
-#define RGX_CR_SOFT_RESET_RASCAL_CORE_SHIFT               (31U)
-#define RGX_CR_SOFT_RESET_RASCAL_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
-#define RGX_CR_SOFT_RESET_RASCAL_CORE_EN                  (IMG_UINT64_C(0X0000000080000000))
-#define RGX_CR_SOFT_RESET_DUST_B_CORE_SHIFT               (30U)
-#define RGX_CR_SOFT_RESET_DUST_B_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_B_CORE_EN                  (IMG_UINT64_C(0X0000000040000000))
-#define RGX_CR_SOFT_RESET_DUST_A_CORE_SHIFT               (29U)
-#define RGX_CR_SOFT_RESET_DUST_A_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
-#define RGX_CR_SOFT_RESET_DUST_A_CORE_EN                  (IMG_UINT64_C(0X0000000020000000))
-#define RGX_CR_SOFT_RESET_FB_TLCACHE_SHIFT                (28U)
-#define RGX_CR_SOFT_RESET_FB_TLCACHE_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
-#define RGX_CR_SOFT_RESET_FB_TLCACHE_EN                   (IMG_UINT64_C(0X0000000010000000))
-#define RGX_CR_SOFT_RESET_SLC_SHIFT                       (27U)
-#define RGX_CR_SOFT_RESET_SLC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFF7FFFFFF))
-#define RGX_CR_SOFT_RESET_SLC_EN                          (IMG_UINT64_C(0X0000000008000000))
-#define RGX_CR_SOFT_RESET_TLA_SHIFT                       (26U)
-#define RGX_CR_SOFT_RESET_TLA_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
-#define RGX_CR_SOFT_RESET_TLA_EN                          (IMG_UINT64_C(0X0000000004000000))
-#define RGX_CR_SOFT_RESET_UVS_SHIFT                       (25U)
-#define RGX_CR_SOFT_RESET_UVS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
-#define RGX_CR_SOFT_RESET_UVS_EN                          (IMG_UINT64_C(0X0000000002000000))
-#define RGX_CR_SOFT_RESET_TE_SHIFT                        (24U)
-#define RGX_CR_SOFT_RESET_TE_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
-#define RGX_CR_SOFT_RESET_TE_EN                           (IMG_UINT64_C(0X0000000001000000))
-#define RGX_CR_SOFT_RESET_GPP_SHIFT                       (23U)
-#define RGX_CR_SOFT_RESET_GPP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
-#define RGX_CR_SOFT_RESET_GPP_EN                          (IMG_UINT64_C(0X0000000000800000))
-#define RGX_CR_SOFT_RESET_FBDC_SHIFT                      (22U)
-#define RGX_CR_SOFT_RESET_FBDC_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFFFBFFFFF))
-#define RGX_CR_SOFT_RESET_FBDC_EN                         (IMG_UINT64_C(0X0000000000400000))
-#define RGX_CR_SOFT_RESET_FBC_SHIFT                       (21U)
-#define RGX_CR_SOFT_RESET_FBC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFDFFFFF))
-#define RGX_CR_SOFT_RESET_FBC_EN                          (IMG_UINT64_C(0X0000000000200000))
-#define RGX_CR_SOFT_RESET_PM_SHIFT                        (20U)
-#define RGX_CR_SOFT_RESET_PM_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
-#define RGX_CR_SOFT_RESET_PM_EN                           (IMG_UINT64_C(0X0000000000100000))
-#define RGX_CR_SOFT_RESET_PBE_SHIFT                       (19U)
-#define RGX_CR_SOFT_RESET_PBE_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFF7FFFF))
-#define RGX_CR_SOFT_RESET_PBE_EN                          (IMG_UINT64_C(0X0000000000080000))
-#define RGX_CR_SOFT_RESET_USC_SHARED_SHIFT                (18U)
-#define RGX_CR_SOFT_RESET_USC_SHARED_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFFFFBFFFF))
-#define RGX_CR_SOFT_RESET_USC_SHARED_EN                   (IMG_UINT64_C(0X0000000000040000))
-#define RGX_CR_SOFT_RESET_MCU_L1_SHIFT                    (17U)
-#define RGX_CR_SOFT_RESET_MCU_L1_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFFFDFFFF))
-#define RGX_CR_SOFT_RESET_MCU_L1_EN                       (IMG_UINT64_C(0X0000000000020000))
-#define RGX_CR_SOFT_RESET_BIF_SHIFT                       (16U)
-#define RGX_CR_SOFT_RESET_BIF_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFEFFFF))
-#define RGX_CR_SOFT_RESET_BIF_EN                          (IMG_UINT64_C(0X0000000000010000))
-#if defined(RGX_FEATURE_COMPUTE)
-#define RGX_CR_SOFT_RESET_CDM_SHIFT                       (15U)
-#define RGX_CR_SOFT_RESET_CDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFF7FFF))
-#define RGX_CR_SOFT_RESET_CDM_EN                          (IMG_UINT64_C(0X0000000000008000))
-#endif /* RGX_FEATURE_COMPUTE */
-
-#define RGX_CR_SOFT_RESET_VDM_SHIFT                       (14U)
-#define RGX_CR_SOFT_RESET_VDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
-#define RGX_CR_SOFT_RESET_VDM_EN                          (IMG_UINT64_C(0X0000000000004000))
-#if defined(RGX_FEATURE_TESSELLATION)
-#define RGX_CR_SOFT_RESET_TESS_SHIFT                      (13U)
-#define RGX_CR_SOFT_RESET_TESS_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
-#define RGX_CR_SOFT_RESET_TESS_EN                         (IMG_UINT64_C(0X0000000000002000))
-#endif /* RGX_FEATURE_TESSELLATION */
-
-#define RGX_CR_SOFT_RESET_PDS_SHIFT                       (12U)
-#define RGX_CR_SOFT_RESET_PDS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
-#define RGX_CR_SOFT_RESET_PDS_EN                          (IMG_UINT64_C(0X0000000000001000))
-#define RGX_CR_SOFT_RESET_ISP_SHIFT                       (11U)
-#define RGX_CR_SOFT_RESET_ISP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFF7FF))
-#define RGX_CR_SOFT_RESET_ISP_EN                          (IMG_UINT64_C(0X0000000000000800))
-#define RGX_CR_SOFT_RESET_TSP_SHIFT                       (10U)
-#define RGX_CR_SOFT_RESET_TSP_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
-#define RGX_CR_SOFT_RESET_TSP_EN                          (IMG_UINT64_C(0X0000000000000400))
-#define RGX_CR_SOFT_RESET_TPU_MCU_DEMUX_SHIFT             (4U)
-#define RGX_CR_SOFT_RESET_TPU_MCU_DEMUX_CLRMSK            (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
-#define RGX_CR_SOFT_RESET_TPU_MCU_DEMUX_EN                (IMG_UINT64_C(0X0000000000000010))
-#define RGX_CR_SOFT_RESET_MCU_L0_SHIFT                    (3U)
-#define RGX_CR_SOFT_RESET_MCU_L0_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
-#define RGX_CR_SOFT_RESET_MCU_L0_EN                       (IMG_UINT64_C(0X0000000000000008))
-#define RGX_CR_SOFT_RESET_TPU_SHIFT                       (2U)
-#define RGX_CR_SOFT_RESET_TPU_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
-#define RGX_CR_SOFT_RESET_TPU_EN                          (IMG_UINT64_C(0X0000000000000004))
-#define RGX_CR_SOFT_RESET_USC_SHIFT                       (0U)
-#define RGX_CR_SOFT_RESET_USC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_SOFT_RESET_USC_EN                          (IMG_UINT64_C(0X0000000000000001))
-#endif /* RGX_FEATURE_PBE2_IN_XE */ 
-
-
-#if !defined(RGX_FEATURE_PBE2_IN_XE)
-/*
-    Register RGX_CR_SOFT_RESET
-*/
-#define RGX_CR_SOFT_RESET                                 (0x0100U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__MASKFULL              (IMG_UINT64_C(0xFFE7FFFFFFFFFC1D))
 #define RGX_CR_SOFT_RESET_MASKFULL                        (IMG_UINT64_C(0x00E7FFFFFFFFFC1D))
-#if defined(RGX_FEATURE_RAY_TRACING)
+#define RGX_CR_SOFT_RESET__PBE2_XE__PHANTOM3_CORE_SHIFT   (63U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__PHANTOM3_CORE_CLRMSK  (IMG_UINT64_C(0X7FFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__PHANTOM3_CORE_EN      (IMG_UINT64_C(0X8000000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__PHANTOM2_CORE_SHIFT   (62U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__PHANTOM2_CORE_CLRMSK  (IMG_UINT64_C(0XBFFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__PHANTOM2_CORE_EN      (IMG_UINT64_C(0X4000000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__BERNADO2_CORE_SHIFT   (61U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__BERNADO2_CORE_CLRMSK  (IMG_UINT64_C(0XDFFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__BERNADO2_CORE_EN      (IMG_UINT64_C(0X2000000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__JONES_CORE_SHIFT      (60U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__JONES_CORE_CLRMSK     (IMG_UINT64_C(0XEFFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__JONES_CORE_EN         (IMG_UINT64_C(0X1000000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__TILING_CORE_SHIFT     (59U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__TILING_CORE_CLRMSK    (IMG_UINT64_C(0XF7FFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__TILING_CORE_EN        (IMG_UINT64_C(0X0800000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__TE3_SHIFT             (58U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__TE3_CLRMSK            (IMG_UINT64_C(0XFBFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__TE3_EN                (IMG_UINT64_C(0X0400000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__VCE_SHIFT             (57U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__VCE_CLRMSK            (IMG_UINT64_C(0XFDFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__VCE_EN                (IMG_UINT64_C(0X0200000000000000))
+#define RGX_CR_SOFT_RESET__PBE2_XE__VBS_SHIFT             (56U)
+#define RGX_CR_SOFT_RESET__PBE2_XE__VBS_CLRMSK            (IMG_UINT64_C(0XFEFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET__PBE2_XE__VBS_EN                (IMG_UINT64_C(0X0100000000000000))
 #define RGX_CR_SOFT_RESET_DPX1_CORE_SHIFT                 (55U)
 #define RGX_CR_SOFT_RESET_DPX1_CORE_CLRMSK                (IMG_UINT64_C(0XFF7FFFFFFFFFFFFF))
 #define RGX_CR_SOFT_RESET_DPX1_CORE_EN                    (IMG_UINT64_C(0X0080000000000000))
@@ -1225,12 +637,9 @@
 #define RGX_CR_SOFT_RESET_VRDM_SHIFT                      (49U)
 #define RGX_CR_SOFT_RESET_VRDM_CLRMSK                     (IMG_UINT64_C(0XFFFDFFFFFFFFFFFF))
 #define RGX_CR_SOFT_RESET_VRDM_EN                         (IMG_UINT64_C(0X0002000000000000))
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 #define RGX_CR_SOFT_RESET_MCU_FBTC_SHIFT                  (48U)
 #define RGX_CR_SOFT_RESET_MCU_FBTC_CLRMSK                 (IMG_UINT64_C(0XFFFEFFFFFFFFFFFF))
 #define RGX_CR_SOFT_RESET_MCU_FBTC_EN                     (IMG_UINT64_C(0X0001000000000000))
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 #define RGX_CR_SOFT_RESET_PHANTOM1_CORE_SHIFT             (47U)
 #define RGX_CR_SOFT_RESET_PHANTOM1_CORE_CLRMSK            (IMG_UINT64_C(0XFFFF7FFFFFFFFFFF))
 #define RGX_CR_SOFT_RESET_PHANTOM1_CORE_EN                (IMG_UINT64_C(0X0000800000000000))
@@ -1252,8 +661,6 @@
 #define RGX_CR_SOFT_RESET_TORNADO_CORE_SHIFT              (41U)
 #define RGX_CR_SOFT_RESET_TORNADO_CORE_CLRMSK             (IMG_UINT64_C(0XFFFFFDFFFFFFFFFF))
 #define RGX_CR_SOFT_RESET_TORNADO_CORE_EN                 (IMG_UINT64_C(0X0000020000000000))
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
 #define RGX_CR_SOFT_RESET_DUST_H_CORE_SHIFT               (40U)
 #define RGX_CR_SOFT_RESET_DUST_H_CORE_CLRMSK              (IMG_UINT64_C(0XFFFFFEFFFFFFFFFF))
 #define RGX_CR_SOFT_RESET_DUST_H_CORE_EN                  (IMG_UINT64_C(0X0000010000000000))
@@ -1329,21 +736,15 @@
 #define RGX_CR_SOFT_RESET_BIF_SHIFT                       (16U)
 #define RGX_CR_SOFT_RESET_BIF_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFEFFFF))
 #define RGX_CR_SOFT_RESET_BIF_EN                          (IMG_UINT64_C(0X0000000000010000))
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_SOFT_RESET_CDM_SHIFT                       (15U)
 #define RGX_CR_SOFT_RESET_CDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFF7FFF))
 #define RGX_CR_SOFT_RESET_CDM_EN                          (IMG_UINT64_C(0X0000000000008000))
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_SOFT_RESET_VDM_SHIFT                       (14U)
 #define RGX_CR_SOFT_RESET_VDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
 #define RGX_CR_SOFT_RESET_VDM_EN                          (IMG_UINT64_C(0X0000000000004000))
-#if defined(RGX_FEATURE_TESSELLATION)
 #define RGX_CR_SOFT_RESET_TESS_SHIFT                      (13U)
 #define RGX_CR_SOFT_RESET_TESS_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
 #define RGX_CR_SOFT_RESET_TESS_EN                         (IMG_UINT64_C(0X0000000000002000))
-#endif /* RGX_FEATURE_TESSELLATION */
-
 #define RGX_CR_SOFT_RESET_PDS_SHIFT                       (12U)
 #define RGX_CR_SOFT_RESET_PDS_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
 #define RGX_CR_SOFT_RESET_PDS_EN                          (IMG_UINT64_C(0X0000000000001000))
@@ -1365,15 +766,15 @@
 #define RGX_CR_SOFT_RESET_USC_SHIFT                       (0U)
 #define RGX_CR_SOFT_RESET_USC_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
 #define RGX_CR_SOFT_RESET_USC_EN                          (IMG_UINT64_C(0X0000000000000001))
-#endif /* !defined(RGX_FEATURE_PBE2_IN_XE) */
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 /*
     Register RGX_CR_SOFT_RESET2
 */
 #define RGX_CR_SOFT_RESET2                                (0x0108U)
-#define RGX_CR_SOFT_RESET2_MASKFULL                       (IMG_UINT64_C(0x0000000000000FFF))
+#define RGX_CR_SOFT_RESET2_MASKFULL                       (IMG_UINT64_C(0x00000000001FFFFF))
+#define RGX_CR_SOFT_RESET2_SPFILTER_SHIFT                 (12U)
+#define RGX_CR_SOFT_RESET2_SPFILTER_CLRMSK                (0XFFE00FFFU)
 #define RGX_CR_SOFT_RESET2_TDM_SHIFT                      (11U)
 #define RGX_CR_SOFT_RESET2_TDM_CLRMSK                     (0XFFFFF7FFU)
 #define RGX_CR_SOFT_RESET2_TDM_EN                         (0X00000800U)
@@ -1404,122 +805,29 @@
 #define RGX_CR_SOFT_RESET2_PIXEL_SHIFT                    (2U)
 #define RGX_CR_SOFT_RESET2_PIXEL_CLRMSK                   (0XFFFFFFFBU)
 #define RGX_CR_SOFT_RESET2_PIXEL_EN                       (0X00000004U)
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_SOFT_RESET2_CDM_SHIFT                      (1U)
 #define RGX_CR_SOFT_RESET2_CDM_CLRMSK                     (0XFFFFFFFDU)
 #define RGX_CR_SOFT_RESET2_CDM_EN                         (0X00000002U)
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_SOFT_RESET2_VERTEX_SHIFT                   (0U)
 #define RGX_CR_SOFT_RESET2_VERTEX_CLRMSK                  (0XFFFFFFFEU)
 #define RGX_CR_SOFT_RESET2_VERTEX_EN                      (0X00000001U)
 
 
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
-
-#if defined(RGX_FEATURE_SIGNAL_SNOOPING)
 /*
     Register RGX_CR_EVENT_STATUS
 */
 #define RGX_CR_EVENT_STATUS                               (0x0130U)
-#define RGX_CR_EVENT_STATUS_MASKFULL                      (IMG_UINT64_C(0x00000000E007FFFF))
-#if defined(RGX_FEATURE_FASTRENDER_DM)
-#define RGX_CR_EVENT_STATUS_TDM_FENCE_FINISHED_SHIFT      (31U)
-#define RGX_CR_EVENT_STATUS_TDM_FENCE_FINISHED_CLRMSK     (0X7FFFFFFFU)
-#define RGX_CR_EVENT_STATUS_TDM_FENCE_FINISHED_EN         (0X80000000U)
-#define RGX_CR_EVENT_STATUS_TDM_BUFFER_STALL_SHIFT        (30U)
-#define RGX_CR_EVENT_STATUS_TDM_BUFFER_STALL_CLRMSK       (0XBFFFFFFFU)
-#define RGX_CR_EVENT_STATUS_TDM_BUFFER_STALL_EN           (0X40000000U)
-#endif /* RGX_FEATURE_FASTRENDER_DM */
-
-#define RGX_CR_EVENT_STATUS_COMPUTE_SIGNAL_FAILURE_SHIFT  (29U)
-#define RGX_CR_EVENT_STATUS_COMPUTE_SIGNAL_FAILURE_CLRMSK (0XDFFFFFFFU)
-#define RGX_CR_EVENT_STATUS_COMPUTE_SIGNAL_FAILURE_EN     (0X20000000U)
-#if defined(RGX_FEATURE_FASTRENDER_DM)
-#define RGX_CR_EVENT_STATUS_TDM_CONTEXT_STORE_FINISHED_SHIFT (18U)
-#define RGX_CR_EVENT_STATUS_TDM_CONTEXT_STORE_FINISHED_CLRMSK (0XFFFBFFFFU)
-#define RGX_CR_EVENT_STATUS_TDM_CONTEXT_STORE_FINISHED_EN (0X00040000U)
-#endif /* RGX_FEATURE_FASTRENDER_DM */
-
-#define RGX_CR_EVENT_STATUS_SPFILTER_SIGNAL_UPDATE_SHIFT  (17U)
-#define RGX_CR_EVENT_STATUS_SPFILTER_SIGNAL_UPDATE_CLRMSK (0XFFFDFFFFU)
-#define RGX_CR_EVENT_STATUS_SPFILTER_SIGNAL_UPDATE_EN     (0X00020000U)
-#define RGX_CR_EVENT_STATUS_COMPUTE_BUFFER_STALL_SHIFT    (16U)
-#define RGX_CR_EVENT_STATUS_COMPUTE_BUFFER_STALL_CLRMSK   (0XFFFEFFFFU)
-#define RGX_CR_EVENT_STATUS_COMPUTE_BUFFER_STALL_EN       (0X00010000U)
-#define RGX_CR_EVENT_STATUS_USC_TRIGGER_SHIFT             (15U)
-#define RGX_CR_EVENT_STATUS_USC_TRIGGER_CLRMSK            (0XFFFF7FFFU)
-#define RGX_CR_EVENT_STATUS_USC_TRIGGER_EN                (0X00008000U)
-#define RGX_CR_EVENT_STATUS_ZLS_FINISHED_SHIFT            (14U)
-#define RGX_CR_EVENT_STATUS_ZLS_FINISHED_CLRMSK           (0XFFFFBFFFU)
-#define RGX_CR_EVENT_STATUS_ZLS_FINISHED_EN               (0X00004000U)
-#define RGX_CR_EVENT_STATUS_GPIO_ACK_SHIFT                (13U)
-#define RGX_CR_EVENT_STATUS_GPIO_ACK_CLRMSK               (0XFFFFDFFFU)
-#define RGX_CR_EVENT_STATUS_GPIO_ACK_EN                   (0X00002000U)
-#define RGX_CR_EVENT_STATUS_GPIO_REQ_SHIFT                (12U)
-#define RGX_CR_EVENT_STATUS_GPIO_REQ_CLRMSK               (0XFFFFEFFFU)
-#define RGX_CR_EVENT_STATUS_GPIO_REQ_EN                   (0X00001000U)
-#define RGX_CR_EVENT_STATUS_POWER_ABORT_SHIFT             (11U)
-#define RGX_CR_EVENT_STATUS_POWER_ABORT_CLRMSK            (0XFFFFF7FFU)
-#define RGX_CR_EVENT_STATUS_POWER_ABORT_EN                (0X00000800U)
-#define RGX_CR_EVENT_STATUS_POWER_COMPLETE_SHIFT          (10U)
-#define RGX_CR_EVENT_STATUS_POWER_COMPLETE_CLRMSK         (0XFFFFFBFFU)
-#define RGX_CR_EVENT_STATUS_POWER_COMPLETE_EN             (0X00000400U)
-#define RGX_CR_EVENT_STATUS_MMU_PAGE_FAULT_SHIFT          (9U)
-#define RGX_CR_EVENT_STATUS_MMU_PAGE_FAULT_CLRMSK         (0XFFFFFDFFU)
-#define RGX_CR_EVENT_STATUS_MMU_PAGE_FAULT_EN             (0X00000200U)
-#define RGX_CR_EVENT_STATUS_PM_3D_MEM_FREE_SHIFT          (8U)
-#define RGX_CR_EVENT_STATUS_PM_3D_MEM_FREE_CLRMSK         (0XFFFFFEFFU)
-#define RGX_CR_EVENT_STATUS_PM_3D_MEM_FREE_EN             (0X00000100U)
-#define RGX_CR_EVENT_STATUS_PM_OUT_OF_MEMORY_SHIFT        (7U)
-#define RGX_CR_EVENT_STATUS_PM_OUT_OF_MEMORY_CLRMSK       (0XFFFFFF7FU)
-#define RGX_CR_EVENT_STATUS_PM_OUT_OF_MEMORY_EN           (0X00000080U)
-#define RGX_CR_EVENT_STATUS_TA_TERMINATE_SHIFT            (6U)
-#define RGX_CR_EVENT_STATUS_TA_TERMINATE_CLRMSK           (0XFFFFFFBFU)
-#define RGX_CR_EVENT_STATUS_TA_TERMINATE_EN               (0X00000040U)
-#define RGX_CR_EVENT_STATUS_TA_FINISHED_SHIFT             (5U)
-#define RGX_CR_EVENT_STATUS_TA_FINISHED_CLRMSK            (0XFFFFFFDFU)
-#define RGX_CR_EVENT_STATUS_TA_FINISHED_EN                (0X00000020U)
-#define RGX_CR_EVENT_STATUS_ISP_END_MACROTILE_SHIFT       (4U)
-#define RGX_CR_EVENT_STATUS_ISP_END_MACROTILE_CLRMSK      (0XFFFFFFEFU)
-#define RGX_CR_EVENT_STATUS_ISP_END_MACROTILE_EN          (0X00000010U)
-#define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT      (3U)
-#define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_CLRMSK     (0XFFFFFFF7U)
-#define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_EN         (0X00000008U)
-#if defined(RGX_FEATURE_COMPUTE)
-#define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_SHIFT        (2U)
-#define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_CLRMSK       (0XFFFFFFFBU)
-#define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_EN           (0X00000004U)
-#define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_SHIFT         (1U)
-#define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_CLRMSK        (0XFFFFFFFDU)
-#define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_EN            (0X00000002U)
-#endif /* RGX_FEATURE_COMPUTE */
-
-#define RGX_CR_EVENT_STATUS_TLA_COMPLETE_SHIFT            (0U)
-#define RGX_CR_EVENT_STATUS_TLA_COMPLETE_CLRMSK           (0XFFFFFFFEU)
-#define RGX_CR_EVENT_STATUS_TLA_COMPLETE_EN               (0X00000001U)
-#endif /* RGX_FEATURE_SIGNAL_SNOOPING */ 
-
-
-#if !defined(RGX_FEATURE_SIGNAL_SNOOPING)
-/*
-    Register RGX_CR_EVENT_STATUS
-*/
-#define RGX_CR_EVENT_STATUS                               (0x0130U)
+#define RGX_CR_EVENT_STATUS__SIGNALS__MASKFULL            (IMG_UINT64_C(0x00000000E007FFFF))
 #define RGX_CR_EVENT_STATUS_MASKFULL                      (IMG_UINT64_C(0x00000000FFFFFFFF))
-#if defined(RGX_FEATURE_FASTRENDER_DM)
 #define RGX_CR_EVENT_STATUS_TDM_FENCE_FINISHED_SHIFT      (31U)
 #define RGX_CR_EVENT_STATUS_TDM_FENCE_FINISHED_CLRMSK     (0X7FFFFFFFU)
 #define RGX_CR_EVENT_STATUS_TDM_FENCE_FINISHED_EN         (0X80000000U)
 #define RGX_CR_EVENT_STATUS_TDM_BUFFER_STALL_SHIFT        (30U)
 #define RGX_CR_EVENT_STATUS_TDM_BUFFER_STALL_CLRMSK       (0XBFFFFFFFU)
 #define RGX_CR_EVENT_STATUS_TDM_BUFFER_STALL_EN           (0X40000000U)
-#endif /* RGX_FEATURE_FASTRENDER_DM */
-
 #define RGX_CR_EVENT_STATUS_COMPUTE_SIGNAL_FAILURE_SHIFT  (29U)
 #define RGX_CR_EVENT_STATUS_COMPUTE_SIGNAL_FAILURE_CLRMSK (0XDFFFFFFFU)
 #define RGX_CR_EVENT_STATUS_COMPUTE_SIGNAL_FAILURE_EN     (0X20000000U)
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_EVENT_STATUS_DPX_OUT_OF_MEMORY_SHIFT       (28U)
 #define RGX_CR_EVENT_STATUS_DPX_OUT_OF_MEMORY_CLRMSK      (0XEFFFFFFFU)
 #define RGX_CR_EVENT_STATUS_DPX_OUT_OF_MEMORY_EN          (0X10000000U)
@@ -1553,11 +861,15 @@
 #define RGX_CR_EVENT_STATUS_RDM_FC0_FINISHED_SHIFT        (18U)
 #define RGX_CR_EVENT_STATUS_RDM_FC0_FINISHED_CLRMSK       (0XFFFBFFFFU)
 #define RGX_CR_EVENT_STATUS_RDM_FC0_FINISHED_EN           (0X00040000U)
+#define RGX_CR_EVENT_STATUS__SIGNALS__TDM_CONTEXT_STORE_FINISHED_SHIFT (18U)
+#define RGX_CR_EVENT_STATUS__SIGNALS__TDM_CONTEXT_STORE_FINISHED_CLRMSK (0XFFFBFFFFU)
+#define RGX_CR_EVENT_STATUS__SIGNALS__TDM_CONTEXT_STORE_FINISHED_EN (0X00040000U)
 #define RGX_CR_EVENT_STATUS_SHG_FINISHED_SHIFT            (17U)
 #define RGX_CR_EVENT_STATUS_SHG_FINISHED_CLRMSK           (0XFFFDFFFFU)
 #define RGX_CR_EVENT_STATUS_SHG_FINISHED_EN               (0X00020000U)
-#endif /* RGX_FEATURE_RAY_TRACING */
-
+#define RGX_CR_EVENT_STATUS__SIGNALS__SPFILTER_SIGNAL_UPDATE_SHIFT (17U)
+#define RGX_CR_EVENT_STATUS__SIGNALS__SPFILTER_SIGNAL_UPDATE_CLRMSK (0XFFFDFFFFU)
+#define RGX_CR_EVENT_STATUS__SIGNALS__SPFILTER_SIGNAL_UPDATE_EN (0X00020000U)
 #define RGX_CR_EVENT_STATUS_COMPUTE_BUFFER_STALL_SHIFT    (16U)
 #define RGX_CR_EVENT_STATUS_COMPUTE_BUFFER_STALL_CLRMSK   (0XFFFEFFFFU)
 #define RGX_CR_EVENT_STATUS_COMPUTE_BUFFER_STALL_EN       (0X00010000U)
@@ -1600,19 +912,15 @@
 #define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT      (3U)
 #define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_CLRMSK     (0XFFFFFFF7U)
 #define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_EN         (0X00000008U)
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_SHIFT        (2U)
 #define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_CLRMSK       (0XFFFFFFFBU)
 #define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_EN           (0X00000004U)
 #define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_SHIFT         (1U)
 #define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_CLRMSK        (0XFFFFFFFDU)
 #define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_EN            (0X00000002U)
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_EVENT_STATUS_TLA_COMPLETE_SHIFT            (0U)
 #define RGX_CR_EVENT_STATUS_TLA_COMPLETE_CLRMSK           (0XFFFFFFFEU)
 #define RGX_CR_EVENT_STATUS_TLA_COMPLETE_EN               (0X00000001U)
-#endif /* !defined(RGX_FEATURE_SIGNAL_SNOOPING) */
 
 
 /*
@@ -1786,68 +1094,53 @@
 #define RGX_CR_CDM_CONTEXT_PDS0_CODE_ADDR_ALIGNSIZE       (16U)
 
 
-#if defined(RGX_FEATURE_PDS_TEMPSIZE8)
 /*
     Register RGX_CR_CDM_CONTEXT_PDS1
 */
 #define RGX_CR_CDM_CONTEXT_PDS1                           (0x04B0U)
-#define RGX_CR_CDM_CONTEXT_PDS1_MASKFULL                  (IMG_UINT64_C(0x000000007FFFFFFF))
-#define RGX_CR_CDM_CONTEXT_PDS1_PDS_SEQ_DEP_SHIFT         (30U)
-#define RGX_CR_CDM_CONTEXT_PDS1_PDS_SEQ_DEP_CLRMSK        (0XBFFFFFFFU)
-#define RGX_CR_CDM_CONTEXT_PDS1_PDS_SEQ_DEP_EN            (0X40000000U)
-#define RGX_CR_CDM_CONTEXT_PDS1_USC_SEQ_DEP_SHIFT         (29U)
-#define RGX_CR_CDM_CONTEXT_PDS1_USC_SEQ_DEP_CLRMSK        (0XDFFFFFFFU)
-#define RGX_CR_CDM_CONTEXT_PDS1_USC_SEQ_DEP_EN            (0X20000000U)
-#define RGX_CR_CDM_CONTEXT_PDS1_TARGET_SHIFT              (28U)
-#define RGX_CR_CDM_CONTEXT_PDS1_TARGET_CLRMSK             (0XEFFFFFFFU)
-#define RGX_CR_CDM_CONTEXT_PDS1_TARGET_EN                 (0X10000000U)
-#define RGX_CR_CDM_CONTEXT_PDS1_UNIFIED_SIZE_SHIFT        (22U)
-#define RGX_CR_CDM_CONTEXT_PDS1_UNIFIED_SIZE_CLRMSK       (0XF03FFFFFU)
-#define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SHARED_SHIFT       (21U)
-#define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SHARED_CLRMSK      (0XFFDFFFFFU)
-#define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SHARED_EN          (0X00200000U)
-#define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SIZE_SHIFT         (12U)
-#define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SIZE_CLRMSK        (0XFFE00FFFU)
-#define RGX_CR_CDM_CONTEXT_PDS1_TEMP_SIZE_SHIFT           (7U)
-#define RGX_CR_CDM_CONTEXT_PDS1_TEMP_SIZE_CLRMSK          (0XFFFFF07FU)
-#define RGX_CR_CDM_CONTEXT_PDS1_DATA_SIZE_SHIFT           (1U)
-#define RGX_CR_CDM_CONTEXT_PDS1_DATA_SIZE_CLRMSK          (0XFFFFFF81U)
-#define RGX_CR_CDM_CONTEXT_PDS1_FENCE_SHIFT               (0U)
-#define RGX_CR_CDM_CONTEXT_PDS1_FENCE_CLRMSK              (0XFFFFFFFEU)
-#define RGX_CR_CDM_CONTEXT_PDS1_FENCE_EN                  (0X00000001U)
-#endif /* RGX_FEATURE_PDS_TEMPSIZE8 */ 
-
-
-#if !defined(RGX_FEATURE_PDS_TEMPSIZE8)
-/*
-    Register RGX_CR_CDM_CONTEXT_PDS1
-*/
-#define RGX_CR_CDM_CONTEXT_PDS1                           (0x04B0U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__MASKFULL      (IMG_UINT64_C(0x000000007FFFFFFF))
 #define RGX_CR_CDM_CONTEXT_PDS1_MASKFULL                  (IMG_UINT64_C(0x000000003FFFFFFF))
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__PDS_SEQ_DEP_SHIFT (30U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__PDS_SEQ_DEP_CLRMSK (0XBFFFFFFFU)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__PDS_SEQ_DEP_EN (0X40000000U)
 #define RGX_CR_CDM_CONTEXT_PDS1_PDS_SEQ_DEP_SHIFT         (29U)
 #define RGX_CR_CDM_CONTEXT_PDS1_PDS_SEQ_DEP_CLRMSK        (0XDFFFFFFFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_PDS_SEQ_DEP_EN            (0X20000000U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__USC_SEQ_DEP_SHIFT (29U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__USC_SEQ_DEP_CLRMSK (0XDFFFFFFFU)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__USC_SEQ_DEP_EN (0X20000000U)
 #define RGX_CR_CDM_CONTEXT_PDS1_USC_SEQ_DEP_SHIFT         (28U)
 #define RGX_CR_CDM_CONTEXT_PDS1_USC_SEQ_DEP_CLRMSK        (0XEFFFFFFFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_USC_SEQ_DEP_EN            (0X10000000U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__TARGET_SHIFT  (28U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__TARGET_CLRMSK (0XEFFFFFFFU)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__TARGET_EN     (0X10000000U)
 #define RGX_CR_CDM_CONTEXT_PDS1_TARGET_SHIFT              (27U)
 #define RGX_CR_CDM_CONTEXT_PDS1_TARGET_CLRMSK             (0XF7FFFFFFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_TARGET_EN                 (0X08000000U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__UNIFIED_SIZE_SHIFT (22U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__UNIFIED_SIZE_CLRMSK (0XF03FFFFFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_UNIFIED_SIZE_SHIFT        (21U)
 #define RGX_CR_CDM_CONTEXT_PDS1_UNIFIED_SIZE_CLRMSK       (0XF81FFFFFU)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__COMMON_SHARED_SHIFT (21U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__COMMON_SHARED_CLRMSK (0XFFDFFFFFU)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__COMMON_SHARED_EN (0X00200000U)
 #define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SHARED_SHIFT       (20U)
 #define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SHARED_CLRMSK      (0XFFEFFFFFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SHARED_EN          (0X00100000U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__COMMON_SIZE_SHIFT (12U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__COMMON_SIZE_CLRMSK (0XFFE00FFFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SIZE_SHIFT         (11U)
 #define RGX_CR_CDM_CONTEXT_PDS1_COMMON_SIZE_CLRMSK        (0XFFF007FFU)
 #define RGX_CR_CDM_CONTEXT_PDS1_TEMP_SIZE_SHIFT           (7U)
 #define RGX_CR_CDM_CONTEXT_PDS1_TEMP_SIZE_CLRMSK          (0XFFFFF87FU)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__TEMP_SIZE_SHIFT (7U)
+#define RGX_CR_CDM_CONTEXT_PDS1__TEMPSIZE8__TEMP_SIZE_CLRMSK (0XFFFFF07FU)
 #define RGX_CR_CDM_CONTEXT_PDS1_DATA_SIZE_SHIFT           (1U)
 #define RGX_CR_CDM_CONTEXT_PDS1_DATA_SIZE_CLRMSK          (0XFFFFFF81U)
 #define RGX_CR_CDM_CONTEXT_PDS1_FENCE_SHIFT               (0U)
 #define RGX_CR_CDM_CONTEXT_PDS1_FENCE_CLRMSK              (0XFFFFFFFEU)
 #define RGX_CR_CDM_CONTEXT_PDS1_FENCE_EN                  (0X00000001U)
-#endif /* !defined(RGX_FEATURE_PDS_TEMPSIZE8) */
 
 
 /*
@@ -1865,68 +1158,53 @@
 #define RGX_CR_CDM_TERMINATE_PDS_CODE_ADDR_ALIGNSIZE      (16U)
 
 
-#if defined(RGX_FEATURE_PDS_TEMPSIZE8)
 /*
     Register RGX_CR_CDM_TERMINATE_PDS1
 */
 #define RGX_CR_CDM_TERMINATE_PDS1                         (0x04C0U)
-#define RGX_CR_CDM_TERMINATE_PDS1_MASKFULL                (IMG_UINT64_C(0x000000007FFFFFFF))
-#define RGX_CR_CDM_TERMINATE_PDS1_PDS_SEQ_DEP_SHIFT       (30U)
-#define RGX_CR_CDM_TERMINATE_PDS1_PDS_SEQ_DEP_CLRMSK      (0XBFFFFFFFU)
-#define RGX_CR_CDM_TERMINATE_PDS1_PDS_SEQ_DEP_EN          (0X40000000U)
-#define RGX_CR_CDM_TERMINATE_PDS1_USC_SEQ_DEP_SHIFT       (29U)
-#define RGX_CR_CDM_TERMINATE_PDS1_USC_SEQ_DEP_CLRMSK      (0XDFFFFFFFU)
-#define RGX_CR_CDM_TERMINATE_PDS1_USC_SEQ_DEP_EN          (0X20000000U)
-#define RGX_CR_CDM_TERMINATE_PDS1_TARGET_SHIFT            (28U)
-#define RGX_CR_CDM_TERMINATE_PDS1_TARGET_CLRMSK           (0XEFFFFFFFU)
-#define RGX_CR_CDM_TERMINATE_PDS1_TARGET_EN               (0X10000000U)
-#define RGX_CR_CDM_TERMINATE_PDS1_UNIFIED_SIZE_SHIFT      (22U)
-#define RGX_CR_CDM_TERMINATE_PDS1_UNIFIED_SIZE_CLRMSK     (0XF03FFFFFU)
-#define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SHARED_SHIFT     (21U)
-#define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SHARED_CLRMSK    (0XFFDFFFFFU)
-#define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SHARED_EN        (0X00200000U)
-#define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SIZE_SHIFT       (12U)
-#define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SIZE_CLRMSK      (0XFFE00FFFU)
-#define RGX_CR_CDM_TERMINATE_PDS1_TEMP_SIZE_SHIFT         (7U)
-#define RGX_CR_CDM_TERMINATE_PDS1_TEMP_SIZE_CLRMSK        (0XFFFFF07FU)
-#define RGX_CR_CDM_TERMINATE_PDS1_DATA_SIZE_SHIFT         (1U)
-#define RGX_CR_CDM_TERMINATE_PDS1_DATA_SIZE_CLRMSK        (0XFFFFFF81U)
-#define RGX_CR_CDM_TERMINATE_PDS1_FENCE_SHIFT             (0U)
-#define RGX_CR_CDM_TERMINATE_PDS1_FENCE_CLRMSK            (0XFFFFFFFEU)
-#define RGX_CR_CDM_TERMINATE_PDS1_FENCE_EN                (0X00000001U)
-#endif /* RGX_FEATURE_PDS_TEMPSIZE8 */ 
-
-
-#if !defined(RGX_FEATURE_PDS_TEMPSIZE8)
-/*
-    Register RGX_CR_CDM_TERMINATE_PDS1
-*/
-#define RGX_CR_CDM_TERMINATE_PDS1                         (0x04C0U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__MASKFULL    (IMG_UINT64_C(0x000000007FFFFFFF))
 #define RGX_CR_CDM_TERMINATE_PDS1_MASKFULL                (IMG_UINT64_C(0x000000003FFFFFFF))
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__PDS_SEQ_DEP_SHIFT (30U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__PDS_SEQ_DEP_CLRMSK (0XBFFFFFFFU)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__PDS_SEQ_DEP_EN (0X40000000U)
 #define RGX_CR_CDM_TERMINATE_PDS1_PDS_SEQ_DEP_SHIFT       (29U)
 #define RGX_CR_CDM_TERMINATE_PDS1_PDS_SEQ_DEP_CLRMSK      (0XDFFFFFFFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_PDS_SEQ_DEP_EN          (0X20000000U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__USC_SEQ_DEP_SHIFT (29U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__USC_SEQ_DEP_CLRMSK (0XDFFFFFFFU)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__USC_SEQ_DEP_EN (0X20000000U)
 #define RGX_CR_CDM_TERMINATE_PDS1_USC_SEQ_DEP_SHIFT       (28U)
 #define RGX_CR_CDM_TERMINATE_PDS1_USC_SEQ_DEP_CLRMSK      (0XEFFFFFFFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_USC_SEQ_DEP_EN          (0X10000000U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__TARGET_SHIFT (28U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__TARGET_CLRMSK (0XEFFFFFFFU)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__TARGET_EN   (0X10000000U)
 #define RGX_CR_CDM_TERMINATE_PDS1_TARGET_SHIFT            (27U)
 #define RGX_CR_CDM_TERMINATE_PDS1_TARGET_CLRMSK           (0XF7FFFFFFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_TARGET_EN               (0X08000000U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__UNIFIED_SIZE_SHIFT (22U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__UNIFIED_SIZE_CLRMSK (0XF03FFFFFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_UNIFIED_SIZE_SHIFT      (21U)
 #define RGX_CR_CDM_TERMINATE_PDS1_UNIFIED_SIZE_CLRMSK     (0XF81FFFFFU)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__COMMON_SHARED_SHIFT (21U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__COMMON_SHARED_CLRMSK (0XFFDFFFFFU)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__COMMON_SHARED_EN (0X00200000U)
 #define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SHARED_SHIFT     (20U)
 #define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SHARED_CLRMSK    (0XFFEFFFFFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SHARED_EN        (0X00100000U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__COMMON_SIZE_SHIFT (12U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__COMMON_SIZE_CLRMSK (0XFFE00FFFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SIZE_SHIFT       (11U)
 #define RGX_CR_CDM_TERMINATE_PDS1_COMMON_SIZE_CLRMSK      (0XFFF007FFU)
 #define RGX_CR_CDM_TERMINATE_PDS1_TEMP_SIZE_SHIFT         (7U)
 #define RGX_CR_CDM_TERMINATE_PDS1_TEMP_SIZE_CLRMSK        (0XFFFFF87FU)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__TEMP_SIZE_SHIFT (7U)
+#define RGX_CR_CDM_TERMINATE_PDS1__TEMPSIZE8__TEMP_SIZE_CLRMSK (0XFFFFF07FU)
 #define RGX_CR_CDM_TERMINATE_PDS1_DATA_SIZE_SHIFT         (1U)
 #define RGX_CR_CDM_TERMINATE_PDS1_DATA_SIZE_CLRMSK        (0XFFFFFF81U)
 #define RGX_CR_CDM_TERMINATE_PDS1_FENCE_SHIFT             (0U)
 #define RGX_CR_CDM_TERMINATE_PDS1_FENCE_CLRMSK            (0XFFFFFFFEU)
 #define RGX_CR_CDM_TERMINATE_PDS1_FENCE_EN                (0X00000001U)
-#endif /* !defined(RGX_FEATURE_PDS_TEMPSIZE8) */
 
 
 /*
@@ -1944,79 +1222,72 @@
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS0_CODE_ADDR_ALIGNSIZE  (16U)
 
 
-#if defined(RGX_FEATURE_PDS_TEMPSIZE8)
 /*
     Register RGX_CR_CDM_CONTEXT_LOAD_PDS1
 */
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1                      (0x04E0U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_MASKFULL             (IMG_UINT64_C(0x000000007FFFFFFF))
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_PDS_SEQ_DEP_SHIFT    (30U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_PDS_SEQ_DEP_CLRMSK   (0XBFFFFFFFU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_PDS_SEQ_DEP_EN       (0X40000000U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_USC_SEQ_DEP_SHIFT    (29U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_USC_SEQ_DEP_CLRMSK   (0XDFFFFFFFU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_USC_SEQ_DEP_EN       (0X20000000U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TARGET_SHIFT         (28U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TARGET_CLRMSK        (0XEFFFFFFFU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TARGET_EN            (0X10000000U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_UNIFIED_SIZE_SHIFT   (22U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_UNIFIED_SIZE_CLRMSK  (0XF03FFFFFU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SHARED_SHIFT  (21U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SHARED_CLRMSK (0XFFDFFFFFU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SHARED_EN     (0X00200000U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SIZE_SHIFT    (12U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SIZE_CLRMSK   (0XFFE00FFFU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TEMP_SIZE_SHIFT      (7U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TEMP_SIZE_CLRMSK     (0XFFFFF07FU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_DATA_SIZE_SHIFT      (1U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_DATA_SIZE_CLRMSK     (0XFFFFFF81U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_FENCE_SHIFT          (0U)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_FENCE_CLRMSK         (0XFFFFFFFEU)
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1_FENCE_EN             (0X00000001U)
-#endif /* RGX_FEATURE_PDS_TEMPSIZE8 */ 
-
-
-#if !defined(RGX_FEATURE_PDS_TEMPSIZE8)
-/*
-    Register RGX_CR_CDM_CONTEXT_LOAD_PDS1
-*/
-#define RGX_CR_CDM_CONTEXT_LOAD_PDS1                      (0x04E0U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__MASKFULL (IMG_UINT64_C(0x000000007FFFFFFF))
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_MASKFULL             (IMG_UINT64_C(0x000000003FFFFFFF))
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__PDS_SEQ_DEP_SHIFT (30U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__PDS_SEQ_DEP_CLRMSK (0XBFFFFFFFU)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__PDS_SEQ_DEP_EN (0X40000000U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_PDS_SEQ_DEP_SHIFT    (29U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_PDS_SEQ_DEP_CLRMSK   (0XDFFFFFFFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_PDS_SEQ_DEP_EN       (0X20000000U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__USC_SEQ_DEP_SHIFT (29U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__USC_SEQ_DEP_CLRMSK (0XDFFFFFFFU)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__USC_SEQ_DEP_EN (0X20000000U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_USC_SEQ_DEP_SHIFT    (28U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_USC_SEQ_DEP_CLRMSK   (0XEFFFFFFFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_USC_SEQ_DEP_EN       (0X10000000U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__TARGET_SHIFT (28U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__TARGET_CLRMSK (0XEFFFFFFFU)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__TARGET_EN (0X10000000U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TARGET_SHIFT         (27U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TARGET_CLRMSK        (0XF7FFFFFFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TARGET_EN            (0X08000000U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__UNIFIED_SIZE_SHIFT (22U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__UNIFIED_SIZE_CLRMSK (0XF03FFFFFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_UNIFIED_SIZE_SHIFT   (21U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_UNIFIED_SIZE_CLRMSK  (0XF81FFFFFU)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__COMMON_SHARED_SHIFT (21U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__COMMON_SHARED_CLRMSK (0XFFDFFFFFU)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__COMMON_SHARED_EN (0X00200000U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SHARED_SHIFT  (20U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SHARED_CLRMSK (0XFFEFFFFFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SHARED_EN     (0X00100000U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__COMMON_SIZE_SHIFT (12U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__COMMON_SIZE_CLRMSK (0XFFE00FFFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SIZE_SHIFT    (11U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_COMMON_SIZE_CLRMSK   (0XFFF007FFU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TEMP_SIZE_SHIFT      (7U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_TEMP_SIZE_CLRMSK     (0XFFFFF87FU)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__TEMP_SIZE_SHIFT (7U)
+#define RGX_CR_CDM_CONTEXT_LOAD_PDS1__TEMPSIZE8__TEMP_SIZE_CLRMSK (0XFFFFF07FU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_DATA_SIZE_SHIFT      (1U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_DATA_SIZE_CLRMSK     (0XFFFFFF81U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_FENCE_SHIFT          (0U)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_FENCE_CLRMSK         (0XFFFFFFFEU)
 #define RGX_CR_CDM_CONTEXT_LOAD_PDS1_FENCE_EN             (0X00000001U)
-#endif /* !defined(RGX_FEATURE_PDS_TEMPSIZE8) */
 
 
 /*
     Register RGX_CR_MIPS_WRAPPER_CONFIG
 */
 #define RGX_CR_MIPS_WRAPPER_CONFIG                        (0x0810U)
-#define RGX_CR_MIPS_WRAPPER_CONFIG_MASKFULL               (IMG_UINT64_C(0x000000000001FFFF))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_MASKFULL               (IMG_UINT64_C(0x000000010F01FFFF))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_L2_CACHE_OFF_SHIFT     (32U)
+#define RGX_CR_MIPS_WRAPPER_CONFIG_L2_CACHE_OFF_CLRMSK    (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_L2_CACHE_OFF_EN        (IMG_UINT64_C(0X0000000100000000))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_OS_ID_SHIFT            (25U)
+#define RGX_CR_MIPS_WRAPPER_CONFIG_OS_ID_CLRMSK           (IMG_UINT64_C(0XFFFFFFFFF1FFFFFF))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_TRUSTED_SHIFT          (24U)
+#define RGX_CR_MIPS_WRAPPER_CONFIG_TRUSTED_CLRMSK         (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_TRUSTED_EN             (IMG_UINT64_C(0X0000000001000000))
 #define RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_SHIFT    (16U)
 #define RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_CLRMSK   (IMG_UINT64_C(0XFFFFFFFFFFFEFFFF))
-#define RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MIPS32   (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS (IMG_UINT64_C(0x0000000000010000))
+#define RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MIPS32   (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS (IMG_UINT64_C(0x0000000000010000))  
 #define RGX_CR_MIPS_WRAPPER_CONFIG_REGBANK_BASE_ADDR_SHIFT (0U)
 #define RGX_CR_MIPS_WRAPPER_CONFIG_REGBANK_BASE_ADDR_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF0000))
 
@@ -2037,9 +1308,14 @@
     Register RGX_CR_MIPS_ADDR_REMAP1_CONFIG2
 */
 #define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2                   (0x0820U)
-#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF01F))
+#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF1FF))
 #define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_SHIFT    (12U)
 #define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK   (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_SHIFT       (6U)
+#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFFFFFE3F))
+#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_SHIFT     (5U)
+#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK    (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_EN        (IMG_UINT64_C(0X0000000000000020))
 #define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_REGION_SIZE_POW2_SHIFT (0U)
 #define RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_REGION_SIZE_POW2_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFE0))
 
@@ -2060,9 +1336,14 @@
     Register RGX_CR_MIPS_ADDR_REMAP2_CONFIG2
 */
 #define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2                   (0x0830U)
-#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF01F))
+#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF1FF))
 #define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_SHIFT    (12U)
 #define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK   (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_OS_ID_SHIFT       (6U)
+#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_OS_ID_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFFFFFE3F))
+#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_TRUSTED_SHIFT     (5U)
+#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_TRUSTED_CLRMSK    (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_TRUSTED_EN        (IMG_UINT64_C(0X0000000000000020))
 #define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_REGION_SIZE_POW2_SHIFT (0U)
 #define RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_REGION_SIZE_POW2_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFE0))
 
@@ -2083,14 +1364,75 @@
     Register RGX_CR_MIPS_ADDR_REMAP3_CONFIG2
 */
 #define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2                   (0x0840U)
-#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF01F))
+#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF1FF))
 #define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_SHIFT    (12U)
 #define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK   (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_OS_ID_SHIFT       (6U)
+#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_OS_ID_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFFFFFE3F))
+#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_TRUSTED_SHIFT     (5U)
+#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_TRUSTED_CLRMSK    (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_TRUSTED_EN        (IMG_UINT64_C(0X0000000000000020))
 #define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_REGION_SIZE_POW2_SHIFT (0U)
 #define RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_REGION_SIZE_POW2_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFE0))
 
 
 /*
+    Register RGX_CR_MIPS_ADDR_REMAP4_CONFIG1
+*/
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1                   (0x0848U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF001))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_BASE_ADDR_IN_SHIFT (12U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_BASE_ADDR_IN_CLRMSK (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MODE_ENABLE_SHIFT (0U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MODE_ENABLE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MODE_ENABLE_EN    (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+    Register RGX_CR_MIPS_ADDR_REMAP4_CONFIG2
+*/
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2                   (0x0850U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF1FF))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_ADDR_OUT_SHIFT    (12U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_ADDR_OUT_CLRMSK   (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_OS_ID_SHIFT       (6U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_OS_ID_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFFFFFE3F))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_TRUSTED_SHIFT     (5U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_TRUSTED_CLRMSK    (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_TRUSTED_EN        (IMG_UINT64_C(0X0000000000000020))
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_REGION_SIZE_POW2_SHIFT (0U)
+#define RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_REGION_SIZE_POW2_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFE0))
+
+
+/*
+    Register RGX_CR_MIPS_ADDR_REMAP5_CONFIG1
+*/
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1                   (0x0858U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF001))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_BASE_ADDR_IN_SHIFT (12U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_BASE_ADDR_IN_CLRMSK (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_SHIFT (0U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_EN    (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+    Register RGX_CR_MIPS_ADDR_REMAP5_CONFIG2
+*/
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2                   (0x0860U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_MASKFULL          (IMG_UINT64_C(0x00000000FFFFF1FF))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_ADDR_OUT_SHIFT    (12U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_ADDR_OUT_CLRMSK   (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_OS_ID_SHIFT       (6U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_OS_ID_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFFFFFE3F))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_TRUSTED_SHIFT     (5U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_TRUSTED_CLRMSK    (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_TRUSTED_EN        (IMG_UINT64_C(0X0000000000000020))
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_REGION_SIZE_POW2_SHIFT (0U)
+#define RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_REGION_SIZE_POW2_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFE0))
+
+
+/*
     Register RGX_CR_MIPS_WRAPPER_IRQ_ENABLE
 */
 #define RGX_CR_MIPS_WRAPPER_IRQ_ENABLE                    (0x08A0U)
@@ -2699,45 +2041,29 @@
 #define RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK (0XFFFF0000U)
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 /*
     Register RGX_CR_MTS_GARTEN_WRAPPER_CONFIG
 */
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG                  (0x0B50U)
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_MASKFULL         (IMG_UINT64_C(0x000FF0FFFFFFF701))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT (44U)
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK (IMG_UINT64_C(0XFFF00FFFFFFFFFFF))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_SHIFT (12U)
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PERSISTENCE_SHIFT (9U)
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PERSISTENCE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF9FF))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_SLC_COHERENT_SHIFT (8U)
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_SLC_COHERENT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_SLC_COHERENT_EN (IMG_UINT64_C(0X0000000000000100))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_SHIFT  (0U)
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META   (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_MTS    (IMG_UINT64_C(0x0000000000000001))
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */ 
-
-
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-/*
-    Register RGX_CR_MTS_GARTEN_WRAPPER_CONFIG
-*/
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG                  (0x0B50U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__MASKFULL (IMG_UINT64_C(0x000FF0FFFFFFF701))
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_MASKFULL         (IMG_UINT64_C(0x0000FFFFFFFFF001))
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT (44U)
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK (IMG_UINT64_C(0XFFFF0FFFFFFFFFFF))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_SHIFT (44U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_CLRMSK (IMG_UINT64_C(0XFFF00FFFFFFFFFFF))
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_SHIFT   (40U)
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_CLRMSK  (IMG_UINT64_C(0XFFFFF0FFFFFFFFFF))
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_SHIFT (12U)
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PERSISTENCE_SHIFT (9U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PERSISTENCE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF9FF))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_SLC_COHERENT_SHIFT (8U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_SLC_COHERENT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_SLC_COHERENT_EN (IMG_UINT64_C(0X0000000000000100))
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_SHIFT  (0U)
 #define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META   (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_MTS    (IMG_UINT64_C(0x0000000000000001))
-#endif /* !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META   (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_MTS    (IMG_UINT64_C(0x0000000000000001))  
 
 
 /*
@@ -2775,13 +2101,10 @@
 */
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE                 (0x0BA8U)
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_MASKFULL        (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM7_SHIFT       (56U)
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM7_CLRMSK      (IMG_UINT64_C(0X00FFFFFFFFFFFFFF))
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM6_SHIFT       (48U)
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM6_CLRMSK      (IMG_UINT64_C(0XFF00FFFFFFFFFFFF))
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM5_SHIFT       (40U)
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM5_CLRMSK      (IMG_UINT64_C(0XFFFF00FFFFFFFFFF))
 #define RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE_DM4_SHIFT       (32U)
@@ -2825,6 +2148,15 @@
 #define RGX_CR_GARTEN_SLC_FORCE_COHERENCY_EN              (0X00000001U)
 
 
+/*
+    Register RGX_CR_PPP
+*/
+#define RGX_CR_PPP                                        (0x0CD0U)
+#define RGX_CR_PPP_MASKFULL                               (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_PPP_CHECKSUM_SHIFT                         (0U)
+#define RGX_CR_PPP_CHECKSUM_CLRMSK                        (00000000U)
+
+
 #define RGX_CR_ISP_RENDER_DIR_TYPE_MASK                   (0x00000003U)
 /*
  Top-left to bottom-right */
@@ -2911,14 +2243,19 @@
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_ONE               (00000000U)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_TWO               (0X00001000U)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_THREE             (0X00002000U)
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_FOUR              (0X00003000U)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_FIVE              (0X00004000U)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_SIX               (0X00005000U)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_SEVEN             (0X00006000U)
 #define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_EIGHT             (0X00007000U)
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_NINE              (0X00008000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_TEN               (0X00009000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_ELEVEN            (0X0000A000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_TWELVE            (0X0000B000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_THIRTEEN          (0X0000C000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_FOURTEEN          (0X0000D000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_FIFTEEN           (0X0000E000U)
+#define RGX_CR_ISP_CTL_PIPE_ENABLE_PIPE_SIXTEEN           (0X0000F000U)
 #define RGX_CR_ISP_CTL_VALID_ID_SHIFT                     (4U)
 #define RGX_CR_ISP_CTL_VALID_ID_CLRMSK                    (0XFFFFFC0FU)
 #define RGX_CR_ISP_CTL_UPASS_START_SHIFT                  (0U)
@@ -2926,105 +2263,6 @@
 
 
 /*
-    Register RGX_CR_ISP_STORE0
-*/
-#define RGX_CR_ISP_STORE0                                 (0x1008U)
-#define RGX_CR_ISP_STORE0_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE0_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE0_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE0_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE0_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE0_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE0_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE0_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE0_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE0_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE0_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE0_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE0_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE0_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE0_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE0_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_STORE1
-*/
-#define RGX_CR_ISP_STORE1                                 (0x1010U)
-#define RGX_CR_ISP_STORE1_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE1_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE1_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE1_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE1_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE1_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE1_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE1_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE1_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE1_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE1_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE1_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE1_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE1_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE1_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE1_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_STORE2
-*/
-#define RGX_CR_ISP_STORE2                                 (0x1018U)
-#define RGX_CR_ISP_STORE2_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE2_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE2_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE2_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE2_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE2_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE2_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE2_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE2_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE2_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE2_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE2_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE2_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE2_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE2_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE2_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME0
-*/
-#define RGX_CR_ISP_RESUME0                                (0x1020U)
-#define RGX_CR_ISP_RESUME0_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME0_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME0_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME0_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME0_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME1
-*/
-#define RGX_CR_ISP_RESUME1                                (0x1028U)
-#define RGX_CR_ISP_RESUME1_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME1_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME1_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME1_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME1_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME2
-*/
-#define RGX_CR_ISP_RESUME2                                (0x1030U)
-#define RGX_CR_ISP_RESUME2_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME2_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME2_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME2_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME2_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
     Register RGX_CR_ISP_STATUS
 */
 #define RGX_CR_ISP_STATUS                                 (0x1038U)
@@ -3040,174 +2278,6 @@
 #define RGX_CR_ISP_STATUS_EOR_EN                          (0X00000001U)
 
 
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-/*
-    Register RGX_CR_ISP_STORE3
-*/
-#define RGX_CR_ISP_STORE3                                 (0x1060U)
-#define RGX_CR_ISP_STORE3_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE3_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE3_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE3_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE3_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE3_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE3_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE3_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE3_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE3_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE3_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE3_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE3_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE3_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE3_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE3_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_STORE4
-*/
-#define RGX_CR_ISP_STORE4                                 (0x1068U)
-#define RGX_CR_ISP_STORE4_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE4_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE4_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE4_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE4_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE4_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE4_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE4_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE4_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE4_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE4_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE4_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE4_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE4_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE4_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE4_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_STORE5
-*/
-#define RGX_CR_ISP_STORE5                                 (0x1070U)
-#define RGX_CR_ISP_STORE5_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE5_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE5_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE5_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE5_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE5_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE5_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE5_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE5_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE5_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE5_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE5_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE5_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE5_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE5_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE5_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME3
-*/
-#define RGX_CR_ISP_RESUME3                                (0x1078U)
-#define RGX_CR_ISP_RESUME3_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME3_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME3_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME3_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME3_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME4
-*/
-#define RGX_CR_ISP_RESUME4                                (0x1080U)
-#define RGX_CR_ISP_RESUME4_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME4_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME4_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME4_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME4_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME5
-*/
-#define RGX_CR_ISP_RESUME5                                (0x1088U)
-#define RGX_CR_ISP_RESUME5_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME5_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME5_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME5_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME5_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_STORE6
-*/
-#define RGX_CR_ISP_STORE6                                 (0x10A0U)
-#define RGX_CR_ISP_STORE6_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE6_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE6_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE6_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE6_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE6_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE6_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE6_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE6_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE6_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE6_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE6_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE6_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE6_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE6_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE6_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_STORE7
-*/
-#define RGX_CR_ISP_STORE7                                 (0x10A8U)
-#define RGX_CR_ISP_STORE7_MASKFULL                        (IMG_UINT64_C(0x000000007F3FF3FF))
-#define RGX_CR_ISP_STORE7_ACTIVE_SHIFT                    (30U)
-#define RGX_CR_ISP_STORE7_ACTIVE_CLRMSK                   (0XBFFFFFFFU)
-#define RGX_CR_ISP_STORE7_ACTIVE_EN                       (0X40000000U)
-#define RGX_CR_ISP_STORE7_EOR_SHIFT                       (29U)
-#define RGX_CR_ISP_STORE7_EOR_CLRMSK                      (0XDFFFFFFFU)
-#define RGX_CR_ISP_STORE7_EOR_EN                          (0X20000000U)
-#define RGX_CR_ISP_STORE7_TILE_LAST_SHIFT                 (28U)
-#define RGX_CR_ISP_STORE7_TILE_LAST_CLRMSK                (0XEFFFFFFFU)
-#define RGX_CR_ISP_STORE7_TILE_LAST_EN                    (0X10000000U)
-#define RGX_CR_ISP_STORE7_MT_SHIFT                        (24U)
-#define RGX_CR_ISP_STORE7_MT_CLRMSK                       (0XF0FFFFFFU)
-#define RGX_CR_ISP_STORE7_TILE_X_SHIFT                    (12U)
-#define RGX_CR_ISP_STORE7_TILE_X_CLRMSK                   (0XFFC00FFFU)
-#define RGX_CR_ISP_STORE7_TILE_Y_SHIFT                    (0U)
-#define RGX_CR_ISP_STORE7_TILE_Y_CLRMSK                   (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME6
-*/
-#define RGX_CR_ISP_RESUME6                                (0x10B0U)
-#define RGX_CR_ISP_RESUME6_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME6_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME6_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME6_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME6_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-/*
-    Register RGX_CR_ISP_RESUME7
-*/
-#define RGX_CR_ISP_RESUME7                                (0x10B8U)
-#define RGX_CR_ISP_RESUME7_MASKFULL                       (IMG_UINT64_C(0x00000000003FF3FF))
-#define RGX_CR_ISP_RESUME7_TILE_X_SHIFT                   (12U)
-#define RGX_CR_ISP_RESUME7_TILE_X_CLRMSK                  (0XFFC00FFFU)
-#define RGX_CR_ISP_RESUME7_TILE_Y_SHIFT                   (0U)
-#define RGX_CR_ISP_RESUME7_TILE_Y_CLRMSK                  (0XFFFFFC00U)
-
-
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
 /*
     Register group: RGX_CR_ISP_XTP_RESUME, with 64 repeats
 */
@@ -3346,22 +2416,16 @@
 */
 #define RGX_CR_BIF_CAT_BASE_INDEX                         (0x1240U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_MASKFULL                (IMG_UINT64_C(0x0007070707070707))
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_BIF_CAT_BASE_INDEX_RVTX_SHIFT              (48U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_RVTX_CLRMSK             (IMG_UINT64_C(0XFFF8FFFFFFFFFFFF))
 #define RGX_CR_BIF_CAT_BASE_INDEX_RAY_SHIFT               (40U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_RAY_CLRMSK              (IMG_UINT64_C(0XFFFFF8FFFFFFFFFF))
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 #define RGX_CR_BIF_CAT_BASE_INDEX_HOST_SHIFT              (32U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_HOST_CLRMSK             (IMG_UINT64_C(0XFFFFFFF8FFFFFFFF))
 #define RGX_CR_BIF_CAT_BASE_INDEX_TLA_SHIFT               (24U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_TLA_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFF8FFFFFF))
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_BIF_CAT_BASE_INDEX_CDM_SHIFT               (16U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_CDM_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFFFF8FFFF))
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_BIF_CAT_BASE_INDEX_PIXEL_SHIFT             (8U)
 #define RGX_CR_BIF_CAT_BASE_INDEX_PIXEL_CLRMSK            (IMG_UINT64_C(0XFFFFFFFFFFFFF8FF))
 #define RGX_CR_BIF_CAT_BASE_INDEX_TA_SHIFT                (0U)
@@ -3767,17 +2831,11 @@
 #define RGX_CR_MCU_FENCE_MASKFULL                         (IMG_UINT64_C(0x000007FFFFFFFFE0))
 #define RGX_CR_MCU_FENCE_DM_SHIFT                         (40U)
 #define RGX_CR_MCU_FENCE_DM_CLRMSK                        (IMG_UINT64_C(0XFFFFF8FFFFFFFFFF))
-#define RGX_CR_MCU_FENCE_DM_VERTEX                        (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_MCU_FENCE_DM_PIXEL                         (IMG_UINT64_C(0x0000010000000000))
-#if defined(RGX_FEATURE_COMPUTE)
-#define RGX_CR_MCU_FENCE_DM_COMPUTE                       (IMG_UINT64_C(0x0000020000000000))
-#endif /* RGX_FEATURE_COMPUTE */
-
-#if defined(RGX_FEATURE_RAY_TRACING)
-#define RGX_CR_MCU_FENCE_DM_RAY_VERTEX                    (IMG_UINT64_C(0x0000030000000000))
-#define RGX_CR_MCU_FENCE_DM_RAY                           (IMG_UINT64_C(0x0000040000000000))
-#endif /* RGX_FEATURE_RAY_TRACING */
-
+#define RGX_CR_MCU_FENCE_DM_VERTEX                        (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_MCU_FENCE_DM_PIXEL                         (IMG_UINT64_C(0x0000010000000000))  
+#define RGX_CR_MCU_FENCE_DM_COMPUTE                       (IMG_UINT64_C(0x0000020000000000))  
+#define RGX_CR_MCU_FENCE_DM_RAY_VERTEX                    (IMG_UINT64_C(0x0000030000000000))  
+#define RGX_CR_MCU_FENCE_DM_RAY                           (IMG_UINT64_C(0x0000040000000000))  
 #define RGX_CR_MCU_FENCE_ADDR_SHIFT                       (5U)
 #define RGX_CR_MCU_FENCE_ADDR_CLRMSK                      (IMG_UINT64_C(0XFFFFFF000000001F))
 #define RGX_CR_MCU_FENCE_ADDR_ALIGNSHIFT                  (5U)
@@ -3785,26 +2843,51 @@
 
 
 /*
+    Register RGX_CR_SPFILTER_SIGNAL_DESCR
+*/
+#define RGX_CR_SPFILTER_SIGNAL_DESCR                      (0x2700U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MASKFULL             (IMG_UINT64_C(0x000000000000FFFF))
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_SIZE_SHIFT           (0U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_SIZE_CLRMSK          (0XFFFF0000U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_SIZE_ALIGNSHIFT      (4U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_SIZE_ALIGNSIZE       (16U)
+
+
+/*
+    Register RGX_CR_SPFILTER_SIGNAL_DESCR_MIN
+*/
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MIN                  (0x2708U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MIN_MASKFULL         (IMG_UINT64_C(0x000000FFFFFFFFF0))
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MIN_ADDR_SHIFT       (4U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MIN_ADDR_CLRMSK      (IMG_UINT64_C(0XFFFFFF000000000F))
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MIN_ADDR_ALIGNSHIFT  (4U)
+#define RGX_CR_SPFILTER_SIGNAL_DESCR_MIN_ADDR_ALIGNSIZE   (16U)
+
+
+/*
     Register RGX_CR_SLC_CTRL_MISC
 */
 #define RGX_CR_SLC_CTRL_MISC                              (0x3800U)
-#define RGX_CR_SLC_CTRL_MISC_MASKFULL                     (IMG_UINT64_C(0xFFFFFFFF00FF0105))
+#define RGX_CR_SLC_CTRL_MISC_MASKFULL                     (IMG_UINT64_C(0xFFFFFFFF00FF0107))
 #define RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS_SHIFT          (32U)
 #define RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS_CLRMSK         (IMG_UINT64_C(0X00000000FFFFFFFF))
 #define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SHIFT       (16U)
 #define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_CLRMSK      (IMG_UINT64_C(0XFFFFFFFFFF00FFFF))
-#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_INTERLEAVED_64_BYTE (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_INTERLEAVED_128_BYTE (IMG_UINT64_C(0x0000000000010000))
-#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SIMPLE_HASH1 (IMG_UINT64_C(0x0000000000100000))
-#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SIMPLE_HASH2 (IMG_UINT64_C(0x0000000000110000))
-#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1   (IMG_UINT64_C(0x0000000000200000))
-#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH2_SCRAMBLE (IMG_UINT64_C(0x0000000000210000))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_INTERLEAVED_64_BYTE (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_INTERLEAVED_128_BYTE (IMG_UINT64_C(0x0000000000010000))  
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SIMPLE_HASH1 (IMG_UINT64_C(0x0000000000100000))  
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SIMPLE_HASH2 (IMG_UINT64_C(0x0000000000110000))  
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1   (IMG_UINT64_C(0x0000000000200000))  
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH2_SCRAMBLE (IMG_UINT64_C(0x0000000000210000))  
 #define RGX_CR_SLC_CTRL_MISC_PAUSE_SHIFT                  (8U)
 #define RGX_CR_SLC_CTRL_MISC_PAUSE_CLRMSK                 (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
 #define RGX_CR_SLC_CTRL_MISC_PAUSE_EN                     (IMG_UINT64_C(0X0000000000000100))
 #define RGX_CR_SLC_CTRL_MISC_ENABLE_LINE_USE_LIMIT_SHIFT  (2U)
 #define RGX_CR_SLC_CTRL_MISC_ENABLE_LINE_USE_LIMIT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
 #define RGX_CR_SLC_CTRL_MISC_ENABLE_LINE_USE_LIMIT_EN     (IMG_UINT64_C(0X0000000000000004))
+#define RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_SHIFT (1U)
+#define RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
+#define RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN   (IMG_UINT64_C(0X0000000000000002))
 #define RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_SHIFT  (0U)
 #define RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
 #define RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN     (IMG_UINT64_C(0X0000000000000001))
@@ -3818,15 +2901,12 @@
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_LAZY_SHIFT            (31U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_LAZY_CLRMSK           (0X7FFFFFFFU)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_LAZY_EN               (0X80000000U)
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_VERTEX_SHIFT   (10U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_VERTEX_CLRMSK  (0XFFFFFBFFU)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_VERTEX_EN      (0X00000400U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_SHIFT          (9U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_CLRMSK         (0XFFFFFDFFU)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_EN             (0X00000200U)
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_FRC_SHIFT          (8U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_FRC_CLRMSK         (0XFFFFFEFFU)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_FRC_EN             (0X00000100U)
@@ -3842,12 +2922,9 @@
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_MMU_SHIFT          (4U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_MMU_CLRMSK         (0XFFFFFFEFU)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_MMU_EN             (0X00000010U)
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_COMPUTE_SHIFT      (3U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_COMPUTE_CLRMSK     (0XFFFFFFF7U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_COMPUTE_EN         (0X00000008U)
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_PIXEL_SHIFT        (2U)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_PIXEL_CLRMSK       (0XFFFFFFFBU)
 #define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_PIXEL_EN           (0X00000004U)
@@ -3880,15 +2957,12 @@
 */
 #define RGX_CR_SLC_CTRL_BYPASS                            (0x3828U)
 #define RGX_CR_SLC_CTRL_BYPASS_MASKFULL                   (IMG_UINT64_C(0x000000000FFFFFFF))
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_VERTEX_SHIFT        (27U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_VERTEX_CLRMSK       (0XF7FFFFFFU)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_VERTEX_EN           (0X08000000U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_SHIFT               (26U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_CLRMSK              (0XFBFFFFFFU)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_EN                  (0X04000000U)
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 #define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_SHIFT          (25U)
 #define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_CLRMSK         (0XFDFFFFFFU)
 #define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_EN             (0X02000000U)
@@ -3955,12 +3029,9 @@
 #define RGX_CR_SLC_CTRL_BYPASS_DM_MMU_SHIFT               (4U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_MMU_CLRMSK              (0XFFFFFFEFU)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_MMU_EN                  (0X00000010U)
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_COMPUTE_SHIFT           (3U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_COMPUTE_CLRMSK          (0XFFFFFFF7U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_COMPUTE_EN              (0X00000008U)
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_SLC_CTRL_BYPASS_DM_PIXEL_SHIFT             (2U)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_PIXEL_CLRMSK            (0XFFFFFFFBU)
 #define RGX_CR_SLC_CTRL_BYPASS_DM_PIXEL_EN                (0X00000004U)
@@ -4056,6 +3127,177 @@
 
 
 /*
+    Register RGX_CR_USC_UVS0_CHECKSUM
+*/
+#define RGX_CR_USC_UVS0_CHECKSUM                          (0x5000U)
+#define RGX_CR_USC_UVS0_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVS0_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_USC_UVS0_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_USC_UVS1_CHECKSUM
+*/
+#define RGX_CR_USC_UVS1_CHECKSUM                          (0x5008U)
+#define RGX_CR_USC_UVS1_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVS1_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_USC_UVS1_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_USC_UVS2_CHECKSUM
+*/
+#define RGX_CR_USC_UVS2_CHECKSUM                          (0x5010U)
+#define RGX_CR_USC_UVS2_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVS2_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_USC_UVS2_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_USC_UVS3_CHECKSUM
+*/
+#define RGX_CR_USC_UVS3_CHECKSUM                          (0x5018U)
+#define RGX_CR_USC_UVS3_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVS3_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_USC_UVS3_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_PPP_SIGNATURE
+*/
+#define RGX_CR_PPP_SIGNATURE                              (0x5020U)
+#define RGX_CR_PPP_SIGNATURE_MASKFULL                     (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_PPP_SIGNATURE_VALUE_SHIFT                  (0U)
+#define RGX_CR_PPP_SIGNATURE_VALUE_CLRMSK                 (00000000U)
+
+
+/*
+    Register RGX_CR_TE_SIGNATURE
+*/
+#define RGX_CR_TE_SIGNATURE                               (0x5028U)
+#define RGX_CR_TE_SIGNATURE_MASKFULL                      (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_TE_SIGNATURE_VALUE_SHIFT                   (0U)
+#define RGX_CR_TE_SIGNATURE_VALUE_CLRMSK                  (00000000U)
+
+
+/*
+    Register RGX_CR_TE_CHECKSUM
+*/
+#define RGX_CR_TE_CHECKSUM                                (0x5110U)
+#define RGX_CR_TE_CHECKSUM_MASKFULL                       (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_TE_CHECKSUM_VALUE_SHIFT                    (0U)
+#define RGX_CR_TE_CHECKSUM_VALUE_CLRMSK                   (00000000U)
+
+
+/*
+    Register RGX_CR_USC_UVB_CHECKSUM
+*/
+#define RGX_CR_USC_UVB_CHECKSUM                           (0x5118U)
+#define RGX_CR_USC_UVB_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVB_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_USC_UVB_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_VCE_CHECKSUM
+*/
+#define RGX_CR_VCE_CHECKSUM                               (0x5030U)
+#define RGX_CR_VCE_CHECKSUM_MASKFULL                      (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_VCE_CHECKSUM_VALUE_SHIFT                   (0U)
+#define RGX_CR_VCE_CHECKSUM_VALUE_CLRMSK                  (00000000U)
+
+
+/*
+    Register RGX_CR_ISP_PDS_CHECKSUM
+*/
+#define RGX_CR_ISP_PDS_CHECKSUM                           (0x5038U)
+#define RGX_CR_ISP_PDS_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_ISP_PDS_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_ISP_PDS_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_ISP_TPF_CHECKSUM
+*/
+#define RGX_CR_ISP_TPF_CHECKSUM                           (0x5040U)
+#define RGX_CR_ISP_TPF_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_ISP_TPF_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_ISP_TPF_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_TFPU_PLANE0_CHECKSUM
+*/
+#define RGX_CR_TFPU_PLANE0_CHECKSUM                       (0x5048U)
+#define RGX_CR_TFPU_PLANE0_CHECKSUM_MASKFULL              (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_TFPU_PLANE0_CHECKSUM_VALUE_SHIFT           (0U)
+#define RGX_CR_TFPU_PLANE0_CHECKSUM_VALUE_CLRMSK          (00000000U)
+
+
+/*
+    Register RGX_CR_TFPU_PLANE1_CHECKSUM
+*/
+#define RGX_CR_TFPU_PLANE1_CHECKSUM                       (0x5050U)
+#define RGX_CR_TFPU_PLANE1_CHECKSUM_MASKFULL              (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_TFPU_PLANE1_CHECKSUM_VALUE_SHIFT           (0U)
+#define RGX_CR_TFPU_PLANE1_CHECKSUM_VALUE_CLRMSK          (00000000U)
+
+
+/*
+    Register RGX_CR_PBE_CHECKSUM
+*/
+#define RGX_CR_PBE_CHECKSUM                               (0x5058U)
+#define RGX_CR_PBE_CHECKSUM_MASKFULL                      (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_PBE_CHECKSUM_VALUE_SHIFT                   (0U)
+#define RGX_CR_PBE_CHECKSUM_VALUE_CLRMSK                  (00000000U)
+
+
+/*
+    Register RGX_CR_PDS_DOUTM_STM_SIGNATURE
+*/
+#define RGX_CR_PDS_DOUTM_STM_SIGNATURE                    (0x5060U)
+#define RGX_CR_PDS_DOUTM_STM_SIGNATURE_MASKFULL           (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_PDS_DOUTM_STM_SIGNATURE_VALUE_SHIFT        (0U)
+#define RGX_CR_PDS_DOUTM_STM_SIGNATURE_VALUE_CLRMSK       (00000000U)
+
+
+/*
+    Register RGX_CR_IFPU_ISP_CHECKSUM
+*/
+#define RGX_CR_IFPU_ISP_CHECKSUM                          (0x5068U)
+#define RGX_CR_IFPU_ISP_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_IFPU_ISP_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_IFPU_ISP_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_USC_UVS4_CHECKSUM
+*/
+#define RGX_CR_USC_UVS4_CHECKSUM                          (0x5100U)
+#define RGX_CR_USC_UVS4_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVS4_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_USC_UVS4_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_USC_UVS5_CHECKSUM
+*/
+#define RGX_CR_USC_UVS5_CHECKSUM                          (0x5108U)
+#define RGX_CR_USC_UVS5_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_UVS5_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_USC_UVS5_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
+    Register RGX_CR_PPP_CLIP_CHECKSUM
+*/
+#define RGX_CR_PPP_CLIP_CHECKSUM                          (0x5120U)
+#define RGX_CR_PPP_CLIP_CHECKSUM_MASKFULL                 (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_PPP_CLIP_CHECKSUM_VALUE_SHIFT              (0U)
+#define RGX_CR_PPP_CLIP_CHECKSUM_VALUE_CLRMSK             (00000000U)
+
+
+/*
     Register RGX_CR_PERF_TA_PHASE
 */
 #define RGX_CR_PERF_TA_PHASE                              (0x6008U)
@@ -4652,7 +3894,6 @@
 #define RGX_CR_JONES_IDLE_BIF_EN                          (0X00000001U)
 
 
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 /*
     Register RGX_CR_TORNADO_PERF
 */
@@ -4757,8 +3998,6 @@
 #define RGX_CR_TEXAS_PERF_COUNTER_0_REG_CLRMSK            (00000000U)
 
 
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
 /*
     Register RGX_CR_JONES_PERF
 */
@@ -4808,7 +4047,6 @@
 #define RGX_CR_JONES_PERF_COUNTER_0_REG_CLRMSK            (00000000U)
 
 
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 /*
     Register RGX_CR_BLACKPEARL_PERF
 */
@@ -4864,8 +4102,6 @@
 #define RGX_CR_BLACKPEARL_PERF_COUNTER_0_REG_CLRMSK       (00000000U)
 
 
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
-
 /*
     Register RGX_CR_PBE_PERF
 */
@@ -5279,7 +4515,6 @@
 */
 #define RGX_CR_BIF_TRUST                                  (0xA000U)
 #define RGX_CR_BIF_TRUST_MASKFULL                         (IMG_UINT64_C(0x00000000001FFFFF))
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_BIF_TRUST_OTHER_RAY_VERTEX_DM_TRUSTED_SHIFT (20U)
 #define RGX_CR_BIF_TRUST_OTHER_RAY_VERTEX_DM_TRUSTED_CLRMSK (0XFFEFFFFFU)
 #define RGX_CR_BIF_TRUST_OTHER_RAY_VERTEX_DM_TRUSTED_EN   (0X00100000U)
@@ -5292,14 +4527,11 @@
 #define RGX_CR_BIF_TRUST_MCU_RAY_DM_TRUSTED_SHIFT         (17U)
 #define RGX_CR_BIF_TRUST_MCU_RAY_DM_TRUSTED_CLRMSK        (0XFFFDFFFFU)
 #define RGX_CR_BIF_TRUST_MCU_RAY_DM_TRUSTED_EN            (0X00020000U)
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 #define RGX_CR_BIF_TRUST_ENABLE_SHIFT                     (16U)
 #define RGX_CR_BIF_TRUST_ENABLE_CLRMSK                    (0XFFFEFFFFU)
 #define RGX_CR_BIF_TRUST_ENABLE_EN                        (0X00010000U)
 #define RGX_CR_BIF_TRUST_DM_TRUSTED_SHIFT                 (9U)
 #define RGX_CR_BIF_TRUST_DM_TRUSTED_CLRMSK                (0XFFFF01FFU)
-#if defined(RGX_FEATURE_COMPUTE)
 #define RGX_CR_BIF_TRUST_OTHER_COMPUTE_DM_TRUSTED_SHIFT   (8U)
 #define RGX_CR_BIF_TRUST_OTHER_COMPUTE_DM_TRUSTED_CLRMSK  (0XFFFFFEFFU)
 #define RGX_CR_BIF_TRUST_OTHER_COMPUTE_DM_TRUSTED_EN      (0X00000100U)
@@ -5309,8 +4541,6 @@
 #define RGX_CR_BIF_TRUST_PBE_COMPUTE_DM_TRUSTED_SHIFT     (6U)
 #define RGX_CR_BIF_TRUST_PBE_COMPUTE_DM_TRUSTED_CLRMSK    (0XFFFFFFBFU)
 #define RGX_CR_BIF_TRUST_PBE_COMPUTE_DM_TRUSTED_EN        (0X00000040U)
-#endif /* RGX_FEATURE_COMPUTE */
-
 #define RGX_CR_BIF_TRUST_OTHER_PIXEL_DM_TRUSTED_SHIFT     (5U)
 #define RGX_CR_BIF_TRUST_OTHER_PIXEL_DM_TRUSTED_CLRMSK    (0XFFFFFFDFU)
 #define RGX_CR_BIF_TRUST_OTHER_PIXEL_DM_TRUSTED_EN        (0X00000020U)
@@ -5335,6 +4565,7 @@
     Register RGX_CR_SYS_BUS_SECURE
 */
 #define RGX_CR_SYS_BUS_SECURE                             (0xA100U)
+#define RGX_CR_SYS_BUS_SECURE__SECR__MASKFULL             (IMG_UINT64_C(0x0000000000000001))
 #define RGX_CR_SYS_BUS_SECURE_MASKFULL                    (IMG_UINT64_C(0x0000000000000001))
 #define RGX_CR_SYS_BUS_SECURE_ENABLE_SHIFT                (0U)
 #define RGX_CR_SYS_BUS_SECURE_ENABLE_CLRMSK               (0XFFFFFFFEU)
@@ -5342,53 +4573,85 @@
 
 
 /*
+    Register RGX_CR_FBA_FC0_CHECKSUM
+*/
+#define RGX_CR_FBA_FC0_CHECKSUM                           (0xD170U)
+#define RGX_CR_FBA_FC0_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_FBA_FC0_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_FBA_FC0_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_FBA_FC1_CHECKSUM
+*/
+#define RGX_CR_FBA_FC1_CHECKSUM                           (0xD178U)
+#define RGX_CR_FBA_FC1_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_FBA_FC1_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_FBA_FC1_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_FBA_FC2_CHECKSUM
+*/
+#define RGX_CR_FBA_FC2_CHECKSUM                           (0xD180U)
+#define RGX_CR_FBA_FC2_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_FBA_FC2_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_FBA_FC2_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_FBA_FC3_CHECKSUM
+*/
+#define RGX_CR_FBA_FC3_CHECKSUM                           (0xD188U)
+#define RGX_CR_FBA_FC3_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_FBA_FC3_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_FBA_FC3_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
     Register RGX_CR_CLK_CTRL2
 */
 #define RGX_CR_CLK_CTRL2                                  (0xD200U)
 #define RGX_CR_CLK_CTRL2_MASKFULL                         (IMG_UINT64_C(0x0000000000000F33))
 #define RGX_CR_CLK_CTRL2_MCU_FBTC_SHIFT                   (10U)
 #define RGX_CR_CLK_CTRL2_MCU_FBTC_CLRMSK                  (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
-#define RGX_CR_CLK_CTRL2_MCU_FBTC_OFF                     (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL2_MCU_FBTC_ON                      (IMG_UINT64_C(0x0000000000000400))
-#define RGX_CR_CLK_CTRL2_MCU_FBTC_AUTO                    (IMG_UINT64_C(0x0000000000000800))
-#if defined(RGX_FEATURE_RAY_TRACING)
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_OFF                     (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_ON                      (IMG_UINT64_C(0x0000000000000400))  
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_AUTO                    (IMG_UINT64_C(0x0000000000000800))  
 #define RGX_CR_CLK_CTRL2_VRDM_SHIFT                       (8U)
 #define RGX_CR_CLK_CTRL2_VRDM_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
-#define RGX_CR_CLK_CTRL2_VRDM_OFF                         (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL2_VRDM_ON                          (IMG_UINT64_C(0x0000000000000100))
-#define RGX_CR_CLK_CTRL2_VRDM_AUTO                        (IMG_UINT64_C(0x0000000000000200))
+#define RGX_CR_CLK_CTRL2_VRDM_OFF                         (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL2_VRDM_ON                          (IMG_UINT64_C(0x0000000000000100))  
+#define RGX_CR_CLK_CTRL2_VRDM_AUTO                        (IMG_UINT64_C(0x0000000000000200))  
 #define RGX_CR_CLK_CTRL2_SH_SHIFT                         (4U)
 #define RGX_CR_CLK_CTRL2_SH_CLRMSK                        (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
-#define RGX_CR_CLK_CTRL2_SH_OFF                           (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL2_SH_ON                            (IMG_UINT64_C(0x0000000000000010))
-#define RGX_CR_CLK_CTRL2_SH_AUTO                          (IMG_UINT64_C(0x0000000000000020))
+#define RGX_CR_CLK_CTRL2_SH_OFF                           (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL2_SH_ON                            (IMG_UINT64_C(0x0000000000000010))  
+#define RGX_CR_CLK_CTRL2_SH_AUTO                          (IMG_UINT64_C(0x0000000000000020))  
 #define RGX_CR_CLK_CTRL2_FBA_SHIFT                        (0U)
 #define RGX_CR_CLK_CTRL2_FBA_CLRMSK                       (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
-#define RGX_CR_CLK_CTRL2_FBA_OFF                          (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_CTRL2_FBA_ON                           (IMG_UINT64_C(0x0000000000000001))
-#define RGX_CR_CLK_CTRL2_FBA_AUTO                         (IMG_UINT64_C(0x0000000000000002))
+#define RGX_CR_CLK_CTRL2_FBA_OFF                          (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_CTRL2_FBA_ON                           (IMG_UINT64_C(0x0000000000000001))  
+#define RGX_CR_CLK_CTRL2_FBA_AUTO                         (IMG_UINT64_C(0x0000000000000002))  
 
 
-#endif /* RGX_FEATURE_RAY_TRACING */
-
 /*
     Register RGX_CR_CLK_STATUS2
 */
 #define RGX_CR_CLK_STATUS2                                (0xD208U)
 #define RGX_CR_CLK_STATUS2_MASKFULL                       (IMG_UINT64_C(0x0000000000000015))
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGX_CR_CLK_STATUS2_VRDM_SHIFT                     (4U)
 #define RGX_CR_CLK_STATUS2_VRDM_CLRMSK                    (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
-#define RGX_CR_CLK_STATUS2_VRDM_GATED                     (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS2_VRDM_RUNNING                   (IMG_UINT64_C(0x0000000000000010))
+#define RGX_CR_CLK_STATUS2_VRDM_GATED                     (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS2_VRDM_RUNNING                   (IMG_UINT64_C(0x0000000000000010))  
 #define RGX_CR_CLK_STATUS2_SH_SHIFT                       (2U)
 #define RGX_CR_CLK_STATUS2_SH_CLRMSK                      (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
-#define RGX_CR_CLK_STATUS2_SH_GATED                       (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS2_SH_RUNNING                     (IMG_UINT64_C(0x0000000000000004))
+#define RGX_CR_CLK_STATUS2_SH_GATED                       (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS2_SH_RUNNING                     (IMG_UINT64_C(0x0000000000000004))  
 #define RGX_CR_CLK_STATUS2_FBA_SHIFT                      (0U)
 #define RGX_CR_CLK_STATUS2_FBA_CLRMSK                     (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
-#define RGX_CR_CLK_STATUS2_FBA_GATED                      (IMG_UINT64_C(0000000000000000))
-#define RGX_CR_CLK_STATUS2_FBA_RUNNING                    (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_CLK_STATUS2_FBA_GATED                      (IMG_UINT64_C(0000000000000000))  
+#define RGX_CR_CLK_STATUS2_FBA_RUNNING                    (IMG_UINT64_C(0x0000000000000001))  
 
 
 /*
@@ -5465,9 +4728,6 @@
 #define RGX_CR_RPM_SHG_FPL_WRITE_OFFSET_CLRMSK            (0XFFC00000U)
 
 
-#endif /* RGX_FEATURE_RAY_TRACING */
-
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 /*
     Register RGX_CR_SH_PERF
 */
@@ -5517,9 +4777,60 @@
 #define RGX_CR_SH_PERF_COUNTER_0_REG_CLRMSK               (00000000U)
 
 
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+/*
+    Register RGX_CR_SHF_SHG_CHECKSUM
+*/
+#define RGX_CR_SHF_SHG_CHECKSUM                           (0xD1C0U)
+#define RGX_CR_SHF_SHG_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_SHF_SHG_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_SHF_SHG_CHECKSUM_VALUE_CLRMSK              (00000000U)
 
-#if defined(RGX_FEATURE_RAY_TRACING)
+
+/*
+    Register RGX_CR_SHF_VERTEX_BIF_CHECKSUM
+*/
+#define RGX_CR_SHF_VERTEX_BIF_CHECKSUM                    (0xD1C8U)
+#define RGX_CR_SHF_VERTEX_BIF_CHECKSUM_MASKFULL           (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_SHF_VERTEX_BIF_CHECKSUM_VALUE_SHIFT        (0U)
+#define RGX_CR_SHF_VERTEX_BIF_CHECKSUM_VALUE_CLRMSK       (00000000U)
+
+
+/*
+    Register RGX_CR_SHF_VARY_BIF_CHECKSUM
+*/
+#define RGX_CR_SHF_VARY_BIF_CHECKSUM                      (0xD1D0U)
+#define RGX_CR_SHF_VARY_BIF_CHECKSUM_MASKFULL             (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_SHF_VARY_BIF_CHECKSUM_VALUE_SHIFT          (0U)
+#define RGX_CR_SHF_VARY_BIF_CHECKSUM_VALUE_CLRMSK         (00000000U)
+
+
+/*
+    Register RGX_CR_RPM_BIF_CHECKSUM
+*/
+#define RGX_CR_RPM_BIF_CHECKSUM                           (0xD1D8U)
+#define RGX_CR_RPM_BIF_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_RPM_BIF_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_RPM_BIF_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_SHG_BIF_CHECKSUM
+*/
+#define RGX_CR_SHG_BIF_CHECKSUM                           (0xD1E0U)
+#define RGX_CR_SHG_BIF_CHECKSUM_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_SHG_BIF_CHECKSUM_VALUE_SHIFT               (0U)
+#define RGX_CR_SHG_BIF_CHECKSUM_VALUE_CLRMSK              (00000000U)
+
+
+/*
+    Register RGX_CR_SHG_FE_BE_CHECKSUM
+*/
+#define RGX_CR_SHG_FE_BE_CHECKSUM                         (0xD1E8U)
+#define RGX_CR_SHG_FE_BE_CHECKSUM_MASKFULL                (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_SHG_FE_BE_CHECKSUM_VALUE_SHIFT             (0U)
+#define RGX_CR_SHG_FE_BE_CHECKSUM_VALUE_CLRMSK            (00000000U)
+
+
 /*
     Register DPX_CR_BF_PERF
 */
@@ -5619,6 +4930,15 @@
 
 
 /*
+    Register DPX_CR_RQ_USC_DEBUG
+*/
+#define DPX_CR_RQ_USC_DEBUG                               (0xC110U)
+#define DPX_CR_RQ_USC_DEBUG_MASKFULL                      (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define DPX_CR_RQ_USC_DEBUG_CHECKSUM_SHIFT                (0U)
+#define DPX_CR_RQ_USC_DEBUG_CHECKSUM_CLRMSK               (IMG_UINT64_C(0XFFFFFFFF00000000))
+
+
+/*
     Register DPX_CR_BIF_FAULT_BANK_MMU_STATUS
 */
 #define DPX_CR_BIF_FAULT_BANK_MMU_STATUS                  (0xC5C8U)
@@ -5778,7 +5098,14 @@
 #define DPX_CR_BX_TU_PERF_COUNTER_0_REG_CLRMSK            (00000000U)
 
 
-#endif /* RGX_FEATURE_RAY_TRACING */
+/*
+    Register DPX_CR_RS_PDS_RR_CHECKSUM
+*/
+#define DPX_CR_RS_PDS_RR_CHECKSUM                         (0xC0F0U)
+#define DPX_CR_RS_PDS_RR_CHECKSUM_MASKFULL                (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define DPX_CR_RS_PDS_RR_CHECKSUM_VALUE_SHIFT             (0U)
+#define DPX_CR_RS_PDS_RR_CHECKSUM_VALUE_CLRMSK            (IMG_UINT64_C(0XFFFFFFFF00000000))
+
 
 /*
     Register RGX_CR_MMU_CBASE_MAPPING_CONTEXT
@@ -5971,11 +5298,8 @@
 */
 #define RGX_CR_CONTEXT_MAPPING0                           (0xF078U)
 #define RGX_CR_CONTEXT_MAPPING0_MASKFULL                  (IMG_UINT64_C(0x00000000FFFFFFFF))
-#if defined(RGX_FEATURE_FASTRENDER_DM)
 #define RGX_CR_CONTEXT_MAPPING0_2D_SHIFT                  (24U)
 #define RGX_CR_CONTEXT_MAPPING0_2D_CLRMSK                 (0X00FFFFFFU)
-#endif /* RGX_FEATURE_FASTRENDER_DM */
-
 #define RGX_CR_CONTEXT_MAPPING0_CDM_SHIFT                 (16U)
 #define RGX_CR_CONTEXT_MAPPING0_CDM_CLRMSK                (0XFF00FFFFU)
 #define RGX_CR_CONTEXT_MAPPING0_3D_SHIFT                  (8U)
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/rgxdefs_km.h b/drivers/staging/imgtec/rogue/hwdefs/km/rgxdefs_km.h
index 788dbb0..cb61624 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/rgxdefs_km.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/rgxdefs_km.h
@@ -46,34 +46,77 @@
 #include RGX_BNC_CONFIG_KM_HEADER
 
 #define __IMG_EXPLICIT_INCLUDE_HWDEFS
+#if defined(__KERNEL__)
 #include "rgx_cr_defs_km.h"
+#else
+#include RGX_BVNC_CORE_HEADER
+#include RGX_BNC_CONFIG_HEADER
+#include "rgx_cr_defs.h"
+#endif
 #undef __IMG_EXPLICIT_INCLUDE_HWDEFS
 
+/* The following Macros are picked up through BVNC headers for PDUMP and
+ * no hardware operations to be compatible with old build infrastructure.
+ */
+#if defined(PDUMP) || defined(NO_HARDWARE) || !defined(SUPPORT_MULTIBVNC_RUNTIME_BVNC_ACQUISITION)
 /******************************************************************************
  * Check for valid B.X.N.C
  *****************************************************************************/
 #if !defined(RGX_BVNC_KM_B) || !defined(RGX_BVNC_KM_V) || !defined(RGX_BVNC_KM_N) || !defined(RGX_BVNC_KM_C)
 #error "Need to specify BVNC (RGX_BVNC_KM_B, RGX_BVNC_KM_V, RGX_BVNC_KM_N and RGX_BVNC_C)"
 #endif
+#endif
 
+#if defined(PDUMP) || defined(NO_HARDWARE)
 /* Check core/config compatibility */
-#if (RGX_BVNC_KM_B != RGX_BNC_KM_B) || (RGX_BVNC_KM_N != RGX_BNC_KM_N) || (RGX_BVNC_KM_C != RGX_BNC_KM_C) 
+#if (RGX_BVNC_KM_B != RGX_BNC_KM_B) || (RGX_BVNC_KM_N != RGX_BNC_KM_N) || (RGX_BVNC_KM_C != RGX_BNC_KM_C)
 #error "BVNC headers are mismatching (KM core/config)"
 #endif
 
+#endif
+
 /******************************************************************************
  * RGX Version name
  *****************************************************************************/
 #define _RGX_BVNC_ST2(S)	#S
 #define _RGX_BVNC_ST(S)		_RGX_BVNC_ST2(S)
+#if defined(PDUMP) || defined(NO_HARDWARE) || defined(PVRSRV_GPUVIRT_GUESTDRV) || !defined(SUPPORT_MULTIBVNC_RUNTIME_BVNC_ACQUISITION)
 #define RGX_BVNC_KM			_RGX_BVNC_ST(RGX_BVNC_KM_B) "." _RGX_BVNC_ST(RGX_BVNC_KM_V) "." _RGX_BVNC_ST(RGX_BVNC_KM_N) "." _RGX_BVNC_ST(RGX_BVNC_KM_C)
+#endif
 #define RGX_BVNC_KM_V_ST	_RGX_BVNC_ST(RGX_BVNC_KM_V)
 
 /******************************************************************************
  * RGX Defines
  *****************************************************************************/
 
-#if defined(RGX_FEATURE_META)
+#define			BVNC_FIELD_MASK			((1 << BVNC_FIELD_WIDTH) - 1)
+#define         C_POSITION              (0)
+#define         N_POSITION              ((C_POSITION) + (BVNC_FIELD_WIDTH))
+#define         V_POSITION              ((N_POSITION) + (BVNC_FIELD_WIDTH))
+#define         B_POSITION              ((V_POSITION) + (BVNC_FIELD_WIDTH))
+
+#define         B_POSTION_MASK          (((IMG_UINT64)(BVNC_FIELD_MASK) << (B_POSITION)))
+#define         V_POSTION_MASK          (((IMG_UINT64)(BVNC_FIELD_MASK) << (V_POSITION)))
+#define         N_POSTION_MASK          (((IMG_UINT64)(BVNC_FIELD_MASK) << (N_POSITION)))
+#define         C_POSTION_MASK          (((IMG_UINT64)(BVNC_FIELD_MASK) << (C_POSITION)))
+
+#define         GET_B(x)                (((x) & (B_POSTION_MASK)) >> (B_POSITION))
+#define         GET_V(x)                (((x) & (V_POSTION_MASK)) >> (V_POSITION))
+#define         GET_N(x)                (((x) & (N_POSTION_MASK)) >> (N_POSITION))
+#define         GET_C(x)                (((x) & (C_POSTION_MASK)) >> (C_POSITION))
+
+#define         BVNC_PACK(B,V,N,C)      ((((IMG_UINT64)B)) << (B_POSITION) | \
+                                         (((IMG_UINT64)V)) << (V_POSITION) | \
+                                         (((IMG_UINT64)N)) << (N_POSITION) | \
+                                         (((IMG_UINT64)C)) << (C_POSITION) \
+                                        )
+
+#define RGX_CR_CORE_ID_CONFIG_N_SHIFT                     (8U)
+#define RGX_CR_CORE_ID_CONFIG_C_SHIFT                     (0U)
+
+#define RGX_CR_CORE_ID_CONFIG_N_CLRMSK                    (0XFFFF00FFU)
+#define RGX_CR_CORE_ID_CONFIG_C_CLRMSK                    (0XFFFFFF00U)
+
 /* META cores (required for the RGX_FEATURE_META) */
 #define MTP218   (1)
 #define MTP219   (2)
@@ -84,30 +127,33 @@
 #define RGX_META_COREMEM_32K      (32*1024)
 #define RGX_META_COREMEM_48K      (48*1024)
 #define RGX_META_COREMEM_64K      (64*1024)
+#define RGX_META_COREMEM_128K     (128*1024)
 #define RGX_META_COREMEM_256K     (256*1024)
 
-#if !defined(SUPPORT_TRUSTED_DEVICE)
+#if !defined(__KERNEL__)
+#if (!defined(SUPPORT_TRUSTED_DEVICE) || defined(RGX_FEATURE_META_DMA)) && (RGX_FEATURE_META_COREMEM_SIZE != 0)
 #define RGX_META_COREMEM_SIZE     (RGX_FEATURE_META_COREMEM_SIZE*1024)
-#else
-#define RGX_META_COREMEM_SIZE     (0)
-#endif
-
-#if (RGX_FEATURE_META_COREMEM_SIZE != 0) && !defined(SUPPORT_TRUSTED_DEVICE)
 #define RGX_META_COREMEM          (1)
 #define RGX_META_COREMEM_CODE     (1)
 #if !defined(FIX_HW_BRN_50767)
 #define RGX_META_COREMEM_DATA     (1)
 #endif
+#else
+#undef SUPPORT_META_COREMEM
+#undef RGX_FEATURE_META_COREMEM_SIZE
+#undef RGX_FEATURE_META_DMA
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+#define RGX_META_COREMEM_SIZE         (0)
 #endif
-
-#endif  /*RGX_FEATURE_META*/
+#endif
 
 /* ISP requires valid state on all three pipes regardless of the number of
  * active pipes/tiles in flight.
  */
 #define RGX_MAX_NUM_PIPES	3
 
-#define ROGUE_CACHE_LINE_SIZE				((RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS)/8)
+#define GET_ROGUE_CACHE_LINE_SIZE(x)				((x)/8)
+
 
 #define MAX_HW_TA3DCONTEXTS	2
 
@@ -116,8 +162,6 @@
 #define RGX_CR_CLK_CTRL_ALL_ON   (IMG_UINT64_C(0x5555555555555555)&RGX_CR_CLK_CTRL_MASKFULL)
 #define RGX_CR_CLK_CTRL_ALL_AUTO (IMG_UINT64_C(0xaaaaaaaaaaaaaaaa)&RGX_CR_CLK_CTRL_MASKFULL)
 
-#define RGX_MAX_DUST		MAX(1, RGX_FEATURE_NUM_CLUSTERS/2)
-
 #define RGX_CR_SOFT_RESET_DUST_n_CORE_EN	(RGX_CR_SOFT_RESET_DUST_A_CORE_EN | \
 											 RGX_CR_SOFT_RESET_DUST_B_CORE_EN | \
 											 RGX_CR_SOFT_RESET_DUST_C_CORE_EN | \
@@ -133,7 +177,7 @@
 
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+
 /* SOFT_RESET steps as defined in the TRM */
 #define RGX_S7_SOFT_RESET_DUSTS (RGX_CR_SOFT_RESET_DUST_n_CORE_EN)
 
@@ -150,7 +194,7 @@
                             RGX_CR_SOFT_RESET2_PIXEL_EN | \
 							RGX_CR_SOFT_RESET2_CDM_EN | \
 							RGX_CR_SOFT_RESET2_VERTEX_EN)
-#endif
+
 
 
 #define RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT		(12)
@@ -167,17 +211,51 @@
 #define RGX_REQ_NUM_BERNADOS(CLUSTERS) ((CLUSTERS + 3) / 4)
 #define RGX_REQ_NUM_BLACKPEARLS(CLUSTERS) ((CLUSTERS + 3) / 4)
 
+#if  defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__)
+	#define RGX_GET_NUM_PHANTOMS(x)	 (RGX_REQ_NUM_PHANTOMS(x))
 #if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_NUM_PHANTOMS (RGX_REQ_NUM_PHANTOMS(RGX_FEATURE_NUM_CLUSTERS))
+	#define RGX_NUM_PHANTOMS (RGX_REQ_NUM_PHANTOMS(RGX_FEATURE_NUM_CLUSTERS))
 #else
-#define RGX_NUM_PHANTOMS (1)
+	#define RGX_NUM_PHANTOMS (1)
+#endif
+#else
+	#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+	#define RGX_NUM_PHANTOMS (RGX_REQ_NUM_PHANTOMS(RGX_FEATURE_NUM_CLUSTERS))
+	#else
+	#define RGX_NUM_PHANTOMS (1)
+	#endif
+	#define RGX_GET_NUM_PHANTOMS(x)	 (RGX_REQ_NUM_PHANTOMS(RGX_FEATURE_NUM_CLUSTERS))
 #endif
 
-/* Temporary until RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT is defined for all cores. */
+
+/* RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT is not defined for format 1 cores (so define it now). */
 #if !defined(RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT)
 #define RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT (1)
 #endif
 
+/* META second thread feature depending on META variants and available CoreMem*/
+#if defined(RGX_FEATURE_META) && (RGX_FEATURE_META == MTP218 || RGX_FEATURE_META == MTP219) && defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) && (RGX_FEATURE_META_COREMEM_SIZE == 256)
+#define RGXFW_META_SUPPORT_2ND_THREAD
+#endif
+
+/*
+   Start at 903GiB. Size of 32MB per OSID (see rgxheapconfig.h)
+   NOTE:
+		The firmware heap base and size is defined here to
+		simplify #include dependencies, see rgxheapconfig.h
+		for the full RGX virtual address space layout.
+*/
+#define RGX_FIRMWARE_HEAP_BASE			IMG_UINT64_C(0xE1C0000000)
+#define RGX_FIRMWARE_HEAP_SIZE			(1<<RGX_FW_HEAP_SHIFT)
+#define RGX_FIRMWARE_HEAP_SHIFT			RGX_FW_HEAP_SHIFT
+
+/* Default number of OSIDs is 1 unless GPU Virtualization is supported and enabled */
+#if defined(SUPPORT_PVRSRV_GPUVIRT) && !defined(PVRSRV_GPUVIRT_GUESTDRV) && (PVRSRV_GPUVIRT_NUM_OSID +1> 1)
+#define RGXFW_NUM_OS PVRSRV_GPUVIRT_NUM_OSID
+#else
+#define RGXFW_NUM_OS 1
+#endif
+
 /******************************************************************************
  * WA HWBRNs
  *****************************************************************************/
@@ -188,15 +266,30 @@
 #undef RGX_CR_SOFT_RESET_SLC_SHIFT
 
 /* Remove the SOFT_RESET_SLC_EN bit from SOFT_RESET_MASKFULL */
-#undef RGX_CR_SOFT_RESET_MASKFULL 
+#undef RGX_CR_SOFT_RESET_MASKFULL
 #define RGX_CR_SOFT_RESET_MASKFULL IMG_UINT64_C(0x000001FFF7FFFC1D)
 
 #endif /* FIX_HW_BRN_36492 */
 
+
+#if defined(RGX_CR_JONES_IDLE_MASKFULL)
+/* Workaround for HW BRN 57289 */
+#if (RGX_CR_JONES_IDLE_MASKFULL != 0x0000000000007FFF)
+#error This WA must be updated if RGX_CR_JONES_IDLE is expanded!!!
+#endif
+#undef RGX_CR_JONES_IDLE_MASKFULL
+#undef RGX_CR_JONES_IDLE_TDM_SHIFT
+#undef RGX_CR_JONES_IDLE_TDM_CLRMSK
+#undef RGX_CR_JONES_IDLE_TDM_EN
+#define RGX_CR_JONES_IDLE_MASKFULL                        (IMG_UINT64_C(0x0000000000003FFF))
+#endif
+
+
 #define DPX_MAX_RAY_CONTEXTS 4 /* FIXME should this be in dpx file? */
 #define DPX_MAX_FBA_AP 16
 #define DPX_MAX_FBA_FILTER_WIDTH 24
 
+#if !defined(__KERNEL__)
 #if !defined(RGX_FEATURE_SLC_SIZE_IN_BYTES)
 #if defined(RGX_FEATURE_SLC_SIZE_IN_KILOBYTES)
 #define RGX_FEATURE_SLC_SIZE_IN_BYTES (RGX_FEATURE_SLC_SIZE_IN_KILOBYTES * 1024)
@@ -204,5 +297,7 @@
 #define RGX_FEATURE_SLC_SIZE_IN_BYTES (0)
 #endif
 #endif
+#endif
+
 
 #endif /* _RGXDEFS_KM_H_ */
diff --git a/drivers/staging/imgtec/rogue/hwdefs/km/rgxmmudefs_km.h b/drivers/staging/imgtec/rogue/hwdefs/km/rgxmmudefs_km.h
index 7419db5..fca692d 100644
--- a/drivers/staging/imgtec/rogue/hwdefs/km/rgxmmudefs_km.h
+++ b/drivers/staging/imgtec/rogue/hwdefs/km/rgxmmudefs_km.h
@@ -42,7 +42,7 @@
 /*               ****   Autogenerated C -- do not edit    ****               */
 
 /*
- * Generated by regconv version MAIN@2782796
+ * Generated by regconv version MAIN@3328745
  *   from files:
  *      rogue_bif.def 
  *      rogue_bif.def 
diff --git a/drivers/staging/imgtec/rogue/img_3dtypes.h b/drivers/staging/imgtec/rogue/img_3dtypes.h
index d082c78..c940ff3 100644
--- a/drivers/staging/imgtec/rogue/img_3dtypes.h
+++ b/drivers/staging/imgtec/rogue/img_3dtypes.h
@@ -44,6 +44,8 @@
 #ifndef __IMG_3DTYPES_H__
 #define __IMG_3DTYPES_H__
 
+#include <powervr/buffer_attribs.h>
+
 /**
  * Comparison functions
  * This comparison function is defined as:
@@ -85,19 +87,6 @@
 } IMG_STENCILOP;
 
 /**
- * Memory layout enumeration.
- * Defines how pixels are laid out within a surface.
- */
-typedef enum _IMG_MEMLAYOUT_
-{
-	IMG_MEMLAYOUT_STRIDED,			/**< Resource is strided, one row at a time */
-    IMG_MEMLAYOUT_TWIDDLED,			/**< Resource is 2D twiddled, classic style */
-    IMG_MEMLAYOUT_3DTWIDDLED,       /**< Resource is 3D twiddled, classic style */
-	IMG_MEMLAYOUT_TILED,			/**< Resource is tiled, tiling config specified elsewhere. */
-	IMG_MEMLAYOUT_PAGETILED,		/**< Resource is pagetiled */
-} IMG_MEMLAYOUT;
-
-/**
  * Alpha blending allows colours and textures on one surface
  * to be blended with transparency onto another surface.
  * These definitions apply to both source and destination blending
@@ -217,19 +206,24 @@
 	IMG_CULLMODE_BACKFACING,	/**< Back facing triangles */
 } IMG_CULLMODE;
 
-/**
- * Rotation clockwise
- */
-typedef enum _IMG_ROTATION_
-{
-	IMG_ROTATION_0DEG = 0,
-	IMG_ROTATION_90DEG = 1,
-	IMG_ROTATION_180DEG = 2,
-	IMG_ROTATION_270DEG = 3,
-	IMG_ROTATION_FLIP_Y = 4,
 
-	IMG_ROTATION_BAD = 255,
-} IMG_ROTATION;
+/*! ************************************************************************//**
+@brief          Specifies the MSAA resolve operation.
+*/ /**************************************************************************/
+typedef enum _IMG_RESOLVE_OP_
+{
+	IMG_RESOLVE_BLEND   = 0,          /*!< box filter on the samples */
+	IMG_RESOLVE_MIN     = 1,          /*!< minimum of the samples */
+	IMG_RESOLVE_MAX     = 2,          /*!< maximum of the samples */
+	IMG_RESOLVE_SAMPLE0 = 3,          /*!< choose sample 0 */
+	IMG_RESOLVE_SAMPLE1 = 4,          /*!< choose sample 1 */
+	IMG_RESOLVE_SAMPLE2 = 5,          /*!< choose sample 2 */
+	IMG_RESOLVE_SAMPLE3 = 6,          /*!< choose sample 3 */
+	IMG_RESOLVE_SAMPLE4 = 7,          /*!< choose sample 4 */
+	IMG_RESOLVE_SAMPLE5 = 8,          /*!< choose sample 5 */
+	IMG_RESOLVE_SAMPLE6 = 9,          /*!< choose sample 6 */
+	IMG_RESOLVE_SAMPLE7 = 10,         /*!< choose sample 7 */
+} IMG_RESOLVE_OP;
 
 
 #endif /* __IMG_3DTYPES_H__ */
diff --git a/drivers/staging/imgtec/rogue/img_defs.h b/drivers/staging/imgtec/rogue/img_defs.h
index 155f0c3..398c2f6 100644
--- a/drivers/staging/imgtec/rogue/img_defs.h
+++ b/drivers/staging/imgtec/rogue/img_defs.h
@@ -52,6 +52,12 @@
 #if defined (NO_INLINE_FUNCS)
 	#define	INLINE
 	#define	FORCE_INLINE
+#elif defined(INTEGRITY_OS)
+	#ifndef INLINE
+	#define	INLINE
+	#endif
+	#define	FORCE_INLINE			static
+	#define INLINE_IS_PRAGMA
 #else
 #if defined (__cplusplus)
 	#define INLINE					inline
@@ -76,6 +82,13 @@
 		__GNUC__ > (major) ||									\
 		(__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
 
+/* Ensure Clang's __has_extension macro is defined for all compilers so we
+ * can use it safely in preprocessor conditionals.
+ */
+#if !defined(__has_extension)
+#define __has_extension(e) 0
+#endif
+
 /* Use this in any file, or use attributes under GCC - see below */
 #ifndef PVR_UNREFERENCED_PARAMETER
 #define	PVR_UNREFERENCED_PARAMETER(param) ((void)(param))
@@ -98,12 +111,20 @@
 #if !defined(static_assert) && !defined(_MSC_VER) && \
 		(!defined(__cplusplus) || __cplusplus < 201103L)
 	/* static_assert isn't already available */
-	#if GCC_VERSION_AT_LEAST(4, 6) && !defined(__cplusplus)
+	#if !defined(__cplusplus) && (GCC_VERSION_AT_LEAST(4, 6) || \
+								  (defined(__clang__) && __has_extension(c_static_assert)))
 		#define static_assert _Static_assert
 	#else
 		#define static_assert(expr, message) \
 			extern int _static_assert_failed[2*!!(expr) - 1] __attribute__((unused))
 	#endif
+#else
+#if defined(CONFIG_L4)
+	/* Defined but not compatible with DDK usage
+	   so undefine & ignore */
+	#undef static_assert
+	#define static_assert(expr, message)
+#endif
 #endif
 
 /*! Macro to calculate the n-byte aligned value from that supplied rounding up.
@@ -114,26 +135,6 @@
  */
 #define PVR_ALIGN(_x, _n)   (((_x)+((_n)-1)) & ~((_n)-1))
 
-
-/* The best way to supress unused parameter warnings using GCC is to use a
- * variable attribute.  Place the unref__ between the type and name of an
- * unused parameter in a function parameter list, eg `int unref__ var'. This
- * should only be used in GCC build environments, for example, in files that
- * compile only on Linux. Other files should use UNREFERENCED_PARAMETER */
-#ifdef __GNUC__
-#define unref__ __attribute__ ((unused))
-#else
-#define unref__
-#endif
-
-#if __GNUC__ >= 3
-# define IMG_LIKELY(x) __builtin_expect (!!(x), 1)
-# define IMG_UNLIKELY(x) __builtin_expect (!!(x), 0)
-#else
-# define IMG_LIKELY(x) (x)
-# define IMG_UNLIKELY(x) (x)
-#endif
-
 #if defined(_WIN32)
 
 #if defined(WINDOWS_WDF)
@@ -189,12 +190,6 @@
 			_CRTIMP void __cdecl abort(void);
 		#endif
 	#endif
-	#if defined(EXIT_ON_ABORT)
-		#define IMG_ABORT()	exit(1);
-	#else
-		#define IMG_ABORT()	abort();
-	#endif
-//	#define IMG_ABORT()	img_abort()
 #endif /* UNDER_WDDM */
 #else
 	#if defined(LINUX) || defined(__METAG) || defined(__QNXNTO__)
@@ -210,6 +205,21 @@
 		#define IMG_IMPORT
 		#define IMG_RESTRICT	__restrict__
 
+	#elif defined(INTEGRITY_OS)
+		#define IMG_CALLCONV
+		#define IMG_INTERNAL
+		#define IMG_EXPORT
+		#define IMG_RESTRICT
+		#define C_CALLCONV
+		#define __cdecl
+		/* IMG_IMPORT is defined as IMG_EXPORT so that headers and implementations match.
+		 * Some compilers require the header to be declared IMPORT, while the implementation is declared EXPORT 
+		 */
+		#define	IMG_IMPORT	IMG_EXPORT 
+		#ifndef USE_CODE
+		#define IMG_ABORT()	printf("IMG_ABORT was called.\n")
+
+		#endif
 	#else
 		#error("define an OS")
 	#endif
@@ -224,30 +234,97 @@
 	#endif
 #endif
 
-#if defined(__GNUC__)
-#define IMG_FORMAT_PRINTF(x,y)		__attribute__((format(printf,x,y)))
-#else
-#define IMG_FORMAT_PRINTF(x,y)
-#endif
+/* The best way to suppress unused parameter warnings using GCC is to use a
+ * variable attribute.  Place the __maybe_unused between the type and name of an
+ * unused parameter in a function parameter list, eg `int __maybe_unused var'. This
+ * should only be used in GCC build environments, for example, in files that
+ * compile only on Linux. Other files should use PVR_UNREFERENCED_PARAMETER */
 
-#if defined(__GNUC__)
-#define IMG_WARN_UNUSED_RESULT		__attribute__((warn_unused_result))
-#else
-#define IMG_WARN_UNUSED_RESULT
-#endif
+/* Kernel macros for compiler attributes */
+/* Note: param positions start at 1 */
+#if defined(LINUX) && defined(__KERNEL__)
+	#include <linux/compiler.h>
+#elif defined(__GNUC__) || defined(HAS_GNUC_ATTRIBUTES)
+	#define __must_check       __attribute__((warn_unused_result))
+	#define __maybe_unused     __attribute__((unused))
+	#define __malloc           __attribute__((malloc))
 
-#if defined(_MSC_VER) || defined(CC_ARM)
-	#define IMG_NORETURN __declspec(noreturn)
-#else
-	#if defined(__GNUC__)
-		#define IMG_NORETURN __attribute__((noreturn))
-	#else
-		#define IMG_NORETURN
+	/* Bionic's <sys/cdefs.h> might have defined these already */
+	#if !defined(__packed)
+		#define __packed           __attribute__((packed))
 	#endif
+	#if !defined(__aligned)
+		#define __aligned(n)       __attribute__((aligned(n)))
+	#endif
+
+	/* That one compiler that supports attributes but doesn't support
+	 * the printf attribute... */
+	#if defined(__GNUC__)
+		#define __printf(fmt, va)  __attribute__((format(printf, fmt, va)))
+	#else
+		#define __printf(fmt, va)
+	#endif /* defined(__GNUC__) */
+
+#else
+	/* Silently ignore those attributes */
+	#define __printf(fmt, va)
+	#define __packed
+	#define __aligned(n)
+	#define __must_check
+	#define __maybe_unused
+	#define __malloc
 #endif
 
+
+/* Other attributes, following the same style */
+#if defined(__GNUC__) || defined(HAS_GNUC_ATTRIBUTES)
+	#define __param_nonnull(...)  __attribute__((nonnull(__VA_ARGS__)))
+	#define __returns_nonnull     __attribute__((returns_nonnull))
+#else
+	#define __param_nonnull(...)
+	#define __returns_nonnull
+#endif
+
+
+/* GCC builtins */
+#if defined(LINUX) && defined(__KERNEL__)
+	#include <linux/compiler.h>
+#elif defined(__GNUC__)
+	#define likely(x)   __builtin_expect(!!(x), 1)
+	#define unlikely(x) __builtin_expect(!!(x), 0)
+
+	/* Compiler memory barrier to prevent reordering */
+	#define barrier() __asm__ __volatile__("": : :"memory")
+#else
+	#define barrier() do { static_assert(0, "barrier() isn't supported by your compiler"); } while(0)
+#endif
+
+/* That one OS that defines one but not the other... */
+#ifndef likely
+	#define likely(x)   (x)
+#endif
+#ifndef unlikely
+	#define unlikely(x) (x)
+#endif
+
+
+#if defined(__noreturn)
+	/* Already defined by the Kernel */
+#elif defined(_MSC_VER) || defined(CC_ARM)
+	#define __noreturn __declspec(noreturn)
+#elif defined(__GNUC__) || defined(HAS_GNUC_ATTRIBUTES)
+	#define __noreturn __attribute__((noreturn))
+#else
+	#define __noreturn
+#endif
+
+#ifndef MAX
 #define MAX(a,b) 					(((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
 #define MIN(a,b) 					(((a) < (b)) ? (a) : (b))
+#endif
 
 /* Get a structures address from the address of a member */
 #define IMG_CONTAINER_OF(ptr, type, member) \
@@ -272,21 +349,61 @@
 	void operator=(const C&)
 #endif
 
-#if defined(SUPPORT_PVR_VALGRIND)
-	#if !defined(__METAG)
-		#include "/usr/include/valgrind/memcheck.h"
+#if defined(SUPPORT_PVR_VALGRIND) && !defined(__METAG)
+	#include "/usr/include/valgrind/memcheck.h"
 
-		#define VALGRIND_HEADER_PRESENT
-
-		#define VG_MARK_INITIALIZED(pvData,ui32Size)  VALGRIND_MAKE_MEM_DEFINED(pvData,ui32Size)
-	#else
-		#define VG_MARK_INITIALIZED(pvData,ui32Size) do { } while(0)
-	#endif
+	#define VG_MARK_INITIALIZED(pvData,ui32Size)  VALGRIND_MAKE_MEM_DEFINED(pvData,ui32Size)
+	#define VG_MARK_NOACCESS(pvData,ui32Size) VALGRIND_MAKE_MEM_NOACCESS(pvData,ui32Size)
+	#define VG_MARK_ACCESS(pvData,ui32Size) VALGRIND_MAKE_MEM_UNDEFINED(pvData,ui32Size)
 #else
+	#if defined(_MSC_VER)
+	#	define PVR_MSC_SUPPRESS_4127 __pragma(warning(suppress:4127))
+	#else
+	#	define PVR_MSC_SUPPRESS_4127
+	#endif
 
-	#define VG_MARK_INITIALIZED(pvData,ui32Size) do { } while(0)
+	#define VG_MARK_INITIALIZED(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while(0)
+	#define VG_MARK_NOACCESS(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while(0)
+	#define VG_MARK_ACCESS(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while(0)
 #endif
 
+#define _STRINGIFY(x) # x
+#define IMG_STRINGIFY(x) _STRINGIFY(x)
+
+#if defined(INTEGRITY_OS)
+	/* Definitions not present in INTEGRITY. */
+	#define PATH_MAX	200
+#endif
+
+#if defined (__clang__) || defined (__GNUC__)
+	/* __SIZEOF_POINTER__ is defined already by these compilers */
+#elif defined (INTEGRITY_OS)
+	#if defined (__Ptr_Is_64)
+		#define __SIZEOF_POINTER__ 8
+	#else
+		#define __SIZEOF_POINTER__ 4
+	#endif
+#elif defined(_WIN32)
+	#define __SIZEOF_POINTER__ sizeof(char *)
+#else
+	#warning Unknown OS - using default method to determine whether CPU arch is 64-bit.
+	#define __SIZEOF_POINTER__ sizeof(char *)
+#endif
+
+/* RDI8567: clang/llvm load/store optimisations cause issues with device
+ * memory allocations. Some pointers are made 'volatile' to prevent
+ * this optimisations being applied to writes through that particular pointer.
+ */
+#if defined(__clang__) && defined(__aarch64__)
+#define NOLDSTOPT volatile
+/* after applying 'volatile' to a pointer, we may need to cast it to 'void *'
+ * to keep it compatible with its existing uses
+ */
+#define NOLDSTOPT_VOID (void *)
+#else
+#define NOLDSTOPT
+#define NOLDSTOPT_VOID
+#endif
 
 #endif /* #if !defined (__IMG_DEFS_H__) */
 /*****************************************************************************
diff --git a/drivers/staging/imgtec/rogue/img_types.h b/drivers/staging/imgtec/rogue/img_types.h
index ddb02f2..06fbff1 100644
--- a/drivers/staging/imgtec/rogue/img_types.h
+++ b/drivers/staging/imgtec/rogue/img_types.h
@@ -64,8 +64,9 @@
 #if defined(_MSC_VER)
 	#include "msvc_types.h"
 #elif defined(LINUX) && defined(__KERNEL__)
+	#include <linux/types.h>
 	#include "kernel_types.h"
-#elif defined(LINUX) || defined(__METAG) || defined(__QNXNTO__)
+#elif defined(LINUX) || defined(__METAG) || defined(__QNXNTO__) || defined(INTEGRITY_OS)
 	#include <stddef.h>			/* NULL */
 	#include <inttypes.h>		/* intX_t/uintX_t, format specifiers */
 	#include <limits.h>			/* INT_MIN, etc */
@@ -126,9 +127,8 @@
 	IMG_FORCE_ALIGN = 0x7FFFFFFF
 } IMG_BOOL, *IMG_PBOOL;
 
-#if !defined(LINUX)
+#if defined(UNDER_WDDM) || defined(WINDOWS_WDF)
 typedef void            IMG_VOID, *IMG_PVOID;
-typedef IMG_VOID const* IMG_PCVOID;
 
 typedef uintptr_t		IMG_UINTPTR_T;
 typedef size_t			IMG_SIZE_T;
@@ -137,11 +137,6 @@
 #define IMG_NULL		NULL
 
 typedef IMG_CHAR const* IMG_PCCHAR;
-typedef IMG_UINT16 const* IMG_PCUINT16;
-typedef IMG_INT16 const* IMG_PCINT16;
-typedef IMG_UINT32 const* IMG_PCUINT32;
-typedef IMG_INT32 const* IMG_PCINT32;
-typedef IMG_BOOL const* IMG_PCBOOL;
 #endif
 
 #if defined(_MSC_VER)
@@ -213,21 +208,6 @@
  *
  */
 
-typedef void *IMG_CPU_VIRTADDR;
-
-/* device virtual address */
-typedef struct _IMG_DEV_VIRTADDR
-{
-	IMG_UINT64  uiAddr;
-#define IMG_CAST_TO_DEVVADDR_UINT(var)		(IMG_UINT64)(var)
-	
-} IMG_DEV_VIRTADDR;
-
-typedef IMG_UINT64 IMG_DEVMEM_SIZE_T;
-typedef IMG_UINT64 IMG_DEVMEM_ALIGN_T;
-typedef IMG_UINT64 IMG_DEVMEM_OFFSET_T;
-typedef IMG_UINT32 IMG_DEVMEM_LOG2ALIGN_T;
-
 #define IMG_DEV_VIRTADDR_FMTSPEC "0x%010" IMG_UINT64_FMTSPECX
 #define IMG_DEVMEM_SIZE_FMTSPEC "0x%010" IMG_UINT64_FMTSPECX
 #define IMG_DEVMEM_ALIGN_FMTSPEC "0x%010" IMG_UINT64_FMTSPECX
@@ -239,6 +219,9 @@
 #if defined(UNDER_WDDM) || defined(WINDOWS_WDF)
 	uintptr_t uiAddr;
 #define IMG_CAST_TO_CPUPHYADDR_UINT(var)		(uintptr_t)(var)
+#elif defined(LINUX) && defined(__KERNEL__)
+	phys_addr_t uiAddr;
+#define IMG_CAST_TO_CPUPHYADDR_UINT(var)		(phys_addr_t)(var)
 #else
 	IMG_UINT64 uiAddr;
 #define IMG_CAST_TO_CPUPHYADDR_UINT(var)		(IMG_UINT64)(var)
diff --git a/drivers/staging/imgtec/rogue/imgpixfmts_km.h b/drivers/staging/imgtec/rogue/imgpixfmts_km.h
deleted file mode 100644
index cd2df0a..0000000
--- a/drivers/staging/imgtec/rogue/imgpixfmts_km.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*************************************************************************/ /*!
-@File           imgpixfmts_km.h
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-/*****************************************************************************
- **
- ** WARNING: This file is autogenerated - DO NOT EDIT.
- **
- *****************************************************************************/
-
-#if !defined(_IMGPIXFMTS_KM_H_)
-#define _IMGPIXFMTS_KM_H_
-
-#include "imgyuv.h"
-
-
-typedef enum _IMG_PIXFMT_
-{
-	IMG_PIXFMT_UNKNOWN = 0,
-	IMG_PIXFMT_R8G8B8A8_UNORM = 31,
-	IMG_PIXFMT_R8G8B8X8_UNORM = 36,
-	IMG_PIXFMT_R8G8_UNORM = 61,
-	IMG_PIXFMT_R8_UNORM = 75,
-	IMG_PIXFMT_B5G6R5_UNORM = 84,
-	IMG_PIXFMT_B5G5R5A1_UNORM = 85,
-	IMG_PIXFMT_B5G5R5X1_UNORM = 86,
-	IMG_PIXFMT_B8G8R8A8_UNORM = 87,
-	IMG_PIXFMT_B8G8R8X8_UNORM = 88,
-	IMG_PIXFMT_B4G4R4A4_UNORM = 143,
-	IMG_PIXFMT_UYVY = 169,
-	IMG_PIXFMT_VYUY = 170,
-	IMG_PIXFMT_YUYV = 171,
-	IMG_PIXFMT_YVYU = 172,
-	IMG_PIXFMT_YVU420_2PLANE = 173,
-	IMG_PIXFMT_YUV420_2PLANE = 174,
-	IMG_PIXFMT_YVU420_2PLANE_MACRO_BLOCK = 175,
-	IMG_PIXFMT_YUV420_3PLANE = 176,
-	IMG_PIXFMT_YVU420_3PLANE = 177,
-	IMG_PIXFMT_V8U8Y8A8 = 182,
-	IMG_PIXFMT_YVU8_420_2PLANE_PACK8_P = 243,
-	IMG_PIXFMT_YUV8_420_2PLANE_PACK8_P = 247,
-	IMG_PIXFMT_UYVY10_422_1PLANE_PACK10_CUST1 = 250,
-	IMG_PIXFMT_R5G6B5_UNORM = 252,
-}	IMG_PIXFMT;
-
-#endif /* _IMGPIXFMTS_KM_H_ */
diff --git a/drivers/staging/imgtec/rogue/imgyuv.h b/drivers/staging/imgtec/rogue/imgyuv.h
deleted file mode 100644
index 0bc2e4d..0000000
--- a/drivers/staging/imgtec/rogue/imgyuv.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          YUV defines
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#if !defined(_IMGYUV_H_)
-#define _IMGYUV_H_
-
-typedef enum
-{
-	IMG_COLORSPACE_UNDEFINED = 0,
-	IMG_COLORSPACE_BT601_CONFORMANT_RANGE = 1,
-	IMG_COLORSPACE_BT601_FULL_RANGE = 2,
-	IMG_COLORSPACE_BT709_CONFORMANT_RANGE = 3,
-	IMG_COLORSPACE_BT709_FULL_RANGE = 4,
-	IMG_COLORSPACE_BT2020_CONFORMANT_RANGE = 5,
-	IMG_COLORSPACE_BT2020_FULL_RANGE = 6,
-	IMG_COLORSPACE_BT601_CONFORMANT_RANGE_INVERSE = 7,
-	IMG_COLORSPACE_BT601_FULL_RANGE_INVERSE = 8,
-	IMG_COLORSPACE_BT709_CONFORMANT_RANGE_INVERSE = 9,
-	IMG_COLORSPACE_BT709_FULL_RANGE_INVERSE = 10,
-	IMG_COLORSPACE_BT2020_CONFORMANT_RANGE_INVERSE = 11,
-	IMG_COLORSPACE_BT2020_FULL_RANGE_INVERSE = 12
-} IMG_YUV_COLORSPACE;
-
-typedef enum
-{
-	IMG_CHROMA_INTERP_UNDEFINED = 0,
-	IMG_CHROMA_INTERP_ZERO = 1,
-	IMG_CHROMA_INTERP_QUARTER = 2,
-	IMG_CHROMA_INTERP_HALF = 3,
-	IMG_CHROMA_INTERP_THREEQUARTERS = 4
-} IMG_YUV_CHROMA_INTERP;
-
-
-#endif /* _IMGYUV_H_ */
diff --git a/drivers/staging/imgtec/rogue/ioctl.c b/drivers/staging/imgtec/rogue/ioctl.c
index 67fe775..3ca1f93 100644
--- a/drivers/staging/imgtec/rogue/ioctl.c
+++ b/drivers/staging/imgtec/rogue/ioctl.c
@@ -133,7 +133,10 @@
 	psParams	= (PDBG_IN_FINDSTREAM)pvInBuffer;
 	phStream	= (IMG_SID *)pvOutBuffer;
 
-	*phStream = PStream2SID(ExtDBGDrivFindStream(WIDEPTR_GET_PTR(psParams->pszName, bCompat), psParams->bResetStream));
+	/* Ensure that the name will be NULL terminated */
+	psParams->pszName[DEBUG_STREAM_NAME_MAX-1] = '\0';
+
+	*phStream = PStream2SID(ExtDBGDrivFindStream(psParams->pszName, psParams->bResetStream));
 
 	return(IMG_TRUE);
 }
diff --git a/drivers/staging/imgtec/rogue/ion_sys.h b/drivers/staging/imgtec/rogue/ion_sys.h
index 9b0b32f..6eb76fa 100644
--- a/drivers/staging/imgtec/rogue/ion_sys.h
+++ b/drivers/staging/imgtec/rogue/ion_sys.h
@@ -46,7 +46,6 @@
 #define _ION_SYS_H_
 
 #include "pvrsrv_error.h"
-#include "img_types.h"
 #include PVR_ANDROID_ION_HEADER
 
 
@@ -56,19 +55,6 @@
 
 void IonDevRelease(struct ion_device *psIonDev);
 
-#if defined(LMA)
-IMG_DEV_PHYADDR IonCPUPhysToDevPhys(IMG_CPU_PHYADDR sCPUPhysAddr,
-									IMG_UINT32 ui32Offset);
-#else
-/* This is a no-op for UMA systems. */
-static inline
-IMG_DEV_PHYADDR IonCPUPhysToDevPhys(IMG_CPU_PHYADDR sCPUPhysAddr,
-									IMG_UINT32 ui32Offset)
-{
-	return (IMG_DEV_PHYADDR){ .uiAddr = sCPUPhysAddr.uiAddr + ui32Offset };
-}
-#endif
-
 void IonDeinit(void);
 
 #endif /* _ION_SYS_H_ */
diff --git a/drivers/staging/imgtec/rogue/kernel_compatibility.h b/drivers/staging/imgtec/rogue/kernel_compatibility.h
new file mode 100644
index 0000000..dc1a3aa
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/kernel_compatibility.h
@@ -0,0 +1,189 @@
+/*************************************************************************/ /*!
+@File           services/server/env/linux/kernel_compatibility.h
+@Title          Kernel versions compatibility macros
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Per-version macros to allow code to seamlessly use older kernel
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __KERNEL_COMPATIBILITY_H__
+#define __KERNEL_COMPATIBILITY_H__
+
+#include <linux/version.h>
+
+/*
+ * Stop supporting an old kernel? Remove the top block.
+ * New incompatible kernel?       Append a new block at the bottom.
+ *
+ * Please write you version test as `VERSION < X.Y`, and use the earliest
+ * possible version :)
+ */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
+
+/* Linux 3.7 split VM_RESERVED into VM_DONTDUMP and VM_DONTEXPAND */
+#define VM_DONTDUMP VM_RESERVED
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) */
+
+/*
+ * Note: this fix had to be written backwards because get_unused_fd_flags
+ * was already defined but not exported on kernels < 3.7
+ *
+ * When removing support for kernels < 3.7, this block should be removed
+ * and all `get_unused_fd()` should be manually replaced with
+ * `get_unused_fd_flags(0)`
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+
+/* Linux 3.19 removed get_unused_fd() */
+/* get_unused_fd_flags  was introduced in 3.7 */
+#define get_unused_fd() get_unused_fd_flags(0)
+
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
+
+/* Linux 3.12 introduced a new shrinker API */
+#define SHRINK_STOP (~0UL)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) && defined(CONFIG_ARM)
+
+/* Linux 3.13 renamed ioremap_cached to ioremap_cache */
+#define ioremap_cache(cookie,size) ioremap_cached(cookie,size)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) && defined(CONFIG_ARM) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0))
+
+/* Linux 3.17 changed the 3rd argument from a `struct page ***pages` to
+ * `struct page **pages` */
+#define map_vm_area(area, prot, pages) map_vm_area(area, prot, &pages)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
+
+/*
+ * Linux 4.7 removed this function but its replacement was available since 3.19.
+ */
+#define drm_crtc_send_vblank_event(crtc, e) drm_send_vblank_event((crtc)->dev, drm_crtc_index(crtc), e)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
+
+/* Linux 4.4 renamed GFP_WAIT to GFP_RECLAIM */
+#define __GFP_RECLAIM __GFP_WAIT
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) && !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
+
+/* Linux 4.5 added a new printf-style parameter for debug messages */
+
+#define drm_encoder_init(dev, encoder, funcs, encoder_type, name, ...) \
+        drm_encoder_init(dev, encoder, funcs, encoder_type)
+
+#define drm_universal_plane_init(dev, plane, possible_crtcs, funcs, formats, format_count, type, name, ...) \
+        drm_universal_plane_init(dev, plane, possible_crtcs, funcs, formats, format_count, type)
+
+#define drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs, name, ...) \
+        drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) && !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
+
+/*
+ * Linux 4.6 removed the start and end arguments as it now always maps
+ * the entire DMA-BUF.
+ * Additionally, dma_buf_end_cpu_access() now returns an int error.
+ */
+#define dma_buf_begin_cpu_access(DMABUF, DIRECTION) dma_buf_begin_cpu_access(DMABUF, 0, DMABUF->size, DIRECTION)
+#define dma_buf_end_cpu_access(DMABUF, DIRECTION) ({ dma_buf_end_cpu_access(DMABUF, 0, DMABUF->size, DIRECTION); 0; })
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) && !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318) */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
+
+/* Linux 4.7 removed the first arguments as it's never been used */
+#define drm_gem_object_lookup(filp, handle) drm_gem_object_lookup((filp)->minor->dev, filp, handle)
+
+/* Linux 4.7 replaced nla_put_u64 with nla_put_u64_64bit */
+#define nla_put_u64_64bit(skb, attrtype, value, padattr) nla_put_u64(skb, attrtype, value)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)) */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
+
+/* Linux 4.9 change the second argument to a drm_file pointer */
+#define drm_vma_node_is_allowed(node, file_priv) drm_vma_node_is_allowed(node, (file_priv)->filp)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
+static inline unsigned int refcount_read(const atomic_t *r)
+{
+	return atomic_read(r);
+}
+#define drm_mm_insert_node(mm, node, size) drm_mm_insert_node(mm, node, size, 0, DRM_MM_SEARCH_DEFAULT) 
+
+#define drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd) drm_helper_mode_fill_fb_struct(fb, mode_cmd)
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) */
+
+#if !defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
+#define dev_pm_opp_of_add_table of_init_opp_table
+#define dev_pm_opp_of_remove_table of_free_opp_table
+#endif
+
+
+#endif /* __KERNEL_COMPATIBILITY_H__ */
+/*****************************************************************************
+ End of file (kernel_compatibility.h)
+*****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/kerneldisplay.h b/drivers/staging/imgtec/rogue/kerneldisplay.h
index 4fd9215..d655bdc 100644
--- a/drivers/staging/imgtec/rogue/kerneldisplay.h
+++ b/drivers/staging/imgtec/rogue/kerneldisplay.h
@@ -1,8 +1,9 @@
 /*************************************************************************/ /*!
 @File
-@Title          Interface for 3rd party display class (DC) drivers
+@Title          Interface between 3rd party display controller (DC) drivers
+                and the Services server module.
+@Description    API between Services and the 3rd party DC driver and vice versa.
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    API between services and the 3rd party DC driver and vice versa
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -48,34 +49,78 @@
 extern "C" {
 #endif
 
+#include <powervr/mem_types.h>
+
 #include "pvrsrv_error.h"
 #include "img_types.h"
 #include "pvrsrv_surface.h"
 #include "dc_external.h"
-#include "dc_common.h"
+
+/*!
+ ******************************************************************************
+ @mainpage Introduction and Document Scope
+This document is a function reference for the 3rd party display
+controller interface. The interface ensures that the 3rd party display driver and
+Services can exchange configurations and buffers and can inform each
+other about occurring events like render completion or vsyncs.
+
+This interface should be used and implemented if the 3rd party display driver
+is not using a native OS interface such as the Linux DRM/KMS API.
+
+To fully understand the document the reader should be aware that
+the Services driver - offering PowerVR core and platform functionality to the
+driver layers (OGLES etc.) above - is split into the "Services Client"
+user mode library and the "Services Server" kernel mode driver that communicate
+via the "Services Bridge". The terms "User-Mode" and "Client" are used as
+synonyms as well as "Kernel-Mode" and "Server".
+
+Please refer to the more comprehensive '3rd Party Display Integration Guide'
+for an architecture overview and an explanation of the data flow between a
+client process, Services and the 3rd party display driver. It also contains
+descriptions about how to make use of the client side interface that is supposed
+to be integrated in some kind of display manager like e.g. the Rogue DDK WSEGL
+window manager.
+
+The documented functions are split into different parts:
+- Callbacks that need an implementation by the 3rd party display driver and
+that are used by the Services server, some of them optional (kerneldisplay.h)
+- Functions that the Services server module exports and can be used by the
+3rd party display driver. Mainly to register/deregister a new display device
+and to query state information (kerneldisplay.h)
+- Functions that are called by the client process (a display manager e.g. WSEGL)
+to control the DC interaction (dc_client.h)
+- Commonly used structure definitions to exchange data between the modules
+(dc_external.h, pvrsrv_surface.h)
+ *****************************************************************************/
 
 /*************************************************************************/ /*!
 @Function       GetInfo
 
-@Description    Query the display controller for its information structure
+@Description    Query the display controller for its information structure.
+
+   Called by client function: #PVRSRVDCGetInfo()
+
+   Implementation of this callback is mandatory.
 
 @Input          hDeviceData             Device private data
 
 @Output         psDisplayInfo           Display info structure
-
-@Return         PVRSRV_OK if the query was successful
 */
 /*****************************************************************************/
 typedef void (*GetInfo)(IMG_HANDLE hDeviceData,
-						DC_DISPLAY_INFO *psDisplayInfo);
+                        DC_DISPLAY_INFO *psDisplayInfo);
 
 /*************************************************************************/ /*!
 @Function       PanelQueryCount
 
 @Description    Query the display controller for how many panels are
-                contented to it.
+                connected to it.
 
-@Input          hDeviceData             Device private data
+   Called by client function: #PVRSRVDCPanelQueryCount()
+
+   Implementation of this callback is mandatory.
+
+@Input          hDeviceData            Device private data
 
 @Output         pui32NumPanels         Number of panels
 
@@ -83,7 +128,7 @@
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*PanelQueryCount)(IMG_HANDLE hDeviceData,
-										 IMG_UINT32 *ppui32NumPanels);
+                                        IMG_UINT32 *pui32NumPanels);
 
 /*************************************************************************/ /*!
 @Function       PanelQuery
@@ -91,139 +136,162 @@
 @Description    Query the display controller for information on what panel(s)
                 are connected to it and their properties.
 
+   Called by client function: #PVRSRVDCPanelQuery()
+
+   Implementation of this callback is mandatory.
+
 @Input          hDeviceData             Device private data
 
-@Input          ui32PanelsArraySize    Size of the format and dimension
-                                        array size (i.e. number of panels
-                                        that can be returned)
+@Input          ui32PanelsArraySize     Size of the PanelInfo array
+                                        (i.e. number of panels that
+                                        can be returned)
 
-@Output         pui32NumPanels         Number of panels returned
+@Output         pui32NumPanels          Number of panels returned
 
-@Output         pasFormat               Array of formats
-
-@Output         pasDims                 Array of dimensions
+@Output         pasPanelInfo            Array of formats, allocated beforehand
 
 @Return         PVRSRV_OK if the query was successful
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*PanelQuery)(IMG_HANDLE hDeviceData,
-									IMG_UINT32 ui32PanelsArraySize,
-									IMG_UINT32 *pui32NumPanels,
-									PVRSRV_PANEL_INFO *pasPanelInfo);
+                                   IMG_UINT32 ui32PanelsArraySize,
+                                   IMG_UINT32 *pui32NumPanels,
+                                   PVRSRV_PANEL_INFO *pasPanelInfo);
 
 /*************************************************************************/ /*!
 @Function       FormatQuery
 
-@Description    Query the display controller to see if it supports the specified
+@Description    Query the display controller to check if it supports the specified
                 format(s).
 
+   Called by client function: #PVRSRVDCFormatQuery()
+
+   Implementation of this callback is mandatory.
+
 @Input          hDeviceData             Device private data
 
 @Input          ui32NumFormats          Number of formats to check
+                                        (i.e. length of the Format array)
 
 @Input          pasFormat               Array of formats to check
 
-@Output			pui32Supported          For each format, the number of display
+@Output         pui32Supported          For each format, the number of display
                                         pipes that support that format
 
 @Return         PVRSRV_OK if the query was successful
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*FormatQuery)(IMG_HANDLE hDeviceData,
-									IMG_UINT32 ui32NumFormats,
-									PVRSRV_SURFACE_FORMAT *pasFormat,
-									IMG_UINT32 *pui32Supported);
+                                    IMG_UINT32 ui32NumFormats,
+                                    PVRSRV_SURFACE_FORMAT *pasFormat,
+                                    IMG_UINT32 *pui32Supported);
 
 /*************************************************************************/ /*!
 @Function       DimQuery
 
-@Description    Query the specificed display plane for the display dimensions
+@Description    Query the specified display plane for the display dimensions
                 it supports.
 
+   Called by client function: #PVRSRVDCDimQuery()
+
+   Implementation of this callback is mandatory.
+
 @Input          hDeviceData             Device private data
 
 @Input          ui32NumDims             Number of dimensions to check
+                                        (i.e. length of the Dim array)
 
-@Input          pasDim                  Array of dimentations to check
+@Input          pasDim                  Array of dimensions to check
 
 @Output         pui32Supported          For each dimension, the number of
                                         display pipes that support that
-                                         dimension
+                                        dimension
 
 @Return         PVRSRV_OK if the query was successful
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*DimQuery)(IMG_HANDLE hDeviceData,
-								 IMG_UINT32 ui32NumDims,
-								 PVRSRV_SURFACE_DIMS *psDim,
-								 IMG_UINT32 *pui32Supported);
-
+                                 IMG_UINT32 ui32NumDims,
+                                 PVRSRV_SURFACE_DIMS *pasDim,
+                                 IMG_UINT32 *pui32Supported);
 
 /*************************************************************************/ /*!
 @Function       SetBlank
 
-@Description    Enable/disable blanking of the screen
+@Description    Enable/disable blanking of the screen.
 
-@Input          psConnection            Services connection
+   Called by client function: #PVRSRVDCSetBlank()
 
-@Input          hDevice                 3rd party display class device
+   Implementation of this callback is optional.
 
-@Input          bEnabled                Enable/Disable the blanking
+@Input          hDeviceData             Device private data
+
+@Input          bEnable                 Enable/Disable the blanking
 
 @Return         PVRSRV_OK on success
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*SetBlank)(IMG_HANDLE hDeviceData,
-								 IMG_BOOL bEnabled);
+                                 IMG_BOOL bEnable);
 
 /*************************************************************************/ /*!
 @Function       SetVSyncReporting
 
-@Description    Enable VSync reporting by trigger the global event object on
-                every vsync happened.
+@Description    Enable VSync reporting. If enabled, the 3rd party display
+                driver is expected to call PVRSRVCheckStatus() after a VSync
+                event occurred. This will signal the Services driver global 
+                event object.
 
-@Input          psConnection            Services connection
+   Called by client function: #PVRSRVDCSetVSyncReporting()
 
-@Input          hDevice                 3rd party display class device
+   Implementation of this callback is optional.
 
-@Input          bEnabled                Enable/Disable the reporting
+@Input          hDeviceData             Device private data
+
+@Input          bEnable                 Enable/Disable the reporting
 
 @Return         PVRSRV_OK on success
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*SetVSyncReporting)(IMG_HANDLE hDeviceData,
-										  IMG_BOOL bEnabled);
+                                          IMG_BOOL bEnable);
 
 /*************************************************************************/ /*!
-@Function       PVRSRVDCLastVSyncQuery
+@Function       LastVSyncQuery
 
 @Description    Query the time the last vsync happened.
 
-@Input          psConnection            Services connection
+   Called by client function: #PVRSRVDCLastVSyncQuery()
 
-@Input          hDevice                 3rd party display class device
+   Implementation of this callback is optional.
 
-@Output         pi64Timestamp           the requested timestamp
+@Input          hDeviceData             Device private data
+
+@Output         pi64Timestamp           The requested timestamp
+                                        of the system time in ns
 
 @Return         PVRSRV_OK if the query was successful
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*LastVSyncQuery)(IMG_HANDLE hDeviceData,
-									   IMG_INT64 *pi64Timestamp);
-
-typedef PVRSRV_ERROR (*BufferSystemAcquire)(IMG_HANDLE hDeviceData,
-											IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
-											IMG_UINT32 *pui32PageCount,
-											IMG_UINT32 *pui32PhysHeapID,
-											IMG_UINT32 *pui32ByteStride,
-											IMG_HANDLE *phSystemBuffer);
-
-typedef	void (*BufferSystemRelease)(IMG_HANDLE hSystemBuffer);
+                                       IMG_INT64 *pi64Timestamp);
 
 /*************************************************************************/ /*!
 @Function       ContextCreate
 
 @Description    Create display context.
+                The client application and the display driver have to agree
+                as to what exactly a context represents, Services will just
+                pass it through and tie it to its own concept of a
+                display context.
+                It might contain additional locks, work-queues or other
+                important data that is necessary to drive the interaction
+                with Services. A context is usually associated with one device
+                but that is not a hard requirement.
+
+   Called by client function: #PVRSRVDCDisplayContextCreate()
+
+   Implementation of this callback is mandatory.
 
 @Input          hDeviceData             Device private data
 
@@ -233,19 +301,29 @@
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*ContextCreate)(IMG_HANDLE hDeviceData,
-									  IMG_HANDLE *hDisplayContext);
+                                      IMG_HANDLE *hDisplayContext);
 
 /*************************************************************************/ /*!
 @Function       ContextConfigureCheck
 
 @Description    Check to see if a configuration is valid for the display
-                controller.
+                controller. Because of runtime changes the display context
+                might not be able to work with a certain configuration anymore.
+                This function is intended to be called before ContextConfigure
+                so that the application can query details about the current
+                surface config and then do the ContextConfigure call with
+                the updated data.
+                The arrays should be z-sorted, with the farthest plane
+                first and the nearest plane last.
 
-                Note: This function is optional
+   Called by client function: #PVRSRVDCContextConfigureCheck()
+
+   Implementation of this callback is optional.
 
 @Input          hDisplayContext         Display context
 
 @Input          ui32PipeCount           Number of display pipes to configure
+                                        (length of the input arrays)
 
 @Input          pasSurfAttrib           Array of surface attributes (one for
                                         each display plane)
@@ -257,18 +335,25 @@
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*ContextConfigureCheck)(IMG_HANDLE hDisplayContext,
-											  IMG_UINT32 ui32PipeCount,
-											  PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
-											  IMG_HANDLE *ahBuffers);
+                                              IMG_UINT32 ui32PipeCount,
+                                              PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+                                              IMG_HANDLE *ahBuffers);
 
 /*************************************************************************/ /*!
 @Function       ContextConfigure
 
-@Description    Configuration the display pipeline.
+@Description    Configure the display pipeline to display a given buffer.
+                The arrays should be z-sorted, with the farthest plane first
+                and the nearest plane last.
+
+   Called by client function: #PVRSRVDCContextConfigure(), #PVRSRVDCContextConfigureWithFDSync()
+
+   Implementation of this callback is mandatory.
 
 @Input          hDisplayContext         Display context
 
 @Input          ui32PipeCount           Number of display pipes to configure
+                                        (i.e. length of the input arrays)
 
 @Input          pasSurfAttrib           Array of surface attributes (one for
                                         each display plane)
@@ -282,22 +367,24 @@
 @Input          hConfigData             Config handle which gets passed to
                                         DisplayConfigurationRetired when this
                                         configuration is retired
-
-@Return         PVRSRV_OK if the configuration was successfully queued
 */
 /*****************************************************************************/
 typedef void (*ContextConfigure)(IMG_HANDLE hDisplayContext,
-								 IMG_UINT32 ui32PipeCount,
-								 PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
-								 IMG_HANDLE *ahBuffers,
-								 IMG_UINT32 ui32DisplayPeriod,
-								 IMG_HANDLE hConfigData);
+                                 IMG_UINT32 ui32PipeCount,
+                                 PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+                                 IMG_HANDLE *ahBuffers,
+                                 IMG_UINT32 ui32DisplayPeriod,
+                                 IMG_HANDLE hConfigData);
 
 /*************************************************************************/ /*!
 @Function       ContextDestroy
 
 @Description    Destroy a display context.
 
+   Called by client function: #PVRSRVDCDisplayContextDestroy()
+
+   Implementation of this callback is mandatory.
+
 @Input          hDisplayContext         Display context to destroy
 
 @Return         None
@@ -317,16 +404,22 @@
                 still needs to be created and returned to the caller as well
                 as some information about the buffer that's required upfront.
 
+   Called by client function: #PVRSRVDCBufferAlloc()
+
+   Implementation of this callback is mandatory.
+
 @Input          hDisplayContext         Display context this buffer will be
                                         used on
 
 @Input          psSurfInfo              Attributes of the buffer
 
-@Output         puiLog2PageSize         Log2 of the pagesize of the buffer
+@Output         puiLog2PageSize         Pagesize in log2(bytes) of one page
 
 @Output         pui32PageCount          Number of pages in the buffer
 
-@Output         pui32PhysHeapID         Physcial heap ID to use
+@Output         pui32PhysHeapID         Physical heap ID to use. The physical
+                                        heap has been created in the Services
+                                        system layer.
 
 @Output         pui32ByteStride         Stride (in bytes) of allocated buffer
 
@@ -336,22 +429,30 @@
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*BufferAlloc)(IMG_HANDLE hDisplayContext,
-									DC_BUFFER_CREATE_INFO *psSurfInfo,
-									IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
-									IMG_UINT32 *pui32PageCount,
-									IMG_UINT32 *pui32PhysHeapID,
-									IMG_UINT32 *pui32ByteStride,
-									IMG_HANDLE *phBuffer);
+                                    DC_BUFFER_CREATE_INFO *psSurfInfo,
+                                    IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
+                                    IMG_UINT32 *pui32PageCount,
+                                    IMG_UINT32 *pui32PhysHeapID,
+                                    IMG_UINT32 *pui32ByteStride,
+                                    IMG_HANDLE *phBuffer);
 
 /*************************************************************************/ /*!
 @Function       BufferImport
 
-@Description    Import memory allocated from an external source to the display
-                controller. The DC checks to see if the import is compatible
-                and potentially sets up HW to map the imported buffer, although
-                this isn't require to happen until the first call to DCBufferMap
+@Description    Import memory allocated from an external source (e.g. Services)
+                to the display controller. The DC checks to see if the import
+                is compatible and potentially sets up HW to map the imported
+                buffer, although this isn't required to happen until the first
+                call to BufferMap.
 
-                Note: This is optional
+                Note: Provide this function if the controller
+                can scan out arbitrary memory, allocated for another purpose by
+                Services. To be able to use this buffer (depending on its
+                origin) the display controller probably will need a MMU.
+
+   Called by client function: #PVRSRVDCBufferImport()
+
+   Implementation of this callback is optional.
 
 @Input          hDisplayContext         Display context this buffer will be
                                         used on
@@ -368,45 +469,54 @@
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*BufferImport)(IMG_HANDLE hDisplayContext,
-									 IMG_UINT32 ui32NumPlanes,
-									 IMG_HANDLE **paphImport,
-									 DC_BUFFER_IMPORT_INFO *psSurfAttrib,
-									 IMG_HANDLE *phBuffer);
+                                     IMG_UINT32 ui32NumPlanes,
+                                     IMG_HANDLE **pahImport,
+                                     DC_BUFFER_IMPORT_INFO *psSurfAttrib,
+                                     IMG_HANDLE *phBuffer);
 
 /*************************************************************************/ /*!
 @Function       BufferAcquire
 
-@Description    Acquire the buffer's physcial memory pages. If the buffer doesn't
-                have any memory backing it yet then this will trigger the 3rd
+@Description    Acquire the buffer's physical memory pages. If the buffer doesn't
+                have any memory backing yet then this will trigger the 3rd
                 party driver to allocate it.
 
                 Note: The page count isn't passed back in this function as
-                services has already obtained it during BufferAlloc.
+                Services has already obtained it during BufferAlloc.
+
+   Called when Services requests buffer access for the first time. Usually part
+   of non display class functions.
+
+   Implementation of this callback is mandatory.
 
 @Input          hBuffer                 Handle to the buffer
 
 @Output         pasDevPAddr             Array of device physical page address
                                         of this buffer
 
-@Output         pvLinAddr               CPU virtual address of buffer. This is
-                                        optionial but if you have one you must
+@Output         ppvLinAddr              CPU virtual address of buffer. This is
+                                        optional but if you have one you must
                                         return it otherwise return NULL.
 
 @Return         PVRSRV_OK if the buffer was successfully acquired
 */
 /*****************************************************************************/
 typedef PVRSRV_ERROR (*BufferAcquire)(IMG_HANDLE hBuffer,
-									  IMG_DEV_PHYADDR *pasDevPAddr,
-									  void **ppvLinAddr);
+                                      IMG_DEV_PHYADDR *pasDevPAddr,
+                                      void **ppvLinAddr);
 
 /*************************************************************************/ /*!
 @Function       BufferRelease
 
-@Description    Release the buffer's physcial memory pages.
+@Description    Undo everything done by BufferAcquire.
+                Will release the buffer's physical memory pages if
+                BufferAcquire allocated them.
+
+   Called when Services finished buffer access.
+
+   Implementation of this callback is mandatory.
 
 @Input          hBuffer                 Handle to the buffer
-
-@Return         None
 */
 /*****************************************************************************/
 typedef void (*BufferRelease)(IMG_HANDLE hBuffer);
@@ -416,11 +526,13 @@
 
 @Description    Release a reference to the device buffer. If this was the last
                 reference the 3rd party driver is entitled to free the backing
-                memory.
+                memory and other related resources.
+
+   Called by client function: #PVRSRVDCBufferFree()
+
+   Implementation of this callback is mandatory.
 
 @Input          hBuffer                 Buffer handle we're releasing
-
-@Return         None
 */
 /*****************************************************************************/
 typedef void (*BufferFree)(IMG_HANDLE hBuffer);
@@ -429,8 +541,15 @@
 @Function       BufferMap
 
 @Description    Map the buffer into the display controller
+                Note: This function depends on the behaviour of
+                BufferAlloc/BufferAcquire/BufferImport/BufferSystemAcquire
+                and the controller's ability to map in memory.
+                If the controller has no MMU or the above functions already
+                map the buffer this callback does not need an implementation.
 
-                Note: This function is optional
+   Called by client function: #PVRSRVDCBufferPin()
+
+   Implementation of this callback is optional.
 
 @Input          hBuffer                 Buffer to map
 
@@ -442,96 +561,194 @@
 /*************************************************************************/ /*!
 @Function       BufferUnmap
 
-@Description    Unmap a buffer from the display controller
+@Description    Undo everything done by BufferMap.
+                Usually that means to unmap a buffer from the display controller.
 
-                Note: This function is optional
+   Called by client function: #PVRSRVDCBufferUnpin()
+
+   Implementation of this callback is optional.
 
 @Input          hBuffer                 Buffer to unmap
-
-@Return         None
 */
 /*****************************************************************************/
 typedef void (*BufferUnmap)(IMG_HANDLE hBuffer);
 
 
-/*
-	Function table for server->display
+/*************************************************************************/ /*!
+@Function       BufferSystemAcquire
+
+@Description    DEPRICATED, please use BufferAlloc
+                Acquire the system buffer from the display driver.
+                If the OS should trigger a mode change then it's not allowed to
+                free the previous buffer until Services has released it
+                via BufferSystemRelease. The system buffer has to be associated
+                to a PhysHeapID which can be one of the existing physical heaps
+                if the system buffer is compatible with it or must be a separate
+                heap created for this use.
+
+   Called by client function: #PVRSRVDCSystemBufferAcquire()
+
+   Implementation of this callback is optional.
+
+@Input          hDeviceData             Device private data
+
+@Output         puiLog2PageSize         The physical pagesize in log2(bytes)
+                                        of one page that the buffer is composed of
+
+@Output         pui32PageCount          The number of pages the buffer contains
+
+@Output         pui32PhysHeapID         The ID of the Services PhysHeap that has
+                                        been setup in the system layer
+
+@Output         pui32ByteStride         Byte stride of the buffer
+
+@Output         phSystemBuffer          Handle to the buffer object
+
+@Return         PVRSRV_OK if the query was successful
 */
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*BufferSystemAcquire)(IMG_HANDLE hDeviceData,
+                                            IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
+                                            IMG_UINT32 *pui32PageCount,
+                                            IMG_UINT32 *pui32PhysHeapID,
+                                            IMG_UINT32 *pui32ByteStride,
+                                            IMG_HANDLE *phSystemBuffer);
+
+/*************************************************************************/ /*!
+@Function       BufferSystemRelease
+
+@Description    DEPRICATED, please use BufferFree
+                Release a display buffer acquired with BufferSystemAcquire.
+                Services calls this after it has no use for the buffer anymore.
+                The buffer must not be destroyed before Services releases it
+                with this call.
+
+   Called by client function: #PVRSRVDCSystemBufferRelease()
+
+   Implementation of this callback is optional.
+
+@Input          hSystemBuffer          Handle to the buffer object
+*/
+/*****************************************************************************/
+typedef	void (*BufferSystemRelease)(IMG_HANDLE hSystemBuffer);
+
+#if defined(INTEGRITY_OS)
+typedef PVRSRV_ERROR (*AcquireKernelMappingData)(IMG_HANDLE hBuffer, IMG_HANDLE *phMapping, void **ppPhysAddr);
+typedef PVRSRV_ERROR (*MapMemoryObject)(IMG_HANDLE hBuffer, IMG_HANDLE *phMemObj);
+typedef PVRSRV_ERROR (*UnmapMemoryObject)(IMG_HANDLE hBuffer);
+
+#if defined(USING_HYPERVISOR)
+typedef IMG_HANDLE (*GetPmr)(IMG_HANDLE hBuffer, size_t ulOffset);
+#endif
+#endif
+
+/*!
+ * Function table for functions to be implemented by the display controller
+ * that will be called from within Services.
+ * The table will be provided to Services with the call to DCRegisterDevice.
+ */
 typedef struct _DC_DEVICE_FUNCTIONS_
 {
-	/*! Mandatory query functions */
+	/* Mandatory query functions */
 	GetInfo						pfnGetInfo;
 	PanelQueryCount				pfnPanelQueryCount;
 	PanelQuery					pfnPanelQuery;
 	FormatQuery					pfnFormatQuery;
 	DimQuery					pfnDimQuery;
 
-	/*! Optional blank/vsync function */
-	SetBlank		            pfnSetBlank;
-	SetVSyncReporting		    pfnSetVSyncReporting;
+	/* Optional blank/vsync functions */
+	SetBlank					pfnSetBlank;
+	SetVSyncReporting			pfnSetVSyncReporting;
 	LastVSyncQuery				pfnLastVSyncQuery;
 
-	/*! Mandatory configure function */
+	/* Mandatory configure functions */
 	ContextCreate				pfnContextCreate;
 	ContextDestroy				pfnContextDestroy;
 	ContextConfigure			pfnContextConfigure;
 
-	/*! Optional context function */
+	/* Optional context functions */
 	ContextConfigureCheck		pfnContextConfigureCheck;
 
-	/*! Mandatory buffer functions */
+	/* Mandatory buffer functions */
 	BufferAlloc					pfnBufferAlloc;
 	BufferAcquire				pfnBufferAcquire;
 	BufferRelease				pfnBufferRelease;
 	BufferFree					pfnBufferFree;
 
-	/*! Optional buffer functions, pfnBufferMap and pfnBufferUnmap are paired
-		functions, provide both or neither */
+	/* Optional - Provide this function if your controller can
+	 * scan out arbitrary memory, allocated for another purpose
+	 * by Services. */
 	BufferImport				pfnBufferImport;
+
+	/* Optional - Provide these functions if your controller
+	 * has an MMU and does not (or cannot) map/unmap buffers at
+	 * alloc/free time */
 	BufferMap					pfnBufferMap;
 	BufferUnmap					pfnBufferUnmap;
+
+	/* Optional - DEPRICATED */
 	BufferSystemAcquire			pfnBufferSystemAcquire;
 	BufferSystemRelease			pfnBufferSystemRelease;
+
+#if defined(INTEGRITY_OS)
+	/* The addition of these functions allow dc_server to delegate calls to
+	 * the respective functions on its PMRs towards the DC module
+	 */
+	AcquireKernelMappingData	pfnAcquireKernelMappingData;
+	MapMemoryObject             pfnMapMemoryObject;
+	UnmapMemoryObject           pfnUnmapMemoryObject;
+
+#if defined(USING_HYPERVISOR)
+	GetPmr				pfnGetPmr;
+#endif
+#endif
 } DC_DEVICE_FUNCTIONS;
 
 
 /*
-	functions exported by kernel services for use by 3rd party kernel display
-	class device driver
+ * Functions exported by kernel Services for use by 3rd party kernel display
+ * controller device driver
 */
 
 /*************************************************************************/ /*!
 @Function       DCRegisterDevice
 
-@Description    Register a display class device
+@Description    This needs to be called by the display driver before any further
+                communication with Services.
+                It registers a display controller device with Services. After this
+                registration Services is able to use the display controller
+                and will make use of the callbacks. Services will provide the
+                hDeviceData in the callbacks whenever necessary.
 
 @Input          psFuncTable             Callback function table
 
 @Input          ui32MaxConfigsInFlight  The maximum number of configs that this
-                                        display device can have in-flight.
+                                        display device can have in-flight. This
+                                        determines the number of possible calls
+                                        to ContextConfigure before Services has to
+                                        wait for DCDisplayConfigurationRetired
+                                        calls.
 
-@Input          hDeviceData             3rd party device handle, passed into
-                                        DC callbacks
+@Input          hDeviceData             Device private data passed into callbacks
 
 @Output         phSrvHandle             Services handle to pass back into
                                         UnregisterDCDevice
 
-@Return         PVRSRV_OK if the display class driver was successfully registered
+@Return         PVRSRV_OK if the display controller driver was successfully registered
 */
 /*****************************************************************************/
 PVRSRV_ERROR DCRegisterDevice(DC_DEVICE_FUNCTIONS *psFuncTable,
-							  IMG_UINT32 ui32MaxConfigsInFlight,
-							  IMG_HANDLE hDeviceData,
-							  IMG_HANDLE *phSrvHandle);
+                              IMG_UINT32 ui32MaxConfigsInFlight,
+                              IMG_HANDLE hDeviceData,
+                              IMG_HANDLE *phSrvHandle);
 
 /*************************************************************************/ /*!
 @Function       DCUnregisterDevice
 
-@Description    Unregister a display class device
+@Description    Unregister a display controller device. Undo everything done with
+                DCRegisterDevice. Services will stop using this device.
 
-@Input          hDevice                Services device handle
-
-@Return         None
+@Input          hSrvHandle              Services device handle
 */
 /*****************************************************************************/
 void DCUnregisterDevice(IMG_HANDLE hSrvHandle);
@@ -540,11 +757,9 @@
 @Function       DCDisplayConfigurationRetired
 
 @Description    Called when a configuration as been retired due to a new
-                configuration now being active.
+                configuration now being active. See #PVRSRVDCContextConfigure().
 
 @Input          hConfigData             ConfigData that is being retired
-
-@Return         None
 */
 /*****************************************************************************/
 void DCDisplayConfigurationRetired(IMG_HANDLE hConfigData);
@@ -567,40 +782,41 @@
 @Function       DCImportBufferAcquire
 
 @Description    Acquire information about a buffer that was imported with
-                BufferImport.
+                BufferImport. DCImportBufferRelease has to be called after
+                the buffer will not be used anymore.
 
 @Input          hImport                 Import buffer
 
-@Input          uiLog2PageSize          Log 2 of the DC's page size
+@Input          uiLog2PageSize          Pagesize in log2(bytes) of the buffer
 
 @Output         pui32PageCount          Size of the buffer in pages
 
-@Output         ppasDevPAddr            Array of device physcial page address
+@Output         pasDevPAddr             Array of device physical page address
                                         of this buffer
 
 @Return         PVRSRV_OK if the import buffer was successfully acquired
 */
 /*****************************************************************************/
 PVRSRV_ERROR DCImportBufferAcquire(IMG_HANDLE hImport,
-								   IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
-								   IMG_UINT32 *pui32PageCount,
-								   IMG_DEV_PHYADDR **ppasDevPAddr);
+                                   IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+                                   IMG_UINT32 *pui32PageCount,
+                                   IMG_DEV_PHYADDR **pasDevPAddr);
 
 /*************************************************************************/ /*!
 @Function       DCImportBufferRelease
 
 @Description    Release an imported buffer.
 
-@Input          hImport                 Import handle we're releasing
+@Input          hImport                 Import handle we are releasing
 
-@Input          pasDevPAddr             Import data was returned from
+@Input          pasDevPAddr             Import data which was returned from
                                         DCImportBufferAcquire
-
-@Return         None
 */
 /*****************************************************************************/
 void DCImportBufferRelease(IMG_HANDLE hImport,
-						   IMG_DEV_PHYADDR *pasDevPAddr);
+                           IMG_DEV_PHYADDR *pasDevPAddr);
+
+
 
 #if defined (__cplusplus)
 }
diff --git a/drivers/staging/imgtec/rogue/km_apphint.c b/drivers/staging/imgtec/rogue/km_apphint.c
new file mode 100644
index 0000000..1498941
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/km_apphint.c
@@ -0,0 +1,1422 @@
+/*************************************************************************/ /*!
+@File           km_apphint.c
+@Title          Apphint routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+
+#include "pvr_debugfs.h"
+#include "pvr_uaccess.h"
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <stdbool.h>
+
+/* for action device access */
+#include "pvrsrv.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgxfwutils.h"
+#include "debugmisc_server.h"
+#include "htbserver.h"
+#include "rgxutils.h"
+#include "rgxapi_km.h"
+
+#include "img_defs.h"
+
+/* defines for default values */
+#include "rgx_fwif.h"
+#include "htbuffer_types.h"
+
+#include "pvr_notifier.h"
+
+#include "km_apphint_defs.h"
+#include "km_apphint.h"
+
+#if defined(PDUMP)
+#include <stdarg.h>
+#include "pdump_km.h"
+#endif
+
+/* Size of temporary buffers used to read and write AppHint data.
+ * Must be large enough to contain any strings read/written
+ * but no larger than 4096 with is the buffer size for the
+ * kernel_param_ops .get function.
+ * And less than 1024 to keep the stack frame size within bounds.
+ */
+#define APPHINT_BUFFER_SIZE 512
+
+#define APPHINT_DEVICES_MAX 16
+
+/*
+*******************************************************************************
+ * AppHint mnemonic data type helper tables
+******************************************************************************/
+struct apphint_lookup {
+	char *name;
+	int value;
+};
+
+static const struct apphint_lookup fwt_logtype_tbl[] = {
+	{ "trace", 2},
+	{ "tbi", 1},
+	{ "none", 0}
+};
+
+static const struct apphint_lookup fwt_loggroup_tbl[] = {
+	RGXFWIF_LOG_GROUP_NAME_VALUE_MAP
+};
+
+static const struct apphint_lookup htb_loggroup_tbl[] = {
+#define X(a, b) { #b, HTB_LOG_GROUP_FLAG(a) },
+	HTB_LOG_SFGROUPLIST
+#undef X
+};
+
+static const struct apphint_lookup htb_opmode_tbl[] = {
+	{ "droplatest", HTB_OPMODE_DROPLATEST},
+	{ "dropoldest", HTB_OPMODE_DROPOLDEST},
+	{ "block", HTB_OPMODE_BLOCK}
+};
+
+__maybe_unused
+static const struct apphint_lookup htb_logmode_tbl[] = {
+	{ "all", HTB_LOGMODE_ALLPID},
+	{ "restricted", HTB_LOGMODE_RESTRICTEDPID}
+};
+
+static const struct apphint_lookup timecorr_clk_tbl[] = {
+	{ "mono", 0 },
+	{ "mono_raw", 1 },
+	{ "sched", 2 }
+};
+
+/*
+*******************************************************************************
+ Data types
+******************************************************************************/
+union apphint_value {
+	IMG_UINT64 UINT64;
+	IMG_UINT32 UINT32;
+	IMG_BOOL BOOL;
+	IMG_CHAR *STRING;
+};
+
+struct apphint_action {
+	union {
+		PVRSRV_ERROR (*UINT64)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 *value);
+		PVRSRV_ERROR (*UINT32)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 *value);
+		PVRSRV_ERROR (*BOOL)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL *value);
+		PVRSRV_ERROR (*STRING)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR **value);
+	} query;
+	union {
+		PVRSRV_ERROR (*UINT64)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 value);
+		PVRSRV_ERROR (*UINT32)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 value);
+		PVRSRV_ERROR (*BOOL)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL value);
+		PVRSRV_ERROR (*STRING)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR *value);
+	} set;
+	const PVRSRV_DEVICE_NODE *device;
+	const void *private_data;
+	union apphint_value stored;
+	bool free;
+};
+
+struct apphint_param {
+	IMG_UINT32 id;
+	APPHINT_DATA_TYPE data_type;
+	const void *data_type_helper;
+	IMG_UINT32 helper_size;
+};
+
+struct apphint_init_data {
+	IMG_UINT32 id;			/* index into AppHint Table */
+	APPHINT_CLASS class;
+	IMG_CHAR *name;
+	union apphint_value default_value;
+};
+
+struct apphint_class_state {
+	APPHINT_CLASS class;
+	IMG_BOOL enabled;
+};
+
+struct apphint_work {
+	struct work_struct work;
+	union apphint_value new_value;
+	struct apphint_action *action;
+};
+
+/*
+*******************************************************************************
+ Initialization / configuration table data
+******************************************************************************/
+#define UINT32Bitfield UINT32
+#define UINT32List UINT32
+
+static const struct apphint_init_data init_data_buildvar[] = {
+#define X(a, b, c, d, e) \
+	{APPHINT_ID_ ## a, APPHINT_CLASS_ ## c, #a, {.b=d} },
+	APPHINT_LIST_BUILDVAR
+#undef X
+};
+
+static const struct apphint_init_data init_data_modparam[] = {
+#define X(a, b, c, d, e) \
+	{APPHINT_ID_ ## a, APPHINT_CLASS_ ## c, #a, {.b=d} },
+	APPHINT_LIST_MODPARAM
+#undef X
+};
+
+static const struct apphint_init_data init_data_debugfs[] = {
+#define X(a, b, c, d, e) \
+	{APPHINT_ID_ ## a, APPHINT_CLASS_ ## c, #a, {.b=d} },
+	APPHINT_LIST_DEBUGFS
+#undef X
+};
+
+static const struct apphint_init_data init_data_debugfs_device[] = {
+#define X(a, b, c, d, e) \
+	{APPHINT_ID_ ## a, APPHINT_CLASS_ ## c, #a, {.b=d} },
+	APPHINT_LIST_DEBUGFS_DEVICE
+#undef X
+};
+
+#undef UINT32Bitfield
+#undef UINT32List
+
+/* Don't use the kernel ARRAY_SIZE macro here because it checks
+ * __must_be_array() and we need to be able to use this safely on a NULL ptr.
+ * This will return an undefined size for a NULL ptr - so should only be
+ * used here.
+ */
+#define APPHINT_HELP_ARRAY_SIZE(a) (sizeof((a))/(sizeof((a[0]))))
+
+static const struct apphint_param param_lookup[] = {
+#define X(a, b, c, d, e) \
+	{APPHINT_ID_ ## a, APPHINT_DATA_TYPE_ ## b, e, APPHINT_HELP_ARRAY_SIZE(e) },
+	APPHINT_LIST_ALL
+#undef X
+};
+
+#undef APPHINT_HELP_ARRAY_SIZE
+
+static const struct apphint_class_state class_state[] = {
+#define X(a) {APPHINT_CLASS_ ## a, APPHINT_ENABLED_CLASS_ ## a},
+	APPHINT_CLASS_LIST
+#undef X
+};
+
+/*
+*******************************************************************************
+ Global state
+******************************************************************************/
+/* If the union apphint_value becomes such that it is not possible to read
+ * and write atomically, a mutex may be desirable to prevent a read returning
+ * a partially written state.
+ * This would require a statically initialized mutex outside of the
+ * struct apphint_state to prevent use of an uninitialized mutex when
+ * module_params are provided on the command line.
+ *     static DEFINE_MUTEX(apphint_mutex);
+ */
+static struct apphint_state
+{
+	struct workqueue_struct *workqueue;
+	PVR_DEBUGFS_DIR_DATA *debugfs_device_rootdir[APPHINT_DEVICES_MAX];
+	PVR_DEBUGFS_ENTRY_DATA *debugfs_device_entry[APPHINT_DEVICES_MAX][APPHINT_DEBUGFS_DEVICE_ID_MAX];
+	PVR_DEBUGFS_DIR_DATA *debugfs_rootdir;
+	PVR_DEBUGFS_ENTRY_DATA *debugfs_entry[APPHINT_DEBUGFS_ID_MAX];
+	PVR_DEBUGFS_DIR_DATA *buildvar_rootdir;
+	PVR_DEBUGFS_ENTRY_DATA *buildvar_entry[APPHINT_BUILDVAR_ID_MAX];
+
+	int num_devices;
+	PVRSRV_DEVICE_NODE *devices[APPHINT_DEVICES_MAX];
+	int initialized;
+
+	struct apphint_action val[APPHINT_ID_MAX + ((APPHINT_DEVICES_MAX-1)*APPHINT_DEBUGFS_DEVICE_ID_MAX)];
+
+} apphint = {
+/* statically initialise default values to ensure that any module_params
+ * provided on the command line are not overwritten by defaults.
+ */
+	.val = {
+#define UINT32Bitfield UINT32
+#define UINT32List UINT32
+#define X(a, b, c, d, e) \
+	{ {NULL}, {NULL}, NULL, NULL, {.b=d}, false },
+	APPHINT_LIST_ALL
+#undef X
+#undef UINT32Bitfield
+#undef UINT32List
+	},
+	.initialized = 0,
+	.num_devices = 0
+};
+
+#define APPHINT_DEBUGFS_DEVICE_ID_OFFSET (APPHINT_ID_MAX-APPHINT_DEBUGFS_DEVICE_ID_MAX)
+
+static inline void
+get_apphint_id_from_action_addr(const struct apphint_action * const addr,
+                                APPHINT_ID * const id)
+{
+	*id = (APPHINT_ID)(addr - apphint.val);
+	if (*id >= APPHINT_ID_MAX) {
+		*id -= APPHINT_DEBUGFS_DEVICE_ID_OFFSET;
+		*id %= APPHINT_DEBUGFS_DEVICE_ID_MAX;
+		*id += APPHINT_DEBUGFS_DEVICE_ID_OFFSET;
+	}
+}
+
+static inline void
+get_value_offset_from_device(const PVRSRV_DEVICE_NODE * const device,
+                             int * const offset)
+{
+	int i;
+	for (i = 0; device && i < APPHINT_DEVICES_MAX; i++) {
+		if (apphint.devices[i] == device)
+			break;
+	}
+	if (APPHINT_DEVICES_MAX == i) {
+		PVR_DPF((PVR_DBG_WARNING, "%s: Unregistered device", __func__));
+		i = 0;
+	}
+	*offset = i * APPHINT_DEBUGFS_DEVICE_ID_MAX;
+}
+
+/**
+ * apphint_action_worker - perform an action after an AppHint update has been
+ *                    requested by a UM process
+ *                    And update the record of the current active value
+ */
+static void apphint_action_worker(struct work_struct *work)
+{
+	struct apphint_work *work_pkt = container_of(work,
+	                                             struct apphint_work,
+	                                             work);
+	struct apphint_action *a = work_pkt->action;
+	union apphint_value value = work_pkt->new_value;
+	APPHINT_ID id;
+	PVRSRV_ERROR result = PVRSRV_OK;
+
+	get_apphint_id_from_action_addr(a, &id);
+
+	if (a->set.UINT64) {
+		switch (param_lookup[id].data_type) {
+		case APPHINT_DATA_TYPE_UINT64:
+			result = a->set.UINT64(a->device,
+			                       a->private_data,
+			                       value.UINT64);
+			break;
+
+		case APPHINT_DATA_TYPE_UINT32:
+		case APPHINT_DATA_TYPE_UINT32Bitfield:
+		case APPHINT_DATA_TYPE_UINT32List:
+			result = a->set.UINT32(a->device,
+			                       a->private_data,
+			                       value.UINT32);
+			break;
+
+		case APPHINT_DATA_TYPE_BOOL:
+			result = a->set.BOOL(a->device,
+			                     a->private_data,
+			                     value.BOOL);
+			break;
+
+		case APPHINT_DATA_TYPE_STRING:
+			result = a->set.STRING(a->device,
+								   a->private_data,
+								   value.STRING);
+			kfree(value.STRING);
+			break;
+
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: unrecognised data type (%d), index (%d)",
+			         __func__, param_lookup[id].data_type, id));
+		}
+
+		if (PVRSRV_OK != result) {
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: failed (%s)",
+			         __func__, PVRSRVGetErrorStringKM(result)));
+		}
+	} else {
+		if (a->free) {
+			kfree(a->stored.STRING);
+		}
+		a->stored = value;
+		if (param_lookup[id].data_type == APPHINT_DATA_TYPE_STRING) {
+			a->free = true;
+		}
+		PVR_DPF((PVR_DBG_MESSAGE,
+		         "%s: AppHint value updated before handler is registered, ID(%d)",
+		         __func__, id));
+	}
+	kfree((void *)work_pkt);
+}
+
+static void apphint_action(union apphint_value new_value,
+                           struct apphint_action *action)
+{
+	struct apphint_work *work_pkt = kmalloc(sizeof(*work_pkt), GFP_KERNEL);
+
+	/* queue apphint update on a serialized workqueue to avoid races */
+	if (work_pkt) {
+		work_pkt->new_value = new_value;
+		work_pkt->action = action;
+		INIT_WORK(&work_pkt->work, apphint_action_worker);
+		if (0 == queue_work(apphint.workqueue, &work_pkt->work)) {
+			PVR_DPF((PVR_DBG_ERROR,
+				"%s: failed to queue apphint change request",
+				__func__));
+			goto err_exit;
+		}
+	} else {
+		PVR_DPF((PVR_DBG_ERROR,
+			"%s: failed to alloc memory for apphint change request",
+			__func__));
+			goto err_exit;
+	}
+	return;
+err_exit:
+	kfree(new_value.STRING);
+}
+
+/**
+ * apphint_read - read the different AppHint data types
+ * return -errno or the buffer size
+ */
+static int apphint_read(char *buffer, size_t count, APPHINT_ID ue,
+			 union apphint_value *value)
+{
+	APPHINT_DATA_TYPE data_type = param_lookup[ue].data_type;
+	int result = 0;
+
+	switch (data_type) {
+	case APPHINT_DATA_TYPE_UINT64:
+		if (kstrtou64(buffer, 0, &value->UINT64) < 0) {
+			PVR_DPF((PVR_DBG_ERROR,
+				"%s: Invalid UINT64 input data for id %d: %s",
+				__func__, ue, buffer));
+			result = -EINVAL;
+			goto err_exit;
+		}
+		break;
+	case APPHINT_DATA_TYPE_UINT32:
+		if (kstrtou32(buffer, 0, &value->UINT32) < 0) {
+			PVR_DPF((PVR_DBG_ERROR,
+				"%s: Invalid UINT32 input data for id %d: %s",
+				__func__, ue, buffer));
+			result = -EINVAL;
+			goto err_exit;
+		}
+		break;
+	case APPHINT_DATA_TYPE_BOOL:
+		switch (buffer[0]) {
+		case '0':
+		case 'n':
+		case 'N':
+		case 'f':
+		case 'F':
+			value->BOOL = IMG_FALSE;
+			break;
+		case '1':
+		case 'y':
+		case 'Y':
+		case 't':
+		case 'T':
+			value->BOOL = IMG_TRUE;
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"%s: Invalid BOOL input data for id %d: %s",
+				__func__, ue, buffer));
+			result = -EINVAL;
+			goto err_exit;
+		}
+		break;
+	case APPHINT_DATA_TYPE_UINT32List:
+	{
+		int i;
+		struct apphint_lookup *lookup =
+			(struct apphint_lookup *)
+			param_lookup[ue].data_type_helper;
+		int size = param_lookup[ue].helper_size;
+		/* buffer may include '\n', remove it */
+		char *arg = strsep(&buffer, "\n");
+
+		if (!lookup) {
+			result = -EINVAL;
+			goto err_exit;
+		}
+
+		for (i = 0; i < size; i++) {
+			if (strcasecmp(lookup[i].name, arg) == 0) {
+				value->UINT32 = lookup[i].value;
+				break;
+			}
+		}
+		if (i == size) {
+			if (strlen(arg) == 0) {
+				PVR_DPF((PVR_DBG_ERROR,
+					"%s: No value set for AppHint",
+					__func__));
+			} else {
+				PVR_DPF((PVR_DBG_ERROR,
+					"%s: Unrecognised AppHint value (%s)",
+					__func__, arg));
+			}
+			result = -EINVAL;
+		}
+		break;
+	}
+	case APPHINT_DATA_TYPE_UINT32Bitfield:
+	{
+		int i;
+		struct apphint_lookup *lookup =
+			(struct apphint_lookup *)
+			param_lookup[ue].data_type_helper;
+		int size = param_lookup[ue].helper_size;
+		/* buffer may include '\n', remove it */
+		char *string = strsep(&buffer, "\n");
+		char *token = strsep(&string, ",");
+
+		if (!lookup) {
+			result = -EINVAL;
+			goto err_exit;
+		}
+
+		value->UINT32 = 0;
+		/* empty string is valid to clear the bitfield */
+		while (token && *token) {
+			for (i = 0; i < size; i++) {
+				if (strcasecmp(lookup[i].name, token) == 0) {
+					value->UINT32 |= lookup[i].value;
+					break;
+				}
+			}
+			if (i == size) {
+				PVR_DPF((PVR_DBG_ERROR,
+					"%s: Unrecognised AppHint value (%s)",
+					__func__, token));
+				result = -EINVAL;
+				goto err_exit;
+			}
+			token = strsep(&string, ",");
+		}
+		break;
+	}
+	case APPHINT_DATA_TYPE_STRING:
+	{
+		/* buffer may include '\n', remove it */
+		char *string = strsep(&buffer, "\n");
+		size_t len = strlen(string);
+
+		if (!len) {
+			result = -EINVAL;
+			goto err_exit;
+		}
+
+		++len;
+
+		value->STRING = kmalloc(len, GFP_KERNEL);
+		if (!value->STRING) {
+			result = -ENOMEM;
+			goto err_exit;
+		}
+
+		strlcpy(value->STRING, string, len);
+		break;
+	}
+	default:
+		result = -EINVAL;
+		goto err_exit;
+	}
+
+err_exit:
+	return (result < 0) ? result : count;
+}
+
+/**
+ * apphint_write - write the current AppHint data to a buffer
+ *
+ * Returns length written or -errno
+ */
+static int apphint_write(char *buffer, const size_t size,
+                         const struct apphint_action *a)
+{
+	const struct apphint_param *hint;
+	int result = 0;
+	APPHINT_ID id;
+	union apphint_value value;
+
+	get_apphint_id_from_action_addr(a, &id);
+	hint = &param_lookup[id];
+
+	if (a->query.UINT64) {
+		switch (hint->data_type) {
+		case APPHINT_DATA_TYPE_UINT64:
+			result = a->query.UINT64(a->device,
+			                         a->private_data,
+			                         &value.UINT64);
+			break;
+
+		case APPHINT_DATA_TYPE_UINT32:
+		case APPHINT_DATA_TYPE_UINT32Bitfield:
+		case APPHINT_DATA_TYPE_UINT32List:
+			result = a->query.UINT32(a->device,
+			                         a->private_data,
+			                         &value.UINT32);
+			break;
+
+		case APPHINT_DATA_TYPE_BOOL:
+			result = a->query.BOOL(a->device,
+			                       a->private_data,
+			                       &value.BOOL);
+			break;
+
+		case APPHINT_DATA_TYPE_STRING:
+			result = a->query.STRING(a->device,
+									 a->private_data,
+									 &value.STRING);
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: unrecognised data type (%d), index (%d)",
+			         __func__, hint->data_type, id));
+		}
+
+		if (PVRSRV_OK != result) {
+			PVR_DPF((PVR_DBG_ERROR, "%s: failed (%d), index (%d)",
+			         __func__, result, id));
+		}
+	} else {
+		value = a->stored;
+	}
+
+	switch (hint->data_type) {
+	case APPHINT_DATA_TYPE_UINT64:
+		result += snprintf(buffer + result, size - result,
+				"0x%016llx",
+				value.UINT64);
+		break;
+	case APPHINT_DATA_TYPE_UINT32:
+		result += snprintf(buffer + result, size - result,
+				"0x%08x",
+				value.UINT32);
+		break;
+	case APPHINT_DATA_TYPE_BOOL:
+		result += snprintf(buffer + result, size - result,
+			"%s",
+			value.BOOL ? "Y" : "N");
+		break;
+	case APPHINT_DATA_TYPE_STRING:
+		if (value.STRING) {
+			result += snprintf(buffer + result, size - result,
+				"%s",
+				*value.STRING ? value.STRING : "(none)");
+		} else {
+			result += snprintf(buffer + result, size - result,
+			"(none)");
+		}
+		break;
+	case APPHINT_DATA_TYPE_UINT32List:
+	{
+		struct apphint_lookup *lookup =
+			(struct apphint_lookup *) hint->data_type_helper;
+		IMG_UINT32 i;
+
+		if (!lookup) {
+			result = -EINVAL;
+			goto err_exit;
+		}
+
+		for (i = 0; i < hint->helper_size; i++) {
+			if (lookup[i].value == value.UINT32) {
+				result += snprintf(buffer + result,
+						size - result,
+						"%s",
+						lookup[i].name);
+				break;
+			}
+		}
+		break;
+	}
+	case APPHINT_DATA_TYPE_UINT32Bitfield:
+	{
+		struct apphint_lookup *lookup =
+			(struct apphint_lookup *) hint->data_type_helper;
+		IMG_UINT32 i;
+
+		if (!lookup) {
+			result = -EINVAL;
+			goto err_exit;
+		}
+
+		for (i = 0; i < hint->helper_size; i++) {
+			if (lookup[i].value & value.UINT32) {
+				result += snprintf(buffer + result,
+						size - result,
+						"%s,",
+						lookup[i].name);
+			}
+		}
+		if (result) {
+			/* remove any trailing ',' */
+			--result;
+			*(buffer + result) = '\0';
+		} else {
+			result += snprintf(buffer + result,
+					size - result, "none");
+		}
+		break;
+	}
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+			 "%s: unrecognised data type (%d), index (%d)",
+			 __func__, hint->data_type, id));
+		result = -EINVAL;
+	}
+
+err_exit:
+	return result;
+}
+
+/*
+*******************************************************************************
+ Module parameters initialization - different from debugfs
+******************************************************************************/
+/**
+ * apphint_kparam_set - Handle an update of a module parameter
+ *
+ * Returns 0, or -errno.  arg is in kp->arg.
+ */
+static int apphint_kparam_set(const char *val, const struct kernel_param *kp)
+{
+	char val_copy[APPHINT_BUFFER_SIZE];
+	APPHINT_ID id;
+	union apphint_value value;
+	int result;
+
+	/* need to discard const in case of string comparison */
+	result = strlcpy(val_copy, val, APPHINT_BUFFER_SIZE);
+
+	get_apphint_id_from_action_addr(kp->arg, &id);
+	if (result < APPHINT_BUFFER_SIZE) {
+		result = apphint_read(val_copy, result, id, &value);
+		if (result >= 0) {
+			((struct apphint_action *)kp->arg)->stored = value;
+			if (param_lookup[id].data_type == APPHINT_DATA_TYPE_STRING) {
+				((struct apphint_action *)kp->arg)->free = true;
+			}
+		}
+	} else {
+		PVR_DPF((PVR_DBG_ERROR, "%s: String too long", __func__));
+	}
+	return (result > 0) ? 0 : result;
+}
+
+/**
+ * apphint_kparam_get - handle a read of a module parameter
+ *
+ * Returns length written or -errno.  Buffer is 4k (ie. be short!)
+ */
+static int apphint_kparam_get(char *buffer, const struct kernel_param *kp)
+{
+	return apphint_write(buffer, PAGE_SIZE, kp->arg);
+}
+
+__maybe_unused
+static const struct kernel_param_ops apphint_kparam_fops = {
+	.set = apphint_kparam_set,
+	.get = apphint_kparam_get,
+};
+
+/*
+ * call module_param_cb() for all AppHints listed in APPHINT_LIST_MODPARAM
+ * apphint_modparam_class_ ## resolves to apphint_modparam_enable() except for
+ * AppHint classes that have been disabled.
+ */
+
+#define apphint_modparam_enable(name, number, perm) \
+	module_param_cb(name, &apphint_kparam_fops, &apphint.val[number], perm);
+
+#define X(a, b, c, d, e) \
+	apphint_modparam_class_ ##c(a, APPHINT_ID_ ## a, (S_IRUSR|S_IRGRP|S_IROTH))
+	APPHINT_LIST_MODPARAM
+#undef X
+
+/*
+*******************************************************************************
+ Debugfs get (seq file) operations - supporting functions
+******************************************************************************/
+static void *apphint_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos == 0) {
+		/* We want only one entry in the sequence, one call to show() */
+		return (void *) 1;
+	}
+
+	PVR_UNREFERENCED_PARAMETER(s);
+
+	return NULL;
+}
+
+static void apphint_seq_stop(struct seq_file *s, void *v)
+{
+	PVR_UNREFERENCED_PARAMETER(s);
+	PVR_UNREFERENCED_PARAMETER(v);
+}
+
+static void *apphint_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	PVR_UNREFERENCED_PARAMETER(s);
+	PVR_UNREFERENCED_PARAMETER(v);
+	PVR_UNREFERENCED_PARAMETER(pos);
+	return NULL;
+}
+
+static int apphint_seq_show(struct seq_file *s, void *v)
+{
+	IMG_CHAR km_buffer[APPHINT_BUFFER_SIZE];
+	int result;
+
+	PVR_UNREFERENCED_PARAMETER(v);
+
+	result = apphint_write(km_buffer, APPHINT_BUFFER_SIZE, s->private);
+	if (result < 0) {
+		PVR_DPF((PVR_DBG_ERROR, "%s: failure", __func__));
+	} else {
+		/* debugfs requires a trailing \n, module_params don't */
+		result += snprintf(km_buffer + result,
+				APPHINT_BUFFER_SIZE - result,
+				"\n");
+		seq_puts(s, km_buffer);
+	}
+
+	/* have to return 0 to see output */
+	return (result < 0) ? result : 0;
+}
+
+static const struct seq_operations apphint_seq_fops = {
+	.start = apphint_seq_start,
+	.stop  = apphint_seq_stop,
+	.next  = apphint_seq_next,
+	.show  = apphint_seq_show,
+};
+
+/*
+*******************************************************************************
+ Debugfs supporting functions
+******************************************************************************/
+/**
+ * apphint_set - Handle a debugfs value update
+ */
+static ssize_t apphint_set(const char __user *buffer,
+			    size_t count,
+			    loff_t position,
+			    void *data)
+{
+	APPHINT_ID id;
+	union apphint_value value;
+	struct apphint_action *action = data;
+	char km_buffer[APPHINT_BUFFER_SIZE];
+	int result = 0;
+
+	PVR_UNREFERENCED_PARAMETER(position);
+
+	if (count >= APPHINT_BUFFER_SIZE) {
+		PVR_DPF((PVR_DBG_ERROR, "%s: String too long (%zd)",
+			__func__, count));
+		result = -EINVAL;
+		goto err_exit;
+	}
+
+	if (pvr_copy_from_user(km_buffer, buffer, count)) {
+		PVR_DPF((PVR_DBG_ERROR, "%s: Copy of user data failed",
+			__func__));
+		result = -EFAULT;
+		goto err_exit;
+	}
+	km_buffer[count] = '\0';
+
+	get_apphint_id_from_action_addr(action, &id);
+	result = apphint_read(km_buffer, count, id, &value);
+	if (result >= 0)
+		apphint_action(value, action);
+
+err_exit:
+	return result;
+}
+
+/**
+ * apphint_debugfs_init - Create the specified debugfs entries
+ */
+static int apphint_debugfs_init(char *sub_dir,
+		int device_num,
+		unsigned init_data_size,
+		const struct apphint_init_data *init_data,
+		PVR_DEBUGFS_DIR_DATA *parentdir,
+		PVR_DEBUGFS_DIR_DATA **rootdir, PVR_DEBUGFS_ENTRY_DATA **entry)
+{
+	int result = 0;
+	unsigned i;
+	int device_value_offset = device_num * APPHINT_DEBUGFS_DEVICE_ID_MAX;
+
+	if (*rootdir) {
+		PVR_DPF((PVR_DBG_WARNING,
+			"AppHint DebugFS already created, skipping"));
+		result = -EEXIST;
+		goto err_exit;
+	}
+
+	result = PVRDebugFSCreateEntryDir(sub_dir, parentdir,
+					  rootdir);
+	if (result < 0) {
+		PVR_DPF((PVR_DBG_WARNING,
+			"Failed to create \"%s\" DebugFS directory.", sub_dir));
+		goto err_exit;
+	}
+
+	for (i = 0; i < init_data_size; i++) {
+		if (!class_state[init_data[i].class].enabled)
+			continue;
+
+		result = PVRDebugFSCreateEntry(init_data[i].name,
+				*rootdir,
+				&apphint_seq_fops,
+				apphint_set,
+				NULL,
+				NULL,
+				(void *) &apphint.val[init_data[i].id + device_value_offset],
+				&entry[i]);
+		if (result < 0) {
+			PVR_DPF((PVR_DBG_WARNING,
+				"Failed to create \"%s/%s\" DebugFS entry.",
+				sub_dir, init_data[i].name));
+		}
+	}
+
+err_exit:
+	return result;
+}
+
+/**
+ * apphint_debugfs_deinit- destroy the debugfs entries
+ */
+static void apphint_debugfs_deinit(unsigned num_entries,
+		PVR_DEBUGFS_DIR_DATA **rootdir, PVR_DEBUGFS_ENTRY_DATA **entry)
+{
+	unsigned i;
+
+	for (i = 0; i < num_entries; i++) {
+		if (entry[i]) {
+			PVRDebugFSRemoveEntry(&entry[i]);
+			entry[i] = NULL;
+		}
+	}
+
+	if (*rootdir) {
+		PVRDebugFSRemoveEntryDir(rootdir);
+		*rootdir = NULL;
+	}
+}
+
+/*
+*******************************************************************************
+ AppHint status dump implementation
+******************************************************************************/
+#if defined(PDUMP)
+static void apphint_pdump_values(void *flags, const IMG_CHAR *format, ...)
+{
+	char km_buffer[APPHINT_BUFFER_SIZE];
+	IMG_UINT32 ui32Flags = *(IMG_UINT32 *)flags;
+	va_list ap;
+
+	va_start(ap, format);
+	(void)vsnprintf(km_buffer, APPHINT_BUFFER_SIZE, format, ap);
+	va_end(ap);
+
+	PDumpCommentKM(km_buffer, ui32Flags);
+}
+#endif
+
+static void apphint_dump_values(char *group_name,
+			int device_num,
+			const struct apphint_init_data *group_data,
+			int group_size,
+			DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+			void *pvDumpDebugFile)
+{
+	int i, result;
+	int device_value_offset = device_num * APPHINT_DEBUGFS_DEVICE_ID_MAX;
+	char km_buffer[APPHINT_BUFFER_SIZE];
+
+	PVR_DUMPDEBUG_LOG("  %s", group_name);
+	for (i = 0; i < group_size; i++) {
+		result = apphint_write(km_buffer, APPHINT_BUFFER_SIZE,
+				&apphint.val[group_data[i].id + device_value_offset]);
+
+		if (result <= 0) {
+			PVR_DUMPDEBUG_LOG("    %s: <Error>",
+				group_data[i].name);
+		} else {
+			PVR_DUMPDEBUG_LOG("    %s: %s",
+				group_data[i].name, km_buffer);
+		}
+	}
+}
+
+/**
+ * Callback for debug dump
+ */
+static void apphint_dump_state(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
+			IMG_UINT32 ui32VerbLevel,
+			DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+			void *pvDumpDebugFile)
+{
+	int i, result;
+	char km_buffer[APPHINT_BUFFER_SIZE];
+	PVRSRV_DEVICE_NODE *device = (PVRSRV_DEVICE_NODE *)hDebugRequestHandle;
+
+	if (DEBUG_REQUEST_VERBOSITY_HIGH == ui32VerbLevel) {
+		PVR_DUMPDEBUG_LOG("------[ AppHint Settings ]------");
+
+		apphint_dump_values("Build Vars", 0,
+			init_data_buildvar, ARRAY_SIZE(init_data_buildvar),
+			pfnDumpDebugPrintf, pvDumpDebugFile);
+
+		apphint_dump_values("Module Params", 0,
+			init_data_modparam, ARRAY_SIZE(init_data_modparam),
+			pfnDumpDebugPrintf, pvDumpDebugFile);
+
+		apphint_dump_values("Debugfs Params", 0,
+			init_data_debugfs, ARRAY_SIZE(init_data_debugfs),
+			pfnDumpDebugPrintf, pvDumpDebugFile);
+
+		for (i = 0; i < APPHINT_DEVICES_MAX; i++) {
+			if (!apphint.devices[i]
+			    || (device && device != apphint.devices[i]))
+				continue;
+
+			result = snprintf(km_buffer,
+					  APPHINT_BUFFER_SIZE,
+					  "Debugfs Params Device ID: %d",
+					  i);
+			if (0 > result)
+				continue;
+
+			apphint_dump_values(km_buffer, i,
+					    init_data_debugfs_device,
+					    ARRAY_SIZE(init_data_debugfs_device),
+					    pfnDumpDebugPrintf,
+					    pvDumpDebugFile);
+		}
+	}
+}
+
+/*
+*******************************************************************************
+ Public interface
+******************************************************************************/
+int pvr_apphint_init(void)
+{
+	int result, i;
+
+	if (apphint.initialized) {
+		result = -EEXIST;
+		goto err_out;
+	}
+
+	for (i = 0; i < APPHINT_DEVICES_MAX; i++)
+		apphint.devices[i] = NULL;
+
+	/* create workqueue with strict execution ordering to ensure no
+	 * race conditions when setting/updating apphints from different
+	 * contexts
+	 */
+	apphint.workqueue = alloc_workqueue("apphint_workqueue", WQ_UNBOUND, 1);
+	if (!apphint.workqueue) {
+		result = -ENOMEM;
+		goto err_out;
+	}
+
+	result = apphint_debugfs_init("apphint", 0,
+		ARRAY_SIZE(init_data_debugfs), init_data_debugfs,
+		NULL,
+		&apphint.debugfs_rootdir, apphint.debugfs_entry);
+	if (0 != result)
+		goto err_out;
+
+	result = apphint_debugfs_init("buildvar", 0,
+		ARRAY_SIZE(init_data_buildvar), init_data_buildvar,
+		NULL,
+		&apphint.buildvar_rootdir, apphint.buildvar_entry);
+
+	apphint.initialized = 1;
+
+err_out:
+	return result;
+}
+
+int pvr_apphint_device_register(PVRSRV_DEVICE_NODE *device)
+{
+	int result, i;
+	char device_num[APPHINT_BUFFER_SIZE];
+	int device_value_offset;
+
+	if (!apphint.initialized) {
+		result = -EAGAIN;
+		goto err_out;
+	}
+
+	if (apphint.num_devices+1 >= APPHINT_DEVICES_MAX) {
+		result = -EMFILE;
+		goto err_out;
+	}
+
+	result = snprintf(device_num, APPHINT_BUFFER_SIZE, "%d", apphint.num_devices);
+	if (result < 0) {
+		PVR_DPF((PVR_DBG_WARNING,
+			"snprintf failed (%d)", result));
+		result = -EINVAL;
+		goto err_out;
+	}
+
+	/* Set the default values for the new device */
+	device_value_offset = apphint.num_devices * APPHINT_DEBUGFS_DEVICE_ID_MAX;
+	for (i = 0; i < APPHINT_DEBUGFS_DEVICE_ID_MAX; i++) {
+		apphint.val[init_data_debugfs_device[i].id + device_value_offset].stored
+			= init_data_debugfs_device[i].default_value;
+	}
+
+	result = apphint_debugfs_init(device_num, apphint.num_devices,
+	                              ARRAY_SIZE(init_data_debugfs_device),
+	                              init_data_debugfs_device,
+	                              apphint.debugfs_rootdir,
+	                              &apphint.debugfs_device_rootdir[apphint.num_devices],
+	                              apphint.debugfs_device_entry[apphint.num_devices]);
+	if (0 != result)
+		goto err_out;
+
+	apphint.devices[apphint.num_devices] = device;
+	apphint.num_devices++;
+
+	(void)PVRSRVRegisterDbgRequestNotify(
+			&device->hAppHintDbgReqNotify,
+			device,
+			apphint_dump_state,
+			DEBUG_REQUEST_APPHINT,
+			device);
+
+err_out:
+	return result;
+}
+
+void pvr_apphint_device_unregister(PVRSRV_DEVICE_NODE *device)
+{
+	int i;
+
+	if (!apphint.initialized)
+		return;
+
+	/* find the device */
+	for (i = 0; i < APPHINT_DEVICES_MAX; i++) {
+		if (apphint.devices[i] == device)
+			break;
+	}
+
+	if (APPHINT_DEVICES_MAX == i)
+		return;
+
+	if (device->hAppHintDbgReqNotify) {
+		(void)PVRSRVUnregisterDbgRequestNotify(
+			device->hAppHintDbgReqNotify);
+		device->hAppHintDbgReqNotify = NULL;
+	}
+
+	apphint_debugfs_deinit(APPHINT_DEBUGFS_DEVICE_ID_MAX,
+	                       &apphint.debugfs_device_rootdir[i],
+	                       apphint.debugfs_device_entry[i]);
+
+	apphint.devices[i] = NULL;
+	apphint.num_devices--;
+}
+
+void pvr_apphint_deinit(void)
+{
+	int i;
+
+	if (!apphint.initialized)
+		return;
+
+	/* remove any remaining device data */
+	for (i = 0; apphint.num_devices && i < APPHINT_DEVICES_MAX; i++) {
+		if (apphint.devices[i])
+			pvr_apphint_device_unregister(apphint.devices[i]);
+	}
+
+	/* free all alloc'd string apphints and set to NULL */
+	for (i = 0; i < ARRAY_SIZE(apphint.val); i++) {
+		if (apphint.val[i].free && apphint.val[i].stored.STRING) {
+			kfree(apphint.val[i].stored.STRING);
+			apphint.val[i].stored.STRING = NULL;
+			apphint.val[i].free = false;
+		}
+	}
+
+	apphint_debugfs_deinit(APPHINT_DEBUGFS_ID_MAX,
+			&apphint.debugfs_rootdir, apphint.debugfs_entry);
+	apphint_debugfs_deinit(APPHINT_BUILDVAR_ID_MAX,
+			&apphint.buildvar_rootdir, apphint.buildvar_entry);
+
+	destroy_workqueue(apphint.workqueue);
+
+	apphint.initialized = 0;
+}
+
+void pvr_apphint_dump_state(void)
+{
+#if defined(PDUMP)
+	IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+	apphint_dump_state(NULL, DEBUG_REQUEST_VERBOSITY_HIGH,
+	                   apphint_pdump_values, (void *)&ui32Flags);
+#endif
+	apphint_dump_state(NULL, DEBUG_REQUEST_VERBOSITY_HIGH,
+	                   NULL, NULL);
+}
+
+int pvr_apphint_get_uint64(APPHINT_ID ue, IMG_UINT64 *pVal)
+{
+	int error = -ERANGE;
+
+	if (ue < APPHINT_ID_MAX) {
+		*pVal = apphint.val[ue].stored.UINT64;
+		error = 0;
+	}
+	return error;
+}
+
+int pvr_apphint_get_uint32(APPHINT_ID ue, IMG_UINT32 *pVal)
+{
+	int error = -ERANGE;
+
+	if (ue < APPHINT_ID_MAX) {
+		*pVal = apphint.val[ue].stored.UINT32;
+		error = 0;
+	}
+	return error;
+}
+
+int pvr_apphint_get_bool(APPHINT_ID ue, IMG_BOOL *pVal)
+{
+	int error = -ERANGE;
+
+	if (ue < APPHINT_ID_MAX) {
+		error = 0;
+		*pVal = apphint.val[ue].stored.BOOL;
+	}
+	return error;
+}
+
+int pvr_apphint_get_string(APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size)
+{
+	int error = -ERANGE;
+	if (ue < APPHINT_ID_MAX && apphint.val[ue].stored.STRING) {
+		if (strlcpy(pBuffer, apphint.val[ue].stored.STRING, size) < size) {
+			error = 0;
+		}
+	}
+	return error;
+}
+
+void pvr_apphint_register_handlers_uint64(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	int device_value_offset;
+
+	if (id >= APPHINT_ID_MAX) {
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: AppHint ID (%d) is out of range, max (%d)",
+		         __func__, id, APPHINT_ID_MAX-1));
+		return;
+	}
+
+	get_value_offset_from_device(device, &device_value_offset);
+
+	switch (param_lookup[id].data_type) {
+	case APPHINT_DATA_TYPE_UINT64:
+		break;
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Does not match AppHint data type for ID (%d)",
+		         __func__, id));
+		return;
+	}
+
+	apphint.val[id + device_value_offset] = (struct apphint_action){
+		.query.UINT64 = query,
+		.set.UINT64 = set,
+		.device = device,
+		.private_data = private_data,
+		.stored = apphint.val[id + device_value_offset].stored
+	};
+}
+
+void pvr_apphint_register_handlers_uint32(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	int device_value_offset;
+
+	if (id >= APPHINT_ID_MAX) {
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: AppHint ID (%d) is out of range, max (%d)",
+		         __func__, id, APPHINT_ID_MAX-1));
+		return;
+	}
+
+	get_value_offset_from_device(device, &device_value_offset);
+
+	switch (param_lookup[id].data_type) {
+	case APPHINT_DATA_TYPE_UINT32:
+	case APPHINT_DATA_TYPE_UINT32Bitfield:
+	case APPHINT_DATA_TYPE_UINT32List:
+		break;
+
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Does not match AppHint data type for ID (%d)",
+		         __func__, id));
+		return;
+	}
+
+	apphint.val[id + device_value_offset] = (struct apphint_action){
+		.query.UINT32 = query,
+		.set.UINT32 = set,
+		.device = device,
+		.private_data = private_data,
+		.stored = apphint.val[id + device_value_offset].stored
+	};
+}
+
+void pvr_apphint_register_handlers_bool(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	int device_value_offset;
+
+	if (id >= APPHINT_ID_MAX) {
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: AppHint ID (%d) is out of range, max (%d)",
+		         __func__, id, APPHINT_ID_MAX-1));
+		return;
+	}
+
+	get_value_offset_from_device(device, &device_value_offset);
+
+	switch (param_lookup[id].data_type) {
+	case APPHINT_DATA_TYPE_BOOL:
+		break;
+
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Does not match AppHint data type for ID (%d)",
+		         __func__, id));
+		return;
+	}
+
+	apphint.val[id + device_value_offset] = (struct apphint_action){
+		.query.BOOL = query,
+		.set.BOOL = set,
+		.device = device,
+		.private_data = private_data,
+		.stored = apphint.val[id + device_value_offset].stored
+	};
+}
+
+void pvr_apphint_register_handlers_string(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR **value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR *value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	int device_value_offset;
+
+	if (id >= APPHINT_ID_MAX) {
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: AppHint ID (%d) is out of range, max (%d)",
+		         __func__, id, APPHINT_ID_MAX-1));
+		return;
+	}
+
+	get_value_offset_from_device(device, &device_value_offset);
+
+	switch (param_lookup[id].data_type) {
+	case APPHINT_DATA_TYPE_STRING:
+		break;
+
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Does not match AppHint data type for ID (%d)",
+		         __func__, id));
+		return;
+	}
+
+	apphint.val[id + device_value_offset] = (struct apphint_action){
+		.query.STRING = query,
+		.set.STRING = set,
+		.device = device,
+		.private_data = private_data,
+		.stored = apphint.val[id + device_value_offset].stored
+	};
+}
+
+#endif /* #if defined(SUPPORT_KERNEL_SRVINIT) */
+/* EOF */
+
diff --git a/drivers/staging/imgtec/rogue/km_apphint.h b/drivers/staging/imgtec/rogue/km_apphint.h
new file mode 100644
index 0000000..833b568
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/km_apphint.h
@@ -0,0 +1,151 @@
+/*************************************************************************/ /*!
+@File           km_apphint.h
+@Title          Apphint internal header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Linux kernel AppHint control
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __KM_APPHINT_H__
+#define __KM_APPHINT_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "km_apphint_defs.h"
+#include "device.h"
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+
+int pvr_apphint_init(void);
+void pvr_apphint_deinit(void);
+int pvr_apphint_device_register(PVRSRV_DEVICE_NODE *device);
+void pvr_apphint_device_unregister(PVRSRV_DEVICE_NODE *device);
+void pvr_apphint_dump_state(void);
+
+int pvr_apphint_get_uint64(APPHINT_ID ue, IMG_UINT64 *pVal);
+int pvr_apphint_get_uint32(APPHINT_ID ue, IMG_UINT32 *pVal);
+int pvr_apphint_get_bool(APPHINT_ID ue, IMG_BOOL *pVal);
+int pvr_apphint_get_string(APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size);
+
+void pvr_apphint_register_handlers_uint64(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void * private_data);
+void pvr_apphint_register_handlers_uint32(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data);
+void pvr_apphint_register_handlers_bool(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data);
+void pvr_apphint_register_handlers_string(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR **value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR *value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data);
+
+#else
+
+static INLINE void pvr_apphint_register_handlers_uint64(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void * private_data)
+{
+	PVR_UNREFERENCED_PARAMETER(id);
+	PVR_UNREFERENCED_PARAMETER(query);
+	PVR_UNREFERENCED_PARAMETER(set);
+	PVR_UNREFERENCED_PARAMETER(device);
+	PVR_UNREFERENCED_PARAMETER(private_data);
+}
+
+static INLINE void pvr_apphint_register_handlers_uint32(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT32 value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	PVR_UNREFERENCED_PARAMETER(id);
+	PVR_UNREFERENCED_PARAMETER(query);
+	PVR_UNREFERENCED_PARAMETER(set);
+	PVR_UNREFERENCED_PARAMETER(device);
+	PVR_UNREFERENCED_PARAMETER(private_data);
+}
+
+static INLINE void pvr_apphint_register_handlers_bool(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL *value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_BOOL value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	PVR_UNREFERENCED_PARAMETER(id);
+	PVR_UNREFERENCED_PARAMETER(query);
+	PVR_UNREFERENCED_PARAMETER(set);
+	PVR_UNREFERENCED_PARAMETER(device);
+	PVR_UNREFERENCED_PARAMETER(private_data);
+}
+
+static INLINE void pvr_apphint_register_handlers_string(APPHINT_ID id,
+	PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR **value),
+	PVRSRV_ERROR (*set)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_CHAR *value),
+	const PVRSRV_DEVICE_NODE *device,
+	const void *private_data)
+{
+	PVR_UNREFERENCED_PARAMETER(id);
+	PVR_UNREFERENCED_PARAMETER(query);
+	PVR_UNREFERENCED_PARAMETER(set);
+	PVR_UNREFERENCED_PARAMETER(device);
+	PVR_UNREFERENCED_PARAMETER(private_data);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* __KM_APPHINT_H__ */
+
+/******************************************************************************
+ End of file (apphint.h)
+******************************************************************************/
+
diff --git a/drivers/staging/imgtec/rogue/km_apphint_defs.h b/drivers/staging/imgtec/rogue/km_apphint_defs.h
new file mode 100644
index 0000000..48d0398
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/km_apphint_defs.h
@@ -0,0 +1,304 @@
+/*************************************************************************/ /*!
+@File
+@Title          Services AppHint definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+#ifndef __KM_APPHINT_DEFS_H__
+#define __KM_APPHINT_DEFS_H__
+
+/* NB: The 'DEVICE' AppHints must be last in this list as they will be
+ * duplicated in the case of a driver supporting multiple devices
+ */
+#define APPHINT_LIST_ALL \
+	APPHINT_LIST_BUILDVAR \
+	APPHINT_LIST_MODPARAM \
+	APPHINT_LIST_DEBUGFS \
+	APPHINT_LIST_DEPRECATED \
+	APPHINT_LIST_DEBUGFS_DEVICE
+
+/*
+*******************************************************************************
+ Build variables
+ All of these should be configurable only through the 'default' value
+******************************************************************************/
+#define APPHINT_LIST_BUILDVAR \
+/* name,                            type,           class,       default,                                         helper,         */ \
+X(HWRDebugDumpLimit,                UINT32,         DEBUG,       PVRSRV_APPHINT_HWRDEBUGDUMPLIMIT,                NULL             ) \
+X(EnableTrustedDeviceAceConfig,     BOOL,           GPUVIRT_VAL, PVRSRV_APPHINT_ENABLETRUSTEDDEVICEACECONFIG,     NULL             ) \
+X(HTBufferSize,                     UINT32,         ALWAYS,      PVRSRV_APPHINT_HTBUFFERSIZE,                     NULL             ) \
+X(CleanupThreadPriority,            UINT32,         NEVER,       PVRSRV_APPHINT_CLEANUPTHREADPRIORITY,            NULL             ) \
+X(CleanupThreadWeight,              UINT32,         NEVER,       PVRSRV_APPHINT_CLEANUPTHREADWEIGHT,              NULL             ) \
+X(WatchdogThreadPriority,           UINT32,         NEVER,       PVRSRV_APPHINT_WATCHDOGTHREADPRIORITY,           NULL             ) \
+X(WatchdogThreadWeight,             UINT32,         NEVER,       PVRSRV_APPHINT_WATCHDOGTHREADWEIGHT,             NULL             ) \
+
+/*
+*******************************************************************************
+ Module parameters
+******************************************************************************/
+#define APPHINT_LIST_MODPARAM \
+/* name,                            type,           class,       default,                                         helper,         */ \
+X(EnableSignatureChecks,            BOOL,           PDUMP,       PVRSRV_APPHINT_ENABLESIGNATURECHECKS,            NULL             ) \
+X(SignatureChecksBufSize,           UINT32,         PDUMP,       PVRSRV_APPHINT_SIGNATURECHECKSBUFSIZE,           NULL             ) \
+\
+X(DisableClockGating,               BOOL,           FWDBGCTRL,   PVRSRV_APPHINT_DISABLECLOCKGATING,               NULL             ) \
+X(DisableDMOverlap,                 BOOL,           FWDBGCTRL,   PVRSRV_APPHINT_DISABLEDMOVERLAP,                 NULL             ) \
+\
+X(EnableCDMKillingRandMode,         BOOL,           VALIDATION,  PVRSRV_APPHINT_ENABLECDMKILLINGRANDMODE,         NULL             ) \
+X(EnableFWContextSwitch,            UINT32,         FWDBGCTRL,   PVRSRV_APPHINT_ENABLEFWCONTEXTSWITCH,            NULL             ) \
+X(EnableRDPowerIsland,              UINT32,         FWDBGCTRL,   PVRSRV_APPHINT_ENABLERDPOWERISLAND,              NULL             ) \
+\
+X(GeneralNon4KHeapPageSize,         UINT32,         ALWAYS,      PVRSRV_APPHINT_GENERAL_NON4K_HEAP_PAGE_SIZE,     NULL             ) \
+\
+X(FirmwarePerf,                     UINT32,         VALIDATION,  PVRSRV_APPHINT_FIRMWAREPERF,                     NULL             ) \
+X(FWContextSwitchProfile,           UINT32,         VALIDATION,  PVRSRV_APPHINT_FWCONTEXTSWITCHPROFILE,           NULL             ) \
+X(HWPerfDisableCustomCounterFilter, BOOL,           VALIDATION,  PVRSRV_APPHINT_HWPERFDISABLECUSTOMCOUNTERFILTER, NULL             ) \
+X(HWPerfFWBufSizeInKB,              UINT32,         VALIDATION,  PVRSRV_APPHINT_HWPERFFWBUFSIZEINKB,              NULL             ) \
+X(HWPerfHostBufSizeInKB,            UINT32,         VALIDATION,  PVRSRV_APPHINT_HWPERFHOSTBUFSIZEINKB,            NULL             ) \
+\
+X(JonesDisableMask,                 UINT32,         VALIDATION,  PVRSRV_APPHINT_JONESDISABLEMASK,                 NULL             ) \
+X(NewFilteringMode,                 BOOL,           VALIDATION,  PVRSRV_APPHINT_NEWFILTERINGMODE,                 NULL             ) \
+X(TruncateMode,                     UINT32,         VALIDATION,  PVRSRV_APPHINT_TRUNCATEMODE,                     NULL             ) \
+X(UseMETAT1,                        UINT32,         VALIDATION,  PVRSRV_APPHINT_USEMETAT1,                        NULL             ) \
+X(RGXBVNC,                          STRING,         ALWAYS,      PVRSRV_APPHINT_RGXBVNC,                          NULL             ) \
+
+/*
+*******************************************************************************
+ Debugfs parameters - driver configuration
+******************************************************************************/
+#define APPHINT_LIST_DEBUGFS \
+/* name,                            type,           class,       default,                                         helper,         */ \
+X(EnableHTBLogGroup,                UINT32Bitfield, ALWAYS,      PVRSRV_APPHINT_ENABLEHTBLOGGROUP,                htb_loggroup_tbl ) \
+X(HTBOperationMode,                 UINT32List,     ALWAYS,      PVRSRV_APPHINT_HTBOPERATIONMODE,                 htb_opmode_tbl   ) \
+X(HWPerfFWFilter,                   UINT64,         ALWAYS,      PVRSRV_APPHINT_HWPERFFWFILTER,                   NULL             ) \
+X(HWPerfHostFilter,                 UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFHOSTFILTER,                 NULL             ) \
+X(TimeCorrClock,                    UINT32List,     ALWAYS,      PVRSRV_APPHINT_TIMECORRCLOCK,                    timecorr_clk_tbl )
+
+/*
+*******************************************************************************
+ Debugfs parameters - device configuration
+******************************************************************************/
+#define APPHINT_LIST_DEBUGFS_DEVICE \
+/* name,                            type,           class,       default,                                         helper,         */ \
+/* Device Firmware config */\
+X(AssertOnHWRTrigger,               BOOL,           ALWAYS,      PVRSRV_APPHINT_ASSERTONHWRTRIGGER,               NULL             ) \
+X(AssertOutOfMemory,                BOOL,           ALWAYS,      PVRSRV_APPHINT_ASSERTOUTOFMEMORY,                NULL             ) \
+X(CheckMList,                       BOOL,           ALWAYS,      PVRSRV_APPHINT_CHECKMLIST,                       NULL             ) \
+X(EnableHWR,                        BOOL,           ALWAYS,      APPHNT_BLDVAR_ENABLEHWR,                         NULL             ) \
+X(EnableLogGroup,                   UINT32Bitfield, ALWAYS,      PVRSRV_APPHINT_ENABLELOGGROUP,                   fwt_loggroup_tbl ) \
+X(FirmwareLogType,                  UINT32List,     ALWAYS,      PVRSRV_APPHINT_FIRMWARELOGTYPE,                  fwt_logtype_tbl  ) \
+/* Device host config */ \
+X(EnableAPM,                        UINT32,         ALWAYS,      PVRSRV_APPHINT_ENABLEAPM,                        NULL             ) \
+X(DisableFEDLogging,                BOOL,           ALWAYS,      PVRSRV_APPHINT_DISABLEFEDLOGGING,                NULL             ) \
+X(ZeroFreelist,                     BOOL,           ALWAYS,      PVRSRV_APPHINT_ZEROFREELIST,                     NULL             ) \
+X(DustRequestInject,                BOOL,           VALIDATION,  PVRSRV_APPHINT_DUSTREQUESTINJECT,                NULL             ) \
+X(DisablePDumpPanic,                BOOL,           PDUMP,       PVRSRV_APPHINT_DISABLEPDUMPPANIC,                NULL             ) \
+X(EnableFWPoisonOnFree,             BOOL,           ALWAYS,      PVRSRV_APPHINT_ENABLEFWPOISONONFREE,             NULL             ) \
+X(FWPoisonOnFreeValue,              UINT32,         ALWAYS,      PVRSRV_APPHINT_FWPOISONONFREEVALUE,              NULL             ) \
+
+/*
+*******************************************************************************
+ Deprecated parameters kept for backwards compatibility
+******************************************************************************/
+#define APPHINT_LIST_DEPRECATED \
+/* name,                            type,           class,       default,                                         helper,         */ \
+X(EnableFTraceGPU,                  BOOL,           ALWAYS,      0,                                               NULL             ) \
+X(EnableRTUBypass,                  BOOL,           ALWAYS,      0,                                               NULL             ) \
+\
+X(EnableHWPerf,                     BOOL,           ALWAYS,      0,                                               NULL             ) \
+X(EnableHWPerfHost,                 BOOL,           ALWAYS,      0,                                               NULL             ) \
+\
+X(DisablePDP,                       BOOL,           PDUMP,       PVRSRV_APPHINT_DISABLEPDUMPPANIC,                NULL             ) \
+X(HWPerfFilter0,                    UINT32,         ALWAYS,      0,                                               NULL             ) \
+X(HWPerfFilter1,                    UINT32,         ALWAYS,      0,                                               NULL             ) \
+
+/*
+*******************************************************************************
+ * Types used in the APPHINT_LIST_<GROUP> lists must be defined here.
+ * New types require specific handling code to be added
+******************************************************************************/
+#define APPHINT_DATA_TYPE_LIST \
+X(BOOL) \
+X(UINT64) \
+X(UINT32) \
+X(UINT32Bitfield) \
+X(UINT32List) \
+X(STRING)
+
+#define APPHINT_CLASS_LIST \
+X(ALWAYS) \
+X(NEVER) \
+X(DEBUG) \
+X(FWDBGCTRL) \
+X(PDUMP) \
+X(VALIDATION) \
+X(GPUVIRT_VAL)
+
+/*
+*******************************************************************************
+ Visibility control for module parameters
+ These bind build variables to AppHint Visibility Groups.
+******************************************************************************/
+#define APPHINT_ENABLED_CLASS_ALWAYS IMG_TRUE
+#define APPHINT_ENABLED_CLASS_NEVER IMG_FALSE
+#define apphint_modparam_class_ALWAYS(a, b, c) apphint_modparam_enable(a, b, c)
+#if defined(DEBUG)
+	#define APPHINT_ENABLED_CLASS_DEBUG IMG_TRUE
+	#define apphint_modparam_class_DEBUG(a, b, c) apphint_modparam_enable(a, b, c)
+#else
+	#define APPHINT_ENABLED_CLASS_DEBUG IMG_FALSE
+	#define apphint_modparam_class_DEBUG(a, b, c)
+#endif
+#if defined(SUPPORT_FWDBGCTRL)
+	#define APPHINT_ENABLED_CLASS_FWDBGCTRL IMG_TRUE
+	#define apphint_modparam_class_FWDBGCTRL(a, b, c) apphint_modparam_enable(a, b, c)
+#else
+	#define APPHINT_ENABLED_CLASS_FWDBGCTRL IMG_FALSE
+	#define apphint_modparam_class_FWDBGCTRL(a, b, c)
+#endif
+#if defined(PDUMP)
+	#define APPHINT_ENABLED_CLASS_PDUMP IMG_TRUE
+	#define apphint_modparam_class_PDUMP(a, b, c) apphint_modparam_enable(a, b, c)
+#else
+	#define APPHINT_ENABLED_CLASS_PDUMP IMG_FALSE
+	#define apphint_modparam_class_PDUMP(a, b, c)
+#endif
+#if defined(SUPPORT_VALIDATION)
+	#define APPHINT_ENABLED_CLASS_VALIDATION IMG_TRUE
+	#define apphint_modparam_class_VALIDATION(a, b, c) apphint_modparam_enable(a, b, c)
+#else
+	#define APPHINT_ENABLED_CLASS_VALIDATION IMG_FALSE
+	#define apphint_modparam_class_VALIDATION(a, b, c)
+#endif
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+	#define APPHINT_ENABLED_CLASS_GPUVIRT_VAL IMG_TRUE
+	#define apphint_modparam_class_GPUVIRT_VAL(a, b, c) apphint_modparam_enable(a, b, c)
+#else
+	#define APPHINT_ENABLED_CLASS_GPUVIRT_VAL IMG_FALSE
+	#define apphint_modparam_class_GPUVIRT_VAL(a, b, c)
+#endif
+
+/*
+*******************************************************************************
+ AppHint defaults based on other build parameters
+******************************************************************************/
+#if defined(HWR_DEFAULT_ENABLED)
+	#define APPHNT_BLDVAR_ENABLEHWR         1
+#else
+	#define APPHNT_BLDVAR_ENABLEHWR         0
+#endif
+#if defined(DEBUG)
+	#define APPHNT_BLDVAR_DEBUG             1
+	#define APPHNT_BLDVAR_DBGDUMPLIMIT      RGXFWIF_HWR_DEBUG_DUMP_ALL
+#else
+	#define APPHNT_BLDVAR_DEBUG             0
+	#define APPHNT_BLDVAR_DBGDUMPLIMIT      1
+#endif
+#if defined(DEBUG) || defined(PDUMP)
+#define APPHNT_BLDVAR_ENABLESIGNATURECHECKS     IMG_TRUE
+#else
+#define APPHNT_BLDVAR_ENABLESIGNATURECHECKS     IMG_FALSE
+#endif
+
+/*
+*******************************************************************************
+
+ Table generated enums
+
+******************************************************************************/
+/* Unique ID for all AppHints */
+typedef enum {
+#define X(a, b, c, d, e) APPHINT_ID_ ## a,
+	APPHINT_LIST_ALL
+#undef X
+	APPHINT_ID_MAX
+} APPHINT_ID;
+
+/* ID for build variable Apphints - used for build variable only structures */
+typedef enum {
+#define X(a, b, c, d, e) APPHINT_BUILDVAR_ID_ ## a,
+	APPHINT_LIST_BUILDVAR
+#undef X
+	APPHINT_BUILDVAR_ID_MAX
+} APPHINT_BUILDVAR_ID;
+
+/* ID for Modparam Apphints - used for modparam only structures */
+typedef enum {
+#define X(a, b, c, d, e) APPHINT_MODPARAM_ID_ ## a,
+	APPHINT_LIST_MODPARAM
+#undef X
+	APPHINT_MODPARAM_ID_MAX
+} APPHINT_MODPARAM_ID;
+
+/* ID for Debugfs Apphints - used for debugfs only structures */
+typedef enum {
+#define X(a, b, c, d, e) APPHINT_DEBUGFS_ID_ ## a,
+	APPHINT_LIST_DEBUGFS
+#undef X
+	APPHINT_DEBUGFS_ID_MAX
+} APPHINT_DEBUGFS_ID;
+
+/* ID for Debugfs Device Apphints - used for debugfs device only structures */
+typedef enum {
+#define X(a, b, c, d, e) APPHINT_DEBUGFS_DEVICE_ID_ ## a,
+	APPHINT_LIST_DEBUGFS_DEVICE
+#undef X
+	APPHINT_DEBUGFS_DEVICE_ID_MAX
+} APPHINT_DEBUGFS_DEVICE_ID;
+
+/* data types and actions */
+typedef enum {
+	APPHINT_DATA_TYPE_INVALID = 0,
+#define X(a) APPHINT_DATA_TYPE_ ## a,
+	APPHINT_DATA_TYPE_LIST
+#undef X
+	APPHINT_DATA_TYPE_MAX
+} APPHINT_DATA_TYPE;
+
+typedef enum {
+#define X(a) APPHINT_CLASS_ ## a,
+	APPHINT_CLASS_LIST
+#undef X
+	APPHINT_CLASS_MAX
+} APPHINT_CLASS;
+
+#endif /* __KM_APPHINT_DEFS_H__ */
+
diff --git a/drivers/staging/imgtec/rogue/linkage.h b/drivers/staging/imgtec/rogue/linkage.h
index 92416e3..2cfe060 100644
--- a/drivers/staging/imgtec/rogue/linkage.h
+++ b/drivers/staging/imgtec/rogue/linkage.h
@@ -46,19 +46,15 @@
 #if !defined(__LINKAGE_H__)
 #define __LINKAGE_H__
 
+/*
+ * FIXME: This is declared here to save creating a new header which should be
+ * removed soon anyway as bridge gen should be providing this interface.
+ */
+PVRSRV_ERROR DeviceDepBridgeInit(IMG_UINT64 ui64Features);
+PVRSRV_ERROR DeviceDepBridgeDeInit(IMG_UINT64 ui64Features);
 PVRSRV_ERROR LinuxBridgeInit(void);
 PVRSRV_ERROR LinuxBridgeDeInit(void);
 
-#if !defined(SUPPORT_DRM)
-long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
-
-#if defined(CONFIG_COMPAT)
-long PVRSRV_BridgeCompatDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
-#endif
-#endif
-
-int PVRSRV_MMap(struct file *file, struct vm_area_struct *ps_vma);
-
 PVRSRV_ERROR PVROSFuncInit(void);
 void PVROSFuncDeInit(void);
 
diff --git a/drivers/staging/imgtec/rogue/linuxsrv.h b/drivers/staging/imgtec/rogue/linuxsrv.h
index 11875f9..7023870 100644
--- a/drivers/staging/imgtec/rogue/linuxsrv.h
+++ b/drivers/staging/imgtec/rogue/linuxsrv.h
@@ -45,19 +45,6 @@
 
 #include "dbgdrvif_srv5.h"
 
-typedef struct  tagIOCTL_PACKAGE
-{
-	IMG_UINT32 ui32Cmd;              // ioctl command
-	IMG_UINT32 ui32Size;			   // needs to be correctly set
-	DBG_WIDEPTR	pInBuffer;          // input data buffer
-	IMG_UINT32  ui32InBufferSize;     // size of input data buffer
-	DBG_WIDEPTR    pOutBuffer;         // output data buffer
-	IMG_UINT32  ui32OutBufferSize;    // size of output data buffer
-#if defined(SUPPORT_DRM)
-	IMG_UINT32 ui32PtrSize;
-#endif
-} IOCTL_PACKAGE;
-
 IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,		
 						IMG_UINT32 ui32ControlCode, 
 						void *pInBuffer,
diff --git a/drivers/staging/imgtec/rogue/lists.c b/drivers/staging/imgtec/rogue/lists.c
index e7deb47..e8e7088 100644
--- a/drivers/staging/imgtec/rogue/lists.c
+++ b/drivers/staging/imgtec/rogue/lists.c
@@ -50,86 +50,11 @@
   ===================================================================*/
 
 IMPLEMENT_LIST_ANY(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, IMG_BOOL, IMG_FALSE)
 IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
 IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
 IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
 IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
 IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
-IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT_TAIL(PVRSRV_DEVICE_NODE)
 IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
-
-IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
-IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
-IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
-IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
-
-
-/*===================================================================
-  BELOW ARE IMPLEMENTED SOME COMMON CALLBACKS USED IN DIFFERENT FILES
-  ===================================================================*/
-
-
-/*************************************************************************/ /*!
-@Function       MatchDeviceKM_AnyVaCb
-@Description    Matchs a device node with an id and optionally a class.
-@Input          psDeviceNode  Pointer to the device node.
-@Input          va            Variable argument list, with te following values:
-                                ui32DevIndex  Index of de device to match.
-                                bIgnoreClass  Flag indicating if there's
-                                              no need to check the device class.
-                                eDevClass     Device class, ONLY present if
-                                              bIgnoreClass was IMG_FALSE.
-@Return         The pointer to the device node if it matchs, NULL
-                otherwise.
-*/ /**************************************************************************/
-void* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
-{
-	IMG_UINT32 ui32DevIndex;
-	IMG_BOOL bIgnoreClass;
-	PVRSRV_DEVICE_CLASS eDevClass;
-
-	ui32DevIndex = va_arg(va, IMG_UINT32);
-	bIgnoreClass = va_arg(va, IMG_BOOL);
-	if (!bIgnoreClass)
-	{
-		eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
-	}
-	else
-	{
-		/*this value will never be used, since the short circuit evaluation
-		of the first clause will stop because bIgnoreClass is true, but the
-		compiler complains if it's not initialized.*/
-		eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
-	}
-
-	if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
-		psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
-	{
-		return psDeviceNode;
-	}
-	return NULL;
-}
-
-/*!
-******************************************************************************
-@Function	MatchPowerDeviceIndex_AnyVaCb
-@Description    Matches a power device with its device index.
-@Input          va               Variable argument list
-                ui32DeviceIndex  Device index
-@Return         The pointer to the device it matched, NULL otherwise.
-******************************************************************************/
-void* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
-{
-	IMG_UINT32 ui32DeviceIndex;
-
-	ui32DeviceIndex = va_arg(va, IMG_UINT32);
-
-	if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
-	{
-		return psPowerDev;
-	}
-	else
-	{
-		return NULL;
-	}
-}
diff --git a/drivers/staging/imgtec/rogue/lists.h b/drivers/staging/imgtec/rogue/lists.h
index 93d36cc..e7a900f 100644
--- a/drivers/staging/imgtec/rogue/lists.h
+++ b/drivers/staging/imgtec/rogue/lists.h
@@ -58,20 +58,22 @@
  ppsThis. In order to make a function available for a given type, it is required
  to use the funcion template macro that creates the actual code.
 
- There are 4 main types of functions:
- - INSERT	: given a pointer to the head pointer of the list and a pointer to
- 			  the node, inserts it as the new head.
- - REMOVE	: given a pointer to a node, removes it from its list.
- - FOR EACH	: apply a function over all the elements of a list.
- - ANY		: apply a function over the elements of a list, until one of them
- 			  return a non null value, and then returns it.
+ There are 5 main types of functions:
+ - INSERT	   : given a pointer to the head pointer of the list and a pointer
+                 to the node, inserts it as the new head.
+ - INSERT TAIL : given a pointer to the head pointer of the list and a pointer
+                 to the node, inserts the node at the tail of the list.
+ - REMOVE	   : given a pointer to a node, removes it from its list.
+ - FOR EACH	   : apply a function over all the elements of a list.
+ - ANY		   : apply a function over the elements of a list, until one of them
+                 return a non null value, and then returns it.
 
  The two last functions can have a variable argument form, with allows to pass
  additional parameters to the callback function. In order to do this, the
  callback function must take two arguments, the first is the current node and
  the second is a list of variable arguments (va_list).
 
- The ANY functions have also another for wich specifies the return type of the
+ The ANY functions have also another for which specifies the return type of the
  callback function and the default value returned by the callback function.
 
 */
@@ -270,6 +272,30 @@
 }
 
 /*************************************************************************/ /*!
+@Function       List_##TYPE##_InsertTail
+@Description    Inserts a given node at the end of the list.
+@Input          psHead   The pointer to the pointer to the head node.
+@Input          psNode   The pointer to the node to be inserted.
+*/ /**************************************************************************/
+#define DECLARE_LIST_INSERT_TAIL(TYPE) \
+void List_##TYPE##_InsertTail(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT_TAIL(TYPE) \
+void List_##TYPE##_InsertTail(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+	TYPE *psTempNode = *ppsHead;\
+	if (psTempNode != NULL)\
+	{\
+		while (psTempNode->psNext)\
+			psTempNode = psTempNode->psNext;\
+		ppsHead = &psTempNode->psNext;\
+	}\
+	psNewNode->ppsThis = ppsHead;\
+	psNewNode->psNext = NULL;\
+	*ppsHead = psNewNode;\
+}
+
+/*************************************************************************/ /*!
 @Function       List_##TYPE##_Reverse
 @Description    Reverse a list in place
 @Input          ppsHead    The pointer to the pointer to the head node.
@@ -306,19 +332,15 @@
 
 
 DECLARE_LIST_ANY(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, IMG_BOOL, IMG_FALSE);
 DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
 DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
 DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
 DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
 DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
-DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT_TAIL(PVRSRV_DEVICE_NODE);
 DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
 
-DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
-DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
-DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
-DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
-
 #undef DECLARE_LIST_ANY_2
 #undef DECLARE_LIST_ANY_VA
 #undef DECLARE_LIST_ANY_VA_2
@@ -327,9 +349,6 @@
 #undef DECLARE_LIST_INSERT
 #undef DECLARE_LIST_REMOVE
 
-void* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
-void* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
-
 #endif
 
 /* re-enable warnings */
diff --git a/drivers/staging/imgtec/rogue/lock.h b/drivers/staging/imgtec/rogue/lock.h
index fb01469..74a4136 100644
--- a/drivers/staging/imgtec/rogue/lock.h
+++ b/drivers/staging/imgtec/rogue/lock.h
@@ -71,23 +71,23 @@
 #define OSLockAcquireNested(hLock, subclass) ({mutex_lock_nested((hLock), (subclass)); PVRSRV_OK;})
 #define OSLockRelease(hLock) ({mutex_unlock((hLock)); PVRSRV_OK;})
 
-#define OSLockIsLocked(hLock) ({IMG_BOOL b = ((mutex_is_locked((hLock)) == 1) ? IMG_TRUE : IMG_FALSE); b;})
-#define OSTryLockAcquire(hLock) ({IMG_BOOL b = ((mutex_trylock(hLock) == 1) ? IMG_TRUE : IMG_FALSE); b;})
+#define OSLockIsLocked(hLock) ((mutex_is_locked((hLock)) == 1) ? IMG_TRUE : IMG_FALSE)
+#define OSTryLockAcquire(hLock) ((mutex_trylock(hLock) == 1) ? IMG_TRUE : IMG_FALSE)
 
 /* These _may_ be reordered or optimized away entirely by the compiler/hw */
-#define OSAtomicRead(pCounter)	({IMG_INT rv = atomic_read(pCounter); rv;})
-#define OSAtomicWrite(pCounter, i)	({ atomic_set(pCounter, i); })
+#define OSAtomicRead(pCounter)	atomic_read(pCounter)
+#define OSAtomicWrite(pCounter, i)	atomic_set(pCounter, i)
 
 /* The following atomic operations, in addition to being SMP-safe, also
    imply a memory barrier around the operation  */
-#define OSAtomicIncrement(pCounter)	({IMG_INT rv = atomic_inc_return(pCounter); rv;})
-#define OSAtomicDecrement(pCounter) ({IMG_INT rv = atomic_dec_return(pCounter); rv;})
-#define OSAtomicCompareExchange(pCounter, oldv, newv) ({IMG_INT rv = atomic_cmpxchg(pCounter,oldv,newv); rv;})
+#define OSAtomicIncrement(pCounter) atomic_inc_return(pCounter)
+#define OSAtomicDecrement(pCounter) atomic_dec_return(pCounter)
+#define OSAtomicCompareExchange(pCounter, oldv, newv) atomic_cmpxchg(pCounter,oldv,newv)
 
-#define OSAtomicAdd(pCounter, incr) ({IMG_INT rv = atomic_add_return(incr,pCounter); rv;})
-#define OSAtomicAddUnless(pCounter, incr, test) ({IMG_INT rv = __atomic_add_unless(pCounter,incr,test); rv;})
+#define OSAtomicAdd(pCounter, incr) atomic_add_return(incr,pCounter)
+#define OSAtomicAddUnless(pCounter, incr, test) __atomic_add_unless(pCounter,incr,test)
 
-#define OSAtomicSubtract(pCounter, incr) ({IMG_INT rv = atomic_add_return(-(incr),pCounter); rv;})
+#define OSAtomicSubtract(pCounter, incr) atomic_add_return(-(incr),pCounter)
 #define OSAtomicSubtractUnless(pCounter, incr, test) OSAtomicAddUnless(pCounter, -(incr), test)
 
 #else /* defined(LINUX) && defined(__KERNEL__) */
@@ -95,35 +95,96 @@
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
+/**************************************************************************/ /*!
+@Function       OSLockCreate
+@Description    Creates an operating system lock object.
+@Output         phLock           The created lock.
+@Input          eLockType        The type of lock required. This may be:
+                                 LOCK_TYPE_PASSIVE - the lock will not be used
+                                 in interrupt context or
+                                 LOCK_TYPE_DISPATCH - the lock may be used
+                                 in interrupt context.
+@Return         PVRSRV_OK on success. PVRSRV_ERROR_OUT_OF_MEMORY if the driver
+                cannot allocate CPU memory needed for the lock.
+                PVRSRV_ERROR_INIT_FAILURE if the Operating System fails to
+                allocate the lock.
+ */ /**************************************************************************/
 IMG_INTERNAL
 PVRSRV_ERROR OSLockCreate(POS_LOCK *phLock, LOCK_TYPE eLockType);
+#if defined(INTEGRITY_OS)
+#define OSLockCreateNoStats OSLockCreate
+#endif
 
+/**************************************************************************/ /*!
+@Function       OSLockDestroy
+@Description    Destroys an operating system lock object.
+@Input          hLock            The lock to be destroyed.
+@Return         None.
+ */ /**************************************************************************/
 IMG_INTERNAL
-void OSLockDestroy(POS_LOCK hLock);
+PVRSRV_ERROR OSLockDestroy(POS_LOCK hLock);
 
+#if defined(INTEGRITY_OS)
+#define OSLockDestroyNoStats OSLockDestroy
+#endif
+/**************************************************************************/ /*!
+@Function       OSLockAcquire
+@Description    Acquires an operating system lock.
+                NB. This function must not return until the lock is acquired
+                (meaning the implementation should not timeout or return with
+                an error, as the caller will assume they have the lock).
+@Input          hLock            The lock to be acquired.
+@Return         None.
+ */ /**************************************************************************/
 IMG_INTERNAL
 void OSLockAcquire(POS_LOCK hLock);
 
 /* Nested notation isn't used in UM or other OS's */
+/**************************************************************************/ /*!
+@Function       OSLockAcquireNested
+@Description    For operating systems other than Linux, this equates to an
+                OSLockAcquire() call. On Linux, this function wraps a call
+                to mutex_lock_nested(). This recognises the scenario where
+                there may be multiple subclasses within a particular class
+                of lock. In such cases, the order in which the locks belonging
+                these various subclasses are acquired is important and must be
+                validated.
+@Input          hLock            The lock to be acquired.
+@Input          subclass         The subclass of the lock.
+@Return         None.
+ */ /**************************************************************************/
 #define OSLockAcquireNested(hLock, subclass) OSLockAcquire((hLock))
 
+/**************************************************************************/ /*!
+@Function       OSLockRelease
+@Description    Releases an operating system lock.
+@Input          hLock            The lock to be released.
+@Return         None.
+ */ /**************************************************************************/
 IMG_INTERNAL
 void OSLockRelease(POS_LOCK hLock);
 
+/**************************************************************************/ /*!
+@Function       OSLockIsLocked
+@Description    Tests whether or not an operating system lock is currently
+                locked.
+@Input          hLock            The lock to be tested.
+@Return         IMG_TRUE if locked, IMG_FALSE if not locked.
+ */ /**************************************************************************/
 IMG_INTERNAL
 IMG_BOOL OSLockIsLocked(POS_LOCK hLock);
 
 #if defined(LINUX)
 
 /* Use GCC intrinsics (read/write semantics consistent with kernel-side implementation) */
-#define OSAtomicRead(pCounter) ({IMG_INT rv =  *(volatile int *)&(pCounter)->counter; rv;}) 
-#define OSAtomicWrite(pCounter, i) ({(pCounter)->counter = (IMG_INT) i;}) 
-#define OSAtomicIncrement(pCounter) ({IMG_INT rv = __sync_add_and_fetch((&(pCounter)->counter), 1); rv;}) 
-#define OSAtomicDecrement(pCounter) ({IMG_INT rv = __sync_sub_and_fetch((&(pCounter)->counter), 1); rv;}) 
-#define OSAtomicCompareExchange(pCounter, oldv, newv)  \
-	({IMG_INT rv = __sync_val_compare_and_swap((&(pCounter)->counter), oldv, newv); rv;})
-	
-#define OSAtomicAdd(pCounter, incr) ({IMG_INT rv = __sync_add_and_fetch((&(pCounter)->counter), incr); rv;}) 
+#define OSAtomicRead(pCounter) (*(volatile int *)&(pCounter)->counter)
+#define OSAtomicWrite(pCounter, i) ((pCounter)->counter = (IMG_INT) i)
+#define OSAtomicIncrement(pCounter) __sync_add_and_fetch((&(pCounter)->counter), 1)
+#define OSAtomicDecrement(pCounter) __sync_sub_and_fetch((&(pCounter)->counter), 1)
+#define OSAtomicCompareExchange(pCounter, oldv, newv) \
+	__sync_val_compare_and_swap((&(pCounter)->counter), oldv, newv)
+
+#define OSAtomicAdd(pCounter, incr) __sync_add_and_fetch((&(pCounter)->counter), incr)
 #define OSAtomicAddUnless(pCounter, incr, test) ({ \
 	int c; int old; \
 	c = OSAtomicRead(pCounter); \
@@ -134,38 +195,136 @@
 		c = old; \
 	} c; })
 
-#define OSAtomicSubtract(pCounter, incr) OSAtomicAdd(pCounter, -(incr))	
+#define OSAtomicSubtract(pCounter, incr) OSAtomicAdd(pCounter, -(incr))
 #define OSAtomicSubtractUnless(pCounter, incr, test) OSAtomicAddUnless(pCounter, -(incr), test)
 
 #else
 
 /* These _may_ be reordered or optimized away entirely by the compiler/hw */
+/*************************************************************************/ /*!
+@Function       OSAtomicRead
+@Description    Read the value of a variable atomically.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to read
+@Return         The value of the atomic variable
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicRead(ATOMIC_T *pCounter);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicWrite
+@Description    Write the value of a variable atomically.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to be written to
+@Input          v               The value to write
+@Return         None
+*/ /**************************************************************************/
 IMG_INTERNAL
 void OSAtomicWrite(ATOMIC_T *pCounter, IMG_INT v);
 
 /* For the following atomic operations, in addition to being SMP-safe, 
    should also  have a memory barrier around each operation  */
+/*************************************************************************/ /*!
+@Function       OSAtomicIncrement
+@Description    Increment the value of a variable atomically.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to be incremented
+@Return         The new value of *pCounter.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicIncrement(ATOMIC_T *pCounter);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicDecrement
+@Description    Decrement the value of a variable atomically.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to be decremented
+@Return         The new value of *pCounter.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicDecrement(ATOMIC_T *pCounter);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicAdd
+@Description    Add a specified value to a variable atomically.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to add the value to
+@Input          v               The value to be added
+@Return         The new value of *pCounter.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicAdd(ATOMIC_T *pCounter, IMG_INT v);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicAddUnless
+@Description    Add a specified value to a variable atomically unless it
+                already equals a particular value.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to add the value to
+@Input          v               The value to be added to 'pCounter'
+@Input          t               The test value. If 'pCounter' equals this,
+                                its value will not be adjusted
+@Return         The new value of *pCounter.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicAddUnless(ATOMIC_T *pCounter, IMG_INT v, IMG_INT t);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicSubtract
+@Description    Subtract a specified value to a variable atomically.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to subtract the value from
+@Input          v               The value to be subtracted
+@Return         The new value of *pCounter.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicSubtract(ATOMIC_T *pCounter, IMG_INT v);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicSubtractUnless
+@Description    Subtract a specified value from a variable atomically unless
+                it already equals a particular value.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to subtract the value from
+@Input          v               The value to be subtracted from 'pCounter'
+@Input          t               The test value. If 'pCounter' equals this,
+                                its value will not be adjusted
+@Return         The new value of *pCounter.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicSubtractUnless(ATOMIC_T *pCounter, IMG_INT v, IMG_INT t);
 
+/*************************************************************************/ /*!
+@Function       OSAtomicCompareExchange
+@Description    Set a variable to a given value only if it is currently
+                equal to a specified value. The whole operation must be atomic.
+                Atomic functions must be implemented in a manner that
+                is both symmetric multiprocessor (SMP) safe and has a memory
+                barrier around each operation.
+@Input          pCounter        The atomic variable to be checked and
+                                possibly updated
+@Input          oldv            The value the atomic variable must have in
+                                order to be modified
+@Input          newv            The value to write to the atomic variable if
+                                it equals 'oldv'
+@Return         The value of *pCounter after the function.
+*/ /**************************************************************************/
 IMG_INTERNAL
 IMG_INT OSAtomicCompareExchange(ATOMIC_T *pCounter, IMG_INT oldv, IMG_INT newv);
 
diff --git a/drivers/staging/imgtec/rogue/lock_types.h b/drivers/staging/imgtec/rogue/lock_types.h
index d1947bd..1162737 100644
--- a/drivers/staging/imgtec/rogue/lock_types.h
+++ b/drivers/staging/imgtec/rogue/lock_types.h
@@ -69,6 +69,9 @@
 	 * still have to be shared. This is one such case.
 	 */
 	typedef struct _OS_ATOMIC {IMG_INT counter;} ATOMIC_T;
+#elif defined(INTEGRITY_OS)
+	/*Fixed size data type to hold the largest value*/
+	typedef struct _OS_ATOMIC {IMG_UINT64 counter;} ATOMIC_T;
 #else
 	#error "Please type-define an atomic lock for this environment"
 #endif
diff --git a/drivers/staging/imgtec/rogue/log2.h b/drivers/staging/imgtec/rogue/log2.h
index 1b46a41..fd575bc 100644
--- a/drivers/staging/imgtec/rogue/log2.h
+++ b/drivers/staging/imgtec/rogue/log2.h
@@ -192,10 +192,10 @@
 		{ 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
 	uint32_t r = (n & b[0]) != 0;
 
-	r |= ((n & b[4]) != 0) << 4;
-	r |= ((n & b[3]) != 0) << 3;
-	r |= ((n & b[2]) != 0) << 2;
-	r |= ((n & b[1]) != 0) << 1;
+	r |= (uint32_t) ((n & b[4]) != 0) << 4;
+	r |= (uint32_t) ((n & b[3]) != 0) << 3;
+	r |= (uint32_t) ((n & b[2]) != 0) << 2;
+	r |= (uint32_t) ((n & b[1]) != 0) << 1;
 
 	return r;
 }
@@ -213,11 +213,11 @@
 		  0xFFFF0000FFFF0000ULL, 0xFFFFFFFF00000000ULL };
 	uint32_t r = (n & b[0]) != 0;
 
-	r |= ((n & b[5]) != 0) << 5;
-	r |= ((n & b[4]) != 0) << 4;
-	r |= ((n & b[3]) != 0) << 3;
-	r |= ((n & b[2]) != 0) << 2;
-	r |= ((n & b[1]) != 0) << 1;
+	r |= (uint32_t) ((n & b[5]) != 0) << 5;
+	r |= (uint32_t) ((n & b[4]) != 0) << 4;
+	r |= (uint32_t) ((n & b[3]) != 0) << 3;
+	r |= (uint32_t) ((n & b[2]) != 0) << 2;
+	r |= (uint32_t) ((n & b[1]) != 0) << 1;
 
 	return r;
 }
diff --git a/drivers/staging/imgtec/rogue/main.c b/drivers/staging/imgtec/rogue/main.c
index a9f96ff..9eae72d 100644
--- a/drivers/staging/imgtec/rogue/main.c
+++ b/drivers/staging/imgtec/rogue/main.c
@@ -48,21 +48,8 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/vmalloc.h>
-#include <linux/version.h>
-
-#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRM)
-#include <linux/platform_device.h>
-#endif
-
-#if defined(LDM_PCI) && !defined(SUPPORT_DRM)
-#include <linux/pci.h>
-#endif
-
 #include <asm/uaccess.h>
-
-#if defined(SUPPORT_DRM)
 #include <drm/drmP.h>
-#endif
 
 #include "img_types.h"
 #include "linuxsrv.h"
@@ -73,50 +60,8 @@
 #include "pvr_debug.h"
 #include "pvrmodule.h"
 #include "pvr_uaccess.h"
-
-#if defined(SUPPORT_DRM)
-
-#include "pvr_drm_shared.h"
 #include "pvr_drm.h"
-
-#else /* defined(SUPPORT_DRM) */
-
-#define DRVNAME "dbgdrv"
-MODULE_SUPPORTED_DEVICE(DRVNAME);
-
-static struct class *psDbgDrvClass;
-
-static int AssignedMajorNumber = 0;
-
-long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
-long dbgdrv_ioctl_compat(struct file *, unsigned int, unsigned long);
-
-static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
-{
-	return 0;
-}
-
-static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
-{
-	return 0;
-}
-
-static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
-{
-	return 0;
-}
-
-static struct file_operations dbgdrv_fops =
-{
-	.owner          = THIS_MODULE,
-	.unlocked_ioctl = dbgdrv_ioctl,
-	.compat_ioctl   = dbgdrv_ioctl_compat,
-	.open           = dbgdrv_open,
-	.release        = dbgdrv_release,
-	.mmap           = dbgdrv_mmap,
-};
-
-#endif  /* defined(SUPPORT_DRM) */
+#include "pvr_drv.h"
 
 /* Outward temp buffer used by IOCTL handler allocated once and grows as needed.
  * This optimisation means the debug driver performs less vmallocs/vfrees
@@ -138,11 +83,7 @@
 	*fn_table = &g_sDBGKMServices;
 }
 
-#if defined(SUPPORT_DRM)
 void dbgdrv_cleanup(void)
-#else
-void cleanup_module(void)
-#endif
 {
 	if (g_outTmpBuf)
 	{
@@ -150,11 +91,6 @@
 		g_outTmpBuf = NULL;
 	}
 
-#if !defined(SUPPORT_DRM)
-	device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
-	class_destroy(psDbgDrvClass);
-	unregister_chrdev(AssignedMajorNumber, DRVNAME);
-#endif /* !defined(SUPPORT_DRM) */
 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
 	HostDestroyEventObjects();
 #endif
@@ -163,20 +99,8 @@
 	return;
 }
 
-#if defined(SUPPORT_DRM)
 IMG_INT dbgdrv_init(void)
-#else
-int init_module(void)
-#endif
 {
-#if !defined(SUPPORT_DRM)
-	struct device *psDev;
-#endif
-
-#if !defined(SUPPORT_DRM)
-	int err = -EBUSY;
-#endif
-
 	/* Init API mutex */
 	if ((g_pvAPIMutex=HostCreateMutex()) == NULL)
 	{
@@ -197,60 +121,24 @@
 	(void) HostCreateEventObjects();
 #endif
 
-#if !defined(SUPPORT_DRM)
-	AssignedMajorNumber =
-		register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
-
-	if (AssignedMajorNumber <= 0)
-	{
-		PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
-		goto ErrDestroyEventObjects;
-	}
-
-	/*
-	 * This code (using GPL symbols) facilitates automatic device
-	 * node creation on platforms with udev (or similar).
-	 */
-	psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
-	if (IS_ERR(psDbgDrvClass))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
-				 __func__, PTR_ERR(psDbgDrvClass)));
-		goto ErrUnregisterCharDev;
-	}
-
-	psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0), NULL, DRVNAME);
-	if (IS_ERR(psDev))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
-								__func__, PTR_ERR(psDev)));
-		goto ErrDestroyClass;
-	}
-#endif /* !defined(SUPPORT_DRM) */
-
 	return 0;
-
-#if !defined(SUPPORT_DRM)
-ErrDestroyEventObjects:
-#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
-	HostDestroyEventObjects();
-#endif
-ErrUnregisterCharDev:
-	unregister_chrdev(AssignedMajorNumber, DRVNAME);
-ErrDestroyClass:
-	class_destroy(psDbgDrvClass);
-	return err;
-#endif /* !defined(SUPPORT_DRM) */
 }
 
 static IMG_INT dbgdrv_ioctl_work(void *arg, IMG_BOOL bCompat)
 {
-	IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+	struct drm_pvr_dbgdrv_cmd *psDbgdrvCmd = (struct drm_pvr_dbgdrv_cmd *) arg;
 	char *buffer, *in, *out;
 	unsigned int cmd;
 	void *pBufferIn, *pBufferOut;
 
-	if ((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+	if (psDbgdrvCmd->pad)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Invalid pad value\n"));
+		return -EINVAL;
+	}
+
+	if ((psDbgdrvCmd->in_data_size > (PAGE_SIZE >> 1)) ||
+		(psDbgdrvCmd->out_data_size > (PAGE_SIZE >> 1)))
 	{
 		PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
 		return -1;
@@ -266,18 +154,18 @@
 	in = buffer;
 	out = buffer + (PAGE_SIZE >>1);
 
-	pBufferIn = WIDEPTR_GET_PTR(pIP->pInBuffer, bCompat);
-	pBufferOut = WIDEPTR_GET_PTR(pIP->pOutBuffer, bCompat);
+	pBufferIn = (void *)(uintptr_t) psDbgdrvCmd->in_data_ptr;
+	pBufferOut = (void *)(uintptr_t) psDbgdrvCmd->out_data_ptr;
 
-	if (pvr_copy_from_user(in, pBufferIn, pIP->ui32InBufferSize) != 0)
+	if (pvr_copy_from_user(in, pBufferIn, psDbgdrvCmd->in_data_size) != 0)
 	{
 		goto init_failed;
 	}
 
 	/* Extra -1 because ioctls start at DEBUG_SERVICE_IOCTL_BASE + 1 */
-	cmd = MAKEIOCTLINDEX(pIP->ui32Cmd) - DEBUG_SERVICE_IOCTL_BASE - 1;
+	cmd = MAKEIOCTLINDEX(psDbgdrvCmd->cmd) - DEBUG_SERVICE_IOCTL_BASE - 1;
 
-	if (pIP->ui32Cmd == DEBUG_SERVICE_READ)
+	if (psDbgdrvCmd->cmd == DEBUG_SERVICE_READ)
 	{
 		IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
 		DBG_OUT_READ *psReadOutParams = (DBG_OUT_READ *)out;
@@ -337,7 +225,7 @@
 		(g_DBGDrivProc[cmd])(in, out, bCompat);
 	}
 
-	if (copy_to_user(pBufferOut, out, pIP->ui32OutBufferSize) != 0)
+	if (copy_to_user(pBufferOut, out, psDbgdrvCmd->out_data_size) != 0)
 	{
 		goto init_failed;
 	}
@@ -350,20 +238,12 @@
 	return -EFAULT;
 }
 
-#if defined(SUPPORT_DRM)
 int dbgdrv_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
-#else
-long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
-#endif
 {
 	return dbgdrv_ioctl_work((void *) arg, IMG_FALSE);
 }
 
-#if defined(SUPPORT_DRM)
-int dbgdrv_ioctl_compat(struct drm_device *dev, void *arg, struct drm_file *pFile)
-#else
-long dbgdrv_ioctl_compat(struct file *file, unsigned int ioctlCmd, unsigned long arg)
-#endif
+int dbgdrv_ioctl_compat(struct file *file, unsigned int ioctlCmd, unsigned long arg)
 {
 	return dbgdrv_ioctl_work((void *) arg, IMG_TRUE);
 }
diff --git a/drivers/staging/imgtec/rogue/mem_utils.c b/drivers/staging/imgtec/rogue/mem_utils.c
index 25cad79..1722695 100644
--- a/drivers/staging/imgtec/rogue/mem_utils.c
+++ b/drivers/staging/imgtec/rogue/mem_utils.c
@@ -41,35 +41,34 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-
-#if defined(__KERNEL__)
-#include "osfunc.h"
-#include <linux/string.h>
-#include <linux/version.h>
-#else
-#include "services.h"
-#include <string.h>
-#endif
-
-#if (defined(__arm64__) || defined(__aarch64__) || defined (PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)) && !defined(__QNXNTO__)
-
-/*
- * Make sure that a working kernel is used when compiling for ARM32 because memset() plus
- * some compiler optimisations can lead to undefined behaviour.
+/* This workaround is only *required* on ARM64. Avoid building or including
+ * it by default on other architectures, unless the 'safe memcpy' test flag
+ * is enabled. (The code should work on other architectures.)
  */
-#if defined(__KERNEL__)
-#if defined(LINUX) && defined(CONFIG_ARM) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
-#error "PVRSRVDeviceMemSet() not usable with kernel versions < 3.9, check build config"
-#endif
-#endif
 
-#define ZERO_BUF_SIZE 1024
+#if defined(__arm64__) || defined(__aarch64__) || defined (PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)
 
+/* NOTE: This C file is compiled with -ffreestanding to avoid pattern matching
+ *       by the compiler to stdlib functions, and it must only use the below
+ *       headers. Do not include any IMG or services headers in this file.
+ */
+#include <stddef.h>
+
+/* Prototypes to suppress warnings in -ffreestanding mode */
+void DeviceMemCopy(void *pvDst, const void *pvSrc, size_t uSize);
+void DeviceMemSet(void *pvDst, unsigned char ui8Value, size_t uSize);
+
+/* This file is only intended to be used on platforms which use GCC or Clang,
+ * due to its requirement on __attribute__((vector_size(n))), typeof() and
+ * __SIZEOF__ macros.
+ */
 #if defined(__GNUC__)
+
+#define MIN(a, b) \
+ ({__typeof(a) _a = (a); __typeof(b) _b = (b); _a > _b ? _b : _a;})
+
 #if !defined(DEVICE_MEMSETCPY_ALIGN_IN_BYTES)
-/* In case build system doesn't define below constant define it here to
- * avoid build failure. */
-#define DEVICE_MEMSETCPY_ALIGN_IN_BYTES 8 // by default align to 8 bytes
+#define DEVICE_MEMSETCPY_ALIGN_IN_BYTES __SIZEOF_LONG__
 #endif
 #if DEVICE_MEMSETCPY_ALIGN_IN_BYTES % 2 != 0
 #error "DEVICE_MEMSETCPY_ALIGN_IN_BYTES must be a power of 2"
@@ -77,203 +76,238 @@
 #if DEVICE_MEMSETCPY_ALIGN_IN_BYTES < 4
 #error "DEVICE_MEMSETCPY_ALIGN_IN_BYTES must be equal or greater than 4"
 #endif
-#define PVRSRV_MEM_ALIGN __attribute__ ((aligned (DEVICE_MEMSETCPY_ALIGN_IN_BYTES)))
-#define PVRSRV_MEM_XBIT_ALIGN_MASK (DEVICE_MEMSETCPY_ALIGN_IN_BYTES - 1)
-#define PVRSRV_MEM_32BIT_ALIGN_MASK (0x3)
-#else
-#error "PVRSRV Alignment macros need to be defined for this compiler"
+
+#if __SIZEOF_POINTER__ != __SIZEOF_LONG__
+#error No support for architectures where void* and long are sized differently
 #endif
 
-/******************************************************************************
- Function Name      : OSDeviceMemCopy / PVRSRVDeviceMemCopy
- Inputs             : pvDst - pointer to the destination memory region
-                      pvSrc - pointer to the source memory region
-                      uiSize - size of the memory region that will be copied
- Outputs            :
- Returns            :
- Description        : This is a counterpart of standard memcpy function for
-                      uncached memory. The reason for this function is that
-                      when uncached memory is used and the pointers are not
-                      64-bit aligned on Aarch64 architecture a memory
-                      exception will be thrown. This applies both to user and
-                      kernel space.
-******************************************************************************/
-IMG_EXPORT void PVRSRVDeviceMemCopy(
-        void* pvDst,
-        const void* pvSrc,
-        size_t uiSize)
+#if   __SIZEOF_LONG__ >  DEVICE_MEMSETCPY_ALIGN_IN_BYTES
+/* Meaningless, and harder to do correctly */
+# error Cannot handle DEVICE_MEMSETCPY_ALIGN_IN_BYTES < sizeof(long)
+typedef unsigned long block_t;
+#elif __SIZEOF_LONG__ <= DEVICE_MEMSETCPY_ALIGN_IN_BYTES
+typedef unsigned int block_t
+	__attribute__((vector_size(DEVICE_MEMSETCPY_ALIGN_IN_BYTES)));
+# if defined(__arm64__) || defined(__aarch64__)
+#  if   DEVICE_MEMSETCPY_ALIGN_IN_BYTES == 8
+#   define DEVICE_MEMSETCPY_ARM64
+#   define REGSZ "w"
+#   define REGCL "w"
+#   define BVCLB "r"
+#  elif DEVICE_MEMSETCPY_ALIGN_IN_BYTES == 16
+#   define DEVICE_MEMSETCPY_ARM64
+#   define REGSZ "x"
+#   define REGCL "x"
+#   define BVCLB "r"
+#  elif DEVICE_MEMSETCPY_ALIGN_IN_BYTES == 32
+#   if defined(__ARM_NEON_FP)
+#    define DEVICE_MEMSETCPY_ARM64
+#    define REGSZ "q"
+#    define REGCL "v"
+#    define BVCLB "w"
+#   endif
+#  endif
+#  if defined(DEVICE_MEMSETCPY_ARM64)
+#   if defined(DEVICE_MEMSETCPY_ARM64_NON_TEMPORAL)
+#    define NSHLD() __asm__ ("dmb nshld")
+#    define NSHST() __asm__ ("dmb nshst")
+#    define LDP "ldnp"
+#    define STP "stnp"
+#   else
+#    define NSHLD()
+#    define NSHST()
+#    define LDP "ldp"
+#    define STP "stp"
+#   endif
+ typedef unsigned int block_half_t
+	__attribute__((vector_size(DEVICE_MEMSETCPY_ALIGN_IN_BYTES / 2)));
+#  endif
+# endif
+#endif
+
+__attribute__((visibility("hidden")))
+void DeviceMemCopy(void *pvDst, const void *pvSrc, size_t uSize)
 {
-	/* Use volatile to avoid compiler optimisations */
-	volatile IMG_BYTE * pbySrc = (IMG_BYTE*)pvSrc;
-	volatile IMG_BYTE * pbyDst = (IMG_BYTE*)pvDst;
-	size_t uiTailSize = uiSize;
+	volatile const char *pcSrc = pvSrc;
+	volatile char *pcDst = pvDst;
+	size_t uPreambleBytes;
+	int bBlockCopy = 0;
 
-	/* If both pointers have same alignment we can optimise. */
-	if (((uintptr_t)pbySrc & PVRSRV_MEM_XBIT_ALIGN_MASK)
-	        == ((uintptr_t)pbyDst & PVRSRV_MEM_XBIT_ALIGN_MASK))
+	size_t uSrcUnaligned = (size_t)pcSrc % sizeof(block_t);
+	size_t uDstUnaligned = (size_t)pcDst % sizeof(block_t);
+
+	if (!uSrcUnaligned && !uDstUnaligned)
 	{
-		size_t uiAlignedSize;
-		IMG_UINT uiHeadSize;
-
-		uiHeadSize = (sizeof(void *)
-		        - ((uintptr_t)pbySrc & PVRSRV_MEM_XBIT_ALIGN_MASK))
-		        & PVRSRV_MEM_XBIT_ALIGN_MASK;
-
-		/* For 64bit aligned pointers we will almost always (not if uiSize is 0)
-		 * go in and use memcpy if the size is large enough. For other aligned
-		 * pointers if size is large enough we will copy first few bytes to
-		 * align those pointers to 64bit then use memcpy and after that copy
-		 * remaining bytes.
-		 * If uiSize is less then uiHeadSize we will skip to byte-by-byte
-		 * copy since we can't use memcpy in such case. */
-		if (uiSize > uiHeadSize)
-		{
-			uiSize -= uiHeadSize;
-			uiTailSize = uiSize & PVRSRV_MEM_XBIT_ALIGN_MASK;
-			uiAlignedSize = uiSize - uiTailSize;
-
-			/* Copy few leading bytes to align pointer to 64bit boundary. */
-			while (uiHeadSize--)
-			{
-				*pbyDst++ = *pbySrc++;
-			}
-
-			/* here pointers are already 64bit aligned so we can use memcpy. */
-			memcpy((void*)pbyDst, (void*)pbySrc, uiAlignedSize);
-
-			/* skip over copied data */
-			pbyDst += uiAlignedSize;
-			pbySrc += uiAlignedSize;
-		}
+		/* Neither pointer is unaligned. Optimal case. */
+		bBlockCopy = 1;
 	}
-	/* If pointers are 32bit aligned but not aligned in relation to each
-	 * other.*/
-	else if ((((uintptr_t)pbySrc | (uintptr_t)pbyDst)
-	        & PVRSRV_MEM_32BIT_ALIGN_MASK) == 0)
-	{
-		volatile IMG_UINT32 * pui32Src = (IMG_UINT32*)pbySrc;
-		volatile IMG_UINT32 * pui32Dst = (IMG_UINT32*)pbyDst;
-		size_t uiAlignedSize;
-
-		uiTailSize = uiSize & PVRSRV_MEM_32BIT_ALIGN_MASK;
-		uiAlignedSize = uiSize - uiTailSize;
-
-		/* do the 4 byte copy */
-		uiSize = uiSize >> 2;
-		while (uiSize--)
-		{
-			*pui32Dst++ = *pui32Src++;
-		}
-
-		pbyDst += uiAlignedSize;
-		pbySrc += uiAlignedSize;
-	}
-
-	/* Copy either remaining memory if optimisation was performed but
-	 * size was not aligned or all memory if we need to. */
-	while (uiTailSize--)
-	{
-		*pbyDst++ = *pbySrc++;
-	}
-
-}
-
-/******************************************************************************
- Function Name      : OSDeviceMemSet / PVRSRVDeviceMemSet
- Inputs             : pvDest - pointer to destination memory
-                      ui8Value - the 'set' value
-                      uiSize - size of the memory block
- Outputs            :
- Returns            :
- Description        : This is a counterpart of standard memset function for
-                      uncached memory. The reason for this function is that
-                      when uncached memory is used and the pointer is not
-                      64-bit aligned on Aarch64 architecture an memory
-                      exception will be thrown. This applies both to user and
-                      kernel space.
-******************************************************************************/
-IMG_EXPORT void PVRSRVDeviceMemSet(
-        void *pvDest,
-        IMG_UINT8 ui8Value,
-        size_t uiSize)
-{
-	/* Use volatile to avoid compiler optimisations */
-	volatile IMG_BYTE * pbyDst = (IMG_BYTE*)pvDest;
-	static IMG_BYTE gZeroBuf[ZERO_BUF_SIZE] PVRSRV_MEM_ALIGN = { 0 };
-
-	/* Run workaround if one of the address or size is not aligned, or
-	 * we are zeroing */
-	if ((ui8Value == 0) || ((((size_t)pbyDst | uiSize) & PVRSRV_MEM_XBIT_ALIGN_MASK) != 0))
-	{
-		IMG_UINT32 uiTailSize;
-
-		/* Buffer address unaligned */
-		if ((size_t)pbyDst & PVRSRV_MEM_XBIT_ALIGN_MASK)
-		{
-			/* Increment the buffer pointer */
-			for (; uiSize > 0 && ((size_t)pbyDst & PVRSRV_MEM_XBIT_ALIGN_MASK); uiSize--)
-			{
-				*pbyDst++ = ui8Value;
-			}
-			/* Did loop stop because size is zero? */
-			if (uiSize == 0) return;
-		}
-
-		/* Set the remaining part of the buffer */
-		if (ui8Value)
-		{
-			/* Non-zero set */
-			uiTailSize = (uiSize & PVRSRV_MEM_XBIT_ALIGN_MASK);
-
-			memset((void*) pbyDst, (IMG_INT) ui8Value, (size_t) uiSize-uiTailSize);
-			pbyDst += uiSize-uiTailSize;
-		}
-		else
-		{
-			/* Zero set */
-			uiTailSize = (uiSize & PVRSRV_MEM_XBIT_ALIGN_MASK);
-			uiSize -= uiTailSize;
-
-			while (uiSize > 1024)
-			{
-				memcpy((void*) pbyDst, gZeroBuf, (size_t) ZERO_BUF_SIZE);
-				pbyDst +=ZERO_BUF_SIZE;
-				uiSize -= ZERO_BUF_SIZE;
-			}
-			memcpy((void*) pbyDst, gZeroBuf, (size_t) uiSize);
-			pbyDst += uiSize;
-		}
-
-		/* Handle any tail bytes, loop skipped in tail is 0 */
-		for (; uiTailSize > 0; uiTailSize--)
-		{
-			*pbyDst++ = ui8Value;
-		}
-	}
-	/* Alignment fine, non-zero set, no need to work around device memory
-	 * use with ARM64 libc */
 	else
 	{
-		memset(pvDest, (IMG_INT) ui8Value, (size_t) uiSize);
+		if (uSrcUnaligned == uDstUnaligned)
+		{
+			/* Neither pointer is usefully aligned, but they are misaligned in
+			 * the same way, so we can copy a preamble in a slow way, then
+			 * optimize the rest.
+			 */
+			uPreambleBytes = MIN(sizeof(block_t) - uDstUnaligned, uSize);
+			uSize -= uPreambleBytes;
+			while (uPreambleBytes)
+			{
+				*pcDst++ = *pcSrc++;
+				uPreambleBytes--;
+			}
+
+			bBlockCopy = 1;
+		}
+		else if ((uSrcUnaligned | uDstUnaligned) % sizeof(int) == 0)
+		{
+			/* Both pointers are at least 32-bit aligned, and we assume that
+			 * the processor must handle all kinds of 32-bit load-stores.
+			 * NOTE: Could we optimize this with a non-temporal version?
+			 */
+			if (uSize >= sizeof(int))
+			{
+				volatile int *piSrc = (int *)pcSrc;
+				volatile int *piDst = (int *)pcDst;
+
+				while (uSize >= sizeof(int))
+				{
+					*piDst++ = *piSrc++;
+					uSize -= sizeof(int);
+				}
+
+				pcSrc = (char *)piSrc;
+				pcDst = (char *)piDst;
+			}
+		}
+	}
+
+	if (bBlockCopy && uSize >= sizeof(block_t))
+	{
+		volatile block_t *pSrc = (block_t *)pcSrc;
+		volatile block_t *pDst = (block_t *)pcDst;
+
+		NSHLD();
+
+		while (uSize >= sizeof(block_t))
+		{
+#if defined(DEVICE_MEMSETCPY_ARM64)
+			__asm__ (LDP " " REGSZ "0, " REGSZ "1, [%[pSrc]]\n\t"
+			         STP " " REGSZ "0, " REGSZ "1, [%[pDst]]"
+						:
+						: [pSrc] "r" (pSrc), [pDst] "r" (pDst)
+						: "memory", REGCL "0", REGCL "1");
+#else
+			*pDst = *pSrc;
+#endif
+			pDst++;
+			pSrc++;
+			uSize -= sizeof(block_t);
+		}
+
+		NSHST();
+
+		pcSrc = (char *)pSrc;
+		pcDst = (char *)pDst;
+	}
+
+	while (uSize)
+	{
+		*pcDst++ = *pcSrc++;
+		uSize--;
 	}
 }
 
-#else /* (defined(__arm64__) || defined(__aarch64__) || defined (PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)) && !defined(__QNXNTO__) */
-
-IMG_EXPORT void PVRSRVDeviceMemCopy(
-        void*       pvDst,
-        const void* pvSrc,
-        size_t      uiSize)
+__attribute__((visibility("hidden")))
+void DeviceMemSet(void *pvDst, unsigned char ui8Value, size_t uSize)
 {
-	memcpy(pvDst, pvSrc, uiSize);
+	volatile char *pcDst = pvDst;
+	size_t uPreambleBytes;
+
+	size_t uDstUnaligned = (size_t)pcDst % sizeof(block_t);
+
+	if (uDstUnaligned)
+	{
+		uPreambleBytes = MIN(sizeof(block_t) - uDstUnaligned, uSize);
+		uSize -= uPreambleBytes;
+		while (uPreambleBytes)
+		{
+			*pcDst++ = ui8Value;
+			uPreambleBytes--;
+		}
+	}
+
+	if (uSize >= sizeof(block_t))
+	{
+		volatile block_t *pDst = (block_t *)pcDst;
+#if defined(DEVICE_MEMSETCPY_ARM64)
+		block_half_t bValue;
+#else
+		block_t bValue;
+# endif
+		size_t i;
+
+		for (i = 0; i < sizeof(bValue) / sizeof(unsigned int); i++)
+			bValue[i] = ui8Value << 24U |
+			            ui8Value << 16U |
+			            ui8Value <<  8U |
+			            ui8Value;
+
+		NSHLD();
+
+		while (uSize >= sizeof(block_t))
+		{
+#if defined(DEVICE_MEMSETCPY_ARM64)
+			__asm__ (STP " %" REGSZ "[bValue], %" REGSZ "[bValue], [%[pDst]]"
+						:
+						: [bValue] BVCLB (bValue), [pDst] "r" (pDst)
+						: "memory");
+#else
+			*pDst = bValue;
+#endif
+			pDst++;
+			uSize -= sizeof(block_t);
+		}
+
+		NSHST();
+
+		pcDst = (char *)pDst;
+	}
+
+	while (uSize)
+	{
+		*pcDst++ = ui8Value;
+		uSize--;
+	}
 }
 
-IMG_EXPORT void PVRSRVDeviceMemSet(
-        void *pvDest,
-        IMG_UINT8 ui8Value,
-        size_t uiSize)
+#else /* !defined(__GNUC__) */
+
+/* Potentially very slow (but safe) fallbacks for non-GNU C compilers */
+
+void DeviceMemCopy(void *pvDst, const void *pvSrc, size_t uSize)
 {
-	memset(pvDest, ui8Value, uiSize);
+	volatile const char *pcSrc = pvSrc;
+	volatile char *pcDst = pvDst;
+
+	while (uSize)
+	{
+		*pcDst++ = *pcSrc++;
+		uSize--;
+	}
 }
 
-#endif /* (defined(__arm64__) || defined(__aarch64__) || defined (PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY))) && !defined(__QNXNTO__) */
+void DeviceMemSet(void *pvDst, unsigned char ui8Value, size_t uSize)
+{
+	volatile char *pcDst = pvDst;
+
+	while (uSize)
+	{
+		*pcDst++ = ui8Value;
+		uSize--;
+	}
+}
+
+#endif /* !defined(__GNUC__) */
+
+#endif /* defined(__arm64__) || defined(__aarch64__) || defined (PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY) */
diff --git a/drivers/staging/imgtec/rogue/mm.c b/drivers/staging/imgtec/rogue/mm.c
deleted file mode 100644
index 5721567..0000000
--- a/drivers/staging/imgtec/rogue/mm.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Misc memory management utility functions for Linux
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include <asm/io.h>
-
-#include "img_defs.h"
-#include "pvr_debug.h"
-#include "mm.h"
-#include "pvrsrv_memallocflags.h"
-#include "devicemem_server_utils.h"
-
-#include <linux/version.h>
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0))
- #if defined(CONFIG_ARM)
-  #define ioremap_cache(x,y) ioremap_cached(x,y)
- #endif
-#endif
-
-void *
-_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
-               IMG_UINT32 ui32Bytes,
-               IMG_UINT32 ui32MappingFlags,
-               IMG_CHAR *pszFileName,
-               IMG_UINT32 ui32Line)
-{
-	void *pvIORemapCookie;
-	IMG_UINT32 ui32CPUCacheMode = DevmemCPUCacheMode(ui32MappingFlags);
-
-	switch (ui32CPUCacheMode)
-	{
-		case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
-				pvIORemapCookie = (void *)ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
-				break;
-		case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
-#if defined(CONFIG_X86) || defined(CONFIG_ARM) || defined(CONFIG_ARM64)
-				pvIORemapCookie = (void *)ioremap_wc(BasePAddr.uiAddr, ui32Bytes);
-#else
-				pvIORemapCookie = (void *)ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
-#endif
-				break;
-		case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
-#if defined(CONFIG_X86) || defined(CONFIG_ARM)
-				pvIORemapCookie = (void *)ioremap_cache(BasePAddr.uiAddr, ui32Bytes);
-#else
-				pvIORemapCookie = (void *)ioremap(BasePAddr.uiAddr, ui32Bytes);
-#endif
-				break;
-		default:
-				return NULL;
-				break;
-	}
-
-    PVR_UNREFERENCED_PARAMETER(pszFileName);
-    PVR_UNREFERENCED_PARAMETER(ui32Line);
-
-    return pvIORemapCookie;
-}
-
-
-void
-_IOUnmapWrapper(void *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
-{
-    PVR_UNREFERENCED_PARAMETER(pszFileName);
-    PVR_UNREFERENCED_PARAMETER(ui32Line);
-
-    iounmap(pvIORemapCookie);
-}
diff --git a/drivers/staging/imgtec/rogue/mm.h b/drivers/staging/imgtec/rogue/mm.h
deleted file mode 100644
index e8a4447..0000000
--- a/drivers/staging/imgtec/rogue/mm.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Declares various memory management utility functions for Linux.
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#ifndef __IMG_LINUX_MM_H__
-#define __IMG_LINUX_MM_H__
-
-#include <asm/io.h>
-/*!
- *******************************************************************************
- * @brief Reserve physical IO memory and create a CPU virtual mapping for it
- *
- * @param BasePAddr 
- * @param ui32Bytes  
- * @param ui32MappingFlags  
- *
- * @return 
- ******************************************************************************/
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
-	_IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
-#else
-#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
-	_IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
-#endif
-void *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
-					  IMG_UINT32 ui32Bytes,
-					  IMG_UINT32 ui32MappingFlags,
-					  IMG_CHAR *pszFileName,
-					  IMG_UINT32 ui32Line);
-
-/*!
- ******************************************************************************
- * @brief Unmaps an IO memory mapping created using IORemap
- *
- * @param pvIORemapCookie  
- *
- * @return 
- ******************************************************************************/
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-#define IOUnmapWrapper(pvIORemapCookie) \
-	_IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
-#else
-#define IOUnmapWrapper(pvIORemapCookie) \
-	_IOUnmapWrapper(pvIORemapCookie, NULL, 0)
-#endif
-void _IOUnmapWrapper(void *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
-
-#endif /* __IMG_LINUX_MM_H__ */
diff --git a/drivers/staging/imgtec/rogue/mm_common.h b/drivers/staging/imgtec/rogue/mm_common.h
index 8478434..4de0a19 100644
--- a/drivers/staging/imgtec/rogue/mm_common.h
+++ b/drivers/staging/imgtec/rogue/mm_common.h
@@ -45,6 +45,7 @@
 #define MM_COMMON_H
 
 #define DEVICEMEM_HISTORY_TEXT_BUFSZ 40
+#define DEVICEMEM_HISTORY_ALLOC_INDEX_NONE 0xFFFFFFFF
 
 #endif
 
diff --git a/drivers/staging/imgtec/rogue/mmu_common.c b/drivers/staging/imgtec/rogue/mmu_common.c
index e7bc25a..0fe2f28 100644
--- a/drivers/staging/imgtec/rogue/mmu_common.c
+++ b/drivers/staging/imgtec/rogue/mmu_common.c
@@ -46,6 +46,7 @@
 /* Our own interface */
 #include "mmu_common.h"
 
+#include "rgx_bvnc_defs_km.h"
 /*
 Interfaces to other modules:
 
@@ -76,14 +77,19 @@
 #include "pmr.h"
 /* include/ */
 #include "pvr_debug.h"
+#include "pvr_notifier.h"
 #include "pvrsrv_error.h"
 #include "pvrsrv.h"
 #include "htbuffer.h"
 
+#include "rgxdevice.h"
+
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 #include "physmem_lma.h"
 #endif
 
+#include "dllist.h"
+
 // #define MMU_OBJECT_REFCOUNT_DEBUGING 1
 #if defined (MMU_OBJECT_REFCOUNT_DEBUGING)
 #define MMU_OBJ_DBG(x)	PVR_DPF(x);
@@ -100,6 +106,56 @@
 	MMU_MOD_UNMAP,
 } MMU_MOD;
 
+
+/*!
+ * Refcounted structure that is shared between the context and
+ * the cleanup thread items.
+ * It is used to keep track of all cleanup items and whether the creating
+ * MMU context has been destroyed and therefore is not allowed to be
+ * accessed anymore.
+ *
+ * The cleanup thread is used to defer the freeing of the page tables
+ * because we have to make sure that the MMU cache has been invalidated.
+ * If we don't take care of this the MMU might partially access cached
+ * and uncached tables which might lead to inconsistencies and in the
+ * worst case to MMU pending faults on random memory.
+ */
+typedef struct _MMU_CTX_CLEANUP_DATA_
+{
+	/*! Refcount to know when this structure can be destroyed */
+	ATOMIC_T iRef;
+	/*! Protect items in this structure, especially the refcount */
+	POS_LOCK hCleanupLock;
+	/*! List of all cleanup items currently in flight */
+	DLLIST_NODE sMMUCtxCleanupItemsHead;
+	/*! Was the MMU context destroyed and should not be accessed anymore? */
+	IMG_BOOL bMMUContextExists;
+} MMU_CTX_CLEANUP_DATA;
+
+
+/*!
+ * Structure holding one or more page tables that need to be
+ * freed after the MMU cache has been flushed which is signalled when
+ * the stored sync has a value that is <= the required value.
+ */
+typedef struct _MMU_CLEANUP_ITEM_
+{
+	/*! Cleanup thread data */
+	PVRSRV_CLEANUP_THREAD_WORK sCleanupThreadFn;
+	/*! List to hold all the MMU_MEMORY_MAPPINGs, i.e. page tables */
+	DLLIST_NODE sMMUMappingHead;
+	/*! Node of the cleanup item list for the context */
+	DLLIST_NODE sMMUCtxCleanupItem;
+	/* Pointer to the cleanup meta data */
+	MMU_CTX_CLEANUP_DATA *psMMUCtxCleanupData;
+	/* Sync to query if the MMU cache was flushed */
+	PVRSRV_CLIENT_SYNC_PRIM *psSync;
+	/*! The update value of the sync to signal that the cache was flushed */
+	IMG_UINT32 uiRequiredSyncVal;
+	/*! The device node needed to free the page tables */
+	PVRSRV_DEVICE_NODE *psDevNode;
+} MMU_CLEANUP_ITEM;
+
 /*!
 	All physical allocations and frees are relative to this context, so
 	we would get all the allocations of PCs, PDs, and PTs from the same
@@ -123,6 +179,11 @@
 	/*! Size of arena name string */
 	size_t uiPhysMemRANameAllocSize;
 
+	/*! Meta data for deferred cleanup */
+	MMU_CTX_CLEANUP_DATA *psCleanupData;
+	/*! Temporary list of all deferred MMU_MEMORY_MAPPINGs. */
+	DLLIST_NODE sTmpMMUMappingHead;
+
 } MMU_PHYSMEM_CONTEXT;
 
 /*!
@@ -139,13 +200,15 @@
 	/*! Device physical address of this allocation */
 	IMG_DEV_PHYADDR			sDevPAddr;
 	/*! Size of this allocation */
-	size_t				uiSize;
+	size_t					uiSize;
 	/*! Number of current mappings of this allocation */
 	IMG_UINT32				uiCpuVAddrRefCount;
+	/*! Node for the defer free list */
+	DLLIST_NODE				sMMUMappingItem;
 } MMU_MEMORY_MAPPING;
 
 /*!
-	Memory descriptor for MMU objects. There can be more then one memory
+	Memory descriptor for MMU objects. There can be more than one memory
 	descriptor per MMU memory allocation.
 */
 typedef struct _MMU_MEMORY_DESC_
@@ -216,6 +279,7 @@
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
     IMG_UINT32  ui32OSid;
 	IMG_UINT32	ui32OSidReg;
+    IMG_BOOL   bOSidAxiProt;
 #endif
 
 	/*! Lock to ensure exclusive access when manipulating the MMU context or
@@ -228,7 +292,6 @@
 	/* NO OTHER MEMBERS AFTER THIS STRUCTURE ! */
 };
 
-
 static const IMG_DEV_PHYADDR gsBadDevPhyAddr = {MMU_BAD_PHYS_ADDR};
 
 #if defined(DEBUG)
@@ -241,6 +304,228 @@
  *****************************************************************************/
 
 /*************************************************************************/ /*!
+@Function       _FreeMMUMapping
+
+@Description    Free a given dllist of MMU_MEMORY_MAPPINGs and the page tables
+                they represent.
+
+@Input          psDevNode           Device node
+
+@Input          psTmpMMUMappingHead List of MMU_MEMORY_MAPPINGs to free
+*/
+/*****************************************************************************/
+static void
+_FreeMMUMapping(PVRSRV_DEVICE_NODE *psDevNode,
+                PDLLIST_NODE psTmpMMUMappingHead)
+{
+	PDLLIST_NODE psNode, psNextNode;
+
+	/* Free the current list unconditionally */
+	dllist_foreach_node(psTmpMMUMappingHead,
+						psNode,
+						psNextNode)
+	{
+		MMU_MEMORY_MAPPING *psMapping = IMG_CONTAINER_OF(psNode,
+														 MMU_MEMORY_MAPPING,
+														 sMMUMappingItem);
+
+		psDevNode->pfnDevPxFree(psDevNode, &psMapping->sMemHandle);
+		dllist_remove_node(psNode);
+		OSFreeMem(psMapping);
+	}
+}
+
+/*************************************************************************/ /*!
+@Function       _CleanupThread_FreeMMUMapping
+
+@Description    Function to be executed by the cleanup thread to free
+                MMU_MEMORY_MAPPINGs after the MMU cache has been invalidated.
+
+                This function will request a MMU cache invalidate once and
+                retry to free the MMU_MEMORY_MAPPINGs until the invalidate
+                has been executed.
+
+                If the memory context that created this cleanup item has been
+                destroyed in the meantime this function will directly free the
+                MMU_MEMORY_MAPPINGs without waiting for any MMU cache
+                invalidation.
+
+@Input          pvData           Cleanup data in form of a MMU_CLEANUP_ITEM
+
+@Return         PVRSRV_OK if successful otherwise PVRSRV_ERROR_RETRY
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR
+_CleanupThread_FreeMMUMapping(void* pvData)
+{
+	PVRSRV_ERROR eError;
+	MMU_CLEANUP_ITEM *psCleanup = (MMU_CLEANUP_ITEM *) pvData;
+	MMU_CTX_CLEANUP_DATA *psMMUCtxCleanupData = psCleanup->psMMUCtxCleanupData;
+	PVRSRV_DEVICE_NODE *psDevNode = psCleanup->psDevNode;
+	IMG_BOOL bFreeNow;
+	IMG_UINT32 uiSyncCurrent;
+	IMG_UINT32 uiSyncReq;
+
+	OSLockAcquire(psMMUCtxCleanupData->hCleanupLock);
+
+	/* Don't attempt to free anything when the context has been destroyed.
+	 * Especially don't access any device specific structures anymore!*/
+	if (!psMMUCtxCleanupData->bMMUContextExists)
+	{
+		OSFreeMem(psCleanup);
+		eError = PVRSRV_OK;
+		goto e0;
+	}
+
+	if (psCleanup->psSync == NULL)
+	{
+		/* Kick to invalidate the MMU caches and get sync info */
+		psDevNode->pfnMMUCacheInvalidateKick(psDevNode,
+											 &psCleanup->uiRequiredSyncVal,
+											 IMG_TRUE);
+		psCleanup->psSync = psDevNode->psMMUCacheSyncPrim;
+	}
+
+	uiSyncCurrent = *(psCleanup->psSync->pui32LinAddr);
+	uiSyncReq = psCleanup->uiRequiredSyncVal;
+
+	/* Either the invalidate has been executed ... */
+	bFreeNow = (uiSyncCurrent >= uiSyncReq) ? IMG_TRUE :
+			/* ... with the counter wrapped around ... */
+			(uiSyncReq - uiSyncCurrent) > 0xEFFFFFFFUL ? IMG_TRUE :
+			/* ... or are we still waiting for the invalidate? */
+			IMG_FALSE;
+
+#if defined(NO_HARDWARE)
+	/* In NOHW the syncs will never be updated so just free the tables */
+	bFreeNow = IMG_TRUE;
+#endif
+
+	if (bFreeNow)
+	{
+		_FreeMMUMapping(psDevNode, &psCleanup->sMMUMappingHead);
+
+		dllist_remove_node(&psCleanup->sMMUCtxCleanupItem);
+		OSFreeMem(psCleanup);
+
+		eError = PVRSRV_OK;
+	}
+	else
+	{
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+e0:
+
+	/* If this cleanup task has been successfully executed we can
+	 * decrease the context cleanup data refcount. Successfully
+	 * means here that the MMU_MEMORY_MAPPINGs have been freed by
+	 * either this cleanup task of when the MMU context has been
+	 * destroyed. */
+	if (eError == PVRSRV_OK)
+	{
+		OSLockRelease(psMMUCtxCleanupData->hCleanupLock);
+
+		if (OSAtomicDecrement(&psMMUCtxCleanupData->iRef) == 0)
+		{
+			OSLockDestroy(psMMUCtxCleanupData->hCleanupLock);
+			OSFreeMem(psMMUCtxCleanupData);
+		}
+	}
+	else
+	{
+		OSLockRelease(psMMUCtxCleanupData->hCleanupLock);
+	}
+
+
+	return eError;
+}
+
+/*************************************************************************/ /*!
+@Function       _SetupCleanup_FreeMMUMapping
+
+@Description    Setup a cleanup item for the cleanup thread that will
+                kick off a MMU invalidate request and free the associated
+                MMU_MEMORY_MAPPINGs when the invalidate was successful.
+
+@Input          psDevNode           Device node
+
+@Input          psPhysMemCtx        The current MMU physmem context
+*/
+/*****************************************************************************/
+static void
+_SetupCleanup_FreeMMUMapping(PVRSRV_DEVICE_NODE *psDevNode,
+                             MMU_PHYSMEM_CONTEXT *psPhysMemCtx)
+{
+
+	MMU_CLEANUP_ITEM *psCleanupItem;
+	MMU_CTX_CLEANUP_DATA *psCleanupData = psPhysMemCtx->psCleanupData;
+
+	if (dllist_is_empty(&psPhysMemCtx->sTmpMMUMappingHead))
+	{
+		goto e0;
+	}
+
+#if !defined(SUPPORT_MMU_PENDING_FAULT_PROTECTION)
+	/* If users deactivated this we immediately free the page tables */
+	goto e1;
+#endif
+
+	/* Don't defer the freeing if we are currently unloading the driver
+	 * or if the sync has been destroyed */
+	if (PVRSRVGetPVRSRVData()->bUnload ||
+	    psDevNode->psMMUCacheSyncPrim == NULL)
+	{
+		goto e1;
+	}
+
+	/* Allocate a cleanup item */
+	psCleanupItem = OSAllocMem(sizeof(*psCleanupItem));
+	if(!psCleanupItem)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to get memory for deferred page table cleanup. "
+				 "Freeing tables immediately",
+				 __FUNCTION__));
+		goto e1;
+	}
+
+	/* Set sync to NULL to indicate we did not interact with
+	 * the FW yet. Kicking off an MMU cache invalidate should
+	 * be done in the cleanup thread to not waste time here. */
+	psCleanupItem->psSync = NULL;
+	psCleanupItem->uiRequiredSyncVal = 0;
+	psCleanupItem->psDevNode = psDevNode;
+	psCleanupItem->psMMUCtxCleanupData = psCleanupData;
+
+	OSAtomicIncrement(&psCleanupData->iRef);
+
+	/* Move the page tables to free to the cleanup item */
+	dllist_replace_head(&psPhysMemCtx->sTmpMMUMappingHead,
+	                    &psCleanupItem->sMMUMappingHead);
+
+	/* Add the cleanup item itself to the context list */
+	dllist_add_to_tail(&psCleanupData->sMMUCtxCleanupItemsHead,
+	                   &psCleanupItem->sMMUCtxCleanupItem);
+
+	/* Setup the cleanup thread data and add the work item */
+	psCleanupItem->sCleanupThreadFn.pfnFree = _CleanupThread_FreeMMUMapping;
+	psCleanupItem->sCleanupThreadFn.pvData = psCleanupItem;
+	psCleanupItem->sCleanupThreadFn.ui32RetryCount = CLEANUP_THREAD_RETRY_COUNT_DEFAULT;
+	psCleanupItem->sCleanupThreadFn.bDependsOnHW = IMG_TRUE;
+
+	PVRSRVCleanupThreadAddWork(&psCleanupItem->sCleanupThreadFn);
+
+	return;
+
+e1:
+	/* Free the page tables now */
+	_FreeMMUMapping(psDevNode, &psPhysMemCtx->sTmpMMUMappingHead);
+e0:
+	return;
+}
+
+/*************************************************************************/ /*!
 @Function       _CalcPCEIdx
 
 @Description    Calculate the page catalogue index
@@ -313,7 +598,7 @@
     {
         ui32RetVal ++;
     }
-        
+
     return ui32RetVal;
 }
 
@@ -352,7 +637,7 @@
     {
         ui32RetVal ++;
     }
-        
+
     return ui32RetVal;
 }
 
@@ -380,12 +665,13 @@
 @Output         phPriv          Handle which will be passed back when
                                 this import is freed
 
-@Return         IMG_TRUE if import alloc was successful, otherwise IMG_FALSE
+@Return         PVRSRV_OK if import alloc was successful
 */
 /*****************************************************************************/
-static IMG_BOOL _MMU_PhysMem_RAImportAlloc(RA_PERARENA_HANDLE hArenaHandle,
+static PVRSRV_ERROR _MMU_PhysMem_RAImportAlloc(RA_PERARENA_HANDLE hArenaHandle,
                                            RA_LENGTH_T uiSize,
                                            RA_FLAGS_T uiFlags,
+                                           const IMG_CHAR *pszAnnotation,
                                            RA_BASE_T *puiBase,
                                            RA_LENGTH_T *puiActualSize,
                                            RA_PERISPAN_HANDLE *phPriv)
@@ -395,11 +681,13 @@
 	MMU_MEMORY_MAPPING *psMapping;
 	PVRSRV_ERROR eError;
 
+	PVR_UNREFERENCED_PARAMETER(pszAnnotation);
 	PVR_UNREFERENCED_PARAMETER(uiFlags);
 
 	psMapping = OSAllocMem(sizeof(MMU_MEMORY_MAPPING));
 	if (psMapping == NULL)
 	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto e0;
 	}
 
@@ -421,12 +709,12 @@
 	*puiBase = (RA_BASE_T)psMapping->sDevPAddr.uiAddr;
 	*puiActualSize = uiSize;
 
-	return IMG_TRUE;
+	return PVRSRV_OK;
 
 e1:
 	OSFreeMem(psMapping);
 e0:
-	return IMG_FALSE;
+	return eError;
 }
 
 /*************************************************************************/ /*!
@@ -451,15 +739,15 @@
 {
 	MMU_MEMORY_MAPPING *psMapping = (MMU_MEMORY_MAPPING *) hPriv;
 	MMU_PHYSMEM_CONTEXT *psCtx = (MMU_PHYSMEM_CONTEXT *) hArenaHandle;
-	PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *) psCtx->psDevNode;
 
 	PVR_UNREFERENCED_PARAMETER(uiBase);
 
 	/* Check we have dropped all CPU mappings */
 	PVR_ASSERT(psMapping->uiCpuVAddrRefCount == 0);
 
-	psDevNode->pfnDevPxFree(psDevNode, &psMapping->sMemHandle);
-	OSFreeMem(psMapping);
+	/* Add mapping to defer free list */
+	psMapping->psContext = NULL;
+	dllist_add_to_tail(&psCtx->sTmpMMUMappingHead, &psMapping->sMMUMappingItem);
 }
 
 /*************************************************************************/ /*!
@@ -484,41 +772,40 @@
                                       size_t uiBytes,
                                       size_t uiAlignment)
 {
+	PVRSRV_ERROR eError;
 	RA_BASE_T uiPhysAddr;
-	IMG_BOOL bStatus;
 
 	if (!psMemDesc || psMemDesc->bValid)
 	{
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	bStatus = RA_Alloc(psCtx->psPhysMemRA,
-					   uiBytes,
-					   RA_NO_IMPORT_MULTIPLIER,
-					   0, // flags
-					   uiAlignment,
-					   &uiPhysAddr,
-					   NULL,
-					   (RA_PERISPAN_HANDLE *) &psMemDesc->psMapping);
-	if(!bStatus)
+	eError = RA_Alloc(psCtx->psPhysMemRA,
+	                  uiBytes,
+	                  RA_NO_IMPORT_MULTIPLIER,
+	                  0, // flags
+	                  uiAlignment,
+	                  "",
+	                  &uiPhysAddr,
+	                  NULL,
+	                  (RA_PERISPAN_HANDLE *) &psMemDesc->psMapping);
+	if(PVRSRV_OK != eError)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "_MMU_PhysMemAlloc: ERROR call to RA_Alloc() failed"));
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
+		return eError;
 	}
 
 	psMemDesc->bValid = IMG_TRUE;
 	psMemDesc->pvCpuVAddr = NULL;
-	psMemDesc->sDevPAddr.uiAddr = (uintptr_t) uiPhysAddr;
+	psMemDesc->sDevPAddr.uiAddr = (IMG_UINT64) uiPhysAddr;
 
 	if (psMemDesc->psMapping->uiCpuVAddrRefCount == 0)
 	{
-		PVRSRV_ERROR eError;
-
 		eError = psCtx->psDevNode->pfnDevPxMap(psCtx->psDevNode,
-										&psMemDesc->psMapping->sMemHandle,
-										psMemDesc->psMapping->uiSize,
-										&psMemDesc->psMapping->sDevPAddr,
-										&psMemDesc->psMapping->pvCpuVAddr);
+		                                       &psMemDesc->psMapping->sMemHandle,
+		                                       psMemDesc->psMapping->uiSize,
+		                                       &psMemDesc->psMapping->sDevPAddr,
+		                                       &psMemDesc->psMapping->pvCpuVAddr);
 		if (eError != PVRSRV_OK)
 		{
 			RA_Free(psCtx->psPhysMemRA, psMemDesc->sDevPAddr.uiAddr);
@@ -527,7 +814,8 @@
 	}
 
 	psMemDesc->psMapping->uiCpuVAddrRefCount++;
-	psMemDesc->pvCpuVAddr = (IMG_UINT8 *) psMemDesc->psMapping->pvCpuVAddr + (psMemDesc->sDevPAddr.uiAddr - psMemDesc->psMapping->sDevPAddr.uiAddr);
+	psMemDesc->pvCpuVAddr = (IMG_UINT8 *) psMemDesc->psMapping->pvCpuVAddr
+	                        + (psMemDesc->sDevPAddr.uiAddr - psMemDesc->psMapping->sDevPAddr.uiAddr);
 	psMemDesc->uiOffset = (psMemDesc->sDevPAddr.uiAddr - psMemDesc->psMapping->sDevPAddr.uiAddr);
 	psMemDesc->uiSize = uiBytes;
 	PVR_ASSERT(psMemDesc->pvCpuVAddr != NULL);
@@ -579,23 +867,22 @@
                                            MMU_CONTEXT *psMMUContext)
 {
 	/* Do flag conversion between devmem flags and MMU generic flags */
-
 	if (bInvalidate == IMG_FALSE)
 	{
 		*uiMMUProtFlags |= ( (uiMappingFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK)
 							>> PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET)
 							<< MMU_PROTFLAGS_DEVICE_OFFSET;
 
-		if (uiMappingFlags & PVRSRV_MEMALLOCFLAG_GPU_READABLE)
+		if (PVRSRV_CHECK_GPU_READABLE(uiMappingFlags))
 		{
 			*uiMMUProtFlags |= MMU_PROTFLAGS_READABLE;
 		}
-		if (uiMappingFlags & PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE)
+		if (PVRSRV_CHECK_GPU_WRITEABLE(uiMappingFlags))
 		{
 			*uiMMUProtFlags |= MMU_PROTFLAGS_WRITEABLE;
 		}
 
-		switch ( DevmemDeviceCacheMode(uiMappingFlags) )
+		switch (DevmemDeviceCacheMode(psMMUContext->psDevNode, uiMappingFlags))
 		{
 			case PVRSRV_MEMALLOCFLAG_GPU_UNCACHED:
 			case PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE:
@@ -608,33 +895,32 @@
 					return;
 		}
 
-		if (DevmemDeviceCacheCoherency(uiMappingFlags))
+		if (DevmemDeviceCacheCoherency(psMMUContext->psDevNode, uiMappingFlags))
 		{
 			*uiMMUProtFlags |= MMU_PROTFLAGS_CACHE_COHERENT;
 		}
-#if defined(RGX_FEATURE_MIPS)
-		/*
-			If we are allocating on the MMU of the firmware processor, the cached/uncached attributes
-			must depend on the FIRMWARE_CACHED allocation flag.
-		 */
-		if (psMMUContext->psDevAttrs == psMMUContext->psDevNode->psFirmwareMMUDevAttrs)
-		{
-			if (uiMappingFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED))
-			{
-				*uiMMUProtFlags |= MMU_PROTFLAGS_CACHED;
-			}
-			else
-			{
-				*uiMMUProtFlags &= ~MMU_PROTFLAGS_CACHED;
 
+		if( (psMMUContext->psDevNode->pfnCheckDeviceFeature) && \
+				psMMUContext->psDevNode->pfnCheckDeviceFeature(psMMUContext->psDevNode, RGX_FEATURE_MIPS_BIT_MASK))
+		{
+			/*
+				If we are allocating on the MMU of the firmware processor, the cached/uncached attributes
+				must depend on the FIRMWARE_CACHED allocation flag.
+			 */
+			if (psMMUContext->psDevAttrs == psMMUContext->psDevNode->psFirmwareMMUDevAttrs)
+			{
+				if (uiMappingFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED))
+				{
+					*uiMMUProtFlags |= MMU_PROTFLAGS_CACHED;
+				}
+				else
+				{
+					*uiMMUProtFlags &= ~MMU_PROTFLAGS_CACHED;
+
+				}
+				*uiMMUProtFlags &= ~MMU_PROTFLAGS_CACHE_COHERENT;
 			}
-			*uiMMUProtFlags &= ~MMU_PROTFLAGS_CACHE_COHERENT;
 		}
-#elif defined(RGX_FEATURE_META)
-		PVR_UNREFERENCED_PARAMETER(psMMUContext);
-#else
-#error ("Build Misconfiguration. A firmware processor must be defined")
-#endif
 	}
 	else
 	{
@@ -666,14 +952,12 @@
 								const MMU_PxE_CONFIG *psConfig,
 								MMU_LEVEL eMMULevel,
 								MMU_MEMORY_DESC *psMemDesc,
-								IMG_UINT8 uiLog2Align)
+								IMG_UINT32 uiLog2Align)
 {
 	PVRSRV_ERROR eError;
 	size_t uiBytes;
 	size_t uiAlign;
-#if defined(PDUMP)
-	PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psDevNode;
-#endif
+
 	PVR_ASSERT(psConfig->uiBytesPerEntry != 0);
 
 	uiBytes = uiNumEntries * psConfig->uiBytesPerEntry;
@@ -692,12 +976,15 @@
 
 	/*
 		Clear the object
-		Note: if any MMUs are cleared with non-zero values then will need a custom
-		clear function
+		Note: if any MMUs are cleared with non-zero values then will need a
+		custom clear function
+		Note: 'Cached' is wrong for the LMA + ARM64 combination, but this is
+		unlikely
 	*/
-	OSMemSet(psMemDesc->pvCpuVAddr, 0, uiBytes);
+	OSCachedMemSet(psMemDesc->pvCpuVAddr, 0, uiBytes);
 
-	eError = psMMUContext->psDevNode->pfnDevPxClean(&psMemDesc->psMapping->sMemHandle,
+	eError = psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+	                                                &psMemDesc->psMapping->sMemHandle,
 	                                                psMemDesc->uiOffset,
 	                                                psMemDesc->uiSize);
 	if(eError != PVRSRV_OK)
@@ -708,28 +995,28 @@
 #if defined(PDUMP)
 	PDUMPCOMMENT("Alloc MMU object");
 
-	PDumpMMUMalloc(psDevNode->pszMMUPxPDumpMemSpaceName,
-                   eMMULevel,
-                   &psMemDesc->sDevPAddr,
-                   uiBytes,    
-                   uiAlign,
-                   psMMUContext->psDevAttrs->eMMUType);
-	
+	PDumpMMUMalloc(psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+	               eMMULevel,
+	               &psMemDesc->sDevPAddr,
+	               uiBytes,
+	               uiAlign,
+	               psMMUContext->psDevAttrs->eMMUType);
+
 	PDumpMMUDumpPxEntries(eMMULevel,
-						  psDevNode->pszMMUPxPDumpMemSpaceName,
-						  psMemDesc->pvCpuVAddr,
-						  psMemDesc->sDevPAddr,
-						  0,
-						  uiNumEntries,
-						  NULL, NULL, 0, /* pdump symbolic info is irrelevant here */
-						  psConfig->uiBytesPerEntry,
-						  uiLog2Align,
-						  psConfig->uiAddrShift,
-						  psConfig->uiAddrMask,
-						  psConfig->uiProtMask,
-						  psConfig->uiValidEnMask,
-						  0,
-						  psMMUContext->psDevAttrs->eMMUType);
+	                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+	                      psMemDesc->pvCpuVAddr,
+	                      psMemDesc->sDevPAddr,
+	                      0,
+	                      uiNumEntries,
+	                      NULL, NULL, 0, /* pdump symbolic info is irrelevant here */
+	                      psConfig->uiBytesPerEntry,
+	                      uiLog2Align,
+	                      psConfig->uiAddrShift,
+	                      psConfig->uiAddrMask,
+	                      psConfig->uiProtMask,
+	                      psConfig->uiValidEnMask,
+	                      0,
+	                      psMMUContext->psDevAttrs->eMMUType);
 #endif
 
 	return PVRSRV_OK;
@@ -756,18 +1043,17 @@
 static void _PxMemFree(MMU_CONTEXT *psMMUContext,
 					   MMU_MEMORY_DESC *psMemDesc, MMU_LEVEL eMMULevel)
 {
-#if defined(PDUMP)
-	PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psDevNode;
-#endif
 #if defined(MMU_CLEARMEM_ON_FREE)
 	PVRSRV_ERROR eError;
 
 	/*
 		Clear the MMU object
-		Note: if any MMUs are cleared with non-zero values then will need a custom
-		clear function
+		Note: if any MMUs are cleared with non-zero values then will need a
+		custom clear function
+		Note: 'Cached' is wrong for the LMA + ARM64 combination, but this is
+		unlikely
 	*/
-	OSMemSet(psMemDesc->pvCpuVAddr, 0, psMemDesc->ui32Bytes);
+	OSCachedMemSet(psMemDesc->pvCpuVAddr, 0, psMemDesc->ui32Bytes);
 
 #if defined(PDUMP)
 	PDUMPCOMMENT("Clear MMU object before freeing it");
@@ -777,7 +1063,10 @@
 #if defined(PDUMP)
 	PDUMPCOMMENT("Free MMU object");
 	{
-		PDumpMMUFree(psDevNode->pszMMUPxPDumpMemSpaceName, eMMULevel, &psMemDesc->sDevPAddr, psMMUContext->psDevAttrs->eMMUType);
+		PDumpMMUFree(psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+		             eMMULevel,
+		             &psMemDesc->sDevPAddr,
+		             psMMUContext->psDevAttrs->eMMUType);
 	}
 #else
 	PVR_UNREFERENCED_PARAMETER(eMMULevel);
@@ -801,9 +1090,25 @@
 {
 	MMU_MEMORY_DESC *psMemDesc = &psLevel->sMemDesc;
 	IMG_UINT64 ui64PxE64;
+	IMG_UINT64 uiAddr = psDevPAddr->uiAddr;
+
+	if(psMMUContext->psDevNode->pfnCheckDeviceFeature(psMMUContext->psDevNode, \
+			RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		/*
+		 * If mapping for the MIPS FW context, check for sensitive PAs
+		 */
+		if (psMMUContext->psDevAttrs == psMMUContext->psDevNode->psFirmwareMMUDevAttrs
+			&& RGXMIPSFW_SENSITIVE_ADDR(uiAddr))
+		{
+			PVRSRV_RGXDEV_INFO *psDevice = (PVRSRV_RGXDEV_INFO *)psMMUContext->psDevNode->pvDevice;
+
+			uiAddr = psDevice->sTrampoline.sPhysAddr.uiAddr + RGXMIPSFW_TRAMPOLINE_OFFSET(uiAddr);
+		}
+	}
 
 	/* Calculate Entry */
-	ui64PxE64 =    psDevPAddr->uiAddr /* Calculate the offset to that base */
+	ui64PxE64 =    uiAddr /* Calculate the offset to that base */
 	            >> psConfig->uiAddrLog2Align /* Shift away the useless bits, because the alignment is very coarse and we address by alignment */
 	            << psConfig->uiAddrShift /* Shift back to fit address in the Px entry */
 	             & psConfig->uiAddrMask; /* Delete unused bits */
@@ -841,22 +1146,22 @@
 
 #if defined (PDUMP)
 	PDumpMMUDumpPxEntries(MMU_LEVEL_1,
-						  psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName,
-						  psMemDesc->pvCpuVAddr,
-						  psMemDesc->sDevPAddr,
-						  uiIndex,
-						  1,
-						  pszMemspaceName,
-						  pszSymbolicAddr,
-						  uiSymbolicAddrOffset,
-						  psConfig->uiBytesPerEntry,
-						  psConfig->uiAddrLog2Align,
-						  psConfig->uiAddrShift,
-						  psConfig->uiAddrMask,
-						  psConfig->uiProtMask,
-						  psConfig->uiValidEnMask,
-						  0,
-						  psMMUContext->psDevAttrs->eMMUType);
+	                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+	                      psMemDesc->pvCpuVAddr,
+	                      psMemDesc->sDevPAddr,
+	                      uiIndex,
+	                      1,
+	                      pszMemspaceName,
+	                      pszSymbolicAddr,
+	                      uiSymbolicAddrOffset,
+	                      psConfig->uiBytesPerEntry,
+	                      psConfig->uiAddrLog2Align,
+	                      psConfig->uiAddrShift,
+	                      psConfig->uiAddrMask,
+	                      psConfig->uiProtMask,
+	                      psConfig->uiValidEnMask,
+	                      0,
+	                      psMMUContext->psDevAttrs->eMMUType);
 #endif /*PDUMP*/
 
 	return PVRSRV_OK;
@@ -984,7 +1289,7 @@
 				uiIndex, eMMULevel,
 				HTBLOG_U64_BITS_HIGH(ui64PxE64), HTBLOG_U64_BITS_LOW(ui64PxE64),
 				(uiProtFlags & MMU_PROTFLAGS_INVALID)? 0: 1);
-			break;	
+			break;
 		}
 		case 8:
 		{
@@ -1001,7 +1306,7 @@
 				uiIndex, eMMULevel,
 				HTBLOG_U64_BITS_HIGH(pui64Px[uiIndex]), HTBLOG_U64_BITS_LOW(pui64Px[uiIndex]),
 				(uiProtFlags & MMU_PROTFLAGS_INVALID)? 0: 1);
-			break;	
+			break;
 		}
 		default:
 			PVR_DPF((PVR_DBG_ERROR, "%s: PxE size not supported (%d) for level %d",
@@ -1012,22 +1317,22 @@
 
 #if defined (PDUMP)
 	PDumpMMUDumpPxEntries(eMMULevel,
-						  psDevNode->pszMMUPxPDumpMemSpaceName,
-						  psMemDesc->pvCpuVAddr,
-						  psMemDesc->sDevPAddr,
-						  uiIndex,
-						  1,
-						  pszMemspaceName,
-						  pszSymbolicAddr,
-						  uiSymbolicAddrOffset,
-						  psConfig->uiBytesPerEntry,
-						  psConfig->uiAddrLog2Align,
-						  psConfig->uiAddrShift,
-						  psConfig->uiAddrMask,
-						  psConfig->uiProtMask,
-						  psConfig->uiValidEnMask,
-						  0,
-						  psMMUContext->psDevAttrs->eMMUType);
+	                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+	                      psMemDesc->pvCpuVAddr,
+	                      psMemDesc->sDevPAddr,
+	                      uiIndex,
+	                      1,
+	                      pszMemspaceName,
+	                      pszSymbolicAddr,
+	                      uiSymbolicAddrOffset,
+	                      psConfig->uiBytesPerEntry,
+	                      psConfig->uiAddrLog2Align,
+	                      psConfig->uiAddrShift,
+	                      psConfig->uiAddrMask,
+	                      psConfig->uiProtMask,
+	                      psConfig->uiValidEnMask,
+	                      0,
+	                      psMMUContext->psDevAttrs->eMMUType);
 #endif
 
 	psDevNode->pfnMMUCacheInvalidate(psDevNode, psMMUContext->hDevData,
@@ -1063,7 +1368,7 @@
 
 @Input          psMMUContext    MMU context to operate on
 
-@Input          psLevel                 Level info on which to to free the
+@Input          psLevel                 Level info on which to free the
                                         specified range
 
 @Input          auiStartArray           Array of start indexes (one for each level)
@@ -1078,7 +1383,7 @@
 @Input          aeMMULevel              Array of MMU levels (one for each level)
 
 @Input          pui32CurrentLevel       Pointer to a variable which is set to our
-                                        current level 
+                                        current level
 
 @Input          uiStartIndex            Start index of the range to free
 
@@ -1160,34 +1465,35 @@
 								uiNextStartIndex, uiNextEndIndex,
 								bNextFirst, bNextLast, uiLog2DataPageSize))
 			{
+				PVRSRV_ERROR eError;
+
+				/* Un-wire the entry */
+				eError = _SetupPxE(psMMUContext,
+								psLevel,
+								i,
+								psConfig,
+								aeMMULevel[uiThisLevel],
+								NULL,
+#if defined(PDUMP)
+								NULL,	/* Only required for data page */
+								NULL,	/* Only required for data page */
+								0,      /* Only required for data page */
+#endif
+								MMU_PROTFLAGS_INVALID,
+								uiLog2DataPageSize);
+
+				PVR_ASSERT(eError == PVRSRV_OK);
+
+				/* Free table of the level below, pointed to by this table entry.
+				 * We don't destroy the table inside the above _MMU_FreeLevel call because we
+				 * first have to set the table entry of the level above to invalid. */
+				_PxMemFree(psMMUContext, &psNextLevel->sMemDesc, aeMMULevel[*pui32CurrentLevel]);
+				OSFreeMem(psNextLevel);
+
 				/* The level below us is empty, drop the refcount and clear the pointer */
 				psLevel->ui32RefCount--;
 				psLevel->apsNextLevel[i] = NULL;
 
-				/* Level 1 PTE reprogramming is done in the unmap */
-				if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
-				{
-					PVRSRV_ERROR eError;
-
-					/* Un-wire the entry */
-					eError = _SetupPxE(psMMUContext,
-									psLevel,
-									i,
-									psConfig,
-									aeMMULevel[uiThisLevel],
-									NULL,
-#if defined(PDUMP)
-									NULL,	/* Only required for data page */
-									NULL,	/* Only required for data page */
-									0,      /* Only required for data page */
-#endif
-									MMU_PROTFLAGS_INVALID,
-									uiLog2DataPageSize);		
-
-					PVR_ASSERT(eError == PVRSRV_OK);
-				}
-
-
 				/* Check we haven't wrapped around */
 				PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
 			}
@@ -1198,30 +1504,26 @@
 			psLevel->ui32RefCount--;
 		}
 
-
+		/*
+		   Free this level if it is no longer referenced, unless it's the base
+		   level in which case it's part of the MMU context and should be freed
+		   when the MMU context is freed
+		*/
+		if ((psLevel->ui32RefCount == 0) && (psLevel != &psMMUContext->sBaseLevelInfo))
+		{
+			bFreed = IMG_TRUE;
+		}
 	}
 
 	/* Level one flushing is done when we actually write the table entries */
 	if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
 	{
-		psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
+		psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+		                                       &psLevel->sMemDesc.psMapping->sMemHandle,
 		                                       uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
 		                                       (uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
 	}
 
-	/*
-	   Free this level if it is no longer referenced, unless it's the base
-	   level in which case it's part of the MMU context and should be freed
-	   when the MMU context is freed
-	*/
-	if ((psLevel->ui32RefCount == 0) && (psLevel != &psMMUContext->sBaseLevelInfo))
-	{
-		_PxMemFree(psMMUContext, &psLevel->sMemDesc, aeMMULevel[uiThisLevel]);
-		OSFreeMem(psLevel);
-		psLevel = NULL;
-		bFreed = IMG_TRUE;
-	}
-
 	MMU_OBJ_DBG((PVR_DBG_ERROR, "_MMU_FreeLevel end: level = %d, refcount = %d",
 				aeMMULevel[uiThisLevel], bFreed?0:psLevel->ui32RefCount));
 
@@ -1264,7 +1566,7 @@
 @Input          aeMMULevel              Array of MMU levels (one for each level)
 
 @Input          pui32CurrentLevel       Pointer to a variable which is set to our
-                                        current level 
+                                        current level
 
 @Input          uiStartIndex            Start index of the range to free
 
@@ -1305,7 +1607,7 @@
 				uiEndIndex, psLevel->ui32RefCount));
 
 	/* Go from uiStartIndex to uiEndIndex through the Px */
-	for (i = uiStartIndex;i < uiEndIndex;i++) 
+	for (i = uiStartIndex;i < uiEndIndex;i++)
 	{
 		/* Only try an allocation if this is not the last level */
 		/*Because a PT allocation is already done while setting the entry in PD */
@@ -1330,13 +1632,12 @@
 				{
 					ui32AllocSize += sizeof(MMU_Levelx_INFO *) * (uiNextEntries - 1);
 				}
-				psNextLevel = OSAllocMem(ui32AllocSize);
+				psNextLevel = OSAllocZMem(ui32AllocSize);
 				if (psNextLevel == NULL)
 				{
 					uiAllocState = 0;
 					goto e0;
 				}
-				OSMemSet(psNextLevel, 0, ui32AllocSize);
 
 				/* Hook in this level for next time */
 				psLevel->apsNextLevel[i] = psNextLevel;
@@ -1434,9 +1735,10 @@
 	/* Level one flushing is done when we actually write the table entries */
 	if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
 	{
-		eError = psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
-														uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-														(uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
+		eError = psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+		                                                &psLevel->sMemDesc.psMapping->sMemHandle,
+		                                                uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+		                                                (uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
 		if (eError != PVRSRV_OK)
 			goto e0;
 	}
@@ -1451,8 +1753,8 @@
 	PVR_DPF((PVR_DBG_ERROR, "_MMU_AllocLevel: Error %d allocating Px for level %d in stage %d"
 							,eError, aeMMULevel[uiThisLevel], uiAllocState));
 
-	/* the start value of index variable i is nor initialised on purpose 
-	   indeed this for loop deinitialise what has already been initialised 
+	/* the start value of index variable i is nor initialised on purpose
+	   indeed this for loop deinitialise what has already been initialised
 	   just before failing in reverse order. So the i index has already the
 	   right value. */
 	for (/* i already set */ ; i>= uiStartIndex  &&  i< uiEndIndex; i--)
@@ -1569,7 +1871,7 @@
 
 @Input          ppsMMUDevVAddrConfig    Device virtual address config
 
-@Input			phPriv					Private data of page size config		
+@Input			phPriv					Private data of page size config
 
 @Return         IMG_TRUE if the last reference to psLevel was dropped
 */
@@ -1740,7 +2042,9 @@
 @Function       _FreePageTables
 
 @Description    Free page tables and any higher level MMU objects at are no
-                longer referenced for the specified virtual range
+                longer referenced for the specified virtual range.
+                This will fill the temporary free list of the MMU context which
+                needs cleanup after the call.
 
 @Input          psMMUContext            MMU context to operate on
 
@@ -1937,6 +2241,7 @@
 
 }
 
+
 /*****************************************************************************
  *                     Public interface functions                            *
  *****************************************************************************/
@@ -1985,7 +2290,7 @@
 	ui32Size = sizeof(MMU_CONTEXT) + 
 						((ui32BaseObjects - 1) * sizeof(MMU_Levelx_INFO *));
 
-	psMMUContext = OSAllocMem(ui32Size);
+	psMMUContext = OSAllocZMem(ui32Size);
 	if (psMMUContext == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: ERROR call to OSAllocMem failed"));
@@ -1993,8 +2298,6 @@
 		goto e0;
 	}
 
-	OSMemSet (psMMUContext, 0, ui32Size);
-
 #if defined(PDUMP)
 	/* Clear the refcount */
 	psMMUContext->ui32PDumpContextIDRefCount = 0;
@@ -2006,15 +2309,18 @@
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 {
 	IMG_UINT32 ui32OSid, ui32OSidReg;
-	RetrieveOSidsfromPidList(OSGetCurrentClientProcessIDKM(), &ui32OSid, &ui32OSidReg);
-	MMU_SetOSids(psMMUContext, ui32OSid, ui32OSidReg);
+    IMG_BOOL bOSidAxiProt;
+
+    RetrieveOSidsfromPidList(OSGetCurrentClientProcessIDKM(), &ui32OSid, &ui32OSidReg, &bOSidAxiProt);
+
+    MMU_SetOSids(psMMUContext, ui32OSid, ui32OSidReg, bOSidAxiProt);
 }
 #endif
 
-	/* 
+	/*
 	  Allocate physmem context and set it up
 	 */
-	psCtx = OSAllocMem(sizeof (MMU_PHYSMEM_CONTEXT));
+	psCtx = OSAllocZMem(sizeof(MMU_PHYSMEM_CONTEXT));
 	if (psCtx == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: ERROR call to OSAllocMem failed"));
@@ -2023,7 +2329,6 @@
 	}
 	psMMUContext->psPhysMemCtx = psCtx;
 
-	OSMemSet (psCtx, 0, sizeof(MMU_PHYSMEM_CONTEXT));
 	psCtx->psDevNode = psDevNode;
 
 	OSSNPrintf(sBuf, sizeof(sBuf)-1, "pgtables %p", psCtx);
@@ -2054,6 +2359,21 @@
 		goto e3;
 	}
 
+	/* Setup cleanup meta data to check if a MMU context
+	 * has been destroyed and should not be accessed anymore */
+	psCtx->psCleanupData = OSAllocMem(sizeof(*(psCtx->psCleanupData)));
+	if (psCtx->psCleanupData == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: ERROR call to OSAllocMem failed"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e4;
+	}
+
+	OSLockCreate(&psCtx->psCleanupData->hCleanupLock, LOCK_TYPE_PASSIVE);
+	psCtx->psCleanupData->bMMUContextExists = IMG_TRUE;
+	dllist_init(&psCtx->psCleanupData->sMMUCtxCleanupItemsHead);
+	OSAtomicWrite(&psCtx->psCleanupData->iRef, 1);
+
 	/* allocate the base level object */
 	/*
 	   Note: Although this is not required by the this file until
@@ -2070,9 +2390,11 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: Failed to alloc level 1 object"));
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto e4;
+		goto e5;
 	}
 
+	dllist_init(&psMMUContext->psPhysMemCtx->sTmpMMUMappingHead);
+
 	psMMUContext->sBaseLevelInfo.ui32NumOfEntries = ui32BaseObjects;
 	psMMUContext->sBaseLevelInfo.ui32RefCount = 0;
 
@@ -2081,7 +2403,7 @@
 	if(eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: Failed to create lock for MMU_CONTEXT"));
-		goto e5;
+		goto e6;
 	}
 
 	/* return context */
@@ -2089,8 +2411,10 @@
 
 	return PVRSRV_OK;
 
-e5:
+e6:
 	_PxMemFree(psMMUContext, &psMMUContext->sBaseLevelInfo.sMemDesc, psDevAttrs->eTopLevel);
+e5:
+	OSFreeMem(psCtx->psCleanupData);
 e4:
 	RA_Delete(psCtx->psPhysMemRA);
 e3:
@@ -2110,6 +2434,10 @@
 MMU_ContextDestroy (MMU_CONTEXT *psMMUContext)
 {
 	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	PDLLIST_NODE psNode, psNextNode;
+
+	PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *) psMMUContext->psDevNode;
+	MMU_CTX_CLEANUP_DATA *psCleanupData = psMMUContext->psPhysMemCtx->psCleanupData;
 
 	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_ContextDestroy: Enter"));
 
@@ -2120,10 +2448,47 @@
 		PVR_ASSERT(psMMUContext->sBaseLevelInfo.ui32RefCount == 0);
 	}
 
-	/* Free the top level MMU object */
+	/* Cleanup lock must be acquired before MMUContext lock. Reverse order
+	 * may lead to a deadlock and is reported by lockdep. */
+	OSLockAcquire(psCleanupData->hCleanupLock);
+	OSLockAcquire(psMMUContext->hLock);
+
+	/* Free the top level MMU object - will be put on defer free list.
+	 * This has to be done before the step below that will empty the
+	 * defer-free list. */
 	_PxMemFree(psMMUContext,
-				&psMMUContext->sBaseLevelInfo.sMemDesc,
-				psMMUContext->psDevAttrs->eTopLevel);
+	           &psMMUContext->sBaseLevelInfo.sMemDesc,
+	           psMMUContext->psDevAttrs->eTopLevel);
+
+	/* Empty the temporary defer-free list of Px */
+	_FreeMMUMapping(psDevNode, &psMMUContext->psPhysMemCtx->sTmpMMUMappingHead);
+	PVR_ASSERT(dllist_is_empty(&psMMUContext->psPhysMemCtx->sTmpMMUMappingHead));
+
+	/* Empty the defer free list so the cleanup thread will
+	 * not have to access any MMU context related structures anymore */
+	dllist_foreach_node(&psCleanupData->sMMUCtxCleanupItemsHead,
+	                    psNode,
+	                    psNextNode)
+	{
+		MMU_CLEANUP_ITEM *psCleanup = IMG_CONTAINER_OF(psNode,
+		                                               MMU_CLEANUP_ITEM,
+		                                               sMMUCtxCleanupItem);
+
+		_FreeMMUMapping(psDevNode, &psCleanup->sMMUMappingHead);
+
+		dllist_remove_node(psNode);
+	}
+	PVR_ASSERT(dllist_is_empty(&psCleanupData->sMMUCtxCleanupItemsHead));
+
+	psCleanupData->bMMUContextExists = IMG_FALSE;
+
+	OSLockRelease(psCleanupData->hCleanupLock);
+
+	if (OSAtomicDecrement(&psCleanupData->iRef) == 0)
+	{
+		OSLockDestroy(psCleanupData->hCleanupLock);
+		OSFreeMem(psCleanupData);
+	}
 
 	/* Free physmem context */
 	RA_Delete(psMMUContext->psPhysMemCtx->psPhysMemRA);
@@ -2133,6 +2498,8 @@
 
 	OSFreeMem(psMMUContext->psPhysMemCtx);
 
+	OSLockRelease(psMMUContext->hLock);
+
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 	RemovePidOSidCoupling(OSGetCurrentClientProcessIDKM());
 #endif
@@ -2156,7 +2523,7 @@
            IMG_UINT32 uiProtFlags,
 		   IMG_DEVMEM_SIZE_T uDevVAddrAlignment,
 		   IMG_DEV_VIRTADDR *psDevVAddr,
-		   IMG_UINT8 uiLog2PageSize)
+		   IMG_UINT32 uiLog2PageSize)
 {
     PVRSRV_ERROR eError;
     IMG_DEV_VIRTADDR sDevVAddrEnd;
@@ -2245,11 +2612,27 @@
 	sDevVAddrEnd = sDevVAddr;
 	sDevVAddrEnd.uiAddr += uiSize;
 
+	/* The Cleanup lock has to be taken before the MMUContext hLock to
+	 * prevent deadlock scenarios. It is necessary only for parts of
+	 * _SetupCleanup_FreeMMUMapping though.*/
+	OSLockAcquire(psMMUContext->psPhysMemCtx->psCleanupData->hCleanupLock);
+
 	OSLockAcquire(psMMUContext->hLock);
 
-	_FreePageTables(psMMUContext, sDevVAddr, sDevVAddrEnd, uiLog2DataPageSize);
+	_FreePageTables(psMMUContext,
+	                sDevVAddr,
+	                sDevVAddrEnd,
+	                uiLog2DataPageSize);
+
+	_SetupCleanup_FreeMMUMapping(psMMUContext->psDevNode,
+	                             psMMUContext->psPhysMemCtx);
 
 	OSLockRelease(psMMUContext->hLock);
+
+	OSLockRelease(psMMUContext->psPhysMemCtx->psCleanupData->hCleanupLock);
+
+	return;
+
 }
 
 PVRSRV_ERROR
@@ -2260,9 +2643,9 @@
              IMG_UINT32 ui32PhysPgOffset,
              IMG_UINT32 ui32MapPageCount,
              IMG_UINT32 *paui32MapIndices,
-             IMG_UINT8 uiLog2PageSize)
+             IMG_UINT32 uiLog2PageSize)
 {
-	PVRSRV_ERROR eError = ~PVRSRV_OK;
+	PVRSRV_ERROR eError;
 	IMG_HANDLE hPriv;
 
 	MMU_Levelx_INFO *psLevel = NULL;
@@ -2294,8 +2677,8 @@
 	IMG_BOOL bNeedBacking = IMG_FALSE;
 
 #if defined(PDUMP)
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicAddress[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicAddress[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
 
 	PDUMPCOMMENT("Wire up Page Table entries to point to the Data Pages (%lld bytes)",
@@ -2441,17 +2824,28 @@
 
 #if defined(DEBUG)
 {
+			IMG_INT32	i32FeatureVal = 0;
 			IMG_UINT32 ui32BitLength = FloorLog2(sDevPAddr.uiAddr);
-			if (ui32BitLength > RGX_FEATURE_PHYS_BUS_WIDTH )
-			{
-				PVR_DPF((PVR_DBG_ERROR,"_MMU_MapPage Failed. The physical address bitlength (%d) "
-				         "is greater than what the chip can handle (%d).",
-				         ui32BitLength, RGX_FEATURE_PHYS_BUS_WIDTH));
 
-				PVR_ASSERT(ui32BitLength <= RGX_FEATURE_PHYS_BUS_WIDTH );
-				eError = PVRSRV_ERROR_INVALID_PARAMS;
-				goto e1;
-			}
+			i32FeatureVal = psMMUContext->psDevNode->pfnGetDeviceFeatureValue(psMMUContext->psDevNode, \
+														RGX_FEATURE_PHYS_BUS_WIDTH_BIT_MASK);
+			do {
+				/* i32FeatureVal can be negative for cases where this feature is undefined
+				 * In that situation we need to bail out than go ahead with debug comparison */
+				if(0 > i32FeatureVal)
+					break;
+
+				if (ui32BitLength > i32FeatureVal )
+				{
+					PVR_DPF((PVR_DBG_ERROR,"_MMU_MapPage Failed. The physical address bitlength (%d) "
+							 "is greater than what the chip can handle (%d).",
+							 ui32BitLength, i32FeatureVal));
+
+					PVR_ASSERT(ui32BitLength <= i32FeatureVal );
+					eError = PVRSRV_ERROR_INVALID_PARAMS;
+					goto e3;
+				}
+			}while(0);
 }
 #endif /*DEBUG*/
 
@@ -2481,9 +2875,10 @@
 				/* Flush if we moved to another psLevel, i.e. page table */
 				if (psPrevLevel != NULL)
 				{
-					eError = psMMUContext->psDevNode->pfnDevPxClean(&psPrevLevel->sMemDesc.psMapping->sMemHandle,
-																	uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
-																	(uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+					eError = psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+					                                                &psPrevLevel->sMemDesc.psMapping->sMemHandle,
+					                                                uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
+					                                                (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 					if (eError != PVRSRV_OK)
 						goto e3;
 				}
@@ -2504,7 +2899,7 @@
 			                   &sDevPAddr,
 			                   IMG_FALSE,
 #if defined(PDUMP)
-			                   (bValid)?aszMemspaceName:(psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName),
+			                   (bValid)?aszMemspaceName:(psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName),
 			                   (bValid)?aszSymbolicAddress:DUMMY_PAGE,
 			                   (bValid)?uiSymbolicAddrOffset:0,
 #endif /*PDUMP*/
@@ -2536,9 +2931,10 @@
 	/* Flush the last level we touched */
 	if (psLevel != NULL)
 	{
-		eError = psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
-														uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-														(uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+		eError = psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+		                                                &psLevel->sMemDesc.psMapping->sMemHandle,
+		                                                uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+		                                                (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 		if (eError != PVRSRV_OK)
 			goto e3;
 	}
@@ -2595,7 +2991,7 @@
                 IMG_DEV_VIRTADDR sDevVAddrBase,
                 IMG_UINT32 ui32PageCount,
                 IMG_UINT32 *pai32FreeIndices,
-                IMG_UINT8 uiLog2PageSize,
+                IMG_UINT32 uiLog2PageSize,
                 IMG_BOOL bDummyBacking)
 {
 	IMG_UINT32 uiPTEIndex = 0, ui32Loop=0;
@@ -2612,13 +3008,14 @@
 	IMG_DEV_PHYADDR sDummyPgDevPhysAddr;
 	IMG_BOOL bUnmap = IMG_TRUE;
 
-	sDummyPgDevPhysAddr.uiAddr = psMMUContext->psDevNode->sDummyPage.ui64DummyPgPhysAddr;
 #if defined(PDUMP)
 	PDUMPCOMMENT("Invalidate %d entries in page tables for virtual range: 0x%010llX to 0x%010llX",
 	             ui32PageCount,
 	             (IMG_UINT64)sDevVAddr.uiAddr,
 	             ((IMG_UINT64)sDevVAddr.uiAddr) + (uiPageSize*ui32PageCount)-1);
 #endif
+
+	sDummyPgDevPhysAddr.uiAddr = psMMUContext->psDevNode->sDummyPage.ui64DummyPgPhysAddr;
 	bUnmap = (bDummyBacking)?IMG_FALSE:IMG_TRUE;
 	/* Get PT and address configs */
 	_MMU_GetPTConfig(psMMUContext, (IMG_UINT32) uiLog2PageSize,
@@ -2666,7 +3063,8 @@
 			/* Flush if we moved to another psLevel, i.e. page table */
 			if (psPrevLevel != NULL)
 			{
-				psMMUContext->psDevNode->pfnDevPxClean(&psPrevLevel->sMemDesc.psMapping->sMemHandle,
+				psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+				                                       &psPrevLevel->sMemDesc.psMapping->sMemHandle,
 				                                       uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
 				                                       (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 			}
@@ -2686,7 +3084,7 @@
 		              (bDummyBacking)?&sDummyPgDevPhysAddr:&gsBadDevPhyAddr,
 		              bUnmap,
 #if defined(PDUMP)
-		              (bDummyBacking)?(psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName):NULL,
+		              (bDummyBacking)?(psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName):NULL,
 		              (bDummyBacking)?DUMMY_PAGE:NULL,
 		              0U,
 #endif
@@ -2704,7 +3102,8 @@
 	/* Flush the last level we touched */
 	if (psLevel != NULL)
 	{
-		psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
+		psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+		                                       &psLevel->sMemDesc.psMapping->sMemHandle,
 		                                       uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
 		                                       (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 	}
@@ -2735,7 +3134,7 @@
             const PMR *psPMR,
             IMG_DEVMEM_SIZE_T uiSizeBytes,
             PVRSRV_MEMALLOCFLAGS_T uiMappingFlags,
-            IMG_UINT8 uiLog2PageSize)
+            IMG_UINT32 uiLog2PageSize)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
 	IMG_UINT32 uiCount, i;
@@ -2755,8 +3154,8 @@
 	IMG_UINT32 uiFlushStart = 0;
 
 #if defined(PDUMP)
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicAddress[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicAddress[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
 	IMG_UINT32 ui32MappedCount = 0;
 	PDUMPCOMMENT("Wire up Page Table entries to point to the Data Pages (%lld bytes)", uiSizeBytes);
@@ -2787,8 +3186,8 @@
 		{
 			/* Should allocation fail, clean-up here before exit */
 			PVR_DPF((PVR_DBG_ERROR, "Failed to allocate PMR device PFN state"));
-			eError = PVRSRV_ERROR_OUT_OF_MEMORY;			
-			OSFreeMem(psDevPAddr);			
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			OSFreeMem(psDevPAddr);
 			goto e0;
 		}
     }
@@ -2852,18 +3251,26 @@
 	{
 #if defined(DEBUG)
 {
-			IMG_UINT32 ui32BitLength = FloorLog2(psDevPAddr[i].uiAddr);
-			if (ui32BitLength > RGX_FEATURE_PHYS_BUS_WIDTH )
-			{
-				PVR_DPF((PVR_DBG_ERROR,"_MMU_MapPage Failed. The physical address bitlength (%d) "
-				         "is greater than what the chip can handle (%d).",
-				         ui32BitLength, RGX_FEATURE_PHYS_BUS_WIDTH));
+	IMG_INT32	i32FeatureVal = 0;
+	IMG_UINT32 ui32BitLength = FloorLog2(psDevPAddr[i].uiAddr);
+	i32FeatureVal = psMMUContext->psDevNode->pfnGetDeviceFeatureValue(psMMUContext->psDevNode, \
+			RGX_FEATURE_PHYS_BUS_WIDTH_BIT_MASK);
+	do {
+		if(0 > i32FeatureVal)
+			break;
 
-				PVR_ASSERT(ui32BitLength <= RGX_FEATURE_PHYS_BUS_WIDTH );
-				eError = PVRSRV_ERROR_INVALID_PARAMS;
-				OSLockRelease(psMMUContext->hLock);
-				goto e1;
-			}
+		if (ui32BitLength > i32FeatureVal )
+		{
+			PVR_DPF((PVR_DBG_ERROR,"_MMU_MapPage Failed. The physical address bitlength (%d) "
+					"is greater than what the chip can handle (%d).",
+					ui32BitLength, i32FeatureVal));
+
+			PVR_ASSERT(ui32BitLength <= i32FeatureVal );
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			OSLockRelease(psMMUContext->hLock);
+			goto e1;
+		}
+	}while(0);
 }
 #endif /*DEBUG*/
 #if defined(PDUMP)
@@ -2906,9 +3313,10 @@
 		}
 		else
 		{
-			eError = psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
-															uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-															(uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+			eError = psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+			                                                &psLevel->sMemDesc.psMapping->sMemHandle,
+			                                                uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+			                                                (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 			if (eError != PVRSRV_OK)
 				goto e2;
 
@@ -2968,7 +3376,7 @@
 MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
                  IMG_DEV_VIRTADDR sDevVAddrBase,
                  IMG_UINT32 ui32PageCount,
-                 IMG_UINT8 uiLog2PageSize)
+                 IMG_UINT32 uiLog2PageSize)
 {
 	IMG_UINT32 uiPTEIndex = 0, ui32Loop=0;
 	IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
@@ -3057,23 +3465,23 @@
 			IMG_FALSE);
 
 #if defined (PDUMP)
-	PDumpMMUDumpPxEntries(MMU_LEVEL_1,
-						  psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName,
-						  psLevel->sMemDesc.pvCpuVAddr,
-						  psLevel->sMemDesc.sDevPAddr,
-						  uiPTEIndex,
-						  1,
-						  NULL,
-						  NULL,
-						  0,
-						  psConfig->uiBytesPerEntry,
-						  psConfig->uiAddrLog2Align,
-						  psConfig->uiAddrShift,
-						  psConfig->uiAddrMask,
-						  psConfig->uiProtMask,
-						  psConfig->uiValidEnMask,
-						  0,
-						  psMMUContext->psDevAttrs->eMMUType);
+		PDumpMMUDumpPxEntries(MMU_LEVEL_1,
+		                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+		                      psLevel->sMemDesc.pvCpuVAddr,
+		                      psLevel->sMemDesc.sDevPAddr,
+		                      uiPTEIndex,
+		                      1,
+		                      NULL,
+		                      NULL,
+		                      0,
+		                      psConfig->uiBytesPerEntry,
+		                      psConfig->uiAddrLog2Align,
+		                      psConfig->uiAddrShift,
+		                      psConfig->uiAddrMask,
+		                      psConfig->uiProtMask,
+		                      psConfig->uiValidEnMask,
+		                      0,
+		                      psMMUContext->psDevAttrs->eMMUType);
 #endif /*PDUMP*/
 
 		sDevVAddr.uiAddr += uiPageSize;
@@ -3086,9 +3494,10 @@
 		}
 		else
 		{
-			psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
-												   uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-												   (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+			psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+			                                       &psLevel->sMemDesc.psMapping->sMemHandle,
+			                                       uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+			                                       (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 
 			_MMU_GetPTInfo(psMMUContext, sDevVAddr, psDevVAddrConfig,
 						   &psLevel, &uiPTEIndex);
@@ -3141,8 +3550,8 @@
 	IMG_BOOL bValid;
 
 #if defined(PDUMP)
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicAddress[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicAddress[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
 	IMG_DEVMEM_OFFSET_T uiNextSymName;
 
@@ -3172,7 +3581,13 @@
 		if (bMakeValid == IMG_TRUE)
 		{
 			/* Only set valid if physical address exists (sparse allocs might have none)*/
-			PMR_IsOffsetValid(psPMR, i<<uiLog2PageSize, &bValid);
+			eError = PMR_IsOffsetValid(psPMR, uiLog2PageSize, 1, i<<uiLog2PageSize, &bValid);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Cannot determine validity of page table entries page"));
+				goto e_exit;
+			}
+
 			if (bValid)
 			{
 				if (psConfig->uiBytesPerEntry == 8)
@@ -3210,30 +3625,29 @@
 		}
 
 #if defined(PDUMP)
-
 		PMR_PDumpSymbolicAddr(psPMR, i<<uiLog2PageSize,
-							   sizeof(aszMemspaceName), &aszMemspaceName[0],
-							   sizeof(aszSymbolicAddress), &aszSymbolicAddress[0],
-							   &uiSymbolicAddrOffset,
-							   &uiNextSymName);
+		                      sizeof(aszMemspaceName), &aszMemspaceName[0],
+		                      sizeof(aszSymbolicAddress), &aszSymbolicAddress[0],
+		                      &uiSymbolicAddrOffset,
+		                      &uiNextSymName);
 
 		PDumpMMUDumpPxEntries(MMU_LEVEL_1,
-							  psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName,
-							  psLevel->sMemDesc.pvCpuVAddr,
-							  psLevel->sMemDesc.sDevPAddr,
-							  uiPTIndex,
-							  1,
-							  aszMemspaceName,
-							  aszSymbolicAddress,
-							  uiSymbolicAddrOffset,
-							  psConfig->uiBytesPerEntry,
-							  psConfig->uiAddrLog2Align,
-							  psConfig->uiAddrShift,
-							  psConfig->uiAddrMask,
-							  psConfig->uiProtMask,
-							  psConfig->uiValidEnMask,
-							  0,
-							  psMMUContext->psDevAttrs->eMMUType);
+		                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+		                      psLevel->sMemDesc.pvCpuVAddr,
+		                      psLevel->sMemDesc.sDevPAddr,
+		                      uiPTIndex,
+		                      1,
+		                      aszMemspaceName,
+		                      aszSymbolicAddress,
+		                      uiSymbolicAddrOffset,
+		                      psConfig->uiBytesPerEntry,
+		                      psConfig->uiAddrLog2Align,
+		                      psConfig->uiAddrShift,
+		                      psConfig->uiAddrMask,
+		                      psConfig->uiProtMask,
+		                      psConfig->uiValidEnMask,
+		                      0,
+		                      psMMUContext->psDevAttrs->eMMUType);
 #endif /*PDUMP*/
 
 		sDevVAddr.uiAddr += uiPageSize;
@@ -3247,9 +3661,10 @@
 		else
 		{
 
-			eError = psMMUContext->psDevNode->pfnDevPxClean(&psLevel->sMemDesc.psMapping->sMemHandle,
-															uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-															(uiPTIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+			eError = psMMUContext->psDevNode->pfnDevPxClean(psMMUContext->psDevNode,
+			                                                &psLevel->sMemDesc.psMapping->sMemHandle,
+			                                                uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+			                                                (uiPTIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 			if (eError != PVRSRV_OK)
 				goto e_exit;
 
@@ -3309,20 +3724,22 @@
     MMU_SetOSid, MMU_GetOSid
 */
 
-void MMU_SetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg)
+void MMU_SetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg, IMG_BOOL bOSidAxiProt)
 {
-	psMMUContext->ui32OSid = ui32OSid;
-	psMMUContext->ui32OSidReg = ui32OSidReg;
+    psMMUContext->ui32OSid     = ui32OSid;
+    psMMUContext->ui32OSidReg  = ui32OSidReg;
+    psMMUContext->bOSidAxiProt = bOSidAxiProt;
 
     return ;
 }
 
-void MMU_GetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 *pui32OSid, IMG_UINT32 *pui32OSidReg)
+void MMU_GetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 *pui32OSid, IMG_UINT32 *pui32OSidReg, IMG_BOOL *pbOSidAxiProt)
 {
-	*pui32OSid = psMMUContext->ui32OSid;
-	*pui32OSidReg = psMMUContext->ui32OSidReg;
+    *pui32OSid     = psMMUContext->ui32OSid;
+    *pui32OSidReg  = psMMUContext->ui32OSidReg;
+    *pbOSidAxiProt = psMMUContext->bOSidAxiProt;
 
-	return ;
+    return ;
 }
 
 #endif
@@ -3353,7 +3770,7 @@
 
 	/*
 		At this point we don't know the page size so assume it's 4K.
-		When we get the the PD level (MMU_LEVEL_2) we can check to see
+		When we get the PD level (MMU_LEVEL_2) we can check to see
 		if this assumption is correct.
 	*/
 	eError = psDevAttrs->pfnGetPageSizeConfiguration(12,
@@ -3611,7 +4028,7 @@
                          psDevId->pszPDumpDevName,
                          psMMUContext->sBaseLevelInfo.sMemDesc.bValid?"MMUPC_":"XXX",
                          ui64PhysAddr);
-    
+
     if (uiCount + 1 > uiPDumpSymbolicNameBufferSize)
     {
         return PVRSRV_ERROR_INVALID_PARAMS;
@@ -3630,28 +4047,27 @@
                           IMG_UINT32 ui32WordSize,
                           IMG_UINT32 ui32AlignShift,
                           IMG_UINT32 ui32Shift,
-						  PDUMP_FLAGS_T uiPdumpFlags)
+                          PDUMP_FLAGS_T uiPdumpFlags)
 {
-    PVRSRV_ERROR eError;
-    IMG_CHAR aszPageCatBaseSymbolicAddr[100];
-	const IMG_CHAR *pszPDumpDevName = psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName;
-
+	PVRSRV_ERROR eError;
+	IMG_CHAR aszPageCatBaseSymbolicAddr[100];
+	const IMG_CHAR *pszPDumpDevName = psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName;
 
 	eError = MMU_ContextDerivePCPDumpSymAddr(psMMUContext,
                                              &aszPageCatBaseSymbolicAddr[0],
                                              sizeof(aszPageCatBaseSymbolicAddr));
-    if (eError ==  PVRSRV_OK)
-    {
+	if (eError ==  PVRSRV_OK)
+	{
 		eError = PDumpWriteSymbAddress(pszSpaceName,
-										   uiOffset,
-										   aszPageCatBaseSymbolicAddr,
-										   0, /* offset -- Could be non-zero for var. pgsz */
-										   pszPDumpDevName,
-										   ui32WordSize,
-										   ui32AlignShift,
-										   ui32Shift,
-										   uiPdumpFlags | PDUMP_FLAGS_CONTINUOUS);
-    }
+		                               uiOffset,
+		                               aszPageCatBaseSymbolicAddr,
+		                               0, /* offset -- Could be non-zero for var. pgsz */
+		                               pszPDumpDevName,
+		                               ui32WordSize,
+		                               ui32AlignShift,
+		                               ui32Shift,
+		                               uiPdumpFlags | PDUMP_FLAGS_CONTINUOUS);
+	}
 
     return eError;
 }
@@ -3680,7 +4096,7 @@
 
 /*
 	MMU_ReleasePDumpMMUContext
-*/ 
+*/
 PVRSRV_ERROR MMU_ReleasePDumpMMUContext(MMU_CONTEXT *psMMUContext)
 {
 	PVRSRV_DEVICE_IDENTIFIER *psDevId = &psMMUContext->psDevNode->sDevId;
diff --git a/drivers/staging/imgtec/rogue/mmu_common.h b/drivers/staging/imgtec/rogue/mmu_common.h
index 84e481f..32483b6 100644
--- a/drivers/staging/imgtec/rogue/mmu_common.h
+++ b/drivers/staging/imgtec/rogue/mmu_common.h
@@ -116,6 +116,8 @@
 {
 	PDUMP_MMU_TYPE eMMUType;
 
+	IMG_CHAR *pszMMUPxPDumpMemSpaceName;
+
 	/*! The type of the top level object */
 	MMU_LEVEL eTopLevel;
 
@@ -321,7 +323,7 @@
            IMG_UINT32 uiProtFlags,
            IMG_DEVMEM_SIZE_T uDevVAddrAlignment,
            IMG_DEV_VIRTADDR *psDevVAddr,
-           IMG_UINT8 uiLog2PageSize);
+           IMG_UINT32 uiLog2PageSize);
 
 
 /*************************************************************************/ /*!
@@ -382,7 +384,7 @@
              IMG_UINT32 ui32PhysPgOffset,
              IMG_UINT32 ui32MapPageCount,
              IMG_UINT32 *paui32MapIndices,
-             IMG_UINT8 uiLog2PageSize);
+             IMG_UINT32 uiLog2PageSize);
 
 /*************************************************************************/ /*!
 @Function       MMU_UnmapPages
@@ -415,7 +417,7 @@
                 IMG_DEV_VIRTADDR sDevVAddr,
                 IMG_UINT32 ui32PageCount,
                 IMG_UINT32 *pai32UnmapIndicies,
-                IMG_UINT8 uiLog2PageSize,
+                IMG_UINT32 uiLog2PageSize,
                 IMG_BOOL bDummyBacking);
 
 /*************************************************************************/ /*!
@@ -445,7 +447,7 @@
                 const PMR *psPMR,
                 IMG_DEVMEM_SIZE_T uiSizeBytes,
                 PVRSRV_MEMALLOCFLAGS_T uiMappingFlags,
-                IMG_UINT8 uiLog2PageSize);
+                IMG_UINT32 uiLog2PageSize);
 
 /*************************************************************************/ /*!
 @Function       MMU_UnmapPMRFast
@@ -468,7 +470,7 @@
 MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
                  IMG_DEV_VIRTADDR sDevVAddrBase,
                  IMG_UINT32 ui32PageCount,
-                 IMG_UINT8 uiLog2PageSize);
+                 IMG_UINT32 uiLog2PageSize);
 
 /*************************************************************************/ /*!
 @Function       MMU_ChangeValidity
@@ -546,28 +548,34 @@
 
 @Input			ui32OSidReg				The value that the firmware will assign to the
 										registers.
+
+@Input          bOSidAxiProt            Toggles whether the AXI prot bit will be set or
+                                        not.
 @Return None
 */
 /***********************************************************************************/
 
-void MMU_SetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg);
+void MMU_SetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg, IMG_BOOL bOSidAxiProt);
 
 /***********************************************************************************/ /*!
 @Function       MMU_GetOSid
 
 @Description    Retrieve the OSid associated with the MMU context.
 
-@Input          psMMUContext            MMU context to store the OSid on
+@Input          psMMUContext            MMU context in which the OSid is stored
 
-@Output			ui32OSid                the OSid in question
+@Output			pui32OSid               The OSid in question
 
-@Output			ui32OSidReg				The OSid that the firmware will assign to the
-										registers
+@Output			pui32OSidReg            The OSid that the firmware will assign to the
+                                        registers.
+
+@Output         pbOSidAxiProt           Toggles whether the AXI prot bit will be set or
+                                        not.
 @Return None
 */
 /***********************************************************************************/
 
-void MMU_GetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 * pui32OSid, IMG_UINT32 * pui32OSidReg);
+void MMU_GetOSids(MMU_CONTEXT *psMMUContext, IMG_UINT32 * pui32OSid, IMG_UINT32 * pui32OSidReg, IMG_BOOL *pbOSidAxiProt);
 #endif
 
 /*************************************************************************/ /*!
diff --git a/drivers/staging/imgtec/rogue/module_common.c b/drivers/staging/imgtec/rogue/module_common.c
index c399e58..edee32c 100644
--- a/drivers/staging/imgtec/rogue/module_common.c
+++ b/drivers/staging/imgtec/rogue/module_common.c
@@ -40,13 +40,6 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include <linux/version.h>
-
-#if (!defined(LDM_PLATFORM) && !defined(LDM_PCI)) || \
-	(defined(LDM_PLATFORM) && defined(LDM_PCI))
-	#error "LDM_PLATFORM or LDM_PCI must be defined"
-#endif
-
 #include <linux/module.h>
 
 #include "pvr_debugfs.h"
@@ -59,10 +52,8 @@
 #include "module_common.h"
 #include "pvrsrv.h"
 #include "pvr_hwperf.h"
-
-#if defined(SUPPORT_DRM)
-#include "pvr_drm.h"
-#endif
+#include "pvr_drv.h"
+#include <linux/moduleparam.h>
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 #include "pvr_sync.h"
@@ -77,321 +68,130 @@
 #endif
 
 #if defined(SUPPORT_KERNEL_SRVINIT)
+#include "km_apphint.h"
 #include "srvinit.h"
 #endif
 
-#if defined(PVRSRV_NEED_PVR_DPF) || defined(DEBUG)
-#include <linux/moduleparam.h>
-#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(DEBUG) */
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+#include "vmm_pvz_server.h"
+#if defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
+#include "vmm_pvz_mdm.h"
+#endif
+#endif
+#endif
 
 #if defined(PVRSRV_NEED_PVR_DPF)
 extern IMG_UINT32 gPVRDebugLevel;
 module_param(gPVRDebugLevel, uint, 0644);
-MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
+MODULE_PARM_DESC(gPVRDebugLevel,
+				 "Sets the level of debug output (default 0x7)");
 #endif /* defined(PVRSRV_NEED_PVR_DPF) */
 
 #if defined(DEBUG)
 extern IMG_UINT32 gPMRAllocFail;
 module_param(gPMRAllocFail, uint, 0644);
 MODULE_PARM_DESC(gPMRAllocFail, "When number of PMR allocs reaches"
-        " this value, it will fail (default value is 0 which"
-        "means that alloc function will behave normally).");
+				 " this value, it will fail (default value is 0 which"
+				 "means that alloc function will behave normally).");
 #endif /* defined(DEBUG) */
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-/* 
- * Kernel symbol clash if re-exported by guest drivers in multi-driver model
- */
-#else
-/* 
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+extern unsigned int gui32RGXLoadTimeDevCount;
+
+extern char *gazRGXBVNCList[PVRSRV_MAX_DEVICES];
+module_param_array_named(RGXBVNC, gazRGXBVNCList, charp, &gui32RGXLoadTimeDevCount, S_IRUGO);
+MODULE_PARM_DESC(RGXBVNC, "Array of comma separated strings that define BVNC info of the devices. "
+		"module parameter usage is RGXBVNC=x.x.x.x,y.y.y.y etc");
+#endif
+
+#if defined(SUPPORT_DISPLAY_CLASS)
+/* Display class interface */
+#include "kerneldisplay.h"
+EXPORT_SYMBOL(DCRegisterDevice);
+EXPORT_SYMBOL(DCUnregisterDevice);
+EXPORT_SYMBOL(DCDisplayConfigurationRetired);
+EXPORT_SYMBOL(DCDisplayHasPendingCommand);
+EXPORT_SYMBOL(DCImportBufferAcquire);
+EXPORT_SYMBOL(DCImportBufferRelease);
+
+/* Physmem interface (required by LMA DC drivers) */
+#include "physheap.h"
+EXPORT_SYMBOL(PhysHeapAcquire);
+EXPORT_SYMBOL(PhysHeapRelease);
+EXPORT_SYMBOL(PhysHeapGetType);
+EXPORT_SYMBOL(PhysHeapRegionGetCpuPAddr);
+EXPORT_SYMBOL(PhysHeapRegionGetSize);
+EXPORT_SYMBOL(PhysHeapCpuPAddrToDevPAddr);
+
+EXPORT_SYMBOL(PVRSRVSystemInstallDeviceLISR);
+EXPORT_SYMBOL(PVRSRVSystemUninstallDeviceLISR);
+#endif
+
+/* Host para-virtz call handlers  (required by guest drivers) */
+#if defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+EXPORT_SYMBOL(PvzServerCreateDevConfig);
+EXPORT_SYMBOL(PvzServerDestroyDevConfig);
+EXPORT_SYMBOL(PvzServerCreateDevConfig2);
+EXPORT_SYMBOL(PvzServerDestroyDevConfig2);
+EXPORT_SYMBOL(PvzServerCreateDevPhysHeaps);
+EXPORT_SYMBOL(PvzServerDestroyDevPhysHeaps);
+EXPORT_SYMBOL(PvzServerMapDevPhysHeap);
+EXPORT_SYMBOL(PvzServerUnmapDevPhysHeap);
+EXPORT_SYMBOL(PvzServerCreateDevPhysHeaps2);
+EXPORT_SYMBOL(PvzServerDestroyDevPhysHeaps2);
+#endif
+#endif
+
+#if !(defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL))
+#include "pvr_notifier.h"
+
+/*
  * Export some symbols that may be needed by other drivers
- * 
+ *
  * When support for GPU virtualization is present and the multi-driver
- * model (multi-drivers in same OS instance) is being used, then only
- * the hyperv driver is a true device drivers (i.e. is registered with
+ * model (multiple drivers in same OS kernel) is being used, then only
+ * the host driver is a true device drivers (i.e. is registered with
  * the kernel to manage the physical device), the other guest drivers
  * are all modules.
  */
 EXPORT_SYMBOL(PVRSRVCheckStatus);
+EXPORT_SYMBOL(PVRSRVGetDriverStatus);
 EXPORT_SYMBOL(PVRSRVGetErrorStringKM);
 
 #include "rgxapi_km.h"
+#if defined(SUPPORT_SHARED_SLC) && !defined(PVRSRV_GPUVIRT_GUESTDRV)
+/* Guest drivers do not perform device management so RGXInitSLC is absent */
+EXPORT_SYMBOL(RGXInitSLC);
+#endif
+
 EXPORT_SYMBOL(RGXHWPerfConnect);
 EXPORT_SYMBOL(RGXHWPerfDisconnect);
 EXPORT_SYMBOL(RGXHWPerfControl);
 EXPORT_SYMBOL(RGXHWPerfConfigureAndEnableCounters);
 EXPORT_SYMBOL(RGXHWPerfDisableCounters);
-EXPORT_SYMBOL(RGXHWPerfAcquireData);
-EXPORT_SYMBOL(RGXHWPerfReleaseData);
+EXPORT_SYMBOL(RGXHWPerfAcquireEvents);
+EXPORT_SYMBOL(RGXHWPerfReleaseEvents);
+EXPORT_SYMBOL(RGXHWPerfConvertCRTimeStamp);
+#if defined(SUPPORT_KERNEL_HWPERF_TEST)
+EXPORT_SYMBOL(OSAddTimer);
+EXPORT_SYMBOL(OSEnableTimer);
+EXPORT_SYMBOL(OSDisableTimer);
+EXPORT_SYMBOL(OSRemoveTimer);
 #endif
-
-DEFINE_MUTEX(gPVRSRVLock);
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-/* Functionality is n/a for guest drivers in multi-driver model */
-#else
-static DEFINE_MUTEX(gsPMMutex);
-static IMG_BOOL bDriverIsSuspended;
-static IMG_BOOL bDriverIsShutdown;
-
-#if !defined(SUPPORT_DRM_EXT)
-LDM_DEV *gpsPVRLDMDev;
 #endif
 
-DEFINE_MUTEX(gGlobalLookupPMRLock);
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVDriverShutdown
-
- @Description
-
- Suspend device operation for system shutdown.  This is called as part of the
- system halt/reboot process.  The driver is put into a quiescent state by
- setting the power state to D3.
-
- @input pDevice - the device for which shutdown is requested
-
- @Return nothing
-
-*****************************************************************************/
-void PVRSRVDriverShutdown(LDM_DEV *pDevice)
-{
-	PVR_TRACE(("PVRSRVDriverShutdown (pDevice=%p)", pDevice));
-
-	mutex_lock(&gsPMMutex);
-
-	if (!bDriverIsShutdown && !bDriverIsSuspended)
-	{
-		/*
-		 * Take the bridge mutex, and never release it, to stop
-		 * processes trying to use the driver after it has been
-		 * shutdown.
-		 */
-		OSAcquireBridgeLock();
-
-		(void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_OFF, IMG_TRUE);
-	}
-
-	bDriverIsShutdown = IMG_TRUE;
-
-	/* The bridge mutex is held on exit */
-	mutex_unlock(&gsPMMutex);
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVDriverSuspend
-
- @Description
-
- Suspend device operation.
-
- @input pDevice - the device for which resume is requested
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-int PVRSRVDriverSuspend(struct device *pDevice)
-{
-	int res = 0;
-
-	PVR_TRACE(( "PVRSRVDriverSuspend (pDevice=%p)", pDevice));
-
-	mutex_lock(&gsPMMutex);
-
-	if (!bDriverIsSuspended && !bDriverIsShutdown)
-	{
-		OSAcquireBridgeLock();
-
-		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_OFF, IMG_TRUE) == PVRSRV_OK)
-		{
-			bDriverIsSuspended = IMG_TRUE;
-			OSSetDriverSuspended();
-		}
-		else
-		{
-			res = -EINVAL;
-		}
-		OSReleaseBridgeLock();
-	}
-
-	mutex_unlock(&gsPMMutex);
-
-	return res;
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVDriverResume
-
- @Description
-
- Resume device operation.
-
- @input pDevice - the device for which resume is requested
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-int PVRSRVDriverResume(struct device *pDevice)
-{
-	int res = 0;
-
-	PVR_TRACE(("PVRSRVDriverResume (pDevice=%p)", pDevice));
-
-	mutex_lock(&gsPMMutex);
-
-	if (bDriverIsSuspended && !bDriverIsShutdown)
-	{
-		OSAcquireBridgeLock();
-
-		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_ON, IMG_TRUE) == PVRSRV_OK)
-		{
-			bDriverIsSuspended = IMG_FALSE;
-			OSClearDriverSuspended();
-		}
-		else
-		{
-			res = -EINVAL;
-		}
-		OSReleaseBridgeLock();
-	}
-
-	mutex_unlock(&gsPMMutex);
-
-	return res;
-}
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL) */
-
-#if defined(SUPPORT_DRM)
-#define PRIVATE_DATA(pFile) (PVR_DRM_FILE_FROM_FILE(pFile)->driver_priv)
-#else
-#define PRIVATE_DATA(pFile) ((pFile)->private_data)
-#endif
-
-static void *PVRSRVFindRGXDevNode(PVRSRV_DEVICE_NODE *psDevNode)
-{
-	if (psDevNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
-	{
-		return psDevNode;
-	}
-
-	return NULL;
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVCommonOpen
-
- @Description
-
- Open the PVR services node.
-
- @input pFile - the file handle data for the actual file being opened
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-int PVRSRVCommonOpen(struct file *pFile)
-{
-	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-	ENV_CONNECTION_PRIVATE_DATA sPrivData;
-	void *pvConnectionData;
-	PVRSRV_ERROR eError;
-	int iErr;
-
-	OSAcquireBridgeLock();
-
-	if (!psPVRSRVData)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: No device data", __func__));
-		iErr = -ENODEV;
-		goto ErrorUnlock;
-	}
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	eError = SrvInit();
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: SrvInit failed (%d)", __func__, eError));
-		iErr = -ENODEV;
-		goto ErrorUnlock;
-	}
-#endif
-
-	sPrivData.psDevNode = List_PVRSRV_DEVICE_NODE_Any(psPVRSRVData->psDeviceNodeList,
-							  PVRSRVFindRGXDevNode);
-	if (!sPrivData.psDevNode)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get device node", __func__));
-		iErr = -ENODEV;
-		goto ErrorUnlock;
-	}
-
-	sPrivData.psFile = pFile;
-
-	/*
-	 * Here we pass the file pointer which will passed through to our
-	 * OSConnectionPrivateDataInit function where we can save it so
-	 * we can back reference the file structure from it's connection
-	 */
-	eError = PVRSRVConnectionConnect(&pvConnectionData, (void *) &sPrivData);
-	if (eError != PVRSRV_OK)
-	{
-		iErr = -ENOMEM;
-		goto ErrorUnlock;
-	}
-
-	PRIVATE_DATA(pFile) = pvConnectionData;
-	OSReleaseBridgeLock();
-
-	return 0;
-
-ErrorUnlock:
-	OSReleaseBridgeLock();
-	return iErr;
-}
-
-/*!
-******************************************************************************
-
- @Function		PVRSRVCommonRelease
-
- @Description
-
- Release access the PVR services node - called when a file is closed, whether
- at exit or using close(2) system call.
-
- @input pFile - the file handle data for the actual file being released
-
- @Return 0 for success or <0 for an error.
-
-*****************************************************************************/
-void PVRSRVCommonRelease(struct file *pFile)
-{
-	void *pvConnectionData;
-
-	OSAcquireBridgeLock();
-
-	pvConnectionData = PRIVATE_DATA(pFile);
-	if (pvConnectionData)
-	{
-		PVRSRVConnectionDisconnect(pvConnectionData);
-		PRIVATE_DATA(pFile) = NULL;
-	}
-
-	OSReleaseBridgeLock();
-}
-
-
 CONNECTION_DATA *LinuxConnectionFromFile(struct file *pFile)
 {
-	return (pFile)? PRIVATE_DATA(pFile): NULL;
+	if (pFile)
+	{
+		struct drm_file *psDRMFile = pFile->private_data;
+
+		return psDRMFile->driver_priv;
+	}
+
+	return NULL;
 }
 
 struct file *LinuxFileFromConnection(CONNECTION_DATA *psConnection)
@@ -404,19 +204,24 @@
 	return psEnvConnection->psFile;
 }
 
-/*!
-*****************************************************************************
-
- @Function		PVRSRVDriverInit
-
- @Description	Do the driver-specific initialisation (as opposed to
-              the device-specific initialisation.)
-
-*****************************************************************************/
-int PVRSRVDriverInit(void)
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDriverInit
+@Description  Common one time driver initialisation
+@Return       int           0 on success and a Linux error code otherwise
+*/ /***************************************************************************/
+int PVRSRVCommonDriverInit(void)
 {
+	PVRSRV_ERROR pvrerr;
 	int error = 0;
 
+#if defined(PDUMP)
+	error = dbgdrv_init();
+	if (error != 0)
+	{
+		return error;
+	}
+#endif
+
 	error = PVRDebugFSInit();
 	if (error != 0)
 	{
@@ -437,19 +242,38 @@
 
 	LinuxBridgeInit();
 
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	error = pvr_apphint_init();
+	if (error != 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: failed AppHint setup(%d)",
+			 __func__, error));
+	}
+#endif
+
+	pvrerr = PVRSRVDriverInit();
+	if (pvrerr != PVRSRV_OK)
+	{
+		return -ENODEV;
+	}
+
 	return 0;
 }
 
-/*!
-*****************************************************************************
-
- @Function		PVRSRVDriverDeinit
-
- @Description	Unwind PVRSRVDriverInit
-
-*****************************************************************************/
-void PVRSRVDriverDeinit(void)
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDriverDeinit
+@Description  Common one time driver de-initialisation
+@Return       void
+*/ /***************************************************************************/
+void PVRSRVCommonDriverDeinit(void)
 {
+	PVRSRVDriverDeInit();
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	pvr_apphint_deinit();
+#endif
+
 	LinuxBridgeDeInit();
 
 	PVROSFuncDeInit();
@@ -458,38 +282,47 @@
 	PVRSRVStatsDestroy();
 #endif
 	PVRDebugFSDeInit();
+
+#if defined(PDUMP)
+	dbgdrv_cleanup();
+#endif
 }
 
-/*!
-*****************************************************************************
-
- @Function		PVRSRVDeviceInit
-
- @Description	Do the initialisation we have to do after registering the device
-
-*****************************************************************************/
-int PVRSRVDeviceInit(void)
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceInit
+@Description  Common device related initialisation.
+@Input        psDeviceNode  The device node for which initialisation should be
+                            performed
+@Return       int           0 on success and a Linux error code otherwise
+*/ /***************************************************************************/
+int PVRSRVCommonDeviceInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 	int error = 0;
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 	{
-		PVRSRV_ERROR eError = pvr_sync_init();
+		PVRSRV_ERROR eError = pvr_sync_init(psDeviceNode);
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create sync (%d)", eError));
+			PVR_DPF((PVR_DBG_ERROR, "%s: unable to create sync (%d)",
+					 __func__, eError));
 			return -EBUSY;
 		}
 	}
 #endif
 
 #if defined(SUPPORT_BUFFER_SYNC)
-	error = pvr_buffer_sync_init();
-	if (error != 0)
+	psDeviceNode->psBufferSyncContext =
+		pvr_buffer_sync_context_create(psDeviceNode);
+	if (IS_ERR(psDeviceNode->psBufferSyncContext))
 	{
+		error = PTR_ERR(psDeviceNode->psBufferSyncContext);
+		psDeviceNode->psBufferSyncContext = NULL;
+
 		PVR_DPF((PVR_DBG_ERROR,
-			 "%s: unable to initialise buffer_sync support (%d)",
-			 __func__, error));
+				 "%s: unable to initialise buffer_sync support (%d)",
+				 __func__, error));
 		return error;
 	}
 #endif
@@ -497,41 +330,262 @@
 	error = PVRDebugCreateDebugFSEntries();
 	if (error != 0)
 	{
-		PVR_DPF((PVR_DBG_WARNING, "PVRCore_Init: failed to create default debugfs entries (%d)", error));
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: failed to create default debugfs entries (%d)",
+			 __func__, error));
 	}
 
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+	error = PVRGpuTraceInit(psDeviceNode);
+	if (error != 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: failed to initialise PVR GPU Tracing (%d)",
+			 __func__, error));
+	}
+#endif
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	/* register the AppHint device control before device initialisation
+	 * so individual AppHints can be configured during the init phase
+	 */
+	error = pvr_apphint_device_register(psDeviceNode);
+	if (error != 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: failed to initialise device AppHints (%d)",
+			 __func__, error));
+	}
+#else
 	error = PVRSRVHWperfCreateDebugFs();
 	if (error != 0)
 	{
-		PVR_DPF((PVR_DBG_WARNING, "PVRCore_Init: failed to initialise HWPerf debugfs (%d)", error));
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: failed to initialise HWPerf debugfs (%d)",
+			  __func__, error));
+	}
+#endif
+
+	/*Initialize the device dependent bridges */
+
+	error = DeviceDepBridgeInit(psDevInfo->sDevFeatureCfg.ui64Features);
+	if (error != 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: Device dependent bridge initialization failed (%d)",
+			 __func__, error));
 	}
 
 	return 0;
 }
 
-/*!
-*****************************************************************************
-
- @Function		PVRSRVDeviceDeinit
-
- @Description	Unwind PVRSRVDeviceInit
-
-*****************************************************************************/
-void PVRSRVDeviceDeinit(void)
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceDeinit
+@Description  Common device related de-initialisation.
+@Input        psDeviceNode  The device node for which de-initialisation should
+                            be performed
+@Return       void
+*/ /***************************************************************************/
+void PVRSRVCommonDeviceDeinit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
+	int error = 0;
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	pvr_apphint_device_unregister(psDeviceNode);
+#else
 	PVRSRVHWperfDestroyDebugFs();
+#endif
 
 #if defined(SUPPORT_GPUTRACE_EVENTS)
-	PVRGpuTraceDeInit();
+	PVRGpuTraceDeInit(psDeviceNode);
 #endif
 
 	PVRDebugRemoveDebugFSEntries();
 
 #if defined(SUPPORT_BUFFER_SYNC)
-	pvr_buffer_sync_deinit();
+	pvr_buffer_sync_context_destroy(psDeviceNode->psBufferSyncContext);
 #endif
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 	pvr_sync_deinit();
 #endif
+
+	error = DeviceDepBridgeDeInit(psDevInfo->sDevFeatureCfg.ui64Features);
+	if (error != 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+			 "%s: Device dependent bridge deinitialization failed (%d)",
+			 __func__, error));
+	}
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceShutdown
+@Description  Common device shutdown.
+@Input        psDeviceNode  The device node representing the device that should
+                            be shutdown
+@Return       void
+*/ /***************************************************************************/
+
+void PVRSRVCommonDeviceShutdown(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/*
+	 * Take the bridge mutex, and never release it, to stop processes trying to
+	 * use the driver after it has been shutdown.
+	 */
+	OSAcquireBridgeLock();
+
+	(void) PVRSRVSetDeviceSystemPowerState(psDeviceNode,
+										   PVRSRV_SYS_POWER_STATE_OFF);
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceSuspend
+@Description  Common device suspend.
+@Input        psDeviceNode  The device node representing the device that should
+                            be suspended
+@Return       int           0 on success and a Linux error code otherwise
+*/ /***************************************************************************/
+int PVRSRVCommonDeviceSuspend(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/*
+	 * OSSetDriverSuspended prevents processes from using the driver while it's
+	 * suspended (this is needed for Android). Acquire the bridge lock first to
+	 * ensure the driver isn't currently in use.
+	 */
+	OSAcquireBridgeLock();
+	OSSetDriverSuspended();
+	OSReleaseBridgeLock();
+
+	if (PVRSRVSetDeviceSystemPowerState(psDeviceNode,
+										PVRSRV_SYS_POWER_STATE_OFF) != PVRSRV_OK)
+	{
+		OSClearDriverSuspended();
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceResume
+@Description  Common device resume.
+@Input        psDeviceNode  The device node representing the device that should
+                            be resumed
+@Return       int           0 on success and a Linux error code otherwise
+*/ /***************************************************************************/
+int PVRSRVCommonDeviceResume(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if (PVRSRVSetDeviceSystemPowerState(psDeviceNode,
+										PVRSRV_SYS_POWER_STATE_ON) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+
+	OSClearDriverSuspended();
+
+	/*
+	 * Reprocess the device queues in case commands were blocked during
+	 * suspend.
+	 */
+	if (psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_ACTIVE)
+	{
+		PVRSRVCheckStatus(NULL);
+	}
+
+	return 0;
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceOpen
+@Description  Common device open.
+@Input        psDeviceNode  The device node representing the device being
+                            opened by a user mode process
+@Input        psDRMFile     The DRM file data that backs the file handle
+                            returned to the user mode process
+@Return       int           0 on success and a Linux error code otherwise
+*/ /***************************************************************************/
+int PVRSRVCommonDeviceOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
+						   struct drm_file *psDRMFile)
+{
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	ENV_CONNECTION_PRIVATE_DATA sPrivData;
+	void *pvConnectionData;
+	PVRSRV_ERROR eError;
+	int iErr = 0;
+
+	OSAcquireBridgeLock();
+
+	if (!psPVRSRVData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: No device data", __func__));
+		iErr = -ENODEV;
+		goto e1;
+	}
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	if (psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_INIT)
+	{
+		eError = PVRSRVDeviceInitialise(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise device (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+			iErr = -ENODEV;
+			goto e1;
+		}
+	}
+#endif
+
+	sPrivData.psDevNode = psDeviceNode;
+	sPrivData.psFile = psDRMFile->filp;
+
+	/*
+	 * Here we pass the file pointer which will passed through to our
+	 * OSConnectionPrivateDataInit function where we can save it so
+	 * we can back reference the file structure from it's connection
+	 */
+	eError = PVRSRVConnectionConnect(&pvConnectionData, (void *) &sPrivData);
+	if (eError != PVRSRV_OK)
+	{
+		iErr = -ENOMEM;
+		goto e1;
+	}
+
+	psDRMFile->driver_priv = pvConnectionData;
+	OSReleaseBridgeLock();
+
+out:
+	return iErr;
+e1:
+	OSReleaseBridgeLock();
+	goto out;
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVCommonDeviceRelease
+@Description  Common device release.
+@Input        psDeviceNode  The device node for the device that the given file
+                            represents
+@Input        psDRMFile     The DRM file data that's being released
+@Return       void
+*/ /***************************************************************************/
+void PVRSRVCommonDeviceRelease(PVRSRV_DEVICE_NODE *psDeviceNode,
+							   struct drm_file *psDRMFile)
+{
+	void *pvConnectionData;
+
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+	OSAcquireBridgeLock();
+
+	pvConnectionData = psDRMFile->driver_priv;
+	if (pvConnectionData)
+	{
+		PVRSRVConnectionDisconnect(pvConnectionData);
+		psDRMFile->driver_priv = NULL;
+	}
+
+	OSReleaseBridgeLock();
 }
diff --git a/drivers/staging/imgtec/rogue/module_common.h b/drivers/staging/imgtec/rogue/module_common.h
index 7886dff..69d55e4 100644
--- a/drivers/staging/imgtec/rogue/module_common.h
+++ b/drivers/staging/imgtec/rogue/module_common.h
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@File
+@File           module_common.h
 @Title          Common linux module setup header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
@@ -43,50 +43,25 @@
 #ifndef _MODULE_COMMON_H_
 #define _MODULE_COMMON_H_
 
-#if defined(LDM_PLATFORM)
-#include <linux/platform_device.h>
-#define	LDM_DEV	struct platform_device
-#endif /*LDM_PLATFORM */
+/* DRVNAME is the name we use to register our driver. */
+#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
 
-#if defined(LDM_PCI)
-#include <linux/pci.h>
-#define	LDM_DEV	struct pci_dev
-#endif /* LDM_PCI */
+struct _PVRSRV_DEVICE_NODE_;
+struct drm_file;
 
-extern LDM_DEV *gpsPVRLDMDev;
+int PVRSRVCommonDriverInit(void);
+void PVRSRVCommonDriverDeinit(void);
 
-/*
- * Linux 3.8 and newer kernels no longer support __devinitdata, __devinit, __devexit, or
- * __devexit_p.
- */
-#if !defined(__devinitdata)
-#define __devinitdata
-#endif
-#if !defined(__devinit)
-#define __devinit
-#endif
-#if !defined(__devexit)
-#define __devexit
-#endif
-#if !defined(__devexit_p)
-#define __devexit_p(x) (&(x))
-#endif
+int PVRSRVCommonDeviceInit(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+void PVRSRVCommonDeviceDeinit(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-/* Functionality is n/a for guest drivers in a multi-driver model */
-#else
-void PVRSRVDriverShutdown(LDM_DEV *device);
-int PVRSRVDriverSuspend(struct device *device);
-int PVRSRVDriverResume(struct device *device);
-#endif
+void PVRSRVCommonDeviceShutdown(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+int PVRSRVCommonDeviceSuspend(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+int PVRSRVCommonDeviceResume(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 
-int PVRSRVCommonOpen(struct file *pFile);
-void PVRSRVCommonRelease(struct file *pFile);
-
-int PVRSRVDriverInit(void);
-void PVRSRVDriverDeinit(void);
-
-int PVRSRVDeviceInit(void);
-void PVRSRVDeviceDeinit(void);
+int PVRSRVCommonDeviceOpen(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+						   struct drm_file *psDRMFile);
+void PVRSRVCommonDeviceRelease(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+							   struct drm_file *psDRMFile);
 
 #endif /* _MODULE_COMMON_H_ */
diff --git a/drivers/staging/imgtec/rogue/os_srvinit_param.c b/drivers/staging/imgtec/rogue/os_srvinit_param.c
deleted file mode 100644
index 2650e9a..0000000
--- a/drivers/staging/imgtec/rogue/os_srvinit_param.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Services initialisation parameter support
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Services initialisation parameter support functions for
-		the Linux kernel.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include "pvr_debug.h"
-#include "os_srvinit_param.h"
-
-void 
-*SrvInitParamOpen(void)
-{
-	return NULL;
-}
-
-void
-SrvInitParamClose(void *pvState)
-{
-	(void) pvState;
-}
-
-void
-_SrvInitParamGetBOOL(IMG_BOOL *pbValue, bool bDefault)
-{
-	*pbValue = bDefault;
-}
-
-void
-_SrvInitParamGetUINT32(IMG_UINT32 *pui32Value, unsigned int uiDefault)
-{
-	*pui32Value = uiDefault;
-}
-
-bool
-_SrvInitParamGetUINT32BitField(IMG_UINT32 *puiValue, unsigned int uiDefault, const char **ppszValues, unsigned int uiNum, const SRV_INIT_PARAM_UINT32_LOOKUP *psLookup, unsigned int uiSize, const char *pszName)
-{
-	IMG_UINT32 uiValue = uiDefault;
-	bool bRet = false;
-	unsigned i, j;
-
-	for (i = 0; i < uiNum; i++)
-	{
-		const char *pszValue = ppszValues[i];
-
-		for (j = 0; j < uiSize; j++)
-		{
-			if (strcmp(psLookup[j].pszValue, pszValue) == 0)
-			{
-				uiValue |= psLookup[j].ui32Value;
-				bRet = true;
-				break;
-			}
-		}
-		if (j ==  uiSize)
-		{
-			if (strlen(pszValue) == 0)
-			{
-				PVR_DPF((PVR_DBG_WARNING, "No value set for initialisation parameter %s", pszName));
-			}
-			else
-			{
-				PVR_DPF((PVR_DBG_WARNING, "Unrecognised value (%s) for initialisation parameter %s", pszValue, pszName));
-			}
-		}
-	}
-
-	*puiValue = uiValue;
-
-	return bRet;
-}
-
-bool
-_SrvInitParamGetUINT32List(IMG_UINT32 *puiValue, unsigned int uiDefault, const char *pszValue, const SRV_INIT_PARAM_UINT32_LOOKUP *psLookup, unsigned int uiSize, const char *pszName)
-{
-	IMG_UINT32 uiValue = uiDefault;
-	bool bRet = false;
-	unsigned i;
-
-	if (pszValue != NULL)
-	{
-		bRet = true;
-
-		for (i = 0; i < uiSize; i++)
-		{
-			if (strcmp(psLookup[i].pszValue, pszValue) == 0)
-			{
-				uiValue = psLookup[i].ui32Value;
-				break;
-			}
-		}
-		if (i ==  uiSize)
-		{
-			if (strlen(pszValue) == 0)
-			{
-				PVR_DPF((PVR_DBG_WARNING, "No value set for initialisation parameter %s", pszName));
-			}
-			else
-			{
-				PVR_DPF((PVR_DBG_WARNING, "Unrecognised value (%s) for initialisation parameter %s", pszValue, pszName));
-			}
-		}
-	}
-
-	*puiValue = uiValue;
-
-	return bRet;
-}
diff --git a/drivers/staging/imgtec/rogue/os_srvinit_param.h b/drivers/staging/imgtec/rogue/os_srvinit_param.h
index 549d321..8f50445 100644
--- a/drivers/staging/imgtec/rogue/os_srvinit_param.h
+++ b/drivers/staging/imgtec/rogue/os_srvinit_param.h
@@ -44,71 +44,28 @@
 #ifndef __OS_SRVINIT_PARAM_H__
 #define __OS_SRVINIT_PARAM_H__
 
+#include "km_apphint_defs.h"
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/stat.h>
-
-#include "img_defs.h"
-#include "img_types.h"
-
-typedef struct
-{
-	IMG_CHAR *pszValue;
-	IMG_UINT32 ui32Value;
-} SRV_INIT_PARAM_UINT32_LOOKUP;
-
-void *SrvInitParamOpen(void);
-void SrvInitParamClose(void *pvState);
-
-#define	SrvInitParamInitBOOL(name, defval) \
-	static bool __SrvInitParam_ ## name = defval; \
-	module_param_named(name, __SrvInitParam_ ## name, bool, S_IRUGO);
-
-void _SrvInitParamGetBOOL(IMG_BOOL *pbValue, bool bDefault);
+#define SrvInitParamOpen() 0
+#define SrvInitParamClose(pvState) ((void)(pvState))
 
 #define	SrvInitParamGetBOOL(state, name, value) \
-		_SrvInitParamGetBOOL(&(value), __SrvInitParam_ ## name)
-
-#define	SrvInitParamInitUINT32(name, defval) \
-	static unsigned int __SrvInitParam_ ## name = defval; \
-	module_param_named(name, __SrvInitParam_ ## name, uint, S_IRUGO);
-
-void _SrvInitParamGetUINT32(IMG_UINT32 *pui32Value, unsigned int uiDefault);
+	pvr_apphint_get_bool(APPHINT_ID_ ## name, &value)
 
 #define	SrvInitParamGetUINT32(state, name, value) \
-		_SrvInitParamGetUINT32(&(value), __SrvInitParam_ ## name)
+	pvr_apphint_get_uint32(APPHINT_ID_ ## name, &value)
 
-#define	SrvInitParamInitUINT32BitField(name, inival, lookup) \
-	static unsigned int __SrvInitParam_ ## name = inival; \
-	static SRV_INIT_PARAM_UINT32_LOOKUP * \
-		__SrvInitParamLookup_ ## name = &lookup[0]; \
-	static const unsigned int __SrvInitParamSize_ ## name = \
-					ARRAY_SIZE(lookup); \
-	static char * __SrvInitParamArray_ ## name [ARRAY_SIZE(lookup)]; \
-	static unsigned int _SrvInitParamNum_ ## name = 0; \
-	static const char * __SrvInitParamName_ ## name = #name; \
-	module_param_array_named(name, __SrvInitParamArray_ ## name, charp, &_SrvInitParamNum_ ## name, S_IRUGO);
+#define	SrvInitParamGetUINT64(state, name, value) \
+	pvr_apphint_get_uint64(APPHINT_ID_ ## name, &value)
 
-bool _SrvInitParamGetUINT32BitField(IMG_UINT32 *puiValue, unsigned int uiDefault, const char **ppszValues, unsigned int uiNum, const SRV_INIT_PARAM_UINT32_LOOKUP *psLookup, unsigned int uiSize, const char *pszName);
+#define SrvInitParamGetSTRING(state, name, buffer, size) \
+	pvr_apphint_get_string(APPHINT_ID_ ## name, buffer, size)
 
 #define	SrvInitParamGetUINT32BitField(state, name, value) \
-		_SrvInitParamGetUINT32BitField(&(value), __SrvInitParam_ ## name, (const char **)__SrvInitParamArray_ ## name,  _SrvInitParamNum_ ## name, __SrvInitParamLookup_ ## name, __SrvInitParamSize_ ## name, __SrvInitParamName_ ## name)
-
-#define	SrvInitParamInitUINT32List(name, defval, lookup) \
-	static unsigned int __SrvInitParam_ ## name = defval; \
-	static SRV_INIT_PARAM_UINT32_LOOKUP * \
-		__SrvInitParamLookup_ ## name = &lookup[0]; \
-	static const unsigned int __SrvInitParamSize_ ## name = \
-					ARRAY_SIZE(lookup); \
-	static const char * __SrvInitParamName_ ## name = #name; \
-	static char * __SrvInitParamString_ ## name = NULL; \
-	module_param_named(name, __SrvInitParamString_ ## name, charp, S_IRUGO);
-
-bool _SrvInitParamGetUINT32List(IMG_UINT32 *puiValue, unsigned int uiDefault, const char *pszValue, const SRV_INIT_PARAM_UINT32_LOOKUP *psLookup, unsigned int uiSize, const char *pszName);
+	pvr_apphint_get_uint32(APPHINT_ID_ ## name, &value)
 
 #define	SrvInitParamGetUINT32List(state, name, value) \
-		_SrvInitParamGetUINT32List(&(value), __SrvInitParam_ ## name, __SrvInitParamString_ ## name, __SrvInitParamLookup_ ## name, __SrvInitParamSize_ ## name,  __SrvInitParamName_ ## name)
+	pvr_apphint_get_uint32(APPHINT_ID_ ## name, &value)
 
 
 #endif /* __OS_SRVINIT_PARAM_H__ */
diff --git a/drivers/staging/imgtec/rogue/osconnection_server.c b/drivers/staging/imgtec/rogue/osconnection_server.c
index 8035585..fd464df 100644
--- a/drivers/staging/imgtec/rogue/osconnection_server.c
+++ b/drivers/staging/imgtec/rogue/osconnection_server.c
@@ -47,6 +47,8 @@
 #include "allocmem.h"
 #include "pvr_debug.h"
 
+#include <linux/sched.h>
+
 #if defined (SUPPORT_ION)
 #include <linux/err.h>
 #include PVR_ANDROID_ION_HEADER
@@ -67,7 +69,7 @@
 	ENV_ION_CONNECTION_DATA *psIonConnection;
 #endif
 
-	*phOsPrivateData = OSAllocMem(sizeof(ENV_CONNECTION_DATA));
+	*phOsPrivateData = OSAllocZMem(sizeof(ENV_CONNECTION_DATA));
 
 	if (*phOsPrivateData == NULL)
 	{
@@ -76,20 +78,21 @@
 	}
 
 	psEnvConnection = (ENV_CONNECTION_DATA *)*phOsPrivateData;
-	OSMemSet(psEnvConnection, 0, sizeof(*psEnvConnection));
+
+	psEnvConnection->owner = current->tgid;
 
 	/* Save the pointer to our struct file */
 	psEnvConnection->psFile = psPrivData->psFile;
 	psEnvConnection->psDevNode = psPrivData->psDevNode;
 
 #if defined(SUPPORT_ION)
-	psIonConnection = (ENV_ION_CONNECTION_DATA *)OSAllocMem(sizeof(ENV_ION_CONNECTION_DATA));
+	psIonConnection = (ENV_ION_CONNECTION_DATA *)OSAllocZMem(sizeof(ENV_ION_CONNECTION_DATA));
 	if (psIonConnection == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__));
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
-	OSMemSet(psIonConnection, 0, sizeof(*psIonConnection));
+
 	psEnvConnection->psIonData = psIonConnection;
 	/*
 		We can have more then one connection per process so we need more then
diff --git a/drivers/staging/imgtec/rogue/osconnection_server.h b/drivers/staging/imgtec/rogue/osconnection_server.h
index a20d330..192ef58 100644
--- a/drivers/staging/imgtec/rogue/osconnection_server.h
+++ b/drivers/staging/imgtec/rogue/osconnection_server.h
@@ -47,7 +47,7 @@
 #include "handle.h"
 
 
-#if defined(__linux__) || defined(__QNXNTO__)
+#if defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS)
 PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, void *pvOSData);
 PVRSRV_ERROR OSConnectionPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
 
@@ -55,10 +55,20 @@
 
 PVRSRV_DEVICE_NODE* OSGetDevData(CONNECTION_DATA *psConnection);
 
-#else	/* defined(__linux__) */
+#else	/* defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS) */
 #ifdef INLINE_IS_PRAGMA
 #pragma inline(OSConnectionPrivateDataInit)
 #endif
+/*************************************************************************/ /*!
+@Function       OSConnectionPrivateDataInit
+@Description    Allocates and initialises any OS-specific private data
+                relating to a connection.
+                Called from PVRSRVConnectionConnect().
+@Input          pvOSData            pointer to any OS private data
+@Output         phOsPrivateData     handle to the created connection
+                                    private data
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 static INLINE PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, void *pvOSData)
 {
 	PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
@@ -70,6 +80,14 @@
 #ifdef INLINE_IS_PRAGMA
 #pragma inline(OSConnectionPrivateDataDeInit)
 #endif
+/*************************************************************************/ /*!
+@Function       OSConnectionPrivateDataDeInit
+@Description    Frees previously allocated OS-specific private data
+                relating to a connection.
+@Input          hOsPrivateData      handle to the connection private data
+                                    to be freed
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 static INLINE PVRSRV_ERROR OSConnectionPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
 {
 	PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
@@ -96,7 +114,7 @@
 
 	return NULL;
 }
-#endif	/* defined(__linux__) */
+#endif	/* defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS) */
 
 
 #endif /* _OSCONNECTION_SERVER_H_ */
diff --git a/drivers/staging/imgtec/rogue/osfunc.c b/drivers/staging/imgtec/rogue/osfunc.c
index 76602ef..94c1c43 100644
--- a/drivers/staging/imgtec/rogue/osfunc.c
+++ b/drivers/staging/imgtec/rogue/osfunc.c
@@ -45,6 +45,7 @@
 #include <asm/page.h>
 #include <asm/div64.h>
 #include <linux/mm.h>
+#include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/hugetlb.h> 
 #include <linux/slab.h>
@@ -52,8 +53,6 @@
 #include <linux/delay.h>
 #include <linux/genalloc.h>
 #include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <asm/hardirq.h>
 #include <asm/tlbflush.h>
 #include <linux/timer.h>
@@ -69,45 +68,61 @@
 #endif
 #include <linux/kthread.h>
 #include <asm/atomic.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+#include <linux/pfn_t.h>
+#include <linux/pfn.h>
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
+#include <linux/sched/clock.h>
+#include <linux/sched/signal.h>
+#else
+#include <linux/sched.h>
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) */
 
 #include "log2.h"
 #include "osfunc.h"
 #include "img_types.h"
-#include "mm.h"
 #include "allocmem.h"
-#include "env_data.h"
+#include "devicemem_server_utils.h"
 #include "pvr_debugfs.h"
 #include "event.h"
 #include "linkage.h"
 #include "pvr_uaccess.h"
 #include "pvr_debug.h"
-#include "driverlock.h"
+#include "pvrsrv_memallocflags.h"
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #include "process_stats.h"
 #endif
-#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
-#include "syscommon.h"
-#endif
 #include "physmem_osmem_linux.h"
+
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
-#include "virt_support.h"
+#include "dma_support.h"
 #endif
 
+#include "kernel_compatibility.h"
+
 #if defined(VIRTUAL_PLATFORM)
-#define EVENT_OBJECT_TIMEOUT_MS         (120000)
+#define EVENT_OBJECT_TIMEOUT_US		(120000000ULL)
 #else
 #if defined(EMULATOR)
-#define EVENT_OBJECT_TIMEOUT_MS		(2000)
+#define EVENT_OBJECT_TIMEOUT_US		(2000000ULL)
 #else
-#define EVENT_OBJECT_TIMEOUT_MS		(100)
+#define EVENT_OBJECT_TIMEOUT_US		(100000ULL)
 #endif /* EMULATOR */
 #endif
 
+/*
+ * Main driver lock, used to ensure driver code is single threaded. There are
+ * some places where this lock must not be taken, such as in the mmap related
+ * driver entry points.
+ */
+static DEFINE_MUTEX(gPVRSRVLock);
 
 static void *g_pvBridgeBuffers = NULL;
 static atomic_t g_DriverSuspended;
 
-struct task_struct *OSGetBridgeLockOwner(void);
+struct task_struct *BridgeLockGetOwner(void);
+IMG_BOOL BridgeLockIsLocked(void);
 
 
 PVRSRV_ERROR OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
@@ -144,10 +159,12 @@
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-	    PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, uiSize);
+	    PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA,
+	                                        uiSize,
+	                                        (IMG_UINT64)(uintptr_t) psPage);
 #else
 	PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA,
-								 psPage,
+	                             psPage,
 								 sCpuPAddr,
 								 uiSize,
 								 NULL);
@@ -167,9 +184,10 @@
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-	    PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, uiSize);
+	PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA,
+	                                      (IMG_UINT64)(uintptr_t) psPage);
 #else
-	PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, (IMG_UINT64)(uintptr_t)psPage);
+	PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, (IMG_UINT64)(uintptr_t) psPage);
 #endif
 #endif
 
@@ -181,11 +199,12 @@
 						size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
 						void **pvPtr)
 {
-	size_t actualSize = 1<<psMemHandle->ui32Order;
+	size_t actualSize = 1 << (PAGE_SHIFT + psMemHandle->ui32Order);
 	*pvPtr = kmap((struct page*)psMemHandle->u.pvHandle);
 
 	PVR_UNREFERENCED_PARAMETER(psDevPAddr);
 
+	PVR_UNREFERENCED_PARAMETER(actualSize); /* If we don't take an #ifdef path */
 	PVR_UNREFERENCED_PARAMETER(uiSize);
 	PVR_UNREFERENCED_PARAMETER(psDevNode);
 
@@ -214,7 +233,7 @@
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
 	/* Mapping is done a page at a time */
-	PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, (PAGE_SIZE << psMemHandle->ui32Order));
+	PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, (1 << (PAGE_SHIFT + psMemHandle->ui32Order)));
 #else
 	PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, (IMG_UINT64)(uintptr_t)pvPtr);
 #endif
@@ -226,7 +245,8 @@
 	kunmap((struct page*) psMemHandle->u.pvHandle);
 }
 
-PVRSRV_ERROR OSPhyContigPagesClean(PG_HANDLE *psMemHandle,
+PVRSRV_ERROR OSPhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
+                                   PG_HANDLE *psMemHandle,
                                    IMG_UINT32 uiOffset,
                                    IMG_UINT32 uiLength)
 {
@@ -255,7 +275,8 @@
 	sPhysStart.uiAddr = page_to_phys(psPage) + uiOffset;
 	sPhysEnd.uiAddr = sPhysStart.uiAddr + uiLength;
 
-	OSCleanCPUCacheRangeKM(pvVirtAddrStart,
+	OSCleanCPUCacheRangeKM(psDevNode,
+	                       pvVirtAddrStart,
 	                       pvVirtAddrStart + uiLength,
 	                       sPhysStart,
 	                       sPhysEnd);
@@ -273,11 +294,6 @@
 #error "PVRSRV Alignment macros need to be defined for this compiler"
 #endif
 
-/*************************************************************************/ /*!
-@Function       OSCPUCacheAttributeSize
-@Description    Lookup dcache attribute sizes
-@Input          eCacheAttribute
-*/ /**************************************************************************/
 IMG_UINT32 OSCPUCacheAttributeSize(IMG_DCACHE_ATTRIBUTE eCacheAttribute)
 {
 	IMG_UINT32 uiSize = 0;
@@ -298,25 +314,28 @@
 	return uiSize;
 }
 
+IMG_UINT32 OSVSScanf(IMG_CHAR *pStr, const IMG_CHAR *pszFormat, ...)
+{
+	va_list argList;
+	IMG_INT32 iCount = 0;
+
+	va_start(argList, pszFormat);
+	iCount = vsscanf(pStr, pszFormat, argList);
+	va_end(argList);
+
+	return iCount;
+}
+
 IMG_INT OSMemCmp(void *pvBufA, void *pvBufB, size_t uiLen)
 {
 	return (IMG_INT) memcmp(pvBufA, pvBufB, uiLen);
 }
 
-/*************************************************************************/ /*!
-@Function       OSStringNCopy
-@Description    strcpy
-*/ /**************************************************************************/
 IMG_CHAR *OSStringNCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uSize)
 {
 	return strncpy(pszDest, pszSrc, uSize);
 }
 
-/*************************************************************************/ /*!
-@Function       OSSNPrintf
-@Description    snprintf
-@Return         the chars written or -1 on error
-*/ /**************************************************************************/
 IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, size_t ui32Size, const IMG_CHAR *pszFormat, ...)
 {
 	va_list argList;
@@ -344,14 +363,21 @@
 	return strcmp(pStr1, pStr2);
 }
 
-/*************************************************************************/ /*!
-@Function       OSInitEnvData
-@Description    Allocates space for env specific data
-@Input          ppvEnvSpecificData   Pointer to pointer in which to return
-                                     allocated data.
-@Input          ui32MMUMode          MMU mode.
-@Return         PVRSRV_OK
-*/ /**************************************************************************/
+IMG_INT32 OSStringNCompare(const IMG_CHAR *pStr1, const IMG_CHAR *pStr2,
+                          size_t uiSize)
+{
+	return strncmp(pStr1, pStr2, uiSize);
+}
+
+PVRSRV_ERROR OSStringToUINT32(const IMG_CHAR *pStr, IMG_UINT32 ui32Base,
+                              IMG_UINT32 *ui32Result)
+{
+	if (kstrtou32(pStr, ui32Base, ui32Result) != 0)
+		return PVRSRV_ERROR_CONVERSION_FAILED;
+
+	return PVRSRV_OK;
+}
+
 PVRSRV_ERROR OSInitEnvData(void)
 {
 	/* allocate memory for the bridge buffers to be used during an ioctl */
@@ -369,12 +395,6 @@
 }
 
 
-/*************************************************************************/ /*!
-@Function       OSDeInitEnvData
-@Description    frees env specific data memory
-@Input          pvEnvSpecificData   Pointer to private structure
-@Return         PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY
-*/ /**************************************************************************/
 void OSDeInitEnvData(void)
 {
 
@@ -389,18 +409,12 @@
 }
 
 PVRSRV_ERROR OSGetGlobalBridgeBuffers(void **ppvBridgeInBuffer,
-							IMG_UINT32 *pui32BridgeInBufferSize,
-							void **ppvBridgeOutBuffer,
-							IMG_UINT32 *pui32BridgeOutBufferSize)
+									  void **ppvBridgeOutBuffer)
 {
 	PVR_ASSERT (ppvBridgeInBuffer && ppvBridgeOutBuffer);
-	PVR_ASSERT (pui32BridgeInBufferSize && pui32BridgeOutBufferSize);
 
 	*ppvBridgeInBuffer = g_pvBridgeBuffers;
-	*pui32BridgeInBufferSize = PVRSRV_MAX_BRIDGE_IN_SIZE;
-
-	*ppvBridgeOutBuffer = *ppvBridgeInBuffer + *pui32BridgeInBufferSize;
-	*pui32BridgeOutBufferSize = PVRSRV_MAX_BRIDGE_OUT_SIZE;
+	*ppvBridgeOutBuffer = *ppvBridgeInBuffer + PVRSRV_MAX_BRIDGE_IN_SIZE;
 
 	return PVRSRV_OK;
 }
@@ -422,22 +436,11 @@
 	return (0 < atomic_read(&g_DriverSuspended))? IMG_TRUE: IMG_FALSE;
 }
 
-/*************************************************************************/ /*!
-@Function       OSReleaseThreadQuanta
-@Description    Releases thread quanta
-*/ /**************************************************************************/ 
 void OSReleaseThreadQuanta(void)
 {
 	schedule();
 }
 
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
-static inline IMG_UINT32 Clockus(void)
-{
-	return (jiffies * (1000000 / HZ));
-}
-#else
 /* Not matching/aligning this API to the Clockus() API above to avoid necessary
  * multiplication/division operations in calling code.
  */
@@ -460,78 +463,72 @@
 
 	return timenow;
 }
-#endif
 
-/*************************************************************************/ /*!
- @Function OSClockns64
- @Description
-        This function returns the clock in nanoseconds. Unlike OSClockus,
-        OSClockus64 has a near 64-bit range
-*/ /**************************************************************************/
 IMG_UINT64 OSClockns64(void)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
 	return Clockns64();	
-#else
-	return ((IMG_UINT64)Clockus()) * 1000ULL;
-#endif
 }
 
-/*************************************************************************/ /*!
- @Function OSClockus64
- @Description
-        This function returns the clock in microseconds. Unlike OSClockus,
-        OSClockus64 has a near 64-bit range
-*/ /**************************************************************************/
 IMG_UINT64 OSClockus64(void)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
 	IMG_UINT64 timenow = Clockns64();
 	IMG_UINT32 remainder;
+
 	return OSDivide64r64(timenow, 1000, &remainder);
-#else
-	return ((IMG_UINT64)Clockus());
-#endif
 }
 
-
-/*************************************************************************/ /*!
-@Function       OSClockus
-@Description    This function returns the clock in microseconds
-@Return         clock (us)
-*/ /**************************************************************************/ 
 IMG_UINT32 OSClockus(void)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
 	return (IMG_UINT32) OSClockus64();
-#else
-	return Clockus();
-#endif
 }
 
-
-/*************************************************************************/ /*!
-@Function       OSClockms
-@Description    This function returns the clock in milliseconds
-@Return         clock (ms)
-*/ /**************************************************************************/ 
 IMG_UINT32 OSClockms(void)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
 	IMG_UINT64 timenow = Clockns64();
 	IMG_UINT32 remainder;
 
 	return OSDivide64(timenow, 1000000, &remainder);
+}
+
+static inline IMG_UINT64 KClockns64(void)
+{
+	ktime_t sTime = ktime_get();
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+	return sTime;
 #else
-	IMG_UINT64 time, j = (IMG_UINT32)jiffies;
-
-	time = j * (((1 << 16) * 1000) / HZ);
-	time >>= 16;
-
-	return (IMG_UINT32)time;
+	return sTime.tv64;
 #endif
 }
 
+PVRSRV_ERROR OSClockMonotonicns64(IMG_UINT64 *pui64Time)
+{
+	*pui64Time = KClockns64();
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSClockMonotonicus64(IMG_UINT64 *pui64Time)
+{
+	IMG_UINT64 timenow = KClockns64();
+	IMG_UINT32 remainder;
+
+	*pui64Time = OSDivide64r64(timenow, 1000, &remainder);
+	return PVRSRV_OK;
+}
+
+IMG_UINT64 OSClockMonotonicRawns64(void)
+{
+	struct timespec ts;
+
+	getrawmonotonic(&ts);
+	return (IMG_UINT64) ts.tv_sec * 1000000000 + ts.tv_nsec;
+}
+
+IMG_UINT64 OSClockMonotonicRawus64(void)
+{
+	IMG_UINT32 rem;
+	return OSDivide64r64(OSClockMonotonicRawns64(), 1000, &rem);
+}
 
 /*
 	OSWaitus
@@ -551,11 +548,11 @@
 }
 
 
-/*************************************************************************/ /*!
-@Function       OSGetCurrentProcessID
-@Description    Returns ID of current process (thread group)
-@Return         ID of current process
-*****************************************************************************/
+INLINE IMG_UINT64 OSGetCurrentProcessVASpaceSize(void)
+{
+	return (IMG_UINT64)TASK_SIZE;
+}
+
 INLINE IMG_PID OSGetCurrentProcessID(void)
 {
 	if (in_interrupt())
@@ -563,32 +560,14 @@
 		return KERNEL_ID;
 	}
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-	return (IMG_PID)current->pgrp;
-#else
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
 	return (IMG_PID)task_tgid_nr(current);
-#else
-	return (IMG_PID)current->tgid;
-#endif
-#endif
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetCurrentProcessName
-@Description    gets name of current process
-@Return         process name
-*****************************************************************************/
 INLINE IMG_CHAR *OSGetCurrentProcessName(void)
 {
 	return current->comm;
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetCurrentThreadID
-@Description    Returns ID for current thread
-@Return         ID of current thread
-*****************************************************************************/
 INLINE uintptr_t OSGetCurrentThreadID(void)
 {
 	if (in_interrupt())
@@ -599,205 +578,79 @@
 	return current->pid;
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetCurrentClientProcessIDKM
-@Description    Returns ID of current client process (thread group)
-@Return         ID of current client process
-*****************************************************************************/
 IMG_PID OSGetCurrentClientProcessIDKM(void)
 {
 	return OSGetCurrentProcessID();
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetCurrentClientProcessNameKM
-@Description    gets name of current client process
-@Return         client process name
-*****************************************************************************/
 IMG_CHAR *OSGetCurrentClientProcessNameKM(void)
 {
 	return OSGetCurrentProcessName();
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetCurrentClientThreadIDKM
-@Description    Returns ID for current client thread
-@Return         ID of current client thread
-*****************************************************************************/
 uintptr_t OSGetCurrentClientThreadIDKM(void)
 {
 	return OSGetCurrentThreadID();
 }
-/*************************************************************************/ /*!
-@Function       OSGetPageSize
-@Description    gets page size
-@Return         page size
-*/ /**************************************************************************/
+
 size_t OSGetPageSize(void)
 {
 	return PAGE_SIZE;
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetPageShift
-@Description    gets page size
-@Return         page size
-*/ /**************************************************************************/
 size_t OSGetPageShift(void)
 {
 	return PAGE_SHIFT;
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetPageMask
-@Description    gets page mask
-@Return         page size
-*/ /**************************************************************************/
 size_t OSGetPageMask(void)
 {
 	return (OSGetPageSize()-1);
 }
 
-/*************************************************************************/ /*!
-@Function       OSGetOrder
-@Description    gets log base 2 (Order) value of the given size
-@Return         order
-*/ /**************************************************************************/
 size_t OSGetOrder(size_t uSize)
 {
 	return get_order(PAGE_ALIGN(uSize));
 }
 
-#if !defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-/*
-	Device interrupt (ISR/LISR) management is predicated on the following:
-		- For normal/hyperv drivers:
-			- Perform device interrupt management directly (normal case)
-		- For guest drivers, behaviour depends on:
-			- If running on a multi-driver model (same OS instance)
-				- Delegate management to hypervisor driver
-				- Register guest driver device LISRs with hyperv
-				- Hypervisor triggers guests driver device LISRs
-			- Else assume hypervisor vm monitor exposes device/irq abstraction
-				- Manage this virtual device/irq directly like a normal driver
-				- Hypervisor vm monitor triggers device/irq abstraction
-				- Setup for this is outside the scope of the DDK
- */
-#else
-typedef struct _LISR_DATA_ {
-	PFN_LISR pfnLISR;
-	void *pvData;
-	IMG_UINT32 ui32IRQ;
-} LISR_DATA;
-
-/*
-	DeviceISRWrapper
-*/
-static irqreturn_t DeviceISRWrapper(int irq, void *dev_id)
+typedef struct
 {
-	LISR_DATA *psLISRData = (LISR_DATA *) dev_id;
-	IMG_BOOL bStatus = IMG_FALSE;
+	int os_error;
+	PVRSRV_ERROR pvr_error;
+} error_map_t;
 
-	PVR_UNREFERENCED_PARAMETER(irq);
-
-#if defined(SUPPORT_PVRSRV_GPUVIRT) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-	bStatus = SysVirtTriggerAllGuestDeviceLISR() == PVRSRV_OK ? IMG_TRUE : IMG_FALSE;
-#endif
-	bStatus |= psLISRData->pfnLISR(psLISRData->pvData);
-
-	return bStatus ? IRQ_HANDLED : IRQ_NONE;
-}
-#endif
-#endif
-
-/*
-	OSInstallDeviceLISR
-*/
-PVRSRV_ERROR OSInstallDeviceLISR(PVRSRV_DEVICE_CONFIG *psDevConfig,
-				 IMG_HANDLE *hLISRData, 
-				 PFN_LISR pfnLISR,
-				 void *pvData)
+/* return -ve versions of POSIX errors as they are used in this form */
+static const error_map_t asErrorMap[] =
 {
-#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
-	return SysInstallDeviceLISR(psDevConfig->ui32IRQ,
-					psDevConfig->pszName,
-					pfnLISR,
-					pvData,
-					hLISRData);
-#else
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-	return GuestBridgeSysInstallDeviceLISR(PVRSRV_GPUVIRT_OSID,
-									psDevConfig->ui32IRQ,
-									psDevConfig->pszName,
-									pfnLISR,
-									pvData,
-									hLISRData);
-#else
-	LISR_DATA *psLISRData;
-	unsigned long flags = 0;
+	{-EFAULT, PVRSRV_ERROR_BRIDGE_EFAULT},
+	{-EINVAL, PVRSRV_ERROR_BRIDGE_EINVAL},
+	{-ENOMEM, PVRSRV_ERROR_BRIDGE_ENOMEM},
+	{-ERANGE, PVRSRV_ERROR_BRIDGE_ERANGE},
+	{-EPERM,  PVRSRV_ERROR_BRIDGE_EPERM},
+	{-ENOTTY, PVRSRV_ERROR_BRIDGE_ENOTTY},
+	{-ENOTTY, PVRSRV_ERROR_BRIDGE_CALL_FAILED},
+	{-ERANGE, PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL},
+	{-ENOMEM, PVRSRV_ERROR_OUT_OF_MEMORY},
+	{-EINVAL, PVRSRV_ERROR_INVALID_PARAMS},
 
-	psLISRData = OSAllocMem(sizeof(LISR_DATA));
+	{0,       PVRSRV_OK}
+};
 
-	psLISRData->pfnLISR = pfnLISR;
-	psLISRData->pvData = pvData;
-	psLISRData->ui32IRQ = psDevConfig->ui32IRQ;
+#define num_rows(a) (sizeof(a)/sizeof(a[0]))
 
-	if (psDevConfig->bIRQIsShared)
-	{
-		flags |= IRQF_SHARED;
-	}
-
-	if (psDevConfig->eIRQActiveLevel == PVRSRV_DEVICE_IRQ_ACTIVE_HIGH)
-	{
-		flags |= IRQF_TRIGGER_HIGH;
-	}
-	else if (psDevConfig->eIRQActiveLevel == PVRSRV_DEVICE_IRQ_ACTIVE_LOW)
-	{
-		flags |= IRQF_TRIGGER_LOW;
-	}
-
-	PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", 
-				psDevConfig->pszName, psDevConfig->ui32IRQ, pvData));
-
-	if(request_irq(psDevConfig->ui32IRQ, DeviceISRWrapper,
-		flags, psDevConfig->pszName, psLISRData))
-	{
-		PVR_DPF((PVR_DBG_ERROR,
-				"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", 
-				psDevConfig->ui32IRQ));
-
-		return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
-	}
-
-	*hLISRData = (IMG_HANDLE) psLISRData;
-
-	return PVRSRV_OK;
-#endif
-#endif
-}
-
-/*
-	OSUninstallDeviceLISR
-*/
-PVRSRV_ERROR OSUninstallDeviceLISR(IMG_HANDLE hLISRData)
+int PVRSRVToNativeError(PVRSRV_ERROR e)
 {
-#if defined (SUPPORT_SYSTEM_INTERRUPT_HANDLING)
-	return SysUninstallDeviceLISR(hLISRData);
-#else
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(PVRSRV_GPUVIRT_MULTIDRV_MODEL)
-	return GuestBridgeSysUninstallDeviceLISR(PVRSRV_GPUVIRT_OSID, hLISRData);
-#else
-	LISR_DATA *psLISRData = (LISR_DATA *) hLISRData;
-
-	PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psLISRData->ui32IRQ,  psLISRData->pvData));
-
-	free_irq(psLISRData->ui32IRQ, psLISRData);
-	OSFreeMem(psLISRData);
-
-	return PVRSRV_OK;
-#endif	
-#endif
+	int os_error = -EFAULT;
+	int i;
+	for (i = 0; i < num_rows(asErrorMap); i++)
+	{
+		if (e == asErrorMap[i].pvr_error)
+		{
+			os_error = asErrorMap[i].os_error;
+			break;
+		}
+	}
+	return os_error;
 }
 
 #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
@@ -826,7 +679,7 @@
 {
 	MISR_DATA *psMISRData;
 
-	psMISRData = OSAllocMem(sizeof(MISR_DATA));
+	psMISRData = OSAllocMem(sizeof(*psMISRData));
 	if (psMISRData == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -837,7 +690,7 @@
 
 	PVR_TRACE(("Installing MISR with cookie %p", psMISRData));
 
-	psMISRData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue" PVRSRV_GPUVIRT_OSID_STR);
+	psMISRData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
 
 	if (psMISRData->psWorkQueue == NULL)
 	{
@@ -860,7 +713,7 @@
 {
 	MISR_DATA *psMISRData = (MISR_DATA *) hMISRData;
 
-	PVR_TRACE(("Uninstalling MISR"));
+	PVR_TRACE(("Uninstalling MISR with cookie %p", psMISRData));
 
 	destroy_workqueue(psMISRData->psWorkQueue);
 	OSFreeMem(psMISRData);
@@ -884,10 +737,13 @@
 	*/
 #if defined(NO_HARDWARE)
 	psMISRData->pfnMISR(psMISRData->hData);
-#else
-	queue_work(psMISRData->psWorkQueue, &psMISRData->sMISRWork);
-#endif
 	return PVRSRV_OK;
+#else
+	{
+		bool rc = queue_work(psMISRData->psWorkQueue, &psMISRData->sMISRWork);
+		return (rc ? PVRSRV_OK : PVRSRV_ERROR_ALREADY_EXISTS);
+	}
+#endif
 }
 #else	/* defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
 #if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
@@ -914,7 +770,7 @@
 {
 	MISR_DATA *psMISRData;
 
-	psMISRData = OSAllocMem(sizeof(MISR_DATA));
+	psMISRData = OSAllocMem(sizeof(*psMISRData));
 	if (psMISRData == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -938,7 +794,7 @@
 */
 PVRSRV_ERROR OSUninstallMISR(IMG_HANDLE hMISRData)
 {
-	PVR_TRACE(("Uninstalling MISR"));
+	PVR_TRACE(("Uninstalling MISR with cookie %p", psMISRData));
 
 	flush_scheduled_work();
 
@@ -985,7 +841,7 @@
 {
 	MISR_DATA *psMISRData;
 
-	psMISRData = OSAllocMem(sizeof(MISR_DATA));
+	psMISRData = OSAllocMem(sizeof(*psMISRData));
 	if (psMISRData == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -1010,7 +866,7 @@
 {
 	MISR_DATA *psMISRData = (MISR_DATA *) hMISRData;
 
-	PVR_TRACE(("Uninstalling MISR"));
+	PVR_TRACE(("Uninstalling MISR with cookie %p", psMISRData));
 
 	tasklet_kill(&psMISRData->sMISRTasklet);
 
@@ -1036,12 +892,15 @@
 #endif /* #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
 
 /* OS specific values for thread priority */
-const IMG_INT32 ai32OSPriorityValues[OS_THREAD_LAST_PRIORITY] = { -20, /* OS_THREAD_HIGHEST_PRIORITY */
-																  -10, /* OS_THREAD_HIGH_PRIORITY */
-																	0, /* OS_THREAD_NORMAL_PRIORITY */
-																	9, /* OS_THREAD_LOW_PRIORITY */
-																   19, /* OS_THREAD_LOWEST_PRIORITY */
-																  -22};/* OS_THREAD_NOSET_PRIORITY */
+static const IMG_INT32 ai32OSPriorityValues[OS_THREAD_LAST_PRIORITY] =
+{
+	-20, /* OS_THREAD_HIGHEST_PRIORITY */
+	-10, /* OS_THREAD_HIGH_PRIORITY */
+	  0, /* OS_THREAD_NORMAL_PRIORITY */
+	  9, /* OS_THREAD_LOW_PRIORITY */
+	 19, /* OS_THREAD_LOWEST_PRIORITY */
+	-22, /* OS_THREAD_NOSET_PRIORITY */
+};
 
 typedef struct {
 	struct task_struct *kthread;
@@ -1088,7 +947,7 @@
 	OSThreadData *psOSThreadData;
 	PVRSRV_ERROR eError;
 
-	psOSThreadData = OSAllocMem(sizeof(OSThreadData));
+	psOSThreadData = OSAllocMem(sizeof(*psOSThreadData));
 	if (psOSThreadData == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -1145,200 +1004,110 @@
 #endif
 }
 
-/*************************************************************************/ /*!
-@Function       OSMapPhysToLin
-@Description    Maps the physical memory into linear addr range
-@Input          BasePAddr       Physical cpu address
-@Input          ui32Bytes       Bytes to map
-@Input          ui32CacheType   Cache type
-@Return         Linear addr of mapping on success, else NULL
- */ /**************************************************************************/
+PVRSRV_ERROR OSSetThreadPriority(IMG_HANDLE hThread,
+								 IMG_UINT32  nThreadPriority,
+								 IMG_UINT32  nThreadWeight)
+{
+	PVR_UNREFERENCED_PARAMETER(hThread);
+	PVR_UNREFERENCED_PARAMETER(nThreadPriority);
+	PVR_UNREFERENCED_PARAMETER(nThreadWeight);
+ 	/* Default priorities used on this platform */
+	
+	return PVRSRV_OK;
+}
+
 void *
 OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
 			   size_t ui32Bytes,
 			   IMG_UINT32 ui32MappingFlags)
 {
-	void *pvIORemapCookie;
+	void *pvLinAddr;
 
-	pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
-	if(pvIORemapCookie == NULL)
+	if (ui32MappingFlags & ~(PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK))
 	{
-		PVR_ASSERT(0);
+		PVR_ASSERT(!"Found non-cpu cache mode flag when mapping to the cpu");
 		return NULL;
 	}
 
-	return pvIORemapCookie;
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	/*
+	 * This is required to support DMA physheaps for GPU virtualization.
+	 * Unfortunately, if a region of kernel managed memory is turned into
+	 * a DMA buffer, conflicting mappings can come about easily on Linux
+	 * as the original memory is mapped by the kernel as normal cached
+	 * memory whilst DMA buffers are mapped mostly as uncached device or
+	 * cache-coherent device memory. In both cases the system will have
+	 * two conflicting mappings for the same memory region and will have
+	 * "undefined behaviour" for most processors notably ARMv6 onwards
+	 * and some x86 micro-architectures
+	 *
+	 * As a result we perform ioremapping manually, for DMA physheap
+	 * allocations, by translating from CPU/VA <-> BUS/PA.
+	 */
+	pvLinAddr = SysDmaDevPAddrToCpuVAddr(BasePAddr.uiAddr, ui32Bytes);
+	if (pvLinAddr != NULL)
+	{
+		return pvLinAddr;
+	}
+#endif
+
+	switch (ui32MappingFlags)
+	{
+		case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+			pvLinAddr = (void *)ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
+			break;
+		case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+#if defined(CONFIG_X86) || defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+			pvLinAddr = (void *)ioremap_wc(BasePAddr.uiAddr, ui32Bytes);
+#else
+			pvLinAddr = (void *)ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
+#endif
+			break;
+		case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+#if defined(CONFIG_X86) || defined(CONFIG_ARM)
+			pvLinAddr = (void *)ioremap_cache(BasePAddr.uiAddr, ui32Bytes);
+#else
+			pvLinAddr = (void *)ioremap(BasePAddr.uiAddr, ui32Bytes);
+#endif
+			break;
+		case PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT:
+		case PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT:
+			PVR_ASSERT(!"Unexpected cpu cache mode");
+			pvLinAddr = NULL;
+			break;
+		default:
+			PVR_ASSERT(!"Unsupported cpu cache mode");
+			pvLinAddr = NULL;
+			break;
+	}
+
+	return pvLinAddr;
 }
 
 
-/*************************************************************************/ /*!
-@Function       OSUnMapPhysToLin
-@Description    Unmaps memory that was mapped with OSMapPhysToLin
-@Input          pvLinAddr
-@Input          ui32Bytes
-@Return         TRUE on success, else FALSE
-*/ /**************************************************************************/
 IMG_BOOL
 OSUnMapPhysToLin(void *pvLinAddr, size_t ui32Bytes, IMG_UINT32 ui32MappingFlags)
 {
 	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
 
-	IOUnmapWrapper(pvLinAddr);
+	if (ui32MappingFlags & ~(PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK))
+	{
+		PVR_ASSERT(!"Found non-cpu cache mode flag when unmapping from the cpu");
+		return IMG_FALSE;
+	}
+
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	if (SysDmaCpuVAddrToDevPAddr(pvLinAddr))
+	{
+		return IMG_TRUE;
+	}
+#endif
+
+	iounmap(pvLinAddr);
 
 	return IMG_TRUE;
 }
 
-/*
-	OSReadHWReg8
-*/
-IMG_UINT8 OSReadHWReg8(void *pvLinRegBaseAddr,
-						IMG_UINT32	ui32Offset)
-{
-#if !defined(NO_HARDWARE)
-	return (IMG_UINT8) readb((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
-#else
-	return 0x4e;
-#endif
-}
-
-/*
-	OSReadHWReg16
-*/
-IMG_UINT16 OSReadHWReg16(void *pvLinRegBaseAddr,
-						 IMG_UINT32	ui32Offset)
-{
-#if !defined(NO_HARDWARE)
-	return (IMG_UINT16) readw((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
-#else
-	return 0x3a4e;
-#endif
-}
-
-/*
-	OSReadHWReg32
-*/
-IMG_UINT32 OSReadHWReg32(void *pvLinRegBaseAddr,
-						 IMG_UINT32	ui32Offset)
-{
-#if !defined(NO_HARDWARE)
-	return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
-#else
-	return 0x30f73a4e;
-#endif
-}
-
-
-/*
-	OSReadHWReg64
-*/
-IMG_UINT64 OSReadHWReg64(void *pvLinRegBaseAddr,
-						 IMG_UINT32	ui32Offset)
-{
-	IMG_UINT64	ui64Result;
-
-	ui64Result = OSReadHWReg32(pvLinRegBaseAddr, ui32Offset + 4);
-	ui64Result <<= 32;
-	ui64Result |= (IMG_UINT64)OSReadHWReg32(pvLinRegBaseAddr, ui32Offset);
-
-	return ui64Result;
-}
-
-/*
-	OSReadHWRegBank
-*/
-IMG_DEVMEM_SIZE_T OSReadHWRegBank(void *pvLinRegBaseAddr,
-								  IMG_UINT32 ui32Offset,
-								  IMG_UINT8 *pui8DstBuf,
-								  IMG_DEVMEM_SIZE_T uiDstBufLen)
-{
-#if !defined(NO_HARDWARE)
-	IMG_DEVMEM_SIZE_T uiCounter;
-
-	for(uiCounter = 0; uiCounter < uiDstBufLen; uiCounter++) {
-		*(pui8DstBuf + uiCounter) =
-		  readb(pvLinRegBaseAddr + ui32Offset + uiCounter);
-	}
-
-	return uiCounter;
-#else
-	return uiDstBufLen;
-#endif
-}
-
-/*
-	OSWriteHWReg8
-*/
-void OSWriteHWReg8(void			*pvLinRegBaseAddr,
-				   IMG_UINT32	ui32Offset,
-				   IMG_UINT8	ui8Value)
-{
-#if !defined(NO_HARDWARE)
-	writeb(ui8Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
-#endif
-}
-
-/*
-	OSWriteHWReg16
-*/
-void OSWriteHWReg16(void		*pvLinRegBaseAddr,
-					IMG_UINT32	ui32Offset,
-					IMG_UINT16	ui16Value)
-{
-#if !defined(NO_HARDWARE)
-	writew(ui16Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
-#endif
-}
-
-/*
-	OSWriteHWReg32
-*/
-void OSWriteHWReg32(void		*pvLinRegBaseAddr,
-					IMG_UINT32	ui32Offset,
-					IMG_UINT32	ui32Value)
-{
-#if !defined(NO_HARDWARE)
-	writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
-#endif
-}
-
-
-/*
-	OSWriteHWReg64
-*/
-void OSWriteHWReg64(void		*pvLinRegBaseAddr,
-					IMG_UINT32	ui32Offset,
-					IMG_UINT64	ui64Value)
-{
-#if !defined(NO_HARDWARE)
-	IMG_UINT32 ui32ValueLow, ui32ValueHigh;
-
-	ui32ValueLow = ui64Value & 0xffffffff;
-	ui32ValueHigh = ((IMG_UINT64) (ui64Value >> 32)) & 0xffffffff;
-
-	writel(ui32ValueLow, pvLinRegBaseAddr + ui32Offset);
-	writel(ui32ValueHigh, pvLinRegBaseAddr + ui32Offset + 4);
-#endif
-}
-
-IMG_DEVMEM_SIZE_T OSWriteHWRegBank(void *pvLinRegBaseAddr,
-								   IMG_UINT32 ui32Offset,
-								   IMG_UINT8 *pui8SrcBuf,
-								   IMG_DEVMEM_SIZE_T uiSrcBufLen)
-{
-#if !defined(NO_HARDWARE)
-	IMG_DEVMEM_SIZE_T uiCounter;
-
-	for(uiCounter = 0; uiCounter < uiSrcBufLen; uiCounter++) {
-		writeb(*(pui8SrcBuf + uiCounter),
-		       pvLinRegBaseAddr + ui32Offset + uiCounter);
-	}
-
-	return uiCounter;
-#else
-	return uiSrcBufLen;
-#endif
-}
-
 #define	OS_MAX_TIMERS	8
 
 /* Timer callback strucure used by OSAddTimer */
@@ -1362,15 +1131,11 @@
 static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
 
 #if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
-DEFINE_MUTEX(sTimerStructLock);
+static DEFINE_MUTEX(sTimerStructLock);
 #else
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
 /* The lock is used to control access to sTimers */
-static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED;
-#else
 static DEFINE_SPINLOCK(sTimerStructLock);
 #endif
-#endif
 
 static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
 {
@@ -1421,14 +1186,6 @@
 }
 #endif
 
-/*************************************************************************/ /*!
-@Function       OSAddTimer
-@Description    OS specific function to install a timer callback
-@Input          pfnTimerFunc    Timer callback
-@Input         *pvData          Callback data
-@Input          ui32MsTimeout   Callback period
-@Return         Valid handle success, NULL failure
-*/ /**************************************************************************/
 IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, void *pvData, IMG_UINT32 ui32MsTimeout)
 {
 	TIMER_CALLBACK_DATA	*psTimerCBData;
@@ -1502,12 +1259,6 @@
 	return &sTimers[ui32i];
 }
 
-/*************************************************************************/ /*!
-@Function       OSRemoveTimer
-@Description    OS specific function to remove a timer callback
-@Input          hTimer : timer handle
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
 {
 	TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
@@ -1521,13 +1272,6 @@
 	return PVRSRV_OK;
 }
 
-
-/*************************************************************************/ /*!
-@Function       OSEnableTimer
-@Description    OS specific function to enable a timer callback
-@Input          hTimer    Timer handle
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
 {
 	TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
@@ -1548,12 +1292,6 @@
 }
 
 
-/*************************************************************************/ /*!
-@Function       OSDisableTimer
-@Description    OS specific function to disable a timer callback
-@Input          hTimer    Timer handle
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
 {
 	TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
@@ -1593,13 +1331,6 @@
 }
 
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectCreate
-@Description    OS specific function to create an event object
-@Input          pszName      Globally unique event object name (if null name must be autogenerated)
-@Output         hEventObject OS event object info structure
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, IMG_HANDLE *hEventObject)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -1623,12 +1354,6 @@
 }
 
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectDestroy
-@Description    OS specific function to destroy an event object
-@Input          hEventObject   OS event object info structure
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectDestroy(IMG_HANDLE hEventObject)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -1650,85 +1375,44 @@
  * EventObjectWaitTimeout()
  */
 static PVRSRV_ERROR EventObjectWaitTimeout(IMG_HANDLE hOSEventKM,
-										   IMG_UINT32 uiTimeoutMs,
+										   IMG_UINT64 uiTimeoutus,
 										   IMG_BOOL bHoldBridgeLock)
 {
-    PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError;
 
-	if(hOSEventKM && uiTimeoutMs > 0)
+	if(hOSEventKM && uiTimeoutus > 0)
 	{
-		eError = LinuxEventObjectWait(hOSEventKM, uiTimeoutMs, bHoldBridgeLock);
+		eError = LinuxEventObjectWait(hOSEventKM, uiTimeoutus, bHoldBridgeLock);
 	}
 	else
 	{
-		PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: invalid arguments %p, %d", hOSEventKM, uiTimeoutMs ));
+		PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: invalid arguments %p, %lld", hOSEventKM, uiTimeoutus));
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
 	return eError;
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectWaitTimeout
-@Description    Wait for an event with timeout as supplied. Called from client
-@Input          hOSEventKM    OS and kernel specific handle to event object
-@Input          uiTimeoutMs   Non zero time period in milliseconds to wait
-@Return         PVRSRV_ERROR_TIMEOUT : Wait reached wait limit and timed out
-@Return         PVRSRV_ERROR         : any other system error code
-*/ /**************************************************************************/
-PVRSRV_ERROR OSEventObjectWaitTimeout(IMG_HANDLE hOSEventKM, IMG_UINT32 uiTimeoutMs)
+PVRSRV_ERROR OSEventObjectWaitTimeout(IMG_HANDLE hOSEventKM, IMG_UINT64 uiTimeoutus)
 {
-    return EventObjectWaitTimeout(hOSEventKM, uiTimeoutMs, IMG_FALSE);
+	return EventObjectWaitTimeout(hOSEventKM, uiTimeoutus, IMG_FALSE);
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectWait
-@Description    OS specific function to wait for an event object. Called
-				from client. Uses a default wait with 100ms timeout.
-@Input          hOSEventKM    OS and kernel specific handle to event object
-@Return         PVRSRV_ERROR_TIMEOUT  : Reached wait limit and timed out
-@Return         PVRSRV_ERROR  : any other system error code
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
 {
-	return OSEventObjectWaitTimeout(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+	return OSEventObjectWaitTimeout(hOSEventKM, EVENT_OBJECT_TIMEOUT_US);
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectWaitTimeoutAndHoldBridgeLock
-@Description    Wait for an event with timeout as supplied. Called from client
-                NOTE: Holds bridge lock during wait.
-@Input          hOSEventKM    OS and kernel specific handle to event object
-@Input          uiTimeoutMs   Non zero time period in milliseconds to wait
-@Return         PVRSRV_ERROR_TIMEOUT : Wait reached wait limit and timed out
-@Return         PVRSRV_ERROR         : any other system error code
-*/ /**************************************************************************/
-PVRSRV_ERROR OSEventObjectWaitTimeoutAndHoldBridgeLock(IMG_HANDLE hOSEventKM, IMG_UINT32 uiTimeoutMs)
+PVRSRV_ERROR OSEventObjectWaitTimeoutAndHoldBridgeLock(IMG_HANDLE hOSEventKM, IMG_UINT64 uiTimeoutus)
 {
-	return EventObjectWaitTimeout(hOSEventKM, uiTimeoutMs, IMG_TRUE);
+	return EventObjectWaitTimeout(hOSEventKM, uiTimeoutus, IMG_TRUE);
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectWaitAndHoldBridgeLock
-@Description    OS specific function to wait for an event object. Called
-				from client. Uses a default wait with 100ms timeout.
-                NOTE: Holds bridge lock during wait.
-@Input          hOSEventKM    OS and kernel specific handle to event object
-@Return         PVRSRV_ERROR_TIMEOUT  : Reached wait limit and timed out
-@Return         PVRSRV_ERROR  : any other system error code
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectWaitAndHoldBridgeLock(IMG_HANDLE hOSEventKM)
 {
-	return OSEventObjectWaitTimeoutAndHoldBridgeLock(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+	return OSEventObjectWaitTimeoutAndHoldBridgeLock(hOSEventKM, EVENT_OBJECT_TIMEOUT_US);
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectOpen
-@Description    OS specific function to open an event object.  Called from client
-@Input          hEventObject  Pointer to an event object
-@Output         phOSEvent     OS and kernel specific handle to event object
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectOpen(IMG_HANDLE hEventObject,
 											IMG_HANDLE *phOSEvent)
 {
@@ -1751,12 +1435,6 @@
 	return eError;
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectClose
-@Description    OS specific function to close an event object.  Called from client
-@Input          hOSEventKM    OS and kernel specific handle to event object
-@Return         PVRSRV_ERROR  :
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectClose(IMG_HANDLE hOSEventKM)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -1779,12 +1457,6 @@
 	return eError;
 }
 
-/*************************************************************************/ /*!
-@Function       OSEventObjectSignal
-@Description    OS specific function to 'signal' an event object.  Called from L/MISR
-@Input          hOSEventKM   OS and kernel specific handle to event object
-@Return         PVRSRV_ERROR
-*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hEventObject)
 {
 	PVRSRV_ERROR eError;
@@ -1802,24 +1474,11 @@
 	return eError;
 }
 
-/*************************************************************************/ /*!
-@Function       OSProcHasPrivSrvInit
-@Description    Does the process have sufficient privileges to initialise services?
-@Return         IMG_BOOL
-*/ /**************************************************************************/
 IMG_BOOL OSProcHasPrivSrvInit(void)
 {
 	return capable(CAP_SYS_ADMIN) != 0;
 }
 
-/*************************************************************************/ /*!
-@Function       OSCopyToUser
-@Description    Copy a block of data into user space
-@Input          pvSrc
-@Output         pvDest
-@Input          ui32Bytes
-@Return   PVRSRV_ERROR  :
-*/ /**************************************************************************/
 PVRSRV_ERROR OSCopyToUser(void *pvProcess,
 						  void *pvDest,
 						  const void *pvSrc,
@@ -1833,14 +1492,6 @@
 		return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
 }
 
-/*************************************************************************/ /*!
-@Function       OSCopyFromUser
-@Description    Copy a block of data from the user space
-@Output         pvDest
-@Input          pvSrc
-@Input          ui32Bytes
-@Return         PVRSRV_ERROR  :
-*/ /**************************************************************************/
 PVRSRV_ERROR OSCopyFromUser(void *pvProcess,
 							void *pvDest,
 							const void *pvSrc,
@@ -1854,14 +1505,6 @@
 		return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
 }
 
-/*************************************************************************/ /*!
-@Function       OSAccessOK
-@Description    Checks if a user space pointer is valide
-@Input          eVerification
-@Input          pvUserPtr
-@Input          ui32Bytes
-@Return         IMG_BOOL :
-*/ /**************************************************************************/
 IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, void *pvUserPtr, size_t ui32Bytes)
 {
 	IMG_INT linuxType;
@@ -1879,18 +1522,6 @@
 	return access_ok(linuxType, pvUserPtr, ui32Bytes);
 }
 
-
-void OSWriteMemoryBarrier(void)
-{
-	wmb();
-}
-
-
-void OSMemoryBarrier(void)
-{
-	mb();
-}
-
 IMG_UINT64 OSDivide64r64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder)
 {
 	*pui32Remainder = do_div(ui64Divident, ui32Divisor);
@@ -1912,7 +1543,7 @@
 	{
 		PVR_ASSERT(!psTimerWorkQueue);
 
-		psTimerWorkQueue = create_workqueue("pvr_timer" PVRSRV_GPUVIRT_OSID_STR);
+		psTimerWorkQueue = create_workqueue("pvr_timer");
 		if (psTimerWorkQueue == NULL)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
@@ -1970,41 +1601,16 @@
 	mutex_unlock(&gPVRSRVLock);
 }
 
-struct task_struct *OSGetBridgeLockOwner(void)
+struct task_struct *BridgeLockGetOwner(void)
 {
 	return gsOwner;
 }
 
-static struct task_struct *gsPMRLockOwner;
-
-void PMRLock(void)
+IMG_BOOL BridgeLockIsLocked(void)
 {
-	OSLockAcquire(&gGlobalLookupPMRLock);
-	gsPMRLockOwner = current;
+	return OSLockIsLocked(&gPVRSRVLock);
 }
 
-void PMRUnlock(void)
-{
-	gsPMRLockOwner = NULL;
-	OSLockRelease(&gGlobalLookupPMRLock);
-}
-
-static struct task_struct *OSGetPMRLockOwner(void)
-{
-	return gsPMRLockOwner;
-}
-
-IMG_BOOL PMRIsLocked(void)
-{
-	return OSLockIsLocked(&gGlobalLookupPMRLock);
-}
-
-IMG_BOOL PMRIsLockedByMe(void)
-{
-	return (OSGetPMRLockOwner() == current);
-}
-
-
 /*************************************************************************/ /*!
 @Function		OSCreateStatisticEntry
 @Description	Create a statistic entry in the specified folder.
@@ -2046,6 +1652,19 @@
 	PVRDebugFSRemoveStatisticEntry((PVR_DEBUGFS_DRIVER_STAT *)pvEntry);
 } /* OSRemoveStatisticEntry */
 
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+void *OSCreateRawStatisticEntry(const IMG_CHAR *pszFileName, void *pvParentDir,
+                                OS_STATS_PRINT_FUNC *pfStatsPrint)
+{
+	return (void *) PVRDebugFSCreateRawStatisticEntry(pszFileName, pvParentDir,
+	                                                  pfStatsPrint);
+}
+
+void OSRemoveRawStatisticEntry(void *pvEntry)
+{
+	PVRDebugFSRemoveRawStatisticEntry(pvEntry);
+}
+#endif
 
 /*************************************************************************/ /*!
 @Function		OSCreateStatisticFolder
@@ -2081,69 +1700,70 @@
 } /* OSRemoveStatisticFolder */
 
 
-/*************************************************************************/ /*!
-@Function		OSChangeSparseMemCPUAddrMap
-@Description    This function changes the CPU map of the underlying sparse
-				allocation.
-@return			PVRSRV_OK on success & error code on failure.
-*/ /**************************************************************************/
 PVRSRV_ERROR OSChangeSparseMemCPUAddrMap(void **psPageArray,
-		IMG_UINT64 sCpuVAddrBase,
-		uintptr_t sCpuPAHeapBase,
-		IMG_UINT32 ui32AllocPageCount,
-		IMG_UINT32 *pai32AllocIndices,
-		IMG_UINT32 ui32FreePageCount,
-		IMG_UINT32 *pai32FreeIndices,
-		IMG_UINT32	*pui32Status,
-		IMG_BOOL bIsLMA)
+                                         IMG_UINT64 sCpuVAddrBase,
+                                         IMG_CPU_PHYADDR sCpuPAHeapBase,
+                                         IMG_UINT32 ui32AllocPageCount,
+                                         IMG_UINT32 *pai32AllocIndices,
+                                         IMG_UINT32 ui32FreePageCount,
+                                         IMG_UINT32 *pai32FreeIndices,
+                                         IMG_BOOL bIsLMA)
 {
-	int eError = ~PVRSRV_OK;
-	struct mm_struct  *psMM= current->mm;
-	struct vm_area_struct *psVMA=NULL;
-	IMG_UINT64 uiPFN = 0, uiCPUVirtAddr=0;
-	IMG_UINT32	ui32Loop=0, ui32PageSize = OSGetPageSize();
-	struct address_space *mapping = NULL;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+	pfn_t sPFN;
+#else
+	IMG_UINT64 uiPFN;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
+
+	PVRSRV_ERROR eError;
+
+	struct mm_struct  *psMM = current->mm;
+	struct vm_area_struct *psVMA = NULL;
+	struct address_space *psMapping = NULL;
+	struct page *psPage = NULL;
+
+	IMG_UINT64 uiCPUVirtAddr = 0;
+	IMG_UINT32 ui32Loop = 0;
+	IMG_UINT32 ui32PageSize = OSGetPageSize();
 	IMG_BOOL bMixedMap = IMG_FALSE;
-	struct page *page = NULL;
-	PVR_UNREFERENCED_PARAMETER(pui32Status);
 
 	/*
 	 * Acquire the lock before manipulating the VMA
 	 * In this case only mmap_sem lock would suffice as the pages associated with this VMA
-	 * are never meant to be swapped out
+	 * are never meant to be swapped out.
 	 *
-	 * In future in case the pages are marked as swapped, page_table_lock need to be acquired
-	 * in conjunction with this to stop the swap out of the pages
+	 * In the future, in case the pages are marked as swapped, page_table_lock needs
+	 * to be acquired in conjunction with this to disable page swapping.
 	 */
-	/*Find the Virtual Memory Area associated with the user base address */
+
+	/* Find the Virtual Memory Area associated with the user base address */
 	psVMA = find_vma(psMM, (uintptr_t)sCpuVAddrBase);
-	if(NULL == psVMA)
+	if (NULL == psVMA)
 	{
 		eError = PVRSRV_ERROR_PMR_NO_CPU_MAP_FOUND;
 		return eError;
 	}
 
-	/*Acquire the memory sem */
+	/* Acquire the memory sem */
 	down_write(&psMM->mmap_sem);
 
-	mapping = psVMA->vm_file->f_mapping;
+	psMapping = psVMA->vm_file->f_mapping;
 	
-	/*Set the page offset to the correct value as this is disturbed in MMAP_PMR func*/
+	/* Set the page offset to the correct value as this is disturbed in MMAP_PMR func */
 	psVMA->vm_pgoff = (psVMA->vm_start >>  PAGE_SHIFT);
 
-	/*Delete the entries for the pages that got freed */
-	if(ui32FreePageCount && (pai32FreeIndices != NULL))
+	/* Delete the entries for the pages that got freed */
+	if (ui32FreePageCount && (pai32FreeIndices != NULL))
 	{
-		for(ui32Loop = 0; ui32Loop < ui32FreePageCount; ui32Loop++)
+		for (ui32Loop = 0; ui32Loop < ui32FreePageCount; ui32Loop++)
 		{
-			uiCPUVirtAddr = (uintptr_t)(sCpuVAddrBase+(pai32FreeIndices[ui32Loop] * ui32PageSize));
+			uiCPUVirtAddr = (uintptr_t)(sCpuVAddrBase + (pai32FreeIndices[ui32Loop] * ui32PageSize));
 
-			unmap_mapping_range(mapping,uiCPUVirtAddr,ui32PageSize,1);
-
+			unmap_mapping_range(psMapping, uiCPUVirtAddr, ui32PageSize, 1);
 
 #ifndef PVRSRV_UNMAP_ON_SPARSE_CHANGE
 			/*
-			 * Still need to map pages in case remap flag is set
+			 * Still need to map pages in case remap flag is set.
 			 * That is not done until the remap case succeeds
 			 */
 #endif
@@ -2151,22 +1771,28 @@
 		eError = PVRSRV_OK;
 	}
 
-	if((psVMA->vm_flags & VM_MIXEDMAP) || bIsLMA)
+	if ((psVMA->vm_flags & VM_MIXEDMAP) || bIsLMA)
 	{
 		psVMA->vm_flags |=  VM_MIXEDMAP;
 		bMixedMap = IMG_TRUE;
 	}
 	else
 	{
-		if(ui32AllocPageCount && (NULL != pai32AllocIndices))
+		if (ui32AllocPageCount && (NULL != pai32AllocIndices))
 		{
-			for(ui32Loop = 0; ui32Loop < ui32AllocPageCount; ui32Loop++)
+			for (ui32Loop = 0; ui32Loop < ui32AllocPageCount; ui32Loop++)
 			{
 
-				page = (struct page *)psPageArray[pai32AllocIndices[ui32Loop]];
-				uiPFN = page_to_pfn((struct page *)psPageArray[pai32AllocIndices[ui32Loop]]);
+				psPage = (struct page *)psPageArray[pai32AllocIndices[ui32Loop]];
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+				sPFN = page_to_pfn_t(psPage);
 
-				if(!pfn_valid(uiPFN) || (page_count(pfn_to_page(uiPFN)) == 0))
+				if (!pfn_t_valid(sPFN) || page_count(pfn_t_to_page(sPFN)) == 0)
+#else
+				uiPFN = page_to_pfn(psPage);
+
+				if (!pfn_valid(uiPFN) || (page_count(pfn_to_page(uiPFN)) == 0))
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
 				{
 					bMixedMap = IMG_TRUE;
 					psVMA->vm_flags |= VM_MIXEDMAP;
@@ -2176,43 +1802,96 @@
 		}
 	}
 
-	/*Map the pages that got allocated */
-	if(ui32AllocPageCount && (NULL != pai32AllocIndices))
+	/* Map the pages that got allocated */
+	if (ui32AllocPageCount && (NULL != pai32AllocIndices))
 	{
-		for(ui32Loop = 0; ui32Loop < ui32AllocPageCount; ui32Loop++)
+		for (ui32Loop = 0; ui32Loop < ui32AllocPageCount; ui32Loop++)
 		{
-			uiCPUVirtAddr = (uintptr_t)(sCpuVAddrBase+(pai32AllocIndices[ui32Loop] * ui32PageSize));
+			int err;
 
-			unmap_mapping_range(mapping,uiCPUVirtAddr,ui32PageSize, 1);
-			if(bIsLMA)
-			{
-				uiPFN = sCpuPAHeapBase+((IMG_DEV_PHYADDR *)psPageArray)[pai32AllocIndices[ui32Loop]].uiAddr;
-				uiPFN  = uiPFN >> PAGE_SHIFT;
-				page = pfn_to_page(uiPFN);
-			}else{
-				page = (struct page *)psPageArray[pai32AllocIndices[ui32Loop]];
-				uiPFN = page_to_pfn((struct page *)psPageArray[pai32AllocIndices[ui32Loop]]);
-			}
+			uiCPUVirtAddr = (uintptr_t)(sCpuVAddrBase + (pai32AllocIndices[ui32Loop] * ui32PageSize));
+			unmap_mapping_range(psMapping, uiCPUVirtAddr, ui32PageSize, 1);
 
-			if(bMixedMap )
+			if (bIsLMA)
 			{
-				eError = vm_insert_mixed(psVMA,uiCPUVirtAddr, uiPFN);
+				phys_addr_t uiAddr = sCpuPAHeapBase.uiAddr +
+				                     ((IMG_DEV_PHYADDR *)psPageArray)[pai32AllocIndices[ui32Loop]].uiAddr;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+				sPFN = phys_to_pfn_t(uiAddr, 0);
+				psPage = pfn_t_to_page(sPFN);
+#else
+				uiPFN = uiAddr >> PAGE_SHIFT;
+				psPage = pfn_to_page(uiPFN);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
 			}
 			else
 			{
-				eError = vm_insert_page(psVMA,uiCPUVirtAddr,page);
+				psPage = (struct page *)psPageArray[pai32AllocIndices[ui32Loop]];
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+				sPFN = page_to_pfn_t(psPage);
+#else
+				uiPFN = page_to_pfn(psPage);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
 			}
 
-			if(0 != eError)
+			if (bMixedMap)
 			{
-				PVR_DPF((PVR_DBG_MESSAGE,"Remap failure error code: %d", eError));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+				err = vm_insert_mixed(psVMA, uiCPUVirtAddr, sPFN);
+#else
+				err = vm_insert_mixed(psVMA, uiCPUVirtAddr, uiPFN);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
+			}
+			else
+			{
+				err = vm_insert_page(psVMA, uiCPUVirtAddr, psPage);
+			}
+
+			if (err)
+			{
+				PVR_DPF((PVR_DBG_MESSAGE, "Remap failure error code: %d", err));
 				eError = PVRSRV_ERROR_PMR_CPU_PAGE_MAP_FAILED;
 				goto eFailed;
 			}
 		}
 	}
+
 	eError = PVRSRV_OK;
 	eFailed:
 	up_write(&psMM->mmap_sem);
+
 	return eError;
 }
+
+/*************************************************************************/ /*!
+@Function       OSDebugSignalPID
+@Description    Sends a SIGTRAP signal to a specific PID in user mode for
+                debugging purposes. The user mode process can register a handler
+                against this signal.
+                This is necessary to support the Rogue debugger. If the Rogue
+                debugger is not used then this function may be implemented as
+                a stub.
+@Input          ui32PID    The PID for the signal.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSDebugSignalPID(IMG_UINT32 ui32PID)
+{
+	int err;
+	struct pid *psPID;
+
+	psPID = find_vpid(ui32PID);
+	if (psPID == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get PID struct.", __func__));
+		return PVRSRV_ERROR_NOT_FOUND;
+	}
+
+	err = kill_pid(psPID, SIGTRAP, 0);
+	if (err != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Signal Failure %d", __func__, err));
+		return PVRSRV_ERROR_SIGNAL_FAILED;
+	}
+
+	return PVRSRV_OK;
+}
diff --git a/drivers/staging/imgtec/rogue/osfunc.h b/drivers/staging/imgtec/rogue/osfunc.h
index 55f324c..26fb8e2 100644
--- a/drivers/staging/imgtec/rogue/osfunc.h
+++ b/drivers/staging/imgtec/rogue/osfunc.h
@@ -50,17 +50,25 @@
 #define __OSFUNC_H__
 
 
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
 #include <services_kernel_client.h>
 #endif
 
+#if defined(LINUX) && defined(__KERNEL__) && !defined(NO_HARDWARE)
+#include <asm/io.h>
+#endif
+
 #if defined(__QNXNTO__)
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 #endif
 
+#if defined(INTEGRITY_OS)
+#include <string.h>
+#endif
+
 #include "img_types.h"
 #include "pvrsrv_device.h"
 #include "device.h"
@@ -71,43 +79,194 @@
 #define KERNEL_ID			0xffffffffL
 #define ISR_ID				0xfffffffdL
 
+/*************************************************************************/ /*!
+@Function       OSClockns64
+@Description    This function returns the number of ticks since system boot
+                expressed in nanoseconds. Unlike OSClockns, OSClockns64 has
+                a near 64-bit range.
+@Return         The 64-bit clock value, in nanoseconds.
+*/ /**************************************************************************/
 IMG_UINT64 OSClockns64(void);
+
+/*************************************************************************/ /*!
+@Function       OSClockus64
+@Description    This function returns the number of ticks since system boot
+                expressed in microseconds. Unlike   OSClockus, OSClockus64 has
+                a near 64-bit range.
+@Return         The 64-bit clock value, in microseconds.
+*/ /**************************************************************************/
 IMG_UINT64 OSClockus64(void);
+
+/*************************************************************************/ /*!
+@Function       OSClockus
+@Description    This function returns the number of ticks since system boot
+                in microseconds.
+@Return         The 32-bit clock value, in microseconds.
+*/ /**************************************************************************/
 IMG_UINT32 OSClockus(void);
+
+/*************************************************************************/ /*!
+@Function       OSClockms
+@Description    This function returns the number of ticks since system boot
+                in milliseconds.
+@Return         The 32-bit clock value, in milliseconds.
+*/ /**************************************************************************/
 IMG_UINT32 OSClockms(void);
 
+/*************************************************************************/ /*!
+@Function       OSClockMonotonicns64
+@Description    This function returns a clock value based on the system
+                monotonic clock.
+@Output         pui64Time     The 64-bit clock value, in nanoseconds.
+@Return         Error Code.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSClockMonotonicns64(IMG_UINT64 *pui64Time);
+
+/*************************************************************************/ /*!
+@Function       OSClockMonotonicus64
+@Description    This function returns a clock value based on the system
+                monotonic clock.
+@Output         pui64Time     The 64-bit clock value, in microseconds.
+@Return         Error Code.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSClockMonotonicus64(IMG_UINT64 *pui64Time);
+
+/*************************************************************************/ /*!
+@Function       OSClockMonotonicRawns64
+@Description    This function returns a clock value based on the system
+                monotonic raw clock.
+@Return         64bit ns timestamp
+*/ /**************************************************************************/
+IMG_UINT64 OSClockMonotonicRawns64(void);
+
+/*************************************************************************/ /*!
+@Function       OSClockMonotonicRawns64
+@Description    This function returns a clock value based on the system
+                monotonic raw clock.
+@Return         64bit us timestamp
+*/ /**************************************************************************/
+IMG_UINT64 OSClockMonotonicRawus64(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetPageSize
+@Description    This function returns the page size.
+                If the OS is not using memory mappings it should return a
+                default value of 4096.
+@Return         The size of a page, in bytes.
+*/ /**************************************************************************/
 size_t OSGetPageSize(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetPageShift
+@Description    This function returns the page size expressed as a power
+                of two. A number of pages, left-shifted by this value, gives
+                the equivalent size in bytes.
+                If the OS is not using memory mappings it should return a
+                default value of 12.
+@Return         The page size expressed as a power of two.
+*/ /**************************************************************************/
 size_t OSGetPageShift(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetPageMask
+@Description    This function returns a bitmask that may be applied to an
+                address to mask off the least-significant bits so as to
+                leave the start address of the page containing that address.
+@Return         The page mask.
+*/ /**************************************************************************/
 size_t OSGetPageMask(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetOrder
+@Description    This function returns the order of power of two for a given
+                size. Eg. for a uSize of 4096 bytes the function would
+                return 12 (4096 = 2^12).
+@Input          uSize     The size in bytes.
+@Return         The order of power of two.
+*/ /**************************************************************************/
 size_t OSGetOrder(size_t uSize);
 
+typedef void (*PFN_MISR)(void *pvData);
 typedef void (*PFN_THREAD)(void *pvData);
 
+/**************************************************************************/ /*!
+@Function       OSChangeSparseMemCPUAddrMap
+@Description    This function changes the CPU mapping of the underlying
+                sparse allocation. It is used by a PMR 'factory'
+                implementation if that factory supports sparse
+                allocations.
+@Input          psPageArray        array representing the pages in the
+                                   sparse allocation
+@Input          sCpuVAddrBase      the virtual base address of the sparse
+                                   allocation ('first' page)
+@Input          sCpuPAHeapBase     the physical address of the virtual
+                                   base address 'sCpuVAddrBase'
+@Input          ui32AllocPageCount the number of pages referenced in
+                                   'pai32AllocIndices'
+@Input          pai32AllocIndices  list of indices of pages within
+                                   'psPageArray' that we now want to
+                                   allocate and map
+@Input          ui32FreePageCount  the number of pages referenced in
+                                   'pai32FreeIndices'
+@Input          pai32FreeIndices   list of indices of pages within
+                                   'psPageArray' we now want to
+                                   unmap and free
+@Input          bIsLMA             flag indicating if the sparse allocation
+                                   is from LMA or UMA memory
+@Return         PVRSRV_OK on success, a failure code otherwise.
+ */ /**************************************************************************/
 PVRSRV_ERROR OSChangeSparseMemCPUAddrMap(void **psPageArray,
-										IMG_UINT64 sCpuVAddrBase,
-										uintptr_t sCpuPAHeapBase,
-										IMG_UINT32 ui32AllocPageCount,
-										IMG_UINT32 *pai32AllocIndices,
-										IMG_UINT32 ui32FreePageCount,
-										IMG_UINT32 *pai32FreeIndices,
-										IMG_UINT32	*pui32Status,
-										IMG_BOOL bIsLMA);
+                                         IMG_UINT64 sCpuVAddrBase,
+                                         IMG_CPU_PHYADDR sCpuPAHeapBase,
+                                         IMG_UINT32 ui32AllocPageCount,
+                                         IMG_UINT32 *pai32AllocIndices,
+                                         IMG_UINT32 ui32FreePageCount,
+                                         IMG_UINT32 *pai32FreeIndices,
+                                         IMG_BOOL bIsLMA);
 
-PVRSRV_ERROR OSInstallDeviceLISR(PVRSRV_DEVICE_CONFIG *psDevConfig,
-								 IMG_HANDLE *hLISRData,
-								 PFN_LISR pfnLISR,
-								 void *hData);
-PVRSRV_ERROR OSUninstallDeviceLISR(IMG_HANDLE hLISRData);
-
+/*************************************************************************/ /*!
+@Function       OSInstallMISR
+@Description    Installs a Mid-level Interrupt Service Routine (MISR)
+                which handles higher-level processing of interrupts from
+                the device (GPU).
+                An MISR runs outside of interrupt context, and so may be
+                descheduled. This means it can contain code that would
+                not be permitted in the LISR.
+                An MISR is invoked when OSScheduleMISR() is called. This
+                call should be made by installed LISR once it has completed
+                its interrupt processing.
+                Multiple MISRs may be installed by the driver to handle
+                different causes of interrupt.
+@Input          pfnMISR       pointer to the function to be installed
+                              as the MISR
+@Input          hData         private data provided to the MISR
+@Output         hMISRData     handle to the installed MISR (to be used
+                              for a subsequent uninstall)
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSInstallMISR(IMG_HANDLE *hMISRData,
 						   PFN_MISR pfnMISR,
 						   void *hData);
+
+/*************************************************************************/ /*!
+@Function       OSUninstallMISR
+@Description    Uninstalls a Mid-level Interrupt Service Routine (MISR).
+@Input          hMISRData     handle to the installed MISR
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSUninstallMISR(IMG_HANDLE hMISRData);
+
+/*************************************************************************/ /*!
+@Function       OSScheduleMISR
+@Description    Schedules a Mid-level Interrupt Service Routine (MISR) to be
+                executed. An MISR should be executed outside of interrupt
+                context, for example in a work queue.
+@Input          hMISRData     handle to the installed MISR
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSScheduleMISR(IMG_HANDLE hMISRData);
 
 
-
-
 /*************************************************************************/ /*!
 @Function       OSThreadCreate
 @Description    Creates a kernel thread and starts it running. The caller
@@ -166,238 +325,1058 @@
                 thread to finish successfully, thereby providing a sync point
                 for the thread completing its work. No attempt is made to kill
                 or otherwise terminate the thread.
-@Input          phThread  The thread handle returned by OSThreadCreate().
+@Input          hThread   The thread handle returned by OSThreadCreate().
 @Return         Standard PVRSRV_ERROR error code.
 */ /**************************************************************************/
 PVRSRV_ERROR OSThreadDestroy(IMG_HANDLE hThread);
 
-void PVRSRVDeviceMemSet(void *pvDest, IMG_UINT8 ui8Value, size_t ui32Size);
-void PVRSRVDeviceMemCopy(void *pvDst, const void *pvSrc, size_t ui32Size);
+/*************************************************************************/ /*!
+@Function       OSSetThreadPriority
+@Description    Set the priority and weight of a thread
+@Input          hThread  			The thread handle.
+@Input			nThreadPriority		The integer value of the thread priority
+@Input			nThreadWeight		The integer value of the thread weight
+@Return         Standard PVRSRV_ERROR error code.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSSetThreadPriority( IMG_HANDLE hThread,
+								  IMG_UINT32  nThreadPriority,
+								  IMG_UINT32  nThreadWeight);
 
 #if defined(__arm64__) || defined(__aarch64__) || defined (PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)
-#define OSDeviceMemSet(a,b,c) PVRSRVDeviceMemSet((a), (b), (c))
-#define OSDeviceMemCopy(a,b,c) PVRSRVDeviceMemCopy((a), (b), (c))
-#define OSMemSet(a,b,c)  PVRSRVDeviceMemSet((a), (b), (c))
-#define OSMemCopy(a,b,c)  PVRSRVDeviceMemCopy((a), (b), (c))
-#else
-#define OSDeviceMemSet(a,b,c) memset((a), (b), (c))
-#define OSDeviceMemCopy(a,b,c) memcpy((a), (b), (c))
-#define OSMemSet(a,b,c)  memset((a), (b), (c))
-#define OSMemCopy(a,b,c)  memcpy((a), (b), (c))
-#endif
 
-#define OSCachedMemSet(a,b,c) memset((a), (b), (c))
+/* Workarounds for assumptions made that memory will not be mapped uncached
+ * in kernel or user address spaces on arm64 platforms (or other testing).
+ */
+
+/**************************************************************************/ /*!
+@Function       DeviceMemSet
+@Description    Set memory, whose mapping may be uncached, to a given value.
+                On some architectures, additional processing may be needed
+                if the mapping is uncached. In such cases, OSDeviceMemSet()
+                is defined as a call to this function.
+@Input          pvDest     void pointer to the memory to be set
+@Input          ui8Value   byte containing the value to be set
+@Input          ui32Size   the number of bytes to be set to the given value
+@Return         None
+ */ /**************************************************************************/
+void DeviceMemSet(void *pvDest, IMG_UINT8 ui8Value, size_t ui32Size);
+
+/**************************************************************************/ /*!
+@Function       DeviceMemCopy
+@Description    Copy values from one area of memory, to another, when one
+                or both mappings may be uncached.
+                On some architectures, additional processing may be needed
+                if mappings are uncached. In such cases, OSDeviceMemCopy()
+                is defined as a call to this function.
+@Input          pvDst      void pointer to the destination memory
+@Input          pvSrc      void pointer to the source memory
+@Input          ui32Size   the number of bytes to be copied
+@Return         None
+ */ /**************************************************************************/
+void DeviceMemCopy(void *pvDst, const void *pvSrc, size_t ui32Size);
+
+#define OSDeviceMemSet(a,b,c)  DeviceMemSet((a), (b), (c))
+#define OSDeviceMemCopy(a,b,c) DeviceMemCopy((a), (b), (c))
+#define OSCachedMemSet(a,b,c)  memset((a), (b), (c))
 #define OSCachedMemCopy(a,b,c) memcpy((a), (b), (c))
 
+#else /* !(defined(__arm64__) || defined(__aarch64__) || defined(PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)) */
+
+/* Everything else */
+
+/**************************************************************************/ /*!
+@Function       OSDeviceMemSet
+@Description    Set memory, whose mapping may be uncached, to a given value.
+                On some architectures, additional processing may be needed
+                if the mapping is uncached.
+@Input          a     void pointer to the memory to be set
+@Input          b     byte containing the value to be set
+@Input          c     the number of bytes to be set to the given value
+@Return         Pointer to the destination memory.
+ */ /**************************************************************************/
+#define OSDeviceMemSet(a,b,c) memset((a), (b), (c))
+
+/**************************************************************************/ /*!
+@Function       OSDeviceMemCopy
+@Description    Copy values from one area of memory, to another, when one
+                or both mappings may be uncached.
+                On some architectures, additional processing may be needed
+                if mappings are uncached.
+@Input          a     void pointer to the destination memory
+@Input          b     void pointer to the source memory
+@Input          c     the number of bytes to be copied
+@Return         Pointer to the destination memory.
+ */ /**************************************************************************/
+#define OSDeviceMemCopy(a,b,c) memcpy((a), (b), (c))
+
+/**************************************************************************/ /*!
+@Function       OSCachedMemSet
+@Description    Set memory, where the mapping is known to be cached, to a
+                given value. This function exists to allow an optimal memset
+                to be performed when memory is known to be cached.
+@Input          a     void pointer to the memory to be set
+@Input          b     byte containing the value to be set
+@Input          c     the number of bytes to be set to the given value
+@Return         Pointer to the destination memory.
+ */ /**************************************************************************/
+#define OSCachedMemSet(a,b,c)  memset((a), (b), (c))
+
+/**************************************************************************/ /*!
+@Function       OSCachedMemCopy
+@Description    Copy values from one area of memory, to another, when both
+                mappings are known to be cached.
+                This function exists to allow an optimal memcpy to be
+                performed when memory is known to be cached.
+@Input          a     void pointer to the destination memory
+@Input          b     void pointer to the source memory
+@Input          c     the number of bytes to be copied
+@Return         Pointer to the destination memory.
+ */ /**************************************************************************/
+#define OSCachedMemCopy(a,b,c) memcpy((a), (b), (c))
+
+#endif /* !(defined(__arm64__) || defined(__aarch64__) || defined(PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)) */
+
+/**************************************************************************/ /*!
+@Function       OSMapPhysToLin
+@Description    Maps physical memory into a linear address range.
+@Input          BasePAddr    physical CPU address
+@Input          ui32Bytes    number of bytes to be mapped
+@Input          ui32Flags    flags denoting the caching mode to be employed
+                             for the mapping (uncached/write-combined,
+                             cached coherent or cached incoherent).
+                             See pvrsrv_memallocflags.h for full flag bit
+                             definitions.
+@Return         Pointer to the new mapping if successful, NULL otherwise.
+ */ /**************************************************************************/
 void *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, size_t ui32Bytes, IMG_UINT32 ui32Flags);
+
+/**************************************************************************/ /*!
+@Function       OSUnMapPhysToLin
+@Description    Unmaps physical memory previously mapped by OSMapPhysToLin().
+@Input          pvLinAddr    the linear mapping to be unmapped
+@Input          ui32Bytes    number of bytes to be unmapped
+@Input          ui32Flags    flags denoting the caching mode that was employed
+                             for the original mapping.
+@Return         IMG_TRUE if unmapping was successful, IMG_FALSE otherwise.
+ */ /**************************************************************************/
 IMG_BOOL OSUnMapPhysToLin(void *pvLinAddr, size_t ui32Bytes, IMG_UINT32 ui32Flags);
 
-
+/**************************************************************************/ /*!
+@Function       OSCPUOperation
+@Description    Perform the specified cache operation on the CPU.
+@Input          eCacheOp      the type of cache operation to be performed
+@Return         PVRSRV_OK on success, a failure code otherwise.
+ */ /**************************************************************************/
 PVRSRV_ERROR OSCPUOperation(PVRSRV_CACHE_OP eCacheOp);
 
-void OSFlushCPUCacheRangeKM(void *pvVirtStart,
-							void *pvVirtEnd,
-							IMG_CPU_PHYADDR sCPUPhysStart,
-							IMG_CPU_PHYADDR sCPUPhysEnd);
+/**************************************************************************/ /*!
+@Function       OSFlushCPUCacheRangeKM
+@Description    Clean and invalidate the CPU cache for the specified
+                address range.
+@Input          psDevNode     device on which the allocation was made
+@Input          pvVirtStart   virtual start address of the range to be
+                              flushed
+@Input          pvVirtEnd     virtual end address of the range to be
+                              flushed
+@Input          sCPUPhysStart physical start address of the range to be
+                              flushed
+@Input          sCPUPhysEnd   physical end address of the range to be
+                              flushed
+@Return         None
+ */ /**************************************************************************/
+void OSFlushCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                            void *pvVirtStart,
+                            void *pvVirtEnd,
+                            IMG_CPU_PHYADDR sCPUPhysStart,
+                            IMG_CPU_PHYADDR sCPUPhysEnd);
 
 
-void OSCleanCPUCacheRangeKM(void *pvVirtStart,
-							void *pvVirtEnd,
-							IMG_CPU_PHYADDR sCPUPhysStart,
-							IMG_CPU_PHYADDR sCPUPhysEnd);
+/**************************************************************************/ /*!
+@Function       OSCleanCPUCacheRangeKM
+@Description    Clean the CPU cache for the specified address range.
+                This writes out the contents of the cache and unsets the
+                'dirty' bit (which indicates the physical memory is
+                consistent with the cache contents).
+@Input          psDevNode     device on which the allocation was made
+@Input          pvVirtStart   virtual start address of the range to be
+                              cleaned
+@Input          pvVirtEnd     virtual end address of the range to be
+                              cleaned
+@Input          sCPUPhysStart physical start address of the range to be
+                              cleaned
+@Input          sCPUPhysEnd   physical end address of the range to be
+                              cleaned
+@Return         None
+ */ /**************************************************************************/
+void OSCleanCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                            void *pvVirtStart,
+                            void *pvVirtEnd,
+                            IMG_CPU_PHYADDR sCPUPhysStart,
+                            IMG_CPU_PHYADDR sCPUPhysEnd);
 
-void OSInvalidateCPUCacheRangeKM(void *pvVirtStart,
-								 void *pvVirtEnd,
-								 IMG_CPU_PHYADDR sCPUPhysStart,
-								 IMG_CPU_PHYADDR sCPUPhysEnd);
+/**************************************************************************/ /*!
+@Function       OSInvalidateCPUCacheRangeKM
+@Description    Invalidate the CPU cache for the specified address range.
+                The cache must reload data from those addresses if they
+                are accessed.
+@Input          psDevNode     device on which the allocation was made
+@Input          pvVirtStart   virtual start address of the range to be
+                              invalidated
+@Input          pvVirtEnd     virtual end address of the range to be
+                              invalidated
+@Input          sCPUPhysStart physical start address of the range to be
+                              invalidated
+@Input          sCPUPhysEnd   physical end address of the range to be
+                              invalidated
+@Return         None
+ */ /**************************************************************************/
+void OSInvalidateCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                                 void *pvVirtStart,
+                                 void *pvVirtEnd,
+                                 IMG_CPU_PHYADDR sCPUPhysStart,
+                                 IMG_CPU_PHYADDR sCPUPhysEnd);
 
-
+/**************************************************************************/ /*!
+@Function       OSCPUCacheOpAddressType
+@Description    Returns the address type (i.e. virtual/physical/both) that is 
+                used to perform cache maintenance on the CPU. This is used
+				to infer whether the virtual or physical address supplied to
+				the OSxxxCPUCacheRangeKM functions can be omitted when called.
+@Input          uiCacheOp       the type of cache operation to be performed
+@Return         PVRSRV_CACHE_OP_ADDR_TYPE
+ */ /**************************************************************************/
 PVRSRV_CACHE_OP_ADDR_TYPE OSCPUCacheOpAddressType(PVRSRV_CACHE_OP uiCacheOp);
 
+/*!
+ ******************************************************************************
+ * Cache attribute size type
+ *****************************************************************************/
 typedef enum _IMG_DCACHE_ATTRIBUTE_
 {
-	PVR_DCACHE_LINE_SIZE = 0,
-	PVR_DCACHE_ATTRIBUTE_COUNT
+	PVR_DCACHE_LINE_SIZE = 0,    /*!< The cache line size */
+	PVR_DCACHE_ATTRIBUTE_COUNT   /*!< The number of attributes (must be last) */
 } IMG_DCACHE_ATTRIBUTE;
 
+/**************************************************************************/ /*!
+@Function       OSCPUCacheAttributeSize
+@Description    Returns the size of a given cache attribute.
+                Typically this function is used to return the cache line
+                size, but may be extended to return the size of other
+                cache attributes.
+@Input          eCacheAttribute   the cache attribute whose size should
+                                  be returned.
+@Return         The size of the specified cache attribute, in bytes.
+ */ /**************************************************************************/
 IMG_UINT32 OSCPUCacheAttributeSize(IMG_DCACHE_ATTRIBUTE eCacheAttribute);
 
+/*************************************************************************/ /*!
+@Function       OSGetCurrentProcessID
+@Description    Returns ID of current process (thread group)
+@Return         ID of current process
+*****************************************************************************/
 IMG_PID OSGetCurrentProcessID(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetCurrentProcessName
+@Description    Gets the name of current process
+@Return         Process name
+*****************************************************************************/
 IMG_CHAR *OSGetCurrentProcessName(void);
+
+/*************************************************************************/ /*!
+@Function		OSGetCurrentProcessVASpaceSize
+@Description	Returns the CPU virtual address space size of current process
+@Return			Process VA space size
+*/ /**************************************************************************/
+IMG_UINT64 OSGetCurrentProcessVASpaceSize(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetCurrentThreadID
+@Description    Returns ID for current thread
+@Return         ID of current thread
+*****************************************************************************/
 uintptr_t OSGetCurrentThreadID(void);
 
+/*************************************************************************/ /*!
+@Function       OSGetCurrentClientProcessIDKM
+@Description    Returns ID of current client process (thread group) which
+                has made a bridge call into the server.
+                For some operating systems, this may simply be the current
+                process id. For others, it may be that a dedicated thread
+                is used to handle the processing of bridge calls and that
+                some additional processing is required to obtain the ID of
+                the client process making the bridge call.
+@Return         ID of current client process
+*****************************************************************************/
 IMG_PID OSGetCurrentClientProcessIDKM(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetCurrentClientProcessNameKM
+@Description    Gets the name of current client process
+@Return         Client process name
+*****************************************************************************/
 IMG_CHAR *OSGetCurrentClientProcessNameKM(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetCurrentClientThreadIDKM
+@Description    Returns ID for current client thread
+                For some operating systems, this may simply be the current
+                thread id. For others, it may be that a dedicated thread
+                is used to handle the processing of bridge calls and that
+                some additional processing is require to obtain the ID of
+                the client thread making the bridge call.
+@Return         ID of current client thread
+*****************************************************************************/
 uintptr_t OSGetCurrentClientThreadIDKM(void);
 
-
-
-
+/**************************************************************************/ /*!
+@Function       OSMemCmp
+@Description    Compares two blocks of memory for equality.
+@Input          pvBufA      Pointer to the first block of memory
+@Input          pvBufB      Pointer to the second block of memory
+@Input          uiLen       The number of bytes to be compared
+@Return         Value < 0 if pvBufA is less than pvBufB.
+                Value > 0 if pvBufB is less than pvBufA.
+                Value = 0 if pvBufA is equal to pvBufB.
+*****************************************************************************/
 IMG_INT OSMemCmp(void *pvBufA, void *pvBufB, size_t uiLen);
 
+/*************************************************************************/ /*!
+@Function       OSPhyContigPagesAlloc
+@Description    Allocates a number of contiguous physical pages.
+                If allocations made by this function are CPU cached then
+                OSPhyContigPagesClean has to be implemented to write the
+                cached data to memory.
+@Input          psDevNode     the device for which the allocation is
+                              required
+@Input          uiSize        the size of the required allocation (in bytes)
+@Output         psMemHandle   a returned handle to be used to refer to this
+                              allocation
+@Output         psDevPAddr    the physical address of the allocation
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*****************************************************************************/
 PVRSRV_ERROR OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
 							PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr);
 
+/*************************************************************************/ /*!
+@Function       OSPhyContigPagesFree
+@Description    Frees a previous allocation of contiguous physical pages
+@Input          psDevNode     the device on which the allocation was made
+@Input          psMemHandle   the handle of the allocation to be freed
+@Return         None.
+*****************************************************************************/
 void OSPhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle);
 
+/*************************************************************************/ /*!
+@Function       OSPhyContigPagesMap
+@Description    Maps the specified allocation of contiguous physical pages
+                to a kernel virtual address
+@Input          psDevNode     the device on which the allocation was made
+@Input          psMemHandle   the handle of the allocation to be mapped
+@Input          uiSize        the size of the allocation (in bytes)
+@Input          psDevPAddr    the physical address of the allocation
+@Output         pvPtr         the virtual kernel address to which the
+                              allocation is now mapped
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*****************************************************************************/
 PVRSRV_ERROR OSPhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
 						size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
 						void **pvPtr);
 
+/*************************************************************************/ /*!
+@Function       OSPhyContigPagesUnmap
+@Description    Unmaps the kernel mapping for the specified allocation of
+                contiguous physical pages
+@Input          psDevNode     the device on which the allocation was made
+@Input          psMemHandle   the handle of the allocation to be unmapped
+@Input          pvPtr         the virtual kernel address to which the
+                              allocation is currently mapped
+@Return         None.
+*****************************************************************************/
 void OSPhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle, void *pvPtr);
 
 /*************************************************************************/ /*!
 @Function       OSPhyContigPagesClean
 @Description    Write the content of the specified allocation from CPU cache to
                 memory from (start + uiOffset) to (start + uiOffset + uiLength)
-
+                It is expected to be implemented as a cache clean operation but
+                it is allowed to fall back to a cache clean + invalidate
+                (i.e. flush).
+                If allocations returned by OSPhyContigPagesAlloc are always
+                uncached this can be implemented as nop.
+@Input          psDevNode     device on which the allocation was made
 @Input          psMemHandle   the handle of the allocation to be flushed
 @Input          uiOffset      the offset in bytes from the start of the 
                               allocation from where to start flushing
 @Input          uiLength      the amount to flush from the offset in bytes
 @Return         PVRSRV_OK on success, a failure code otherwise.
 *****************************************************************************/
-PVRSRV_ERROR OSPhyContigPagesClean(PG_HANDLE *psMemHandle,
+PVRSRV_ERROR OSPhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
+                                   PG_HANDLE *psMemHandle,
                                    IMG_UINT32 uiOffset,
                                    IMG_UINT32 uiLength);
 
 
+/**************************************************************************/ /*!
+@Function       OSInitEnvData
+@Description    Called to initialise any environment-specific data. This
+                could include initialising the bridge calling infrastructure
+                or device memory management infrastructure.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+ */ /**************************************************************************/
 PVRSRV_ERROR OSInitEnvData(void);
+
+/**************************************************************************/ /*!
+@Function       OSDeInitEnvData
+@Description    The counterpart to OSInitEnvData(). Called to free any
+                resources which may have been allocated by OSInitEnvData().
+@Return         None.
+ */ /**************************************************************************/
 void OSDeInitEnvData(void);
 
+/**************************************************************************/ /*!
+@Function       OSSScanf
+@Description    OS function to support the standard C sscanf() function.
+ */ /**************************************************************************/
+IMG_UINT32 OSVSScanf(IMG_CHAR *pStr, const IMG_CHAR *pszFormat, ...);
+
+/**************************************************************************/ /*!
+@Function       OSStringNCopy
+@Description    OS function to support the standard C strncpy() function.
+ */ /**************************************************************************/
 IMG_CHAR* OSStringNCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uSize);
-IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, size_t ui32Size, const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+/**************************************************************************/ /*!
+@Function       OSSNPrintf
+@Description    OS function to support the standard C snprintf() function.
+ */ /**************************************************************************/
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, size_t ui32Size, const IMG_CHAR *pszFormat, ...) __printf(3, 4);
+
+/**************************************************************************/ /*!
+@Function       OSStringLength
+@Description    OS function to support the standard C strlen() function.
+ */ /**************************************************************************/
 size_t OSStringLength(const IMG_CHAR *pStr);
+
+/**************************************************************************/ /*!
+@Function       OSStringNLength
+@Description    Return the length of a string, excluding the terminating null
+                byte ('\0'), but return at most 'uiCount' bytes. Only the first
+                'uiCount' bytes of 'pStr' are interrogated.
+@Input          pStr     pointer to the string
+@Input          uiCount  the maximum length to return
+@Return         Length of the string if less than 'uiCount' bytes, otherwise
+                'uiCount'.
+ */ /**************************************************************************/
 size_t OSStringNLength(const IMG_CHAR *pStr, size_t uiCount);
+
+/**************************************************************************/ /*!
+@Function       OSStringCompare
+@Description    OS function to support the standard C strcmp() function.
+ */ /**************************************************************************/
 IMG_INT32 OSStringCompare(const IMG_CHAR *pStr1, const IMG_CHAR *pStr2);
 
+/**************************************************************************/ /*!
+@Function       OSStringNCompare
+@Description    OS function to support the standard C strncmp() function.
+ */ /**************************************************************************/
+IMG_INT32 OSStringNCompare(const IMG_CHAR *pStr1, const IMG_CHAR *pStr2,
+                           size_t uiSize);
+
+/**************************************************************************/ /*!
+@Function       OSStringToUINT32
+@Description    Changes string to IMG_UINT32.
+ */ /**************************************************************************/
+PVRSRV_ERROR OSStringToUINT32(const IMG_CHAR *pStr, IMG_UINT32 ui32Base,
+                              IMG_UINT32 *ui32Result);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectCreate
+@Description    Create an event object.
+@Input          pszName         name to assign to the new event object.
+@Output         EventObject     the created event object.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName,
 								 IMG_HANDLE *EventObject);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectDestroy
+@Description    Destroy an event object.
+@Input          hEventObject    the event object to destroy.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectDestroy(IMG_HANDLE hEventObject);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectSignal
+@Description    Signal an event object. Any thread waiting on that event
+                object will be woken.
+@Input          hEventObject    the event object to signal.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hEventObject);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectWait
+@Description    Wait for an event object to signal. The function is passed
+                an OS event object handle (which allows the OS to have the
+                calling thread wait on the associated event object).
+                The calling thread will be rescheduled when the associated
+                event object signals.
+                If the event object has not signalled after a default timeout
+                period (defined in EVENT_OBJECT_TIMEOUT_MS), the function
+                will return with the result code PVRSRV_ERROR_TIMEOUT.
+
+                Note: The global bridge lock should be released while waiting
+                for the event object to signal (if held by the current thread).
+                The following logic should be implemented in the OS
+                implementation:
+                ...
+                bReleasePVRLock = (!bHoldBridgeLock &&
+                                   BridgeLockIsLocked() &&
+                                   current == BridgeLockGetOwner());
+                if (bReleasePVRLock == IMG_TRUE) OSReleaseBridgeLock();
+                ...
+                / * sleep & reschedule - wait for signal * /
+                ...
+                if (bReleasePVRLock == IMG_TRUE) OSReleaseBridgeLock();
+                ...
+
+@Input          hOSEventKM    the OS event object handle associated with
+                              the event object.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM);
-PVRSRV_ERROR OSEventObjectWaitTimeout(IMG_HANDLE hOSEventKM, IMG_UINT32 uiTimeoutMs);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectWaitTimeout
+@Description    Wait for an event object to signal or timeout. The function
+                is passed an OS event object handle (which allows the OS to
+                have the calling thread wait on the associated event object).
+                The calling thread will be rescheduled when the associated
+                event object signals.
+                If the event object has not signalled after the specified
+                timeout period (passed in 'uiTimeoutus'), the function
+                will return with the result code PVRSRV_ERROR_TIMEOUT.
+                NB. The global bridge lock should be released while waiting
+                for the event object to signal (if held by the current thread)
+                See OSEventObjectWait() for details.
+@Input          hOSEventKM    the OS event object handle associated with
+                              the event object.
+@Input          uiTimeoutus   the timeout period (in usecs)
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectWaitTimeout(IMG_HANDLE hOSEventKM, IMG_UINT64 uiTimeoutus);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectWaitAndHoldBridgeLock
+@Description    Wait for an event object to signal. The function is passed
+                an OS event object handle (which allows the OS to have the
+                calling thread wait on the associated event object).
+                The calling thread will be rescheduled when the associated
+                event object signals.
+                If the event object has not signalled after a default timeout
+                period (defined in EVENT_OBJECT_TIMEOUT_MS), the function
+                will return with the result code PVRSRV_ERROR_TIMEOUT.
+                The global bridge lock is held while waiting for the event
+                object to signal (this will prevent other bridge calls from
+                being serviced during this time).
+                See OSEventObjectWait() for details.
+@Input          hOSEventKM    the OS event object handle associated with
+                              the event object.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectWaitAndHoldBridgeLock(IMG_HANDLE hOSEventKM);
-PVRSRV_ERROR OSEventObjectWaitTimeoutAndHoldBridgeLock(IMG_HANDLE hOSEventKM, IMG_UINT32 uiTimeoutMs);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectWaitTimeoutAndHoldBridgeLock
+@Description    Wait for an event object to signal or timeout. The function
+                is passed an OS event object handle (which allows the OS to
+                have the calling thread wait on the associated event object).
+                The calling thread will be rescheduled when the associated
+                event object signals.
+                If the event object has not signalled after the specified
+                timeout period (passed in 'uiTimeoutus'), the function
+                will return with the result code PVRSRV_ERROR_TIMEOUT.
+                The global bridge lock is held while waiting for the event
+                object to signal (this will prevent other bridge calls from
+                being serviced during this time).
+                See OSEventObjectWait() for details.
+@Input          hOSEventKM    the OS event object handle associated with
+                              the event object.
+@Input          uiTimeoutus   the timeout period (in usecs)
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectWaitTimeoutAndHoldBridgeLock(IMG_HANDLE hOSEventKM, IMG_UINT64 uiTimeoutus);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectOpen
+@Description    Open an OS handle on the specified event object.
+                This OS handle may then be used to make a thread wait for
+                that event object to signal.
+@Input          hEventObject    Event object handle.
+@Output         phOSEvent       OS handle to the returned event object.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectOpen(IMG_HANDLE hEventObject,
 											IMG_HANDLE *phOSEvent);
+
+/*************************************************************************/ /*!
+@Function       OSEventObjectClose
+@Description    Close an OS handle previously opened for an event object.
+@Input          hOSEventKM      OS event object handle to close.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEventObjectClose(IMG_HANDLE hOSEventKM);
 
-/* Avoid macros so we don't evaluate pslzSrc twice */
+/**************************************************************************/ /*!
+@Function       OSStringCopy
+@Description    OS function to support the standard C strcpy() function.
+ */ /**************************************************************************/
+/* Avoid macros so we don't evaluate pszSrc twice */
 static INLINE IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
 {
 	return OSStringNCopy(pszDest, pszSrc, OSStringLength(pszSrc) + 1);
 }
 
-/*!
-******************************************************************************
-
- @Function OSWaitus
- 
- @Description 
-    This function implements a busy wait of the specified microseconds
-    This function does NOT release thread quanta
- 
- @Input ui32Timeus - (us)
-
- @Return void
-
-******************************************************************************/ 
+/*************************************************************************/ /*!
+@Function      OSWaitus
+@Description   Implements a busy wait of the specified number of microseconds.
+               This function does NOT release thread quanta.
+@Input         ui32Timeus     The duration of the wait period (in us)
+@Return        None.
+*/ /**************************************************************************/
 void OSWaitus(IMG_UINT32 ui32Timeus);
 
-
-/*!
-******************************************************************************
-
- @Function OSSleepms
- 
- @Description 
-    This function implements a sleep of the specified milliseconds
-    This function may allow pre-emption if implemented
- 
- @Input ui32Timems - (ms)
-
- @Return void
-
-******************************************************************************/ 
+/*************************************************************************/ /*!
+@Function       OSSleepms
+@Description    Implements a sleep of the specified number of milliseconds.
+                This function may allow pre-emption, meaning the thread
+                may potentially not be rescheduled for a longer period.
+@Input          ui32Timems    The duration of the sleep (in ms)
+@Return         None.
+*/ /**************************************************************************/
 void OSSleepms(IMG_UINT32 ui32Timems);
 
+/*************************************************************************/ /*!
+@Function       OSReleaseThreadQuanta
+@Description    Relinquishes the current thread's execution time-slice,
+                permitting the OS scheduler to schedule another thread.
+@Return         None.
+*/ /**************************************************************************/
 void OSReleaseThreadQuanta(void);
 
-IMG_UINT8 OSReadHWReg8(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
-IMG_UINT16 OSReadHWReg16(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
-IMG_UINT32 OSReadHWReg32(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
-IMG_UINT64 OSReadHWReg64(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
-IMG_UINT64 OSReadHWRegBank(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 *pui8DstBuf, IMG_UINT64 ui64DstBufLen);
+#if defined(LINUX) && defined(__KERNEL__) && !defined(NO_HARDWARE)
+	#define OSReadHWReg8(addr, off)  (IMG_UINT8)readb((IMG_PBYTE)(addr) + (off))
+	#define OSReadHWReg16(addr, off) (IMG_UINT16)readw((IMG_PBYTE)(addr) + (off))
+	#define OSReadHWReg32(addr, off) (IMG_UINT32)readl((IMG_PBYTE)(addr) + (off))
+	/* Little endian support only */
+	#define OSReadHWReg64(addr, off) \
+			({ \
+				__typeof__(addr) _addr = addr; \
+				__typeof__(off) _off = off; \
+				(IMG_UINT64) \
+				( \
+					( (IMG_UINT64)(readl((IMG_PBYTE)(_addr) + (_off) + 4)) << 32) \
+					| readl((IMG_PBYTE)(_addr) + (_off)) \
+				); \
+			})
 
-void OSWriteHWReg8(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 ui32Value);
-void OSWriteHWReg16(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT16 ui32Value);
-void OSWriteHWReg32(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
-void OSWriteHWReg64(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT64 ui64Value);
-IMG_UINT64 OSWriteHWRegBank(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 *pui8SrcBuf, IMG_UINT64 ui64rcBufLen);
+	#define OSWriteHWReg8(addr, off, val)  writeb((IMG_UINT8)(val), (IMG_PBYTE)(addr) + (off))
+	#define OSWriteHWReg16(addr, off, val) writew((IMG_UINT16)(val), (IMG_PBYTE)(addr) + (off))
+	#define OSWriteHWReg32(addr, off, val) writel((IMG_UINT32)(val), (IMG_PBYTE)(addr) + (off))
+	/* Little endian support only */
+	#define OSWriteHWReg64(addr, off, val) do \
+			{ \
+				__typeof__(addr) _addr = addr; \
+				__typeof__(off) _off = off; \
+				__typeof__(val) _val = val; \
+				writel((IMG_UINT32)((_val) & 0xffffffff), (_addr) + (_off));	\
+				writel((IMG_UINT32)(((IMG_UINT64)(_val) >> 32) & 0xffffffff), (_addr) + (_off) + 4); \
+			} while (0)
+
+#elif defined(NO_HARDWARE)
+	/* FIXME: OSReadHWReg should not exist in no hardware builds */
+	#define OSReadHWReg8(addr, off)  (0x4eU)
+	#define OSReadHWReg16(addr, off) (0x3a4eU)
+	#define OSReadHWReg32(addr, off) (0x30f73a4eU)
+	#define OSReadHWReg64(addr, off) (0x5b376c9d30f73a4eU)
+
+	#define OSWriteHWReg8(addr, off, val)
+	#define OSWriteHWReg16(addr, off, val)
+	#define OSWriteHWReg32(addr, off, val)
+	#define OSWriteHWReg64(addr, off, val)
+#else
+/*************************************************************************/ /*!
+@Function       OSReadHWReg8
+@Description    Read from an 8-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to read from a location
+                but instead returns a constant value.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be read.
+@Return         The byte read.
+*/ /**************************************************************************/
+	IMG_UINT8 OSReadHWReg8(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+/*************************************************************************/ /*!
+@Function       OSReadHWReg16
+@Description    Read from a 16-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to read from a location
+                but instead returns a constant value.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be read.
+@Return         The word read.
+*/ /**************************************************************************/
+	IMG_UINT16 OSReadHWReg16(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+/*************************************************************************/ /*!
+@Function       OSReadHWReg32
+@Description    Read from a 32-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to read from a location
+                but instead returns a constant value.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be read.
+@Return         The long word read.
+*/ /**************************************************************************/
+	IMG_UINT32 OSReadHWReg32(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+/*************************************************************************/ /*!
+@Function       OSReadHWReg64
+@Description    Read from a 64-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to read from a location
+                but instead returns a constant value.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be read.
+@Return         The long long word read.
+*/ /**************************************************************************/
+	IMG_UINT64 OSReadHWReg64(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+/*************************************************************************/ /*!
+@Function       OSWriteHWReg8
+@Description    Write to an 8-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to write to a location.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be written to.
+@Input          ui8Value           The byte to be written to the register.
+@Return         None.
+*/ /**************************************************************************/
+	void OSWriteHWReg8(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 ui8Value);
+
+/*************************************************************************/ /*!
+@Function       OSWriteHWReg16
+@Description    Write to a 16-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to write to a location.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be written to.
+@Input          ui16Value          The word to be written to the register.
+@Return         None.
+*/ /**************************************************************************/
+	void OSWriteHWReg16(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT16 ui16Value);
+
+/*************************************************************************/ /*!
+@Function       OSWriteHWReg32
+@Description    Write to a 32-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to write to a location.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be written to.
+@Input          ui32Value          The long word to be written to the register.
+@Return         None.
+*/ /**************************************************************************/
+	void OSWriteHWReg32(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+/*************************************************************************/ /*!
+@Function       OSWriteHWReg64
+@Description    Write to a 64-bit memory-mapped device register.
+                The implementation should not permit the compiler to
+                reorder the I/O sequence.
+                The implementation should ensure that for a NO_HARDWARE
+                build the code does not attempt to write to a location.
+@Input          pvLinRegBaseAddr   The virtual base address of the register
+                                   block.
+@Input          ui32Offset         The byte offset from the base address of
+                                   the register to be written to.
+@Input          ui64Value          The long long word to be written to the
+                                   register.
+@Return         None.
+*/ /**************************************************************************/
+	void OSWriteHWReg64(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT64 ui64Value);
+#endif
 
 typedef void (*PFN_TIMER_FUNC)(void*);
+/*************************************************************************/ /*!
+@Function       OSAddTimer
+@Description    OS specific function to install a timer callback. The
+                timer will then need to be enabled, as it is disabled by
+                default.
+                When enabled, the callback will be invoked once the specified
+                timeout has elapsed.
+@Input          pfnTimerFunc    Timer callback
+@Input          *pvData         Callback data
+@Input          ui32MsTimeout   Callback period
+@Return         Valid handle on success, NULL if a failure
+*/ /**************************************************************************/
 IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, void *pvData, IMG_UINT32 ui32MsTimeout);
+
+/*************************************************************************/ /*!
+@Function       OSRemoveTimer
+@Description    Removes the specified timer. The handle becomes invalid and
+                should no longer be used.
+@Input          hTimer          handle of the timer to be removed
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSRemoveTimer(IMG_HANDLE hTimer);
+
+/*************************************************************************/ /*!
+@Function       OSEnableTimer
+@Description    Enable the specified timer. after enabling, the timer will
+                invoke the associated callback at an interval determined by
+                the configured timeout period until disabled.
+@Input          hTimer          handle of the timer to be enabled
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSEnableTimer(IMG_HANDLE hTimer);
+
+/*************************************************************************/ /*!
+@Function       OSDisableTimer
+@Description    Disable the specified timer
+@Input          hTimer          handle of the timer to be disabled
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSDisableTimer(IMG_HANDLE hTimer);
 
 
-/******************************************************************************
-
- @Function		OSPanic
-
- @Description	Take action in response to an unrecoverable driver error
-
- @Input    void
-
- @Return   void
-
-******************************************************************************/
+/*************************************************************************/ /*!
+ @Function      OSPanic
+ @Description   Take action in response to an unrecoverable driver error
+ @Return        None
+*/ /**************************************************************************/
 void OSPanic(void);
 
+/*************************************************************************/ /*!
+@Function       OSProcHasPrivSrvInit
+@Description    Checks whether the current process has sufficient privileges
+                to initialise services
+@Return         IMG_TRUE if it does, IMG_FALSE if it does not.
+*/ /**************************************************************************/
 IMG_BOOL OSProcHasPrivSrvInit(void);
 
+/*!
+ ******************************************************************************
+ * Access operation verification type
+ *****************************************************************************/
 typedef enum _img_verify_test
 {
-	PVR_VERIFY_WRITE = 0,
-	PVR_VERIFY_READ
+	PVR_VERIFY_WRITE = 0,  /*!< Used with OSAccessOK() to check writing is possible */
+	PVR_VERIFY_READ        /*!< Used with OSAccessOK() to check reading is possible */
 } IMG_VERIFY_TEST;
 
+/*************************************************************************/ /*!
+@Function       OSAccessOK
+@Description    Checks that a user space pointer is valid
+@Input          eVerification    the test to be verified. This can be either
+                                 PVRSRV_VERIFY_WRITE or PVRSRV_VERIFY_READ.
+@Input          pvUserPtr        pointer to the memory to be checked
+@Input          ui32Bytes        size of the memory to be checked
+@Return         IMG_TRUE if the specified access is valid, IMG_FALSE if not.
+*/ /**************************************************************************/
 IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, void *pvUserPtr, size_t ui32Bytes);
 
+/*************************************************************************/ /*!
+@Function       OSCopyFromUser
+@Description    Copy data from user-addressable memory to kernel-addressable
+                memory.
+                For operating systems that do not have a user/kernel space
+                distinction, this function should be implemented as a stub
+                which simply returns PVRSRV_ERROR_NOT_SUPPORTED.
+@Input          pvProcess        handle of the connection
+@Input          pvDest           pointer to the destination Kernel memory
+@Input          pvSrc            pointer to the source User memory
+@Input          ui32Bytes        size of the data to be copied
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSCopyToUser(void *pvProcess, void *pvDest, const void *pvSrc, size_t ui32Bytes);
+
+/*************************************************************************/ /*!
+@Function       OSCopyToUser
+@Description    Copy data to user-addressable memory from kernel-addressable
+                memory.
+                For operating systems that do not have a user/kernel space
+                distinction, this function should be implemented as a stub
+                which simply returns PVRSRV_ERROR_NOT_SUPPORTED.
+@Input          pvProcess        handle of the connection
+@Input          pvDest           pointer to the destination User memory
+@Input          pvSrc            pointer to the source Kernel memory
+@Input          ui32Bytes        size of the data to be copied
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSCopyFromUser(void *pvProcess, void *pvDest, const void *pvSrc, size_t ui32Bytes);
 
-#if defined (__linux__) || defined (WINDOWS_WDF)
+#if defined (__linux__) || defined (WINDOWS_WDF) || defined(INTEGRITY_OS)
 #define OSBridgeCopyFromUser OSCopyFromUser
 #define OSBridgeCopyToUser OSCopyToUser
 #else
+/*************************************************************************/ /*!
+@Function       OSBridgeCopyFromUser
+@Description    Copy data from user-addressable memory into kernel-addressable
+                memory as part of a bridge call operation.
+                For operating systems that do not have a user/kernel space
+                distinction, this function will require whatever implementation
+                is needed to pass data for making the bridge function call.
+                For operating systems which do have a user/kernel space
+                distinction (such as Linux) this function may be defined so
+                as to equate to a call to OSCopyFromUser().
+@Input          pvProcess        handle of the connection
+@Input          pvDest           pointer to the destination Kernel memory
+@Input          pvSrc            pointer to the source User memory
+@Input          ui32Bytes        size of the data to be copied
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSBridgeCopyFromUser (void *pvProcess,
 						void *pvDest,
 						const void *pvSrc,
 						size_t ui32Bytes);
+
+/*************************************************************************/ /*!
+@Function       OSBridgeCopyToUser
+@Description    Copy data to user-addressable memory from kernel-addressable
+                memory as part of a bridge call operation.
+                For operating systems that do not have a user/kernel space
+                distinction, this function will require whatever implementation
+                is needed to pass data for making the bridge function call.
+                For operating systems which do have a user/kernel space
+                distinction (such as Linux) this function may be defined so
+                as to equate to a call to OSCopyToUser().
+@Input          pvProcess        handle of the connection
+@Input          pvDest           pointer to the destination User memory
+@Input          pvSrc            pointer to the source Kernel memory
+@Input          ui32Bytes        size of the data to be copied
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSBridgeCopyToUser (void *pvProcess,
 						void *pvDest,
 						const void *pvSrc,
 						size_t ui32Bytes);
 #endif
 
-/* Fairly arbitrary sizes - hopefully enough for all bridge calls */
-#define PVRSRV_MAX_BRIDGE_IN_SIZE      0x2000
-#define PVRSRV_MAX_BRIDGE_OUT_SIZE     0x1000
+/* To be increased if required in future */
+#define PVRSRV_MAX_BRIDGE_IN_SIZE      0x2000    /*!< Size of the memory block used to hold data passed in to a bridge call */
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE     0x1000    /*!< Size of the memory block used to hold data returned from a bridge call */
 
+/*************************************************************************/ /*!
+@Function       OSGetGlobalBridgeBuffers
+@Description    Returns the addresses and sizes of the buffers used to pass
+                data into and out of bridge function calls.
+@Output         ppvBridgeInBuffer         pointer to the input bridge data buffer
+                                          of size PVRSRV_MAX_BRIDGE_IN_SIZE.
+@Output         ppvBridgeOutBuffer        pointer to the output bridge data buffer
+                                          of size PVRSRV_MAX_BRIDGE_OUT_SIZE.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR OSGetGlobalBridgeBuffers (void **ppvBridgeInBuffer,
-							IMG_UINT32 *pui32BridgeInBufferSize,
-							void **ppvBridgeOutBuffer,
-							IMG_UINT32 *pui32BridgeOutBufferSize);
+									   void **ppvBridgeOutBuffer);
 
+/*************************************************************************/ /*!
+@Function       OSSetDriverSuspended
+@Description    Prevent processes from using the driver while it is
+                suspended. This function is not required for most operating
+                systems.
+@Return         IMG_TRUE on success, IMG_FALSE otherwise.
+*/ /**************************************************************************/
 IMG_BOOL OSSetDriverSuspended(void);
+
+/*************************************************************************/ /*!
+@Function       OSClearDriverSuspended
+@Description    Re-allows processes to use the driver when it is no longer
+                suspended. This function is not required for most operating
+                systems.
+@Return         IMG_TRUE on success, IMG_FALSE otherwise.
+*/ /**************************************************************************/
 IMG_BOOL OSClearDriverSuspended(void);
+
+/*************************************************************************/ /*!
+@Function       OSGetDriverSuspended
+@Description    Returns whether or not processes are unable to use the driver
+                (due to  it being suspended). This function is not required
+                for most operating systems.
+@Return         IMG_TRUE if the driver is suspended (use is not possible),
+                IMG_FALSE if the driver is not suspended (use is possible).
+*/ /**************************************************************************/
 IMG_BOOL OSGetDriverSuspended(void);
 
+#if defined(LINUX) && defined(__KERNEL__)
+#define OSWriteMemoryBarrier() wmb()
+#define OSReadMemoryBarrier() rmb()
+#define OSMemoryBarrier() mb()
+#else
+/*************************************************************************/ /*!
+@Function       OSWriteMemoryBarrier
+@Description    Insert a write memory barrier.
+                The write memory barrier guarantees that all store operations
+                (writes) specified before the barrier will appear to happen
+                before all of the store operations specified after the barrier.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 void OSWriteMemoryBarrier(void);
+#define OSReadMemoryBarrier() OSMemoryBarrier()
+/*************************************************************************/ /*!
+@Function       OSMemoryBarrier
+@Description    Insert a read/write memory barrier.
+                The read and write memory barrier guarantees that all load
+                (read) and all store (write) operations specified before the
+                barrier will appear to happen before all of the load/store
+                operations specified after the barrier.
+@Return         None.
+*/ /**************************************************************************/
 void OSMemoryBarrier(void);
+#endif
+
+/*************************************************************************/ /*!
+@Function       PVRSRVToNativeError
+@Description    Returns the OS-specific equivalent error number/code for
+                the specified PVRSRV_ERROR value.
+                If there is no equivalent, or the PVRSRV_ERROR value is
+                PVRSRV_OK (no error), 0 is returned.
+@Return         The OS equivalent error code.
+*/ /**************************************************************************/
+int PVRSRVToNativeError(PVRSRV_ERROR e);
+#define OSPVRSRVToNativeError(e) ( (PVRSRV_OK == e)? 0: PVRSRVToNativeError(e) )
+
 
 #if defined(LINUX) && defined(__KERNEL__)
 
@@ -420,7 +1399,7 @@
 #define OSWRLockAcquireWrite(psLock) ({down_write(psLock); PVRSRV_OK;})
 #define OSWRLockReleaseWrite(psLock) ({up_write(psLock); PVRSRV_OK;})
 
-#elif defined(LINUX) || defined(__QNXNTO__)
+#elif defined(LINUX) || defined(__QNXNTO__) || defined (INTEGRITY_OS)
 /* User-mode unit tests use these definitions on Linux */
 
 typedef struct _OSWR_LOCK_ *POSWR_LOCK;
@@ -440,57 +1419,143 @@
 	typedef struct _OSWR_LOCK_ *POSWR_LOCK;
 #endif
 
+/*************************************************************************/ /*!
+@Function       OSWRLockCreate
+@Description    Create a writer/reader lock.
+                This type of lock allows multiple concurrent readers but
+                only a single writer, allowing for optimized performance.
+@Output         ppsLock     A handle to the created WR lock.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 static INLINE PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock)
 {
 	PVR_UNREFERENCED_PARAMETER(ppsLock);
 	return PVRSRV_OK;
 }
 
+/*************************************************************************/ /*!
+@Function       OSWRLockDestroy
+@Description    Destroys a writer/reader lock.
+@Input          psLock     The handle of the WR lock to be destroyed.
+@Return         None.
+*/ /**************************************************************************/
 static INLINE void OSWRLockDestroy(POSWR_LOCK psLock)
 {
 	PVR_UNREFERENCED_PARAMETER(psLock);
 }
 
+/*************************************************************************/ /*!
+@Function       OSWRLockAcquireRead
+@Description    Acquire a writer/reader read lock.
+                If the write lock is already acquired, the caller will
+                block until it is released.
+@Input          psLock     The handle of the WR lock to be acquired for
+                           reading.
+@Return         None.
+*/ /**************************************************************************/
 static INLINE void OSWRLockAcquireRead(POSWR_LOCK psLock)
 {
 	PVR_UNREFERENCED_PARAMETER(psLock);
 }
 
+/*************************************************************************/ /*!
+@Function       OSWRLockReleaseRead
+@Description    Release a writer/reader read lock.
+@Input          psLock     The handle of the WR lock whose read lock is to
+                           be released.
+@Return         None.
+*/ /**************************************************************************/
 static INLINE void OSWRLockReleaseRead(POSWR_LOCK psLock)
 {
 	PVR_UNREFERENCED_PARAMETER(psLock);
 }
 
+/*************************************************************************/ /*!
+@Function       OSWRLockAcquireWrite
+@Description    Acquire a writer/reader write lock.
+                If the write lock or any read lock are already acquired,
+                the caller will block until all are released.
+@Input          psLock     The handle of the WR lock to be acquired for
+                           writing.
+@Return         None.
+*/ /**************************************************************************/
 static INLINE void OSWRLockAcquireWrite(POSWR_LOCK psLock)
 {
 	PVR_UNREFERENCED_PARAMETER(psLock);
 }
 
+/*************************************************************************/ /*!
+@Function       OSWRLockReleaseWrite
+@Description    Release a writer/reader write lock.
+@Input          psLock     The handle of the WR lock whose write lock is to
+                           be released.
+@Return         None
+*/ /**************************************************************************/
 static INLINE void OSWRLockReleaseWrite(POSWR_LOCK psLock)
 {
 	PVR_UNREFERENCED_PARAMETER(psLock);
 }
 #endif
 
+/*************************************************************************/ /*!
+@Function       OSDivide64r64
+@Description    Divide a 64-bit value by a 32-bit value. Return the 64-bit
+                quotient.
+                The remainder is also returned in 'pui32Remainder'.
+@Input          ui64Divident        The number to be divided.
+@Input          ui32Divisor         The 32-bit value 'ui64Divident' is to
+                                    be divided by.
+@Output         pui32Remainder      The remainder of the division.
+@Return         The 64-bit quotient (result of the division).
+*/ /**************************************************************************/
 IMG_UINT64 OSDivide64r64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder);
+
+/*************************************************************************/ /*!
+@Function       OSDivide64
+@Description    Divide a 64-bit value by a 32-bit value. Return a 32-bit
+                quotient.
+                The remainder is also returned in 'pui32Remainder'.
+                This function allows for a more optional implementation
+                of a 64-bit division when the result is known to be
+                representable in 32-bits.
+@Input          ui64Divident        The number to be divided.
+@Input          ui32Divisor         The 32-bit value 'ui64Divident' is to
+                                    be divided by.
+@Output         pui32Remainder      The remainder of the division.
+@Return         The 32-bit quotient (result of the division).
+*/ /**************************************************************************/
 IMG_UINT32 OSDivide64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder);
 
+/*************************************************************************/ /*!
+@Function       OSDumpStack
+@Description    Dump the current task information and its stack trace.
+@Return         None
+*/ /**************************************************************************/
 void OSDumpStack(void);
 
+/*************************************************************************/ /*!
+@Function       OSAcquireBridgeLock
+@Description    Acquire the global bridge lock.
+                This prevents another bridge call from being actioned while
+                we are still servicing the current bridge call.
+                NB. This function must not return until the lock is acquired
+                (meaning the implementation should not timeout or return with
+                an error, as the caller will assume they have the lock).
+                This function has an OS-specific implementation rather than
+                an abstracted implementation for efficiency reasons, as it
+                is called frequently.
+@Return         None
+*/ /**************************************************************************/
 void OSAcquireBridgeLock(void);
+/*************************************************************************/ /*!
+@Function       OSReleaseBridgeLock
+@Description    Release the global bridge lock.
+                This function has an OS-specific implementation rather than
+                an abstracted implementation for efficiency reasons, as it
+                is called frequently.
+@Return         None
+*/ /**************************************************************************/
 void OSReleaseBridgeLock(void);
-#if defined(LINUX)
-void PMRLock(void);
-void PMRUnlock(void);
-IMG_BOOL PMRIsLocked(void);
-IMG_BOOL PMRIsLockedByMe(void);
-#else
-#define PMRLock()
-#define PMRUnlock()
-#define PMRIsLocked() IMG_FALSE
-#define PMRIsLockedByMe() IMG_FALSE
-#endif
-
 
 /*
  *  Functions for providing support for PID statistics.
@@ -504,17 +1569,143 @@
 typedef IMG_UINT32 (OS_INC_STATS_MEM_REFCOUNT_FUNC)(void *pvStatPtr);
 typedef IMG_UINT32 (OS_DEC_STATS_MEM_REFCOUNT_FUNC)(void *pvStatPtr);
 
+/*************************************************************************/ /*!
+@Function       OSCreateStatisticEntry
+@Description    Create a statistic entry in the specified folder.
+                Where operating systems do not support a debugfs,
+                file system this function may be implemented as a stub.
+@Input          pszName        String containing the name for the entry.
+@Input          pvFolder       Reference from OSCreateStatisticFolder() of the
+                               folder to create the entry in, or NULL for the
+                               root.
+@Input          pfnStatsPrint  Pointer to function that can be used to print the
+                               values of all the statistics.
+@Input          pfnIncMemRefCt Pointer to function that can be used to take a
+                               reference on the memory backing the statistic
+                               entry.
+@Input          pfnDecMemRefCt Pointer to function that can be used to drop a
+                               reference on the memory backing the statistic
+                               entry.
+@Input          pvData         OS specific reference that can be used by
+                               pfnGetElement.
+@Return	        Pointer void reference to the entry created, which can be
+                passed to OSRemoveStatisticEntry() to remove the entry.
+*/ /**************************************************************************/
 void *OSCreateStatisticEntry(IMG_CHAR* pszName, void *pvFolder,
 							 OS_STATS_PRINT_FUNC* pfnStatsPrint,
 							 OS_INC_STATS_MEM_REFCOUNT_FUNC* pfnIncMemRefCt,
 							 OS_DEC_STATS_MEM_REFCOUNT_FUNC* pfnDecMemRefCt,
 							 void *pvData);
+
+/*************************************************************************/ /*!
+@Function       OSRemoveStatisticEntry
+@Description    Removes a statistic entry.
+                Where operating systems do not support a debugfs,
+                file system this function may be implemented as a stub.
+@Input          pvEntry  Pointer void reference to the entry created by
+                         OSCreateStatisticEntry().
+*/ /**************************************************************************/
 void OSRemoveStatisticEntry(void *pvEntry);
+
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+/*************************************************************************/ /*!
+@Function       OSCreateRawStatisticEntry
+@Description    Create a raw statistic entry in the specified folder.
+                Where operating systems do not support a debugfs
+                file system this function may be implemented as a stub.
+@Input          pszFileName    String containing the name for the entry.
+@Input          pvParentDir    Reference from OSCreateStatisticFolder() of the
+                               folder to create the entry in, or NULL for the
+                               root.
+@Input          pfnStatsPrint  Pointer to function that can be used to print the
+                               values of all the statistics.
+@Return	        Pointer void reference to the entry created, which can be
+                passed to OSRemoveRawStatisticEntry() to remove the entry.
+*/ /**************************************************************************/
+void *OSCreateRawStatisticEntry(const IMG_CHAR *pszFileName, void *pvParentDir,
+                                OS_STATS_PRINT_FUNC *pfStatsPrint);
+
+/*************************************************************************/ /*!
+@Function       OSRemoveRawStatisticEntry
+@Description    Removes a raw statistic entry.
+                Where operating systems do not support a debugfs
+                file system this function may be implemented as a stub.
+@Input          pvEntry  Pointer void reference to the entry created by
+                         OSCreateRawStatisticEntry().
+*/ /**************************************************************************/
+void OSRemoveRawStatisticEntry(void *pvEntry);
+#endif
+
+/*************************************************************************/ /*!
+@Function       OSCreateStatisticFolder
+@Description    Create a statistic folder to hold statistic entries.
+                Where operating systems do not support a debugfs,
+                file system this function may be implemented as a stub.
+@Input          pszName   String containing the name for the folder.
+@Input          pvFolder  Reference from OSCreateStatisticFolder() of the folder
+                          to create the folder in, or NULL for the root.
+@Return         Pointer void reference to the folder created, which can be
+                passed to OSRemoveStatisticFolder() to remove the folder.
+*/ /**************************************************************************/
 void *OSCreateStatisticFolder(IMG_CHAR *pszName, void *pvFolder);
+
+/*************************************************************************/ /*!
+@Function       OSRemoveStatisticFolder
+@Description    Removes a statistic folder.
+                Where operating systems do not support a debugfs,
+                file system this function may be implemented as a stub.
+@Input          ppvFolder  Reference from OSCreateStatisticFolder() of the
+                           folder that should be removed.
+                           This needs to be double pointer because it has to
+                           be NULLed right after memory is freed to avoid
+                           possible races and use-after-free situations.
+*/ /**************************************************************************/
 void OSRemoveStatisticFolder(void **ppvFolder);
 
+/*************************************************************************/ /*!
+@Function       OSUserModeAccessToPerfCountersEn
+@Description    Permit User-mode access to CPU performance counter
+                registers.
+                This function is called during device initialisation.
+                Certain CPU architectures may need to explicitly permit
+                User mode access to performance counters - if this is
+                required, the necessary code should be implemented inside
+                this function.
+@Return         None.
+*/ /**************************************************************************/
 void OSUserModeAccessToPerfCountersEn(void);
 
+/*************************************************************************/ /*!
+@Function       OSDebugSignalPID
+@Description    Sends a SIGTRAP signal to a specific PID in user mode for
+                debugging purposes. The user mode process can register a handler
+                against this signal.
+                This is necessary to support the Rogue debugger. If the Rogue
+                debugger is not used then this function may be implemented as
+                a stub.
+@Input          ui32PID    The PID for the signal.
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSDebugSignalPID(IMG_UINT32 ui32PID);
+
+#if defined(LINUX) && defined(__KERNEL__)
+#define OSWarnOn(a) WARN_ON(a)
+#else
+#define OSWarnOn(a) do { if(!!(a)) { OSDumpStack(); } } while(0)
+#endif
+
+#if defined(CONFIG_L4)
+#include <asm/api-l4env/api.h>
+#include <asm/io.h>
+
+#if defined(page_to_phys)
+#undef page_to_phys
+#define page_to_phys(x) l4x_virt_to_phys(x)
+#else
+#error "Unable to override page_to_phys() implementation"
+#endif
+#endif
+
 #endif /* __OSFUNC_H__ */
 
 /******************************************************************************
diff --git a/drivers/staging/imgtec/rogue/osfunc_arm.c b/drivers/staging/imgtec/rogue/osfunc_arm.c
index 69ac10a..d74f328 100644
--- a/drivers/staging/imgtec/rogue/osfunc_arm.c
+++ b/drivers/staging/imgtec/rogue/osfunc_arm.c
@@ -93,12 +93,6 @@
 	#define OUTER_FLUSH_ALL()
 #endif /* CONFIG_OUTER_CACHE */
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
-#else
-#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
-#endif
-
 static void per_cpu_cache_flush(void *arg)
 {
 	PVR_UNREFERENCED_PARAMETER(arg);
@@ -113,24 +107,14 @@
 	{
 		/* Fall-through */
 		case PVRSRV_CACHE_OP_CLEAN:
-			/* No full (inner) cache clean op */
-			ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+			on_each_cpu(per_cpu_cache_flush, NULL, 1);
 			OUTER_CLEAN_RANGE();
 			break;
 
 		case PVRSRV_CACHE_OP_INVALIDATE:
 		case PVRSRV_CACHE_OP_FLUSH:
-			ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
-			/* To use the "deferred flush" (not clean) DDK feature you need a kernel
-			 * implementation of outer_flush_all() for ARM CPUs with an outer cache
-			 * controller (e.g. PL310, common with Cortex A9 and later).
-			 *
-			 * Reference DDKs don't require this functionality, as they will only
-			 * clean the cache, never flush (clean+invalidate) it.
-			 */
+			on_each_cpu(per_cpu_cache_flush, NULL, 1);
 			OUTER_FLUSH_ALL();
-#endif
 			break;
 
 		case PVRSRV_CACHE_OP_NONE:
@@ -148,18 +132,19 @@
 	return eError;
 }
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
 static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
 {
 	return (size_t)((char *)pvEnd - (char *)pvStart);
 }
-#endif
 
-void OSFlushCPUCacheRangeKM(void *pvVirtStart,
-							void *pvVirtEnd,
-							IMG_CPU_PHYADDR sCPUPhysStart,
-							IMG_CPU_PHYADDR sCPUPhysEnd)
+void OSFlushCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                            void *pvVirtStart,
+                            void *pvVirtEnd,
+                            IMG_CPU_PHYADDR sCPUPhysStart,
+                            IMG_CPU_PHYADDR sCPUPhysEnd)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
 	arm_dma_ops.sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
 	arm_dma_ops.sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
@@ -172,43 +157,41 @@
 #endif	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
 }
 
-void OSCleanCPUCacheRangeKM(void *pvVirtStart,
-							void *pvVirtEnd,
-							IMG_CPU_PHYADDR sCPUPhysStart,
-							IMG_CPU_PHYADDR sCPUPhysEnd)
+void OSCleanCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                            void *pvVirtStart,
+                            void *pvVirtEnd,
+                            IMG_CPU_PHYADDR sCPUPhysStart,
+                            IMG_CPU_PHYADDR sCPUPhysEnd)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
 	arm_dma_ops.sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
 #else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
 	/* Inner cache */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
-	dmac_clean_range(pvVirtStart, pvVirtEnd);
-#else
 	dmac_map_area(pvVirtStart, pvr_dmac_range_len(pvVirtStart, pvVirtEnd), DMA_TO_DEVICE);
-#endif
 
 	/* Outer cache */
 	outer_clean_range(sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr);
 #endif	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
 }
 
-void OSInvalidateCPUCacheRangeKM(void *pvVirtStart,
-								 void *pvVirtEnd,
-								 IMG_CPU_PHYADDR sCPUPhysStart,
-								 IMG_CPU_PHYADDR sCPUPhysEnd)
+void OSInvalidateCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                                 void *pvVirtStart,
+                                 void *pvVirtEnd,
+                                 IMG_CPU_PHYADDR sCPUPhysStart,
+                                 IMG_CPU_PHYADDR sCPUPhysEnd)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
 	arm_dma_ops.sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
 #else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
 #if defined(PVR_LINUX_DONT_USE_RANGE_BASED_INVALIDATE)
-	OSCleanCPUCacheRangeKM(pvVirtStart, pvVirtEnd, sCPUPhysStart, sCPUPhysEnd);
+	OSCleanCPUCacheRangeKM(psDevNode, pvVirtStart, pvVirtEnd, sCPUPhysStart, sCPUPhysEnd);
 #else
 	/* Inner cache */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
-	dmac_inv_range(pvVirtStart, pvVirtEnd);
-#else
 	dmac_map_area(pvVirtStart, pvr_dmac_range_len(pvVirtStart, pvVirtEnd), DMA_FROM_DEVICE);
-#endif
 
 	/* Outer cache */
 	outer_inv_range(sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr);
@@ -232,11 +215,13 @@
 static void per_cpu_perf_counter_user_access_en(void *data)
 {
 	PVR_UNREFERENCED_PARAMETER(data);
+#if !defined(CONFIG_L4)
 	/* Enable user-mode access to counters. */
 	asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(PMUSERENR_EN));
+#endif
 }
 
 void OSUserModeAccessToPerfCountersEn(void)
 {
-	ON_EACH_CPU(per_cpu_perf_counter_user_access_en, NULL, 1);
+	on_each_cpu(per_cpu_perf_counter_user_access_en, NULL, 1);
 }
diff --git a/drivers/staging/imgtec/rogue/osfunc_arm64.c b/drivers/staging/imgtec/rogue/osfunc_arm64.c
index cc46590..7d33a4a 100644
--- a/drivers/staging/imgtec/rogue/osfunc_arm64.c
+++ b/drivers/staging/imgtec/rogue/osfunc_arm64.c
@@ -41,6 +41,7 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 #include <linux/version.h>
+#include <linux/cpumask.h>
 #include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 
@@ -48,7 +49,6 @@
 #include "img_types.h"
 #include "osfunc.h"
 #include "pvr_debug.h"
-#include "module_common.h"
 
 #if defined(CONFIG_OUTER_CACHE)
   /* If you encounter a 64-bit ARM system with an outer cache, you'll need
@@ -58,6 +58,32 @@
 	#error "CONFIG_OUTER_CACHE not supported on arm64."
 #endif
 
+static void per_cpu_cache_flush(void *arg)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0))
+	static IMG_BOOL bLog = IMG_TRUE;
+	/*
+		NOTE: Regarding arm64 global flush support on >= Linux v4.2:
+		- Global cache flush support is deprecated from v4.2 onwards
+		- Cache maintenance is done using UM/KM VA maintenance _only_
+		- If you find that more time is spent in VA cache maintenance
+			- Implement arm64 assembly sequence for global flush here
+				- asm volatile ();
+		- If you do not want to implement the global cache assembly
+			- Disable KM cache maintenance support in UM cache.c
+			- Remove this PVR_LOG message
+	*/
+	if (bLog)
+	{
+		PVR_LOG(("Global d-cache flush assembly not implemented, using rangebased flush"));
+		bLog = IMG_FALSE;
+	}
+#else
+	flush_cache_all();
+#endif
+	PVR_UNREFERENCED_PARAMETER(arg);
+}
+
 PVRSRV_ERROR OSCPUOperation(PVRSRV_CACHE_OP uiCacheOp)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -67,7 +93,10 @@
 		case PVRSRV_CACHE_OP_CLEAN:
 		case PVRSRV_CACHE_OP_FLUSH:
 		case PVRSRV_CACHE_OP_INVALIDATE:
+			on_each_cpu(per_cpu_cache_flush, NULL, 1);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0))
 			eError = PVRSRV_ERROR_NOT_IMPLEMENTED;
+#endif
 			break;
 
 		case PVRSRV_CACHE_OP_NONE:
@@ -85,12 +114,14 @@
 	return eError;
 }
 
-void OSFlushCPUCacheRangeKM(void *pvVirtStart,
+void OSFlushCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+							void *pvVirtStart,
 							void *pvVirtEnd,
 							IMG_CPU_PHYADDR sCPUPhysStart,
 							IMG_CPU_PHYADDR sCPUPhysEnd)
 {
-	struct dma_map_ops *dma_ops = get_dma_ops(&gpsPVRLDMDev->dev);
+	struct dma_map_ops *dma_ops = get_dma_ops(psDevNode->psDevConfig->pvOSDevice);
+
 	PVR_UNREFERENCED_PARAMETER(pvVirtStart);
 	PVR_UNREFERENCED_PARAMETER(pvVirtEnd);
 
@@ -98,24 +129,28 @@
 	dma_ops->sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
 }
 
-void OSCleanCPUCacheRangeKM(void *pvVirtStart,
+void OSCleanCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+							void *pvVirtStart,
 							void *pvVirtEnd,
 							IMG_CPU_PHYADDR sCPUPhysStart,
 							IMG_CPU_PHYADDR sCPUPhysEnd)
 {
-	struct dma_map_ops *dma_ops = get_dma_ops(&gpsPVRLDMDev->dev);
+	struct dma_map_ops *dma_ops = get_dma_ops(psDevNode->psDevConfig->pvOSDevice);
+
 	PVR_UNREFERENCED_PARAMETER(pvVirtStart);
 	PVR_UNREFERENCED_PARAMETER(pvVirtEnd);
 
 	dma_ops->sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
 }
 
-void OSInvalidateCPUCacheRangeKM(void *pvVirtStart,
+void OSInvalidateCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+								 void *pvVirtStart,
 								 void *pvVirtEnd,
 								 IMG_CPU_PHYADDR sCPUPhysStart,
 								 IMG_CPU_PHYADDR sCPUPhysEnd)
 {
-	struct dma_map_ops *dma_ops = get_dma_ops(&gpsPVRLDMDev->dev);
+	struct dma_map_ops *dma_ops = get_dma_ops(psDevNode->psDevConfig->pvOSDevice);
+
 	PVR_UNREFERENCED_PARAMETER(pvVirtStart);
 	PVR_UNREFERENCED_PARAMETER(pvVirtEnd);
 
diff --git a/drivers/staging/imgtec/rogue/osfunc_x86.c b/drivers/staging/imgtec/rogue/osfunc_x86.c
index dfd36c1..c672c53 100644
--- a/drivers/staging/imgtec/rogue/osfunc_x86.c
+++ b/drivers/staging/imgtec/rogue/osfunc_x86.c
@@ -40,11 +40,8 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-#include <linux/version.h>
+
 #include <linux/smp.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
-#include <asm/system.h>
-#endif
 
 #include "pvrsrv_error.h"
 #include "img_types.h"
@@ -52,11 +49,6 @@
 #include "osfunc.h"
 #include "pvr_debug.h"
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
-#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
-#else
-#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
-#endif
 
 static void per_cpu_cache_flush(void *arg)
 {
@@ -109,11 +101,13 @@
 	mb();
 }
 
-void OSFlushCPUCacheRangeKM(void *pvVirtStart,
-							void *pvVirtEnd,
-							IMG_CPU_PHYADDR sCPUPhysStart,
-							IMG_CPU_PHYADDR sCPUPhysEnd)
+void OSFlushCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                            void *pvVirtStart,
+                            void *pvVirtEnd,
+                            IMG_CPU_PHYADDR sCPUPhysStart,
+                            IMG_CPU_PHYADDR sCPUPhysEnd)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(sCPUPhysStart);
 	PVR_UNREFERENCED_PARAMETER(sCPUPhysEnd);
 
@@ -121,11 +115,13 @@
 }
 
 
-void OSCleanCPUCacheRangeKM(void *pvVirtStart,
-							void *pvVirtEnd,
-							IMG_CPU_PHYADDR sCPUPhysStart,
-							IMG_CPU_PHYADDR sCPUPhysEnd)
+void OSCleanCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                            void *pvVirtStart,
+                            void *pvVirtEnd,
+                            IMG_CPU_PHYADDR sCPUPhysStart,
+                            IMG_CPU_PHYADDR sCPUPhysEnd)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(sCPUPhysStart);
 	PVR_UNREFERENCED_PARAMETER(sCPUPhysEnd);
 
@@ -133,11 +129,13 @@
 	x86_flush_cache_range(pvVirtStart, pvVirtEnd);
 }
 
-void OSInvalidateCPUCacheRangeKM(void *pvVirtStart,
-								 void *pvVirtEnd,
-								 IMG_CPU_PHYADDR sCPUPhysStart,
-								 IMG_CPU_PHYADDR sCPUPhysEnd)
+void OSInvalidateCPUCacheRangeKM(PVRSRV_DEVICE_NODE *psDevNode,
+                                 void *pvVirtStart,
+                                 void *pvVirtEnd,
+                                 IMG_CPU_PHYADDR sCPUPhysStart,
+                                 IMG_CPU_PHYADDR sCPUPhysEnd)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(sCPUPhysStart);
 	PVR_UNREFERENCED_PARAMETER(sCPUPhysEnd);
 
diff --git a/drivers/staging/imgtec/rogue/oskm_apphint.h b/drivers/staging/imgtec/rogue/oskm_apphint.h
new file mode 100644
index 0000000..8c2444c
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/oskm_apphint.h
@@ -0,0 +1,213 @@
+/*************************************************************************/ /*!
+@File           oskm_apphint.h
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    OS-independent interface for retrieving KM apphints
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include "img_defs.h"
+#if defined(LINUX)
+#include "km_apphint.h"
+#else
+#include "services_client_porting.h"
+#endif
+#if !defined(__OSKM_APPHINT_H__)
+#define __OSKM_APPHINT_H__
+
+
+#if defined(LINUX) && !defined(DOXYGEN)
+#if defined(SUPPORT_KERNEL_SRVINIT)
+static INLINE IMG_UINT os_get_km_apphint_UINT32(void *state, APPHINT_ID id, IMG_UINT32 *pAppHintDefault, IMG_UINT32 *pVal) {
+	return !pvr_apphint_get_uint32(id, pVal);
+}
+static INLINE IMG_UINT os_get_km_apphint_UINT64(void *state, APPHINT_ID id, IMG_UINT64 *pAppHintDefault, IMG_UINT64 *pVal) {
+	return !pvr_apphint_get_uint64(id, pVal);
+}
+static INLINE IMG_UINT os_get_km_apphint_BOOL(void *state, APPHINT_ID id, IMG_BOOL *pAppHintDefault, IMG_BOOL *pVal) {
+	return !pvr_apphint_get_bool(id, pVal);
+}
+static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, IMG_CHAR **pAppHintDefault, IMG_CHAR *buffer, size_t size) {
+	return !pvr_apphint_get_string(id, buffer, size);
+}
+
+#define OSGetKMAppHintUINT32(state, name, appHintDefault, value) \
+	os_get_km_apphint_UINT32(state, APPHINT_ID_ ## name, appHintDefault, value)
+
+#define OSGetKMAppHintUINT64(state, name, appHintDefault, value) \
+	os_get_km_apphint_UINT64(state, APPHINT_ID_ ## name, appHintDefault, value)
+
+#define OSGetKMAppHintBOOL(state, name, appHintDefault, value) \
+	os_get_km_apphint_BOOL(state, APPHINT_ID_ ## name, appHintDefault, value)
+
+#define OSGetKMAppHintSTRING(state, name, appHintDefault, buffer, size) \
+	os_get_km_apphint_STRING(state, APPHINT_ID_ ## name, appHintDefault, buffer, size)
+
+#else
+static INLINE IMG_UINT os_get_apphint_default_UINT32(IMG_UINT32 *pAppHintDefault, IMG_UINT32 *pVal) {
+	*pVal = *pAppHintDefault;
+	return IMG_TRUE;
+}
+static INLINE IMG_UINT os_get_apphint_default_UINT64(IMG_UINT64 *pAppHintDefault, IMG_UINT64 *pVal) {
+	*pVal = *pAppHintDefault;
+	return IMG_TRUE;
+}
+static INLINE IMG_UINT os_get_apphint_default_BOOL(IMG_BOOL *pAppHintDefault, IMG_BOOL *pVal) {
+	*pVal = *pAppHintDefault;
+	return IMG_TRUE;
+}
+static INLINE IMG_UINT os_get_apphint_default_STRING(IMG_CHAR **pAppHintDefault, IMG_CHAR *buffer, IMG_UINT32 size) {
+	strlcpy(buffer, *pAppHintDefault, size);
+	return IMG_TRUE;
+}
+
+#define OSGetKMAppHintUINT32(state, name, appHintDefault, value) \
+	os_get_apphint_default_UINT32(appHintDefault, value)
+
+#define OSGetKMAppHintUINT64(state, name, appHintDefault, value) \
+	os_get_apphint_default_UINT64(appHintDefault, value)
+
+#define OSGetKMAppHintBOOL(state, name, appHintDefault, value) \
+	os_get_apphint_default_BOOL(appHintDefault, value)
+
+#define OSGetKMAppHintSTRING(state, name, appHintDefault, buffer, size) \
+	os_get_apphint_default_STRING(appHintDefault, buffer, size)
+
+#endif
+
+#define OSCreateKMAppHintState(state) \
+	PVR_UNREFERENCED_PARAMETER(state)
+
+#define OSFreeKMAppHintState(state) \
+	PVR_UNREFERENCED_PARAMETER(state)
+
+#else /* #if defined(LINUX) && !defined(DOXYGEN) */
+
+static INLINE IMG_BOOL os_get_km_apphint_STRING(void *state, IMG_CHAR *name, IMG_CHAR **pAppHintDefault, IMG_CHAR *buffer, size_t size) {
+	PVR_UNREFERENCED_PARAMETER(size);
+	return PVRSRVGetAppHint(state, name, IMG_STRING_TYPE, pAppHintDefault, buffer);
+}
+
+/**************************************************************************/ /*!
+@def OSGetKMAppHintUINT32(state, name, appHintDefault, value)
+@Description    Interface for retrieval of uint32 km app hint.
+				For non-linux operating systems, this macro implements a call
+				from server code to PVRSRVGetAppHint() declared in
+				services_client_porting.h, effectively making it 'shared' code.
+@Input          state             App hint state
+@Input          name              Name used to identify app hint
+@Input          appHintDefault    Default value to be returned if no
+								  app hint is found.
+@Output         value             Pointer to returned app hint value.
+ */ /**************************************************************************/
+#define OSGetKMAppHintUINT32(state, name, appHintDefault, value) \
+	PVRSRVGetAppHint(state, # name, IMG_UINT_TYPE, appHintDefault, value)
+
+/**************************************************************************/ /*!
+@def OSGetKMAppHintUINT64(state, name, appHintDefault, value)
+@Description    Interface for retrieval of uint64 km app hint.
+				For non-linux operating systems, this macro implements a call
+				from server code to PVRSRVGetAppHint() declared in
+				services_client_porting.h, effectively making it 'shared' code.
+@Input          state             App hint state
+@Input          name              Name used to identify app hint
+@Input          appHintDefault    Default value to be returned if no
+								  app hint is found.
+@Output         value             Pointer to returned app hint value.
+ */ /**************************************************************************/
+#define OSGetKMAppHintUINT64(state, name, appHintDefault, value) \
+	PVRSRVGetAppHint(state, # name, IMG_UINT_TYPE, appHintDefault, value)
+
+/**************************************************************************/ /*!
+@def OSGetKMAppHintBOOL(state, name, appHintDefault, value)
+@Description    Interface for retrieval of IMG_BOOL km app hint.
+				For non-linux operating systems, this macro implements a call
+				from server code to PVRSRVGetAppHint() declared in
+				services_client_porting.h, effectively making it 'shared' code.
+@Input          state             App hint state
+@Input          name              Name used to identify app hint
+@Input          appHintDefault    Default value to be returned if no
+								  app hint is found.
+@Output         value             Pointer to returned app hint value.
+ */ /**************************************************************************/
+#define OSGetKMAppHintBOOL(state, name, appHintDefault, value) \
+	PVRSRVGetAppHint(state, # name, IMG_UINT_TYPE, appHintDefault, value)
+
+/**************************************************************************/ /*!
+@def OSGetKMAppHintSTRING(state, name, appHintDefault, buffer, size)
+@Description    Interface for retrieval of string km app hint.
+				For non-linux operating systems, this macro implements a call
+				from server code to PVRSRVGetAppHint() declared in
+				services_client_porting.h, effectively making it 'shared' code.
+@Input          state             App hint state
+@Input          name              Name used to identify app hint
+@Input          appHintDefault    Default value to be returned if no
+								  app hint is found.
+@Output         buffer            Buffer used to return app hint string.
+@Input			size			  Size of the buffer.
+ */ /**************************************************************************/
+#define OSGetKMAppHintSTRING(state, name, appHintDefault, buffer, size) \
+	os_get_km_apphint_STRING(state, # name, appHintDefault, buffer, size)
+
+/**************************************************************************/ /*!
+@def OSCreateKMAppHintState(state)
+@Description    Creates the app hint state.
+				For non-linux operating systems, this macro implements a call
+				from server code to PVRSRVCreateAppHintState() declared in
+				services_client_porting.h, effectively making it 'shared' code.
+@Output          state             App hint state
+ */ /**************************************************************************/
+#define OSCreateKMAppHintState(state) \
+	PVRSRVCreateAppHintState(IMG_SRV_UM, 0, state)
+
+/**************************************************************************/ /*!
+@def OSFreeKMAppHintState
+@Description    Free the app hint state.
+				For non-linux operating systems, this macro implements a call
+				from server code to PVRSRVCreateAppHintState() declared in
+				services_client_porting.h, effectively making it 'shared' code.
+@Output          state             App hint state
+ */ /**************************************************************************/
+#define OSFreeKMAppHintState(state) \
+	PVRSRVFreeAppHintState(IMG_SRV_UM, state)
+
+#endif /* #if defined(LINUX) */
+
+#endif /* __OSKM_APPHINT_H__ */
+
+/******************************************************************************
+ End of file (oskm_apphint.h)
+******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/osmmap.h b/drivers/staging/imgtec/rogue/osmmap.h
new file mode 100644
index 0000000..bc83151
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/osmmap.h
@@ -0,0 +1,123 @@
+/*************************************************************************/ /*!
+@File
+@Title          OS Interface for mapping PMRs into CPU space.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    OS abstraction for the mmap2 interface for mapping PMRs into
+                User Mode memory
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _OSMMAP_H_
+#define _OSMMAP_H_
+
+#include <powervr/mem_types.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+/**************************************************************************/ /*!
+@Function       OSMMapPMR
+@Description    Maps the specified PMR into CPU memory so that it may be
+                accessed by the user process.
+                Whether the memory is mapped read only, read/write, or not at
+                all, is dependent on the PMR itself.
+                The PMR handle is opaque to the user, and lower levels of this
+                stack ensure that the handle is private to this process, such that
+                this API cannot be abused to gain access to other people's PMRs.
+                The OS implementation of this function should return the virtual
+                address and length for the User to use. The "PrivData" is to be
+                stored opaquely by the caller (N.B. he should make no assumptions,
+                in particular, NULL is a valid handle) and given back to the
+                call to OSMUnmapPMR.
+                The OS implementation is free to use the PrivData handle for any
+                purpose it sees fit.
+@Input          hBridge              The bridge handle.
+@Input          hPMR                 The handle of the PMR to be mapped.
+@Input          uiPMRLength          The size of the PMR.
+@Input          uiFlags              Flags indicating how the mapping should
+                                     be done (read-only, etc). These may not
+                                     be honoured if the PMR does not permit
+                                     them.
+@Input          uiPMRLength          The size of the PMR.
+@Output         phOSMMapPrivDataOut  Returned private data.
+@Output         ppvMappingAddressOut The returned mapping.
+@Output         puiMappingLengthOut  The size of the returned mapping.
+@Return         PVRSRV_OK on success, failure code otherwise.
+ */ /**************************************************************************/
+extern PVRSRV_ERROR
+OSMMapPMR(IMG_HANDLE hBridge,
+          IMG_HANDLE hPMR,
+          IMG_DEVMEM_SIZE_T uiPMRLength,
+          IMG_UINT32 uiFlags,
+          IMG_HANDLE *phOSMMapPrivDataOut,
+          void **ppvMappingAddressOut,
+          size_t *puiMappingLengthOut);
+
+/**************************************************************************/ /*!
+@Function       OSMUnmapPMR
+@Description    Unmaps the specified PMR from CPU memory.
+                This function is the counterpart to OSMMapPMR.
+                The caller is required to pass the PMR handle back in along
+                with the same 3-tuple of information that was returned by the
+                call to OSMMapPMR in phOSMMapPrivDataOut.
+                It is possible to unmap only part of the original mapping
+                with this call, by specifying only the address range to be
+                unmapped in pvMappingAddress and uiMappingLength.
+@Input          hBridge              The bridge handle.
+@Input          hPMR                 The handle of the PMR to be unmapped.
+@Input          hOSMMapPrivData      The OS private data of the mapping.
+@Input          pvMappingAddress     The address to be unmapped.
+@Input          uiMappingLength      The size to be unmapped.
+@Return         PVRSRV_OK on success, failure code otherwise.
+ */ /**************************************************************************/
+/*
+   FIXME:
+   perhaps this function should take _only_ the hOSMMapPrivData arg,
+   and the implementation is required to store any of the other data
+   items that it requires to do the unmap?
+*/
+extern void
+OSMUnmapPMR(IMG_HANDLE hBridge,
+            IMG_HANDLE hPMR,
+            IMG_HANDLE hOSMMapPrivData,
+            void *pvMappingAddress,
+            size_t uiMappingLength);
+
+
+#endif /* _OSMMAP_H_ */
+
diff --git a/drivers/staging/imgtec/rogue/devicemem_mmap_stub.c b/drivers/staging/imgtec/rogue/osmmap_stub.c
similarity index 99%
rename from drivers/staging/imgtec/rogue/devicemem_mmap_stub.c
rename to drivers/staging/imgtec/rogue/osmmap_stub.c
index 13c4ea7..fbddf87 100644
--- a/drivers/staging/imgtec/rogue/devicemem_mmap_stub.c
+++ b/drivers/staging/imgtec/rogue/osmmap_stub.c
@@ -43,7 +43,7 @@
 */ /**************************************************************************/
 
 /* our exported API */
-#include "devicemem_mmap.h"
+#include "osmmap.h"
 
 /* include/ */
 #include "img_types.h"
diff --git a/drivers/staging/imgtec/rogue/pdump.c b/drivers/staging/imgtec/rogue/pdump.c
index 490a6ff..b49301b 100644
--- a/drivers/staging/imgtec/rogue/pdump.c
+++ b/drivers/staging/imgtec/rogue/pdump.c
@@ -50,7 +50,6 @@
 #include "osfunc.h"
 
 #include "dbgdrvif_srv5.h"
-#include "mm.h"
 #include "allocmem.h"
 #include "pdump_km.h"
 #include "pdump_osfunc.h"
@@ -167,7 +166,7 @@
 /*!
  * \name	PDumpOSVSprintf
  */
-PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, const IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
 {
 	IMG_INT32 n;
 
@@ -189,6 +188,8 @@
 void PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
 {
 	PVR_UNREFERENCED_PARAMETER(pszFormat);
+
+	/* FIXME: Implement using services PVR_DBG or otherwise with kprintf */
 }
 
 /*!
@@ -397,7 +398,7 @@
 
 void PDumpOSDestroyLock(void)
 {
-	/* no destruction work to do, just assert
+	/* no destruction work to be done, just assert
 	 * the lock is not held */
 	PVR_ASSERT(mutex_is_locked(&gsPDumpMutex) == 0);
 }
diff --git a/drivers/staging/imgtec/rogue/pdump.h b/drivers/staging/imgtec/rogue/pdump.h
index bb67914..48d126b 100644
--- a/drivers/staging/imgtec/rogue/pdump.h
+++ b/drivers/staging/imgtec/rogue/pdump.h
@@ -46,12 +46,13 @@
 
 typedef IMG_UINT32 PDUMP_FLAGS_T;
 
+#define PDUMP_FLAGS_NONE		0x00000000UL /*<! Output this entry with no special treatment i.e. output only if in frame range */
 
 #define PDUMP_FLAGS_DEINIT		    0x20000000UL /*<! Output this entry to the de-initialisation section */
 
 #define PDUMP_FLAGS_POWER		0x08000000UL /*<! Output this entry even when a power transition is ongoing */
 
-#define PDUMP_FLAGS_CONTINUOUS		PVRSRV_PDUMP_FLAGS_CONTINUOUS /*<! Defined in serviceS_km.h */
+#define PDUMP_FLAGS_CONTINUOUS		PDUMP_CONT /*<! Defined in serviceS_km.h */
 
 #define PDUMP_FLAGS_PERSISTENT		0x80000000UL /*<! Output this entry always regardless of app and range,
                                                       used by persistent processes e.g. compositor, window mgr etc/ */
@@ -74,5 +75,6 @@
 #define PDUMP_PARAM_N_FILE_NAME     "%%0%%_%02u.prm" /*!< Param filename used when PRM file split */
 #define PDUMP_PARAM_MAX_FILE_NAME   32               /*!< Max Size of parameter name used in out2.txt */
 
+#define PDUMP_IS_CONTINUOUS(flags) 	((flags & PDUMP_FLAGS_CONTINUOUS) != 0)
 
 #endif /* _SERVICES_PDUMP_H_ */
diff --git a/drivers/staging/imgtec/rogue/pdump_common.c b/drivers/staging/imgtec/rogue/pdump_common.c
index 2bc8469..63884a5 100644
--- a/drivers/staging/imgtec/rogue/pdump_common.c
+++ b/drivers/staging/imgtec/rogue/pdump_common.c
@@ -80,15 +80,10 @@
 #define MAX_PDUMP_MMU_CONTEXTS	(32)
 static void *gpvTempBuffer = NULL;
 
-#define PERSISTANT_MAGIC           ((uintptr_t) 0xe33ee33e)
-#define PDUMP_PERSISTENT_HASH_SIZE 10
-
 #define PRM_FILE_SIZE_MAX	0x7FDFFFFFU /*!< Default maximum file size to split output files, 2GB-2MB as fwrite limits it to 2GB-1 on 32bit systems */
 #define FRAME_UNSET			0xFFFFFFFFU /*|< Used to signify no or invalid frame number */
 
 
-static HASH_TABLE *g_psPersistentHash = NULL;
-
 static IMG_BOOL		g_PDumpInitialised = IMG_FALSE;
 static IMG_UINT32	g_ConnectionCount = 0;
 
@@ -132,7 +127,7 @@
 #define PDUMP_REFCOUNT_PRINT(fmt, ...)
 #endif
 
-/* Prototype for the test/debug state dump rotuine used in debugging */
+/* Prototype for the test/debug state dump routine used in debugging */
 void PDumpCommonDumpState(IMG_BOOL bDumpOSLayerState);
 #undef PDUMP_TRACE_STATE
 
@@ -500,7 +495,7 @@
 	/* The following checks are made when the driver has completed initialisation */
 
 	/* If PDump client connected allow continuous flagged writes */
-	if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+	if (PDUMP_IS_CONTINUOUS(ui32Flags))
 	{
 		if (PDumpCtrlCaptureRangeUnset()) /* Is client connected? */
 		{
@@ -512,7 +507,7 @@
 	}
 
 	/* No last/deinit statements allowed when not in initialisation phase */
-	if (ui32Flags & PDUMP_FLAGS_DEINIT)
+	if (PDUMP_IS_CONTINUOUS(ui32Flags))
 	{
 		if (PDumpCtrlInitPhaseComplete())
 		{
@@ -723,7 +718,7 @@
 
 			/* Don't write continuous data if client not connected */
 			PDumpCtrlLockAcquire();
-			if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) && PDumpCtrlCaptureRangeUnset())
+			if (PDUMP_IS_CONTINUOUS(ui32Flags) && PDumpCtrlCaptureRangeUnset())
 			{
 				PDumpCtrlLockRelease();
 				return IMG_TRUE;
@@ -774,6 +769,33 @@
 	return IMG_TRUE;
 }
 
+#if defined(PDUMP_DEBUG_OUTFILES)
+
+static IMG_UINT32 _GenerateChecksum(void *pvData, size_t uiSize)
+{
+	IMG_UINT32 ui32Sum = 0;
+	IMG_UINT32 *pui32Data = pvData;
+	IMG_UINT8 *pui8Data = pvData;
+	IMG_UINT32 i;
+	IMG_UINT32 ui32LeftOver;
+
+	for(i = 0; i < uiSize / sizeof(IMG_UINT32); i++)
+	{
+		ui32Sum += pui32Data[i];
+	}
+
+	ui32LeftOver = uiSize % sizeof(IMG_UINT32);
+
+	while(ui32LeftOver)
+	{
+		ui32Sum += pui8Data[uiSize - ui32LeftOver];
+		ui32LeftOver--;
+	}
+
+	return ui32Sum;
+}
+
+#endif
 
 PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *pui8Data, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags,
 		IMG_UINT32* pui32FileOffset, IMG_CHAR* aszFilenameStr)
@@ -788,7 +810,7 @@
 
 	if (!PDumpWriteAllowed(ui32Flags))
 	{
-		/* Abort write for the above reason but indicate what happended to
+		/* Abort write for the above reason but indicate what happened to
 		 * caller to avoid disrupting the driver, caller should treat it as OK
 		 * but skip any related PDump writes to the script file.  */
 		return PVRSRV_ERROR_PDUMP_NOT_ALLOWED;
@@ -846,6 +868,28 @@
 		PDUMP_HERE(7);
 		PVR_LOGG_IF_ERROR(eError, "PDumpWrite", errExit);
 	}
+#if defined(PDUMP_DEBUG_OUTFILES)
+	else
+	{
+		IMG_UINT32 ui32Checksum;
+		PDUMP_GET_SCRIPT_STRING();
+
+		ui32Checksum = _GenerateChecksum(pui8Data, ui32Size);
+
+		/* CHK CHKSUM SIZE PRMOFFSET PRMFILE */
+		eError = PDumpOSBufprintf(hScript, ui32MaxLen, "-- CHK 0x%08X 0x%08X 0x%08X %s",
+									ui32Checksum,
+									ui32Size,
+									*pui32FileOffset,
+									aszFilenameStr);
+		if(eError != PVRSRV_OK)
+		{
+			goto errExit;
+		}
+
+		PDumpWriteScript(hScript, ui32Flags);
+	}
+#endif
 
 	return PVRSRV_OK;
 
@@ -923,26 +967,6 @@
 						 __FUNCTION__, psPDumpConnectionData, ui32RefCount);
 }
 
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpIsPersistent)
-#endif
-
-IMG_BOOL PDumpIsPersistent(void)
-{
-	IMG_PID uiPID = OSGetCurrentClientProcessIDKM();
-	uintptr_t puiRetrieve;
-
-	puiRetrieve = HASH_Retrieve(g_psPersistentHash, uiPID);
-	if (puiRetrieve != 0)
-	{
-		PVR_ASSERT(puiRetrieve == PERSISTANT_MAGIC);
-		PDUMP_HEREA(110);
-		return IMG_TRUE;
-	}
-	return IMG_FALSE;
-}
-
-
 /**************************************************************************
  * Function Name  : GetTempBuffer
  * Inputs         : None
@@ -953,7 +977,7 @@
 static void *GetTempBuffer(void)
 {
 	/*
-	 * Allocate the temporary buffer, it it hasn't been allocated already.
+	 * Allocate the temporary buffer, if it hasn't been allocated already.
 	 * Return the address of the temporary buffer, or NULL if it
 	 * couldn't be allocated.
 	 * It is expected that the buffer will be allocated once, at driver
@@ -1079,10 +1103,6 @@
 	/* Allocate temporary buffer for copying from user space */
 	(void) GetTempBuffer();
 
-	eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-	g_psPersistentHash = HASH_Create(PDUMP_PERSISTENT_HASH_SIZE);
-	PVR_LOGG_IF_FALSE((g_psPersistentHash != NULL), "Failed to create persistent process hash", errExit);
-
 	/* create the global PDump lock */
 	eError = PDumpCreateLockKM();
 	PVR_LOGG_IF_ERROR(eError, "PDumpCreateLockKM", errExit);
@@ -1096,8 +1116,6 @@
 	PVR_LOGG_IF_ERROR(eError, "PDumpCtrlInit", errExitOSDeInit);
 
 	/* Test PDump initialised and ready by logging driver details */
-	eError = PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Driver Product Name: %s", PVRSRVGetSystemName());
-	PVR_LOGG_IF_ERROR(eError, "PDumpCommentWithFlags", errExitCtrl);
 	eError = PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Driver Product Version: %s - %s (%s)", PVRVERSION_STRING, PVR_BUILD_DIR, PVR_BUILD_TYPE);
 	PVR_LOGG_IF_ERROR(eError, "PDumpCommentWithFlags", errExitCtrl);
 	if (pszEnvComment != NULL)
@@ -1153,33 +1171,6 @@
 	return g_PDumpInitialised;
 }
 
-
-PVRSRV_ERROR PDumpAddPersistantProcess(void)
-{
-	IMG_PID uiPID = OSGetCurrentClientProcessIDKM();
-	uintptr_t puiRetrieve;
-	PVRSRV_ERROR eError = PVRSRV_OK;
-
-	PDUMP_HEREA(121);
-
-	puiRetrieve = HASH_Retrieve(g_psPersistentHash, uiPID);
-	if (puiRetrieve == 0)
-	{
-		if (!HASH_Insert(g_psPersistentHash, uiPID, PERSISTANT_MAGIC))
-		{
-			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		}
-	}
-	else
-	{
-		PVR_ASSERT(puiRetrieve == PERSISTANT_MAGIC);
-	}
-	PDUMP_HEREA(122);
-
-	return eError;
-}
-
-
 void PDumpStopInitPhase(IMG_BOOL bPDumpClient, IMG_BOOL bInitClient)
 {
 	/* Check with the OS we a running on */
@@ -1196,17 +1187,13 @@
 	}
 }
 
-PVRSRV_ERROR PDumpIsLastCaptureFrameKM(void)
+PVRSRV_ERROR PDumpIsLastCaptureFrameKM(IMG_BOOL *pbIsLastCaptureFrame)
 {
-	IMG_BOOL bIsLastCaptureFrame = IMG_FALSE;
-
 	PDumpCtrlLockAcquire();
-	bIsLastCaptureFrame = PDumpCtrlIsLastCaptureFrame();
+	*pbIsLastCaptureFrame = PDumpCtrlIsLastCaptureFrame();
 	PDumpCtrlLockRelease();
 
-	/* We're using INVALID_PARAMS error as true value and OK as false.
-	 * This is mapped to IMG_BOOL in user space. */
-	return bIsLastCaptureFrame ? PVRSRV_ERROR_INVALID_PARAMS : PVRSRV_OK;
+	return PVRSRV_OK;
 }
 
 
@@ -1258,7 +1245,7 @@
 	OSFreeMem(psData);
 }
 
-PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_BOOL bContinuous)
+PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_UINT32 ui32PDumpFlags)
 {
 	DLLIST_NODE *psNode, *psNext;
 	PVRSRV_ERROR eError;
@@ -1272,7 +1259,7 @@
 			PDUMP_Transition_DATA *psData =
 				IMG_CONTAINER_OF(psNode, PDUMP_Transition_DATA, sNode);
 
-			eError = psData->pfnCallback(psData->hPrivData, bInto, bContinuous);
+			eError = psData->pfnCallback(psData->hPrivData, bInto, ui32PDumpFlags);
 
 			if (eError != PVRSRV_OK)
 			{
@@ -1309,13 +1296,15 @@
 	/*
 		Note:
 		As we can't test to see if the new frame will be in capture range
-		before we set the frame number and we don't want to roll back
-		the frame number if we fail then we have to save the "transient"
-		data which decides if we're entering or exiting capture range
-		along with a failure boolean so we know what to do on a retry
+		before we set the frame number and we don't want to roll back the
+		frame number if we fail then we have to save the "transient" data
+		which decides if we're entering or exiting capture range along
+		with a failure boolean so we know what's required on a retry
 	*/
 	if (psPDumpConnectionData->ui32LastSetFrameNumber != ui32Frame)
 	{
+		(void) PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Set pdump frame %u", ui32Frame);
+
 		/*
 			The boolean values below decide if the PDump transition
 			should trigger because of the current context setting the
@@ -1353,7 +1342,7 @@
 
 	if (!bWasInCaptureRange && bIsInCaptureRange)
 	{
-		eError = PDumpTransition(psPDumpConnectionData, IMG_TRUE, IMG_FALSE);
+		eError = PDumpTransition(psPDumpConnectionData, IMG_TRUE, PDUMP_FLAGS_NONE);
 		if (eError != PVRSRV_OK)
 		{
 			goto fail_Transition;
@@ -1361,7 +1350,7 @@
 	}
 	else if (bWasInCaptureRange && !bIsInCaptureRange)
 	{
-		eError = PDumpTransition(psPDumpConnectionData, IMG_FALSE, IMG_FALSE);
+		eError = PDumpTransition(psPDumpConnectionData, IMG_FALSE, PDUMP_FLAGS_NONE);
 		if (eError != PVRSRV_OK)
 		{
 			goto fail_Transition;
@@ -1369,8 +1358,9 @@
 	}
 	else
 	{
-		/* Here both previous and current frames are in or out of range */
-		/* Should never reach here due to the above goto success */
+		/* Here both previous and current frames are in or out of range.
+		 * There is no transition in this case.
+		 */
 	}
 
 	psPDumpConnectionData->bLastTransitionFailed = IMG_FALSE;
@@ -1393,8 +1383,9 @@
 	PVR_DPF((PVR_DBG_WARNING, "PDumpSetFrameKM: ui32Frame( %d )", ui32Frame));
 #endif
 
-	/* Ignore errors as it is not fatal if the comments do not appear */
+#if defined(PDUMP_DEBUG_OUTFILES)
 	(void) PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Set pdump frame %u (pre)", ui32Frame);
+#endif
 
 	eError = _PDumpSetFrameKM(psConnection, ui32Frame);
 	if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
@@ -1402,7 +1393,9 @@
 		PVR_LOG_ERROR(eError, "_PDumpSetFrameKM");
 	}
 
+#if defined(PDUMP_DEBUG_OUTFILES)
 	(void) PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Set pdump frame %u (post)", ui32Frame);
+#endif
 
 	return eError;
 }
@@ -1561,8 +1554,8 @@
                                   IMG_UINT32 ui32Flags)
 {
 	PVRSRV_ERROR eErr;
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
 	IMG_DEVMEM_OFFSET_T uiNextSymName;
 
@@ -1571,9 +1564,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMR,
                                      uiLogicalOffset,
-                                     PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
                                      aszMemspaceName,
-                                     PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
                                      aszSymbolicName,
                                      &uiPDumpSymbolicOffset,
                                      &uiNextSymName);
@@ -1612,8 +1605,8 @@
 								  IMG_UINT32 ui32Flags)
 {
 	PVRSRV_ERROR eErr;
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
 	IMG_DEVMEM_OFFSET_T uiNextSymName;
 
@@ -1622,9 +1615,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMR,
 									 uiLogicalOffset,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceName,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicName,
 									 &uiPDumpSymbolicOffset,
 									 &uiNextSymName);
@@ -1664,8 +1657,8 @@
                                         IMG_UINT32	ui32Flags)
 {
 	PVRSRV_ERROR eErr;
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
 	IMG_DEVMEM_OFFSET_T uiNextSymName;
 
@@ -1674,9 +1667,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMR,
                                      uiLogicalOffset,
-                                     PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
                                      aszMemspaceName,
-                                     PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
                                      aszSymbolicName,
                                      &uiPDumpSymbolicOffset,
                                      &uiNextSymName);
@@ -1852,10 +1845,10 @@
                                   IMG_UINT32	ui32Flags)
 {
 	PVRSRV_ERROR eErr;
-	IMG_CHAR aszMemspaceNameSource[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameSource[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
-	IMG_CHAR aszMemspaceNameDest[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameDest[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceNameSource[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameSource[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_CHAR aszMemspaceNameDest[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameDest[PHYSMEM_PDUMP_MEMSPNAME_SYMB_ADDR_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetSource;
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
 	IMG_DEVMEM_OFFSET_T uiNextSymNameSource;
@@ -1867,9 +1860,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRSource,
                                      uiLogicalOffsetSource,
-                                     PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
                                      aszMemspaceNameSource,
-                                     PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
                                      aszSymbolicNameSource,
                                      &uiPDumpSymbolicOffsetSource,
                                      &uiNextSymNameSource);
@@ -1881,9 +1874,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRDest,
                                      uiLogicalOffsetDest,
-                                     PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
                                      aszMemspaceNameDest,
-                                     PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+                                     PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
                                      aszSymbolicNameDest,
                                      &uiPDumpSymbolicOffsetDest,
                                      &uiNextSymNameDest);
@@ -1926,10 +1919,10 @@
 								  IMG_UINT32	ui32Flags)
 {
 	PVRSRV_ERROR eErr;
-	IMG_CHAR aszMemspaceNameSource[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameSource[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
-	IMG_CHAR aszMemspaceNameDest[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameDest[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceNameSource[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameSource[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_CHAR aszMemspaceNameDest[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameDest[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetSource;
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
 	IMG_DEVMEM_OFFSET_T uiNextSymNameSource;
@@ -1941,9 +1934,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRSource,
 									 uiLogicalOffsetSource,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceNameSource,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicNameSource,
 									 &uiPDumpSymbolicOffsetSource,
 									 &uiNextSymNameSource);
@@ -1955,9 +1948,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRDest,
 									 uiLogicalOffsetDest,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceNameDest,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicNameDest,
 									 &uiPDumpSymbolicOffsetDest,
 									 &uiNextSymNameDest);
@@ -2097,8 +2090,6 @@
 
 	PVR_DPF((PVR_DBG_ERROR, "PDumpSAW\n"));
 
-	uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
 	                          ui32MaxLen,
@@ -2157,11 +2148,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 	PDUMP_DBG(("PDumpRegPolKM"));
-	if ( PDumpIsPersistent() )
-	{
-		/* Don't pdump-poll if the process is persistent */
-		return PVRSRV_OK;
-	}
 
 	ui32PollCount = POLL_COUNT_LONG;
 
@@ -2194,13 +2180,6 @@
 	PDUMP_GET_SCRIPT_STRING();
 	PDUMP_DBG(("PDumpCommentKM"));
 
-#if defined(PDUMP_DEBUG_OUTFILES)
-	/* Include comments in the "extended" init phase.
-	 * The default is to ignore them.
-	 */
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-#endif
-
 	if((pszComment == NULL) || (PDumpOSBuflen(pszComment, ui32MaxLen) == 0))
 	{
 		/* PDumpOSVerifyLineEnding silently fails if pszComment is too short to
@@ -2238,7 +2217,7 @@
 
 	if (!PDumpWriteScript(hScript, ui32Flags))
 	{
-		if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+		if(PDUMP_IS_CONTINUOUS(ui32Flags))
 		{
 			eErr = PVRSRV_ERROR_PDUMP_BUFFER_FULL;
 			PVR_LOGG_IF_ERROR(eErr, "PDumpWriteScript", ErrUnlock);
@@ -2286,15 +2265,33 @@
 PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
 {
 	PVRSRV_ERROR eErr = PVRSRV_OK;
-	PDUMP_va_list ap;
+	va_list args;
+
+	va_start(args, pszFormat);
+	PDumpCommentWithFlagsVA(ui32Flags, pszFormat, args);
+	va_end(args);
+
+	return eErr;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpCommentWithFlagsVA
+ * Inputs         : psPDev    - PDev for PDump device
+ *				  : pszFormat - format string for comment
+ *				  : args      - pre-started va_list args for format string
+ * Outputs        : None
+ * Returns        : None
+ * Description    : PDumps a comments
+**************************************************************************/
+PVRSRV_ERROR PDumpCommentWithFlagsVA(IMG_UINT32 ui32Flags, const IMG_CHAR * pszFormat, va_list args)
+{
+	PVRSRV_ERROR eErr = PVRSRV_OK;
 	PDUMP_GET_MSG_STRING();
 
 	PDUMP_LOCK();
 
 	/* Construct the string */
-	PDUMP_va_start(ap, pszFormat);
-	eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
-	PDUMP_va_end(ap);
+	eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, args);
 
 	if(eErr != PVRSRV_OK)
 	{
@@ -2342,9 +2339,8 @@
 	/* Check the supplied panic reason string is within length limits */
 	PVR_ASSERT(OSStringLength(pszPanicMsg)+sizeof("PANIC   ") < PVRSRV_PDUMP_MAX_COMMENT_SIZE-1);
 
-	/* Add persistent flag if required and obtain lock to keep the multi-line
+	/* Obtain lock to keep the multi-line
 	 * panic statement together in a single atomic write */
-	uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
 	PDUMP_LOCK();
 
 
@@ -2400,10 +2396,8 @@
 	/* Check the supplied panic reason string is within length limits */
 	PVR_ASSERT(OSStringLength(pszErrorMsg)+sizeof(pszFormatStr) < PVRSRV_PDUMP_MAX_COMMENT_SIZE-1);
 
-	/* Add persistent flag if required and obtain lock to keep the multi-line
+	/* Obtain lock to keep the multi-line 
 	 * panic statement together in a single atomic write */
-	uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 
 	/* Write driver error message to the script file */
@@ -2456,11 +2450,6 @@
 	PVRSRV_ERROR eErr=0;
 	PDUMP_GET_SCRIPT_STRING();
 
-	if ( PDumpIsPersistent() )
-	{
-		return PVRSRV_OK;
-	}
-	
 	PDumpCommentWithFlags(ui32PDumpFlags, "Dump bitmap of render.");
 	
 	switch (ePixelFormat)
@@ -3381,12 +3370,8 @@
 
 void PDumpCommonDumpState(IMG_BOOL bDumpOSLayerState)
 {
-	IMG_UINT32* ui32HashData = (IMG_UINT32*)g_psPersistentHash;
-
 	PVR_LOG(("--- PDUMP COMMON: g_PDumpInitialised( %d )",
 			g_PDumpInitialised) );
-	PVR_LOG(("--- PDUMP COMMON: g_psPersistentHash( %p ) uSize( %d ) uCount( %d )",
-			g_psPersistentHash, ui32HashData[0], ui32HashData[1]) );
 	PVR_LOG(("--- PDUMP COMMON: g_PDumpScript.sCh.hInit( %p ) g_PDumpScript.sCh.hMain( %p ) g_PDumpScript.sCh.hDeinit( %p )",
 			g_PDumpScript.sCh.hInit, g_PDumpScript.sCh.hMain, g_PDumpScript.sCh.hDeinit) );
 	PVR_LOG(("--- PDUMP COMMON: g_PDumpParameters.sCh.hInit( %p ) g_PDumpParameters.sCh.hMain( %p ) g_PDumpParameters.sCh.hDeinit( %p )",
diff --git a/drivers/staging/imgtec/rogue/pdump_km.h b/drivers/staging/imgtec/rogue/pdump_km.h
index f98976f..cddf4d6 100644
--- a/drivers/staging/imgtec/rogue/pdump_km.h
+++ b/drivers/staging/imgtec/rogue/pdump_km.h
@@ -44,6 +44,10 @@
 #ifndef _PDUMP_KM_H_
 #define _PDUMP_KM_H_
 
+#if defined(PDUMP)
+#include <stdarg.h>
+#endif
+
 /* services/srvkm/include/ */
 #include "device.h"
 
@@ -51,7 +55,7 @@
 #include "pvrsrv_error.h"
 
 
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
 #include <services_kernel_client.h>
 #endif
@@ -85,14 +89,14 @@
 #endif
 
 typedef struct _PDUMP_CONNECTION_DATA_ PDUMP_CONNECTION_DATA;
-typedef PVRSRV_ERROR (*PFN_PDUMP_TRANSITION)(void **pvData, IMG_BOOL bInto, IMG_BOOL bContinuous);
+typedef PVRSRV_ERROR (*PFN_PDUMP_TRANSITION)(void **pvData, IMG_BOOL bInto, IMG_UINT32 ui32PDumpFlags);
 
 #ifdef PDUMP
 
 /*! Macro used to record a panic in the PDump script stream */
-#define PDUMP_PANIC(_type, _id, _msg) do \
+#define PDUMP_PANIC(_id, _msg) do \
 		{ PVRSRV_ERROR _eE;\
-			_eE = PDumpPanic((PVRSRV_DEVICE_TYPE_ ## _type)<<16 | ((_type ## _PDUMP_PANIC_ ## _id)&0xFFFF), _msg, __FUNCTION__, __LINE__);\
+			_eE = PDumpPanic(((RGX_PDUMP_PANIC_ ## _id) & 0xFFFF), _msg, __FUNCTION__, __LINE__);	\
 			PVR_LOG_IF_ERROR(_eE, "PDumpPanic");\
 		MSC_SUPPRESS_4127\
 		} while (0)
@@ -237,7 +241,11 @@
 
 	PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32	ui32Flags,
 									   IMG_CHAR*	pszFormat,
-									   ...) IMG_FORMAT_PRINTF(2, 3);
+									   ...) __printf(2, 3);
+
+	PVRSRV_ERROR PDumpCommentWithFlagsVA(IMG_UINT32 ui32Flags,
+									    const IMG_CHAR * pszFormat,
+										va_list args);
 
 	PVRSRV_ERROR PDumpPanic(IMG_UINT32      ui32PanicNo,
 							IMG_CHAR*       pszPanicMsg,
@@ -259,27 +267,10 @@
 									 IMG_UINT32		ui32Flags,
 									 IMG_HANDLE		hUniqueTag);
 
-	PVRSRV_ERROR PDumpIsLastCaptureFrameKM(void);
+	PVRSRV_ERROR PDumpIsLastCaptureFrameKM(IMG_BOOL *pbIsLastCaptureFrame);
 
 	PVRSRV_ERROR PDumpIsCaptureFrameKM(IMG_BOOL *bIsCapturing);
 
-	void PDumpMallocPagesPhys(PVRSRV_DEVICE_IDENTIFIER	*psDevID,
-							  IMG_UINT64			ui64DevVAddr,
-							  IMG_PUINT32			pui32PhysPages,
-							  IMG_UINT32			ui32NumPages,
-							  IMG_HANDLE			hUniqueTag);
-	PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
-									IMG_CHAR *pszMemSpace,
-									IMG_UINT32 *pui32MMUContextID,
-									IMG_UINT32 ui32MMUType,
-									IMG_HANDLE hUniqueTag1,
-									IMG_HANDLE hOSMemHandle,
-									void *pvPDCPUAddr);
-	PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
-									IMG_CHAR *pszMemSpace,
-									IMG_UINT32 ui32MMUContextID,
-									IMG_UINT32 ui32MMUType);
-
 	PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
 								const IMG_UINT32 dwRegOffset,
 								IMG_UINT32	ui32Flags);
@@ -290,14 +281,6 @@
 	PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
 	PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
 
-	IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(PVRSRV_DEVICE_IDENTIFIER *psDevId,
-										IMG_CHAR			*pszFileName,
-										IMG_UINT32			ui32FileOffset,
-										IMG_DEV_VIRTADDR	sDevBaseAddr,
-										IMG_UINT32 			ui32Size,
-										IMG_UINT32			ui32MMUContextID,
-										IMG_UINT32 			ui32PDumpFlags);
-
 	PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR		*pszPDumpRegName,
 								  IMG_UINT32	ui32RegOffset,
 								  IMG_UINT32	ui32WPosVal,
@@ -319,13 +302,6 @@
 	void PDumpLock(void);
 	void PDumpUnlock(void);
 
-	/*
-	    Process persistence common API for use by common
-	    clients e.g. mmu and physmem.
-	 */
-	IMG_BOOL PDumpIsPersistent(void);
-	PVRSRV_ERROR PDumpAddPersistantProcess(void);
-
 	PVRSRV_ERROR PDumpIfKM(IMG_CHAR		*pszPDumpCond);
 	PVRSRV_ERROR PDumpElseKM(IMG_CHAR	*pszPDumpCond);
 	PVRSRV_ERROR PDumpFiKM(IMG_CHAR		*pszPDumpCond);
@@ -422,7 +398,7 @@
 extern void PDumpUnregisterTransitionCallback(void *pvHandle);
 
 /* Notify PDump of a Transition into/out of capture range */
-extern PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_BOOL bContinuous);
+extern PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_UINT32 ui32PDumpFlags);
 
 /* Wires-up a MIPS TLB in the page table*/
 extern PVRSRV_ERROR PdumpWireUpMipsTLB(PMR *psPMRSource,
@@ -452,8 +428,6 @@
 	#define PDUMPCOMMENT(...)		PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, __VA_ARGS__)
 	#define PDUMPCOMMENTWITHFLAGS	PDumpCommentWithFlags
 	#define PDUMPREGPOL				PDumpRegPolKM
-	#define PDUMPSETMMUCONTEXT		PDumpSetMMUContext
-	#define PDUMPCLEARMMUCONTEXT	PDumpClearMMUContext
 	#define PDUMPPDREG				PDumpPDReg
 	#define PDUMPPDREGWITHFLAGS		PDumpPDRegWithFlags
 	#define PDUMPREGBASEDCBP		PDumpRegBasedCBP
@@ -469,11 +443,11 @@
 #else
 	/*
 		We should be clearer about which functions can be called
-		across the bridge as this looks rather unblanced
+		across the bridge as this looks rather unbalanced
 	*/
 
 /*! Macro used to record a panic in the PDump script stream */
-#define PDUMP_PANIC(_type, _id, _msg)  ((void)0);
+#define PDUMP_PANIC(_id, _msg)  ((void)0);
 
 /*! Macro used to record a driver error in the PDump script stream to invalidate the capture */
 #define PDUMP_ERROR(_err, _msg) ((void)0);
@@ -539,16 +513,6 @@
 }
 
 #ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpAddPersistantProcess)
-#endif
-static INLINE PVRSRV_ERROR
-PDumpAddPersistantProcess(void)
-{
-	return PVRSRV_OK;
-}
-
-
-#ifdef INLINE_IS_PRAGMA
 #pragma inline(PDumpStopInitPhase)
 #endif
 static INLINE void
@@ -575,7 +539,9 @@
 #pragma inline(PDumpGetFrameKM)
 #endif
 static INLINE PVRSRV_ERROR
-PDumpGetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32* pui32Frame)
+PDumpGetFrameKM(CONNECTION_DATA *psConnection,
+                PVRSRV_DEVICE_NODE *psDeviceNode,
+                IMG_UINT32* pui32Frame)
 {
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(pui32Frame);
@@ -650,9 +616,9 @@
 #pragma inline(PDumpIsLastCaptureFrameKM)
 #endif
 static INLINE PVRSRV_ERROR
-PDumpIsLastCaptureFrameKM(void)
+PDumpIsLastCaptureFrameKM(IMG_BOOL *pbIsLastCaptureFrame)
 {
-	/* PVRSRV_OK means FALSE to the upper levels. */
+	*pbIsLastCaptureFrame = IMG_FALSE;
 	return PVRSRV_OK;
 }
 
@@ -750,11 +716,11 @@
 #pragma inline(PDumpTransition)
 #endif
 static INLINE
-PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_BOOL bContinuous)
+PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_UINT32 ui32PDumpFlags)
 {
 	PVR_UNREFERENCED_PARAMETER(psPDumpConnectionData);
 	PVR_UNREFERENCED_PARAMETER(bInto);
-	PVR_UNREFERENCED_PARAMETER(bContinuous);
+	PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
 	return PVRSRV_OK;
 }
 
@@ -767,8 +733,6 @@
 		#define PDUMPREGREAD64(...)			/ ## * PDUMPREGREAD64(__VA_ARGS__) * ## /
 		#define PDUMPCOMMENT(...)		/ ## * PDUMPCOMMENT(__VA_ARGS__) * ## /
 		#define PDUMPREGPOL(...)		/ ## * PDUMPREGPOL(__VA_ARGS__) * ## /
-		#define PDUMPSETMMUCONTEXT(...)		/ ## * PDUMPSETMMUCONTEXT(__VA_ARGS__) * ## /
-		#define PDUMPCLEARMMUCONTEXT(...)	/ ## * PDUMPCLEARMMUCONTEXT(__VA_ARGS__) * ## /
 		#define PDUMPPDREG(...)			/ ## * PDUMPPDREG(__VA_ARGS__) * ## /
 		#define PDUMPPDREGWITHFLAGS(...)	/ ## * PDUMPPDREGWITHFLAGS(__VA_ARGS__) * ## /
 		#define PDUMPSYNC(...)			/ ## * PDUMPSYNC(__VA_ARGS__) * ## /
@@ -791,7 +755,7 @@
 		#define PDUMP_LOCK			/ ## * PDUMP_LOCK(__VA_ARGS__) * ## /
 		#define PDUMP_UNLOCK			/ ## * PDUMP_UNLOCK(__VA_ARGS__) * ## /
 	#else
-		#if defined LINUX || defined GCC_IA32 || defined GCC_ARM || defined __QNXNTO__
+		#if defined LINUX || defined GCC_IA32 || defined GCC_ARM || defined __QNXNTO__ || defined(INTEGRITY_OS)
 			#define PDUMPINIT	PDumpInitCommon
 			#define PDUMPDEINIT(args...)
 			#define PDUMPREG32(args...)
@@ -800,8 +764,6 @@
 			#define PDUMPREGREAD64(args...)
 			#define PDUMPCOMMENT(args...)
 			#define PDUMPREGPOL(args...)
-			#define PDUMPSETMMUCONTEXT(args...)
-			#define PDUMPCLEARMMUCONTEXT(args...)
 			#define PDUMPPDREG(args...)
 			#define PDUMPPDREGWITHFLAGS(args...)
 			#define PDUMPSYNC(args...)
diff --git a/drivers/staging/imgtec/rogue/pdump_mmu.c b/drivers/staging/imgtec/rogue/pdump_mmu.c
index 7a7a32f..218c6b2 100644
--- a/drivers/staging/imgtec/rogue/pdump_mmu.c
+++ b/drivers/staging/imgtec/rogue/pdump_mmu.c
@@ -47,6 +47,7 @@
 #include "pdump_mmu.h"
 #include "pdump_osfunc.h"
 #include "pdump_km.h"
+#include "pdump_physmem.h"
 #include "osfunc.h"
 #include "pvr_debug.h"
 #include "pvrsrv_error.h"
@@ -54,8 +55,6 @@
 #define MAX_PDUMP_MMU_CONTEXTS	(10)
 static IMG_UINT32 guiPDumpMMUContextAvailabilityMask = (1<<MAX_PDUMP_MMU_CONTEXTS)-1;
 
-/* arbitrary buffer length here. */
-#define MAX_SYMBOLIC_ADDRESS_LENGTH 40
 
 #define MMUPX_FMT(X) ((X<3) ? ((X<2) ?  "MMUPT_\0" : "MMUPD_\0") : "MMUPC_\0")
 #define MIPSMMUPX_FMT(X) ((X<3) ? ((X<2) ?  "MIPSMMUPT_\0" : "MIPSMMUPD_\0") : "MIPSMMUPC_\0")
@@ -183,8 +182,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	if (eMMULevel >= MMU_LEVEL_LAST)
 	{
 		eErr = PVRSRV_ERROR_INVALID_PARAMS;
@@ -266,8 +263,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	if (eMMULevel >= MMU_LEVEL_LAST)
 	{
 		eErr = PVRSRV_ERROR_INVALID_PARAMS;
@@ -338,8 +333,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	/*
 		Write a comment to the PDump2 script streams indicating the memory allocation
@@ -395,8 +388,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	/*
 		Write a comment to the PDUMP2 script streams indicating the memory free
@@ -443,8 +434,8 @@
 								  IMG_UINT64 ui64PxSymAddr)
 {
 
-	IMG_CHAR aszMemspaceNameDest[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameDest[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceNameDest[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameDest[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
 	IMG_DEVMEM_OFFSET_T uiNextSymNameDest;
 	PVRSRV_ERROR eErr = PVRSRV_OK;
@@ -454,9 +445,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRDest,
 									 uiLogicalOffsetDest,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceNameDest,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicNameDest,
 									 &uiPDumpSymbolicOffsetDest,
 									 &uiNextSymNameDest);
@@ -525,15 +516,13 @@
     IMG_INT32  iShiftAmount;
     IMG_CHAR   *pszWrwSuffix = 0;
     void *pvRawBytes = 0;
-    IMG_CHAR aszPxSymbolicAddr[MAX_SYMBOLIC_ADDRESS_LENGTH];
+    IMG_CHAR aszPxSymbolicAddr[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
     IMG_UINT64 ui64PxE64;
     IMG_UINT64 ui64Protflags64;
     IMG_CHAR *pszMMUPX;
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	if (!PDumpReady())
 	{
 		eErr = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
@@ -568,7 +557,7 @@
 		pszMMUPX = MMUPX_FMT(eMMULevel);
 	}
     OSSNPrintf(aszPxSymbolicAddr,
-               MAX_SYMBOLIC_ADDRESS_LENGTH,
+               PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
                ":%s:%s%016llX",
                pszPDumpDevName,
                pszMMUPX,
@@ -908,11 +897,11 @@
 
 
 /**************************************************************************
- * Function Name  : PDumpSetMMUContext
+ * Function Name  : PDumpMMUAllocMMUContext
  * Inputs         :
  * Outputs        : None
  * Returns        : PVRSRV_ERROR
- * Description    : Set MMU Context
+ * Description    : Alloc MMU Context
 **************************************************************************/
 PVRSRV_ERROR PDumpMMUAllocMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
                                      IMG_DEV_PHYADDR sPCDevPAddr,
@@ -929,7 +918,8 @@
 	eErr = _PdumpAllocMMUContext(&ui32MMUContextID);
 	if(eErr != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eErr));
+		PVR_DPF((PVR_DBG_ERROR, "%s: _PdumpAllocMMUContext failed: %d",
+				 __func__, eErr));
         PVR_DBG_BREAK;
 		goto ErrOut;
 	}
@@ -984,11 +974,11 @@
 
 
 /**************************************************************************
- * Function Name  : PDumpClearMMUContext
+ * Function Name  : PDumpMMUFreeMMUContext
  * Inputs         :
  * Outputs        : None
  * Returns        : PVRSRV_ERROR
- * Description    : Clear MMU Context
+ * Description    : Free MMU Context
 **************************************************************************/
 PVRSRV_ERROR PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
                                     IMG_UINT32 ui32MMUContextID)
@@ -1022,7 +1012,8 @@
 	eErr = _PdumpFreeMMUContext(ui32MMUContextID);
 	if(eErr != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eErr));
+		PVR_DPF((PVR_DBG_ERROR, "%s: _PdumpFreeMMUContext failed: %d",
+				 __func__, eErr));
 		goto ErrUnlock;
 	}
 
@@ -1049,8 +1040,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	if (!PDumpReady())
 	{
 		eErr = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
@@ -1111,8 +1100,6 @@
 
 	PDUMP_GET_SCRIPT_STRING();
 
-	ui32PDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	if (!PDumpReady())
 	{
 		eErr = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
@@ -1163,10 +1150,10 @@
 								IMG_UINT32 ui32Flags)
 {
 	PVRSRV_ERROR eErr = PVRSRV_OK;
-	IMG_CHAR aszMemspaceNameSource[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameSource[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
-	IMG_CHAR aszMemspaceNameDest[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameDest[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceNameSource[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameSource[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_CHAR aszMemspaceNameDest[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameDest[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetSource;
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
 	IMG_DEVMEM_OFFSET_T uiNextSymNameSource;
@@ -1177,9 +1164,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRSource,
 									 uiLogicalOffsetSource,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceNameSource,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicNameSource,
 									 &uiPDumpSymbolicOffsetSource,
 									 &uiNextSymNameSource);
@@ -1191,9 +1178,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRDest,
 									 uiLogicalOffsetDest,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceNameDest,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicNameDest,
 									 &uiPDumpSymbolicOffsetDest,
 									 &uiNextSymNameDest);
@@ -1268,8 +1255,8 @@
 									IMG_UINT32 ui32Flags)
 {
 	PVRSRV_ERROR eErr = PVRSRV_OK;
-	IMG_CHAR aszMemspaceNameDest[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicNameDest[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+	IMG_CHAR aszMemspaceNameDest[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicNameDest[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
 	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
 	IMG_DEVMEM_OFFSET_T uiNextSymNameDest;
 
@@ -1278,9 +1265,9 @@
 
 	eErr = PMR_PDumpSymbolicAddr(psPMRDest,
 									 uiLogicalOffsetDest,
-									 PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
 									 aszMemspaceNameDest,
-									 PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT,
+									 PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
 									 aszSymbolicNameDest,
 									 &uiPDumpSymbolicOffsetDest,
 									 &uiNextSymNameDest);
diff --git a/drivers/staging/imgtec/rogue/pdump_mmu.h b/drivers/staging/imgtec/rogue/pdump_mmu.h
index e035657..24c2663 100644
--- a/drivers/staging/imgtec/rogue/pdump_mmu.h
+++ b/drivers/staging/imgtec/rogue/pdump_mmu.h
@@ -80,6 +80,7 @@
 
 typedef struct _PDUMP_MMU_ATTRIB_
 {
+    /* FIXME: would these be better as pointers rather than copies? */
     struct _PDUMP_MMU_ATTRIB_DEVICE_ sDevice;
     struct _PDUMP_MMU_ATTRIB_CONTEXT_ sContext;
     struct _PDUMP_MMU_ATTRIB_HEAP_ sHeap;
@@ -149,6 +150,7 @@
 												IMG_UINT32 uiRegAddr,
 												const IMG_CHAR *pszPDumpPCSymbolicName);
 
+	/* FIXME: split to separate file... (debatable whether this is anything to do with MMU) */
 extern PVRSRV_ERROR
 PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
             IMG_UINT32 uiPDumpMMUCtx,
diff --git a/drivers/staging/imgtec/rogue/pdump_osfunc.h b/drivers/staging/imgtec/rogue/pdump_osfunc.h
index b23d5fd..1ec9ac2 100644
--- a/drivers/staging/imgtec/rogue/pdump_osfunc.h
+++ b/drivers/staging/imgtec/rogue/pdump_osfunc.h
@@ -47,6 +47,16 @@
 #include "pvrsrv_device_types.h"
 
 
+/* FIXME
+ * Some OSes (WinXP,CE) allocate the string on the stack, but some
+ * (Linux) use a global variable/lock instead.
+ * Would be good to use the same across all OSes.
+ *
+ * A handle is returned which represents IMG_CHAR* type on all OSes.
+ *
+ * The allocated buffer length is also returned on OSes where it's
+ * supported (e.g. Linux).
+ */
 #define MAX_PDUMP_STRING_LENGTH (256)
 #if defined(WIN32)
 #define PDUMP_GET_SCRIPT_STRING()	\
@@ -115,31 +125,34 @@
 	eErrorPDump = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
 	PVR_LOGR_IF_ERROR(eErrorPDump, "PDumpOSGetFilenameString");
 
-	/*!
-	 * @name	PDumpOSGetScriptString
-	 * @brief	Get the "script" buffer
-	 * @param	phScript - buffer handle for pdump script
-	 * @param	pui32MaxLen - max length of the script buffer
-	 * @return	error (always PVRSRV_OK on some OSes)
-	 */
+	/**************************************************************************/ /*!
+	@Function       PDumpOSGetScriptString
+	@Description    Get the handle of the PDump "script" buffer.
+	                This function is only called if PDUMP is defined.
+	@Output         phScript           Handle of the PDump script buffer
+	@Output         pui32MaxLen        max length the script buffer can be
+	@Return         PVRSRV_OK on success, a failure code otherwise.
+	*/ /**************************************************************************/
 	PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
 
-	/*!
-	 * @name	PDumpOSGetMessageString
-	 * @brief	Get the "message" buffer
-	 * @param	pszMsg - buffer pointer for pdump messages
-	 * @param	pui32MaxLen - max length of the message buffer
-	 * @return	error (always PVRSRV_OK on some OSes)
-	 */
+	/**************************************************************************/ /*!
+	@Function       PDumpOSGetMessageString
+	@Description    Get the PDump "message" buffer.
+	                This function is only called if PDUMP is defined.
+	@Output         ppszMsg            Pointer to the PDump message buffer
+	@Output         pui32MaxLen        max length the message buffer can be
+	@Return         PVRSRV_OK on success, a failure code otherwise.
+	*/ /**************************************************************************/
 	PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
 
-	/*!
-	 * @name	PDumpOSGetFilenameString
-	 * @brief	Get the "filename" buffer
-	 * @param	ppszFile - buffer pointer for filename
-	 * @param	pui32MaxLen - max length of the filename buffer
-	 * @return	error (always PVRSRV_OK on some OSes)
-	 */
+	/**************************************************************************/ /*!
+	@Function       PDumpOSGetFilenameString
+	@Description    Get the PDump "filename" buffer.
+	                This function is only called if PDUMP is defined.
+	@Output         ppszFile           Pointer to the PDump filename buffer
+	@Output         pui32MaxLen        max length the filename buffer can be
+	@Return         PVRSRV_OK on success, a failure code otherwise.
+	*/ /**************************************************************************/
 	PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
 
 #endif /* __QNXNTO__ */
@@ -157,23 +170,56 @@
 	IMG_HANDLE hDeinit;      /*!< Driver/HW de-initialisation PDump stream */
 } PDUMP_CHANNEL;
 
+/**************************************************************************/ /*!
+@Function       PDumpOSInit
+@Description    Reset the connection to vldbgdrv, then try to connect to
+                PDump streams. This function is only called if PDUMP is
+                defined.
+@Input          psParam            PDump channel to be used for logging
+                                   parameters
+@Input          psScript           PDump channel to be used for logging
+                                   commands / events
+@Output         pui32InitCapMode   The initial PDump capture mode.
+@Output         ppszEnvComment     Environment-specific comment that is
+                                   output when writing to the PDump
+                                   stream (this may be NULL).
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR PDumpOSInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript,
 		IMG_UINT32* pui32InitCapMode, IMG_CHAR** ppszEnvComment);
 
+/**************************************************************************/ /*!
+@Function       PDumpOSDeInit
+@Description    Disconnect the PDump streams and close the connection to
+                vldbgdrv. This function is only called if PDUMP is defined.
+@Input          psParam            PDump parameter channel to be closed
+@Input          psScript           PDump command channel to be closed
+@Return         None
+*/ /**************************************************************************/
 void PDumpOSDeInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript);
 
-/*!
- * @name	PDumpOSSetSplitMarker
- * @brief	Inform the PDump client to start a new file at the given marker.
- * @param	hStream - stream
- * @param   ui32Marker - byte file position
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSSetSplitMarker
+@Description    Inform the PDump client to start a new file at the given
+                marker. This function is only called if PDUMP is defined.
+@Input          hStream            handle of PDump stream
+@Input          ui32Marker         byte file position
+@Return         IMG_TRUE
+*/ /**************************************************************************/
 IMG_BOOL PDumpOSSetSplitMarker(IMG_HANDLE hStream, IMG_UINT32 ui32Marker);
 
-/*
-	PDumpOSDebugDriverWrite - ENV layer write entry point from COMMON layer
-	                          A call back down the PDump software layer
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSDebugDriverWrite
+@Description    Writes a given number of bytes from the specified buffer
+                to a PDump stream. This function is only called if PDUMP
+                is defined.
+@Input          psStream           handle of PDump stream to write into
+@Input          pui8Data           buffer to write data from
+@Input          ui32BCount         number of bytes to write
+@Return         The number of bytes actually written (may be less than
+                ui32BCount if there is insufficient space in the target
+                PDump stream buffer)
+*/ /**************************************************************************/
 IMG_UINT32 PDumpOSDebugDriverWrite(IMG_HANDLE psStream,
                                    IMG_UINT8 *pui8Data,
                                    IMG_UINT32 ui32BCount);
@@ -187,119 +233,114 @@
 #define PDUMP_va_end	va_end
 
 
-/*!
- * @name	PDumpOSBufprintf
- * @brief	Printf to OS-specific pdump state buffer
- * @param	hBuf - buffer handle to write into
- * @param	ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
- * @param	pszFormat - format string
- */
-PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+/**************************************************************************/ /*!
+@Function       PDumpOSBufprintf
+@Description    Printf to OS-specific PDump state buffer. This function is
+                only called if PDUMP is defined.
+@Input          hBuf               handle of buffer to write into
+@Input          ui32ScriptSizeMax  maximum size of data to write (chars)
+@Input          pszFormat          format string
+@Return         None
+*/ /**************************************************************************/
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) __printf(3, 4);
 
-/*!
- * @name	PDumpOSDebugPrintf
- * @brief	Debug message during pdumping
- * @param	pszFormat - format string
- */
-void PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+/**************************************************************************/ /*!
+@Function       PDumpOSDebugPrintf
+@Description    Debug message during PDumping. This function is only called
+                if PDUMP is defined.
+@Input          pszFormat            format string
+@Return         None
+*/ /**************************************************************************/
+void PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) __printf(1, 2);
 
 /*
  * Write into a IMG_CHAR* on all OSes. Can be allocated on the stack or heap.
  */
-/*!
- * @name	PDumpOSSprintf
- * @brief	Printf to IMG char array
- * @param	pszComment - char array to print into
- * @param	pszFormat - format string
- */
-PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+/**************************************************************************/ /*!
+@Function       PDumpOSSprintf
+@Description    Printf to IMG char array. This function is only called if
+                PDUMP is defined.
+@Input          ui32ScriptSizeMax    maximum size of data to write (chars)
+@Input          pszFormat            format string
+@Output         pszComment           char array to print into
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) __printf(3, 4);
 
-/*!
- * @name	PDumpOSVSprintf
- * @brief	Printf to IMG string using variable args (see stdarg.h). This is necessary
- * 			because the ... notation does not support nested function calls.
- * @param	pszMsg - char array to print into
- * @param	ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
- * @param	pszFormat - format string
- * @param	vaArgs - variable args structure (from stdarg.h)
- */
-PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+/**************************************************************************/ /*!
+@Function       PDumpOSVSprintf
+@Description    Printf to IMG string using variable args (see stdarg.h).
+                This is necessary because the '...' notation does not
+                support nested function calls.
+                This function is only called if PDUMP is defined.
+@Input          ui32ScriptSizeMax    maximum size of data to write (chars)
+@Input          pszFormat            format string
+@Input          vaArgs               variable args structure (from stdarg.h)
+@Output         pszMsg               char array to print into
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, const IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) __printf(3, 0);
 
-/*!
- * @name	PDumpOSBuflen
- * @param	hBuffer - handle to buffer
- * @param	ui32BuffeRSizeMax - max size of buffer (chars)
- * @return	length of buffer, will always be <= ui32BufferSizeMax
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSBuflen
+@Description    Returns the length of the specified buffer (in chars).
+                This function is only called if PDUMP is defined.
+@Input          hBuffer              handle to buffer
+@Input          ui32BufferSizeMax    max size of buffer (chars)
+@Return         The length of the buffer, will always be <= ui32BufferSizeMax
+*/ /**************************************************************************/
 IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
 
-/*!
- * @name	PDumpOSVerifyLineEnding
- * @brief	Put line ending sequence at the end if it isn't already there
- * @param	hBuffer - handle to buffer
- * @param	ui32BufferSizeMax - max size of buffer (chars)
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSVerifyLineEnding
+@Description    Put line ending sequence at the end if it isn't already
+                there. This function is only called if PDUMP is defined.
+@Input          hBuffer              handle to buffer
+@Input          ui32BufferSizeMax    max size of buffer (chars)
+@Return         None
+*/ /**************************************************************************/
 void PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
 
-/*!
- * @name	PDumpOSCPUVAddrToDevPAddr
- * @brief	OS function to convert CPU virtual to device physical for dumping pages
- * @param	hOSMemHandle	mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
- * @param	ui32Offset		dword offset into allocation (for use with mem handle, e.g. linux)
- * @param	pui8LinAddr		CPU linear addr (usually a kernel virtual address)
- * @param	ui32PageSize	page size, used for assertion check
- * @return	psDevPAddr		device physical addr
- */
-void PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
-        IMG_HANDLE hOSMemHandle,
-		IMG_UINT32 ui32Offset,
-		IMG_UINT8 *pui8LinAddr,
-		IMG_UINT32 ui32PageSize,
-		IMG_DEV_PHYADDR *psDevPAddr);
-
-/*!
- * @name	PDumpOSCPUVAddrToPhysPages
- * @brief	OS function to convert CPU virtual to backing physical pages
- * @param	hOSMemHandle	mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
- * @param	ui32Offset		offset within mem allocation block
- * @param	pui8LinAddr		CPU linear addr
- * @param	ui32DataPageMask	mask for data page (= data page size -1)
- * @return	pui32PageOffset	CPU page offset (same as device page offset if page sizes equal)
- */
-void PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
-		IMG_UINT32 ui32Offset,
-		IMG_PUINT8 pui8LinAddr,
-		IMG_UINT32 ui32DataPageMask,
-		IMG_UINT32 *pui32PageOffset);
-
-/*!
- * @name	PDumpOSReleaseExecution
- * @brief	OS function to switch to another process, to clear pdump buffers
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSReleaseExecution
+@Description    OS function to switch to another process, to clear PDump
+                buffers.
+                This function can simply wrap OSReleaseThreadQuanta.
+                This function is only called if PDUMP is defined.
+@Return         None
+*/ /**************************************************************************/
 void PDumpOSReleaseExecution(void);
 
-/*!
- * @name	PDumpOSCreateLock
- * @brief	Create the global pdump lock
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSCreateLock
+@Description    Create the global pdump lock. This function is only called
+                if PDUMP is defined.
+@Return         None
+*/ /**************************************************************************/
 PVRSRV_ERROR PDumpOSCreateLock(void);
 
-/*!
- * @name	PDumpOSDestroyLock
- * @brief	Destroy the global pdump lock
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSDestroyLock
+@Description    Destroy the global pdump lock This function is only called
+                if PDUMP is defined.
+@Return         None
+*/ /**************************************************************************/
 void PDumpOSDestroyLock(void);
 
-/*!
- * @name	PDumpOSLock
- * @brief	Acquire the global pdump lock
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSLock
+@Description    Acquire the global pdump lock. This function is only called
+                if PDUMP is defined.
+@Return         None
+*/ /**************************************************************************/
 void PDumpOSLock(void);
 
-/*!
- * @name	PDumpOSUnlock
- * @brief	Release the global pdump lock
- */
+/**************************************************************************/ /*!
+@Function       PDumpOSUnlock
+@Description    Release the global pdump lock. This function is only called
+                if PDUMP is defined.
+@Return         None
+*/ /**************************************************************************/
 void PDumpOSUnlock(void);
 
 /*!
diff --git a/drivers/staging/imgtec/rogue/pdump_physmem.c b/drivers/staging/imgtec/rogue/pdump_physmem.c
index cc42ab0..3776965 100644
--- a/drivers/staging/imgtec/rogue/pdump_physmem.c
+++ b/drivers/staging/imgtec/rogue/pdump_physmem.c
@@ -43,6 +43,12 @@
 
 #if defined(PDUMP)
 
+#if defined(LINUX)
+#include <linux/ctype.h>
+#else
+#include <ctype.h>
+#endif
+
 #include "img_types.h"
 #include "pvr_debug.h"
 #include "pvrsrv_error.h"
@@ -58,17 +64,51 @@
 /* static IMG_UINT32 guiPDumpMMUContextAvailabilityMask = (1<<MAX_PDUMP_MMU_CONTEXTS)-1; */
 
 
-/* arbitrary buffer length here. */
-#define MAX_SYMBOLIC_ADDRESS_LENGTH 40
-
 struct _PDUMP_PHYSMEM_INFO_T_
 {
-    IMG_CHAR aszSymbolicAddress[MAX_SYMBOLIC_ADDRESS_LENGTH];
+    IMG_CHAR aszSymbolicAddress[PHYSMEM_PDUMP_MEMSPNAME_SYMB_ADDR_MAX_LENGTH];
     IMG_UINT64 ui64Size;
     IMG_UINT32 ui32Align;
     IMG_UINT32 ui32SerialNum;
 };
 
+static IMG_BOOL _IsAllowedSym(IMG_CHAR sym)
+{
+	/* Numbers, Characters or '_' are allowed */
+	if (isalnum(sym) || sym == '_')
+		return IMG_TRUE;
+	else
+		return IMG_FALSE;
+}
+
+static IMG_BOOL _IsLowerCaseSym(IMG_CHAR sym)
+{
+	if (sym >= 'a' && sym <= 'z')
+		return IMG_TRUE;
+	else
+		return IMG_FALSE;
+}
+
+void PDumpMakeStringValid(IMG_CHAR *pszString,
+                          IMG_UINT32 ui32StrLen)
+{
+	IMG_UINT32 i;
+	for (i = 0; i < ui32StrLen; i++)
+	{
+		if (_IsAllowedSym(pszString[i]))
+		{
+			if (_IsLowerCaseSym(pszString[i]))
+				pszString[i] = pszString[i]-32;
+			else
+				pszString[i] = pszString[i];
+		}
+		else
+		{
+			pszString[i] = '_';
+		}
+	}
+}
+
 /**************************************************************************
  * Function Name  : PDumpMalloc
  * Inputs         :
@@ -80,6 +120,8 @@
                             const IMG_CHAR *pszSymbolicAddress,
                             IMG_UINT64 ui64Size,
                             IMG_DEVMEM_ALIGN_T uiAlign,
+                            IMG_BOOL bInitialise,
+                            IMG_UINT32 ui32InitValue,
                             IMG_BOOL bForcePersistent,
                             IMG_HANDLE *phHandlePtr)
 {
@@ -97,17 +139,13 @@
 	{
 		ui32Flags |= PDUMP_FLAGS_PERSISTENT;
 	}
-	else
-	{
-		ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-	}
 
 	/*
 		construct the symbolic address
 	*/
 
     OSSNPrintf(psPDumpAllocationInfo->aszSymbolicAddress,
-               sizeof(psPDumpAllocationInfo->aszSymbolicAddress),
+               sizeof(psPDumpAllocationInfo->aszSymbolicAddress)+sizeof(pszDevSpace),
                ":%s:%s",
                pszDevSpace,
                pszSymbolicAddress);
@@ -116,10 +154,22 @@
 		Write to the MMU script stream indicating the memory allocation
 	*/
 	PDUMP_LOCK();
-	eError = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC %s 0x%llX 0x%llX\n",
-                            psPDumpAllocationInfo->aszSymbolicAddress,
-                            ui64Size,
-                            uiAlign);
+	if (bInitialise)
+	{
+		eError = PDumpOSBufprintf(hScript, ui32MaxLen, "CALLOC %s 0x%llX 0x%llX 0x%X\n",
+								psPDumpAllocationInfo->aszSymbolicAddress,
+								ui64Size,
+								uiAlign,
+								ui32InitValue);
+	}
+	else
+	{
+		eError = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC %s 0x%llX 0x%llX\n",
+								psPDumpAllocationInfo->aszSymbolicAddress,
+								ui64Size,
+								uiAlign);
+	}
+
 	if(eError != PVRSRV_OK)
 	{
 		OSFreeMem(psPDumpAllocationInfo);
@@ -157,8 +207,6 @@
 
     psPDumpAllocationInfo = (PDUMP_PHYSMEM_INFO_T *)hPDumpAllocationInfoHandle;
 
-	ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	/*
 		Write to the MMU script stream indicating the memory free
 	*/
@@ -189,8 +237,6 @@
 
 	PDUMP_GET_SCRIPT_STRING()
 
-	uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
                               ui32MaxLen,
@@ -223,8 +269,6 @@
 
 	PDUMP_GET_SCRIPT_STRING()
 
-	uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
                               ui32MaxLen,
@@ -259,8 +303,6 @@
 
 	PDUMP_GET_SCRIPT_STRING()
 
-	uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
                               ui32MaxLen,
@@ -297,8 +339,7 @@
 
 	PDUMP_GET_SCRIPT_STRING()
 
-    uiPDumpFlags = 0; //PDUMP_FLAGS_CONTINUOUS;
-	uiPDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+	uiPDumpFlags = 0;
 
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
@@ -339,9 +380,6 @@
 
 	PDUMP_GET_SCRIPT_STRING()
 
-
-	uiPDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
                               ui32MaxLen,
@@ -380,8 +418,6 @@
 
 	PDUMP_GET_SCRIPT_STRING()
 
-	uiPDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
 	PDUMP_LOCK();
 	eError = PDumpOSBufprintf(hScript,
                               ui32MaxLen,
@@ -448,40 +484,4 @@
 	return eError;
 }
 
-IMG_INTERNAL void
-PDumpPMRMallocPMR(const PMR *psPMR,
-                  IMG_DEVMEM_SIZE_T uiSize,
-                  IMG_DEVMEM_ALIGN_T uiBlockSize,
-                  IMG_BOOL bForcePersistent,
-                  IMG_HANDLE *phPDumpAllocInfoPtr)
-{
-    PVRSRV_ERROR eError;
-    IMG_HANDLE hPDumpAllocInfo;
-    IMG_CHAR aszMemspaceName[30];
-    IMG_CHAR aszSymbolicName[30];
-    IMG_DEVMEM_OFFSET_T uiOffset;
-    IMG_DEVMEM_OFFSET_T uiNextSymName;
-
-    uiOffset = 0;
-    eError = PMR_PDumpSymbolicAddr(psPMR,
-                                   uiOffset,
-                                   sizeof(aszMemspaceName),
-                                   &aszMemspaceName[0],
-                                   sizeof(aszSymbolicName),
-                                   &aszSymbolicName[0],
-                                   &uiOffset,
-				   &uiNextSymName);
-    PVR_ASSERT(eError == PVRSRV_OK);
-    PVR_ASSERT(uiOffset == 0);
-    PVR_ASSERT((uiOffset + uiSize) <= uiNextSymName);
-
-	PDumpMalloc(aszMemspaceName,
-				   aszSymbolicName,
-				   uiSize,
-				   uiBlockSize,
-				   bForcePersistent,
-				   &hPDumpAllocInfo);
-
-	*phPDumpAllocInfoPtr = hPDumpAllocInfo;
-}
 #endif /* PDUMP */
diff --git a/drivers/staging/imgtec/rogue/pdump_physmem.h b/drivers/staging/imgtec/rogue/pdump_physmem.h
index 20f16c8..6363a9c 100644
--- a/drivers/staging/imgtec/rogue/pdump_physmem.h
+++ b/drivers/staging/imgtec/rogue/pdump_physmem.h
@@ -48,6 +48,9 @@
 #include "pvrsrv_error.h"
 #include "pmr.h"
 
+#define PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH 40
+#define PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH 60
+#define PHYSMEM_PDUMP_MEMSPNAME_SYMB_ADDR_MAX_LENGTH (PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH + PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH)
 
 typedef struct _PDUMP_PHYSMEM_INFO_T_ PDUMP_PHYSMEM_INFO_T;
 
@@ -60,18 +63,17 @@
                   minimum contiguity - i.e. smallest allowable
                   page-size. */
                IMG_DEVMEM_ALIGN_T uiAlign,
+               IMG_BOOL bInitialise,
+               IMG_UINT32 ui32InitValue,
                IMG_BOOL bForcePersistent,
                IMG_HANDLE *phHandlePtr);
 
-IMG_INTERNAL void
-PDumpPMRMallocPMR(const PMR *psPMR,
-                  IMG_DEVMEM_SIZE_T uiSize,
-                  IMG_DEVMEM_ALIGN_T uiBlockSize,
-                  IMG_BOOL bForcePersistent,
-                  IMG_HANDLE *phPDumpAllocInfoPtr);
-
 extern
 PVRSRV_ERROR PDumpFree(IMG_HANDLE hPDumpAllocationInfoHandle);
+
+IMG_INTERNAL void
+PDumpMakeStringValid(IMG_CHAR *pszString,
+                     IMG_UINT32 ui32StrLen);
 #else	/* PDUMP */
 
 #ifdef INLINE_IS_PRAGMA
@@ -82,6 +84,8 @@
                const IMG_CHAR *pszSymbolicAddress,
                IMG_UINT64 ui64Size,
                IMG_DEVMEM_ALIGN_T uiAlign,
+               IMG_BOOL bInitialise,
+               IMG_UINT32 ui32InitValue,
                IMG_BOOL bForcePersistent,
                IMG_HANDLE *phHandlePtr)
 {
@@ -89,29 +93,14 @@
 	PVR_UNREFERENCED_PARAMETER(pszSymbolicAddress);
 	PVR_UNREFERENCED_PARAMETER(ui64Size);
 	PVR_UNREFERENCED_PARAMETER(uiAlign);
+	PVR_UNREFERENCED_PARAMETER(bInitialise);
+	PVR_UNREFERENCED_PARAMETER(ui32InitValue);
 	PVR_UNREFERENCED_PARAMETER(bForcePersistent);
 	PVR_UNREFERENCED_PARAMETER(phHandlePtr);
 	PVR_UNREFERENCED_PARAMETER(bForcePersistent);
 	return PVRSRV_OK;
 }
 
-static INLINE void
-PDumpPMRMallocPMR(const PMR *psPMR,
-                  IMG_DEVMEM_SIZE_T uiSize,
-                  IMG_DEVMEM_ALIGN_T uiBlockSize,
-                  IMG_BOOL bForcePersistent,
-                  IMG_HANDLE *phPDumpAllocInfoPtr)
-{
-	PVR_UNREFERENCED_PARAMETER(psPMR);
-	PVR_UNREFERENCED_PARAMETER(uiSize);
-	PVR_UNREFERENCED_PARAMETER(uiBlockSize);
-	PVR_UNREFERENCED_PARAMETER(bForcePersistent);
-	PVR_UNREFERENCED_PARAMETER(phPDumpAllocInfoPtr);
-}
-
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(PVRSRVSyncPrimPDumpPolKM)
-#endif
 static INLINE PVRSRV_ERROR
 PDumpFree(IMG_HANDLE hPDumpAllocationInfoHandle)
 {
@@ -121,15 +110,17 @@
 #endif	/* PDUMP */
 
 #define PMR_DEFAULT_PREFIX "PMR"
-#define PMR_SYMBOLICADDR_FMTSPEC "%s%llu"
+#define PMR_SYMBOLICADDR_FMTSPEC "%s%llu_%llu_%s"
+#define PMR_MEMSPACE_FMTSPEC "%s"
+#define PMR_MEMSPACE_CACHE_COHERENT_FMTSPEC "CC_%s"
 
 #if defined(PDUMP)
-#define PDUMP_PHYSMEM_MALLOC_OSPAGES(pszPDumpMemDevName, ui32SerialNum, ui32Size, ui32Align, phHandlePtr) \
-    PDumpMalloc(pszPDumpMemDevName, PMR_OSALLOCPAGES_PREFIX, ui32SerialNum, ui32Size, ui32Align, phHandlePtr)
+#define PDUMP_PHYSMEM_MALLOC_OSPAGES(pszPDumpMemDevName, ui32SerialNum, ui32Size, ui32Align, bInitialise, ui32InitValue, phHandlePtr) \
+    PDumpMalloc(pszPDumpMemDevName, PMR_OSALLOCPAGES_PREFIX, ui32SerialNum, ui32Size, ui32Align, bInitialise, ui32InitValue, phHandlePtr)
 #define PDUMP_PHYSMEM_FREE_OSPAGES(hHandle) \
     PDumpFree(hHandle)
 #else
-#define PDUMP_PHYSMEM_MALLOC_OSPAGES(pszPDumpMemDevName, ui32SerialNum, ui32Size, ui32Align, phHandlePtr) \
+#define PDUMP_PHYSMEM_MALLOC_OSPAGES(pszPDumpMemDevName, ui32SerialNum, ui32Size, ui32Align, bInitialise, ui32InitValue, phHandlePtr) \
     ((void)(*phHandlePtr=NULL))
 #define PDUMP_PHYSMEM_FREE_OSPAGES(hHandle) \
     ((void)(0))
diff --git a/drivers/staging/imgtec/rogue/pdumpdefs.h b/drivers/staging/imgtec/rogue/pdumpdefs.h
index a7ed2a4..9ab8e97 100644
--- a/drivers/staging/imgtec/rogue/pdumpdefs.h
+++ b/drivers/staging/imgtec/rogue/pdumpdefs.h
@@ -161,6 +161,9 @@
 #define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_BASE			(1 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
 #define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_ENHANCED		(2 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
 #define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V2				(3 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V3_SURFACE		(4 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V3_RESOURCE		(5 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+
 
 /*! PDump Poll Operator */
 typedef enum _PDUMP_POLL_OPERATOR
diff --git a/drivers/staging/imgtec/rogue/physheap.c b/drivers/staging/imgtec/rogue/physheap.c
index 69aaea1..aab4cfc 100644
--- a/drivers/staging/imgtec/rogue/physheap.c
+++ b/drivers/staging/imgtec/rogue/physheap.c
@@ -49,37 +49,33 @@
 #include "allocmem.h"
 #include "pvr_debug.h"
 #include "osfunc.h"
+#include "pvrsrv.h"
 
 struct _PHYS_HEAP_
 {
-	/*! ID of this physcial memory heap */
+	/*! ID of this physical memory heap */
 	IMG_UINT32					ui32PhysHeapID;
 	/*! The type of this heap */
 	PHYS_HEAP_TYPE			eType;
 
-	/*! Start address of the physcial memory heap (LMA only) */
-	IMG_CPU_PHYADDR				sStartAddr;
-	/*! Size of the physcial memory heap (LMA only) */
-	IMG_UINT64					uiSize;
-	/*! Heap card base (GPU view of sStartAddr, LMA only) */
-	IMG_UINT64					uiCardBase;
-
-
-	/*! PDump name of this physcial memory heap */
+	/*! PDump name of this physical memory heap */
 	IMG_CHAR					*pszPDumpMemspaceName;
 	/*! Private data for the translate routines */
 	IMG_HANDLE					hPrivData;
 	/*! Function callbacks */
 	PHYS_HEAP_FUNCTIONS			*psMemFuncs;
 
+	/*! Array of sub-regions of the heap */
+	PHYS_HEAP_REGION			*pasRegions;
+	IMG_UINT32					ui32NumOfRegions;
 
 	/*! Refcount */
 	IMG_UINT32					ui32RefCount;
-	/*! Pointer to next physcial heap */
+	/*! Pointer to next physical heap */
 	struct _PHYS_HEAP_		*psNext;
 };
 
-PHYS_HEAP *g_psPhysHeapList;
+static PHYS_HEAP *g_psPhysHeapList;
 
 #if defined(REFCOUNT_DEBUG)
 #define PHYSHEAP_REFCOUNT_PRINT(fmt, ...)	\
@@ -125,14 +121,14 @@
 
 	psNew->ui32PhysHeapID = psConfig->ui32PhysHeapID;
 	psNew->eType = psConfig->eType;
-	psNew->sStartAddr = psConfig->sStartAddr;
-	psNew->uiCardBase = psConfig->uiCardBase;
-	psNew->uiSize = psConfig->uiSize;
 	psNew->psMemFuncs = psConfig->psMemFuncs;
 	psNew->hPrivData = psConfig->hPrivData;
 	psNew->ui32RefCount = 0;
 	psNew->pszPDumpMemspaceName = psConfig->pszPDumpMemspaceName;
 
+	psNew->pasRegions = psConfig->pasRegions;
+	psNew->ui32NumOfRegions = psConfig->ui32NumOfRegions;
+
 	psNew->psNext = g_psPhysHeapList;
 	g_psPhysHeapList = psNew;
 
@@ -145,7 +141,12 @@
 {
 	PVR_DPF_ENTERED1(psPhysHeap);
 
-	PVR_ASSERT(psPhysHeap->ui32RefCount == 0);
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	if (PVRSRVGetPVRSRVData()->eServicesState == PVRSRV_SERVICES_STATE_OK)
+#endif
+	{
+		PVR_ASSERT(psPhysHeap->ui32RefCount == 0);
+	}
 
 	if (g_psPhysHeapList == psPhysHeap)
 	{
@@ -213,46 +214,59 @@
 	return psPhysHeap->eType;
 }
 
-PVRSRV_ERROR PhysHeapGetAddress(PHYS_HEAP *psPhysHeap,
+/*
+ * This function will set the psDevPAddr to whatever the system layer
+ * has set it for the referenced region.
+ * It will not fail if the psDevPAddr is invalid.
+ */
+PVRSRV_ERROR PhysHeapRegionGetDevPAddr(PHYS_HEAP *psPhysHeap,
+								IMG_UINT32 ui32RegionId,
+								IMG_DEV_PHYADDR *psDevPAddr)
+{
+	if (ui32RegionId < psPhysHeap->ui32NumOfRegions)
+	{
+		*psDevPAddr = psPhysHeap->pasRegions[ui32RegionId].sCardBase;
+		return PVRSRV_OK;
+	}
+	else
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+}
+
+/*
+ * This function will set the psCpuPAddr to whatever the system layer
+ * has set it for the referenced region.
+ * It will not fail if the psCpuPAddr is invalid.
+ */
+PVRSRV_ERROR PhysHeapRegionGetCpuPAddr(PHYS_HEAP *psPhysHeap,
+								IMG_UINT32 ui32RegionId,
 								IMG_CPU_PHYADDR *psCpuPAddr)
 {
-	if (psPhysHeap->eType == PHYS_HEAP_TYPE_LMA)
+	if (ui32RegionId < psPhysHeap->ui32NumOfRegions)
 	{
-		*psCpuPAddr = psPhysHeap->sStartAddr;
+		*psCpuPAddr = psPhysHeap->pasRegions[ui32RegionId].sStartAddr;
 		return PVRSRV_OK;
 	}
-
-	return PVRSRV_ERROR_INVALID_PARAMS;
+	else
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
 }
 
-PVRSRV_ERROR PhysHeapGetBase(PHYS_HEAP *psPhysHeap,
-							 IMG_UINT64 *puiBase)
+PVRSRV_ERROR PhysHeapRegionGetSize(PHYS_HEAP *psPhysHeap,
+								   IMG_UINT32 ui32RegionId,
+								   IMG_UINT64 *puiSize)
 {
-	if (psPhysHeap->eType == PHYS_HEAP_TYPE_LMA)
+	if (ui32RegionId < psPhysHeap->ui32NumOfRegions)
 	{
-		IMG_UINT64 uiTmp = 0;
-		if (psPhysHeap->uiCardBase == --uiTmp)
-		{
-			return PVRSRV_ERROR_INVALID_HEAPINFO;
-		}
-
-		*puiBase = psPhysHeap->uiCardBase;
+		*puiSize = psPhysHeap->pasRegions[ui32RegionId].uiSize;
 		return PVRSRV_OK;
 	}
-
-	return PVRSRV_ERROR_INVALID_PARAMS;
-}
-
-PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
-							   IMG_UINT64 *puiSize)
-{
-	if (psPhysHeap->eType == PHYS_HEAP_TYPE_LMA)
+	else
 	{
-		*puiSize = psPhysHeap->uiSize;
-		return PVRSRV_OK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
-
-	return PVRSRV_ERROR_INVALID_PARAMS;
 }
 
 void PhysHeapCpuPAddrToDevPAddr(PHYS_HEAP *psPhysHeap,
@@ -277,6 +291,18 @@
 												 psDevPAddr);
 }
 
+IMG_UINT32 PhysHeapGetRegionId(PHYS_HEAP *psPhysHeap,
+								PVRSRV_MEMALLOCFLAGS_T uiAllocFlags)
+{
+	if (psPhysHeap->psMemFuncs->pfnGetRegionId == NULL)
+	{
+		return 0;
+	}
+
+	return psPhysHeap->psMemFuncs->pfnGetRegionId(psPhysHeap->hPrivData,
+												 uiAllocFlags);
+}
+
 IMG_CHAR *PhysHeapPDumpMemspaceName(PHYS_HEAP *psPhysHeap)
 {
 	return psPhysHeap->pszPDumpMemspaceName;
@@ -295,3 +321,8 @@
 
 	return PVRSRV_OK;
 }
+
+IMG_UINT32 PhysHeapNumberOfRegions(PHYS_HEAP *psPhysHeap)
+{
+	return psPhysHeap->ui32NumOfRegions;
+}
diff --git a/drivers/staging/imgtec/rogue/physheap.h b/drivers/staging/imgtec/rogue/physheap.h
index 1ab8ebc..add748b 100644
--- a/drivers/staging/imgtec/rogue/physheap.h
+++ b/drivers/staging/imgtec/rogue/physheap.h
@@ -1,6 +1,6 @@
 /*************************************************************************/ /*!
 @File
-@Title          Physcial heap management header
+@Title          Physical heap management header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @Description    Defines the interface for the physical heap management
 @License        Dual MIT/GPLv2
@@ -43,6 +43,7 @@
 
 #include "img_types.h"
 #include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
 
 #ifndef _PHYSHEAP_H_
 #define _PHYSHEAP_H_
@@ -59,12 +60,17 @@
 								   IMG_CPU_PHYADDR *psCpuPAddr,
 								   IMG_DEV_PHYADDR *psDevPAddr);
 
+typedef IMG_UINT32 (*GetRegionId)(IMG_HANDLE hPrivData,
+								   PVRSRV_MEMALLOCFLAGS_T uiAllocationFlags);
+
 typedef struct _PHYS_HEAP_FUNCTIONS_
 {
 	/*! Translate CPU physical address to device physical address */
 	CpuPAddrToDevPAddr	pfnCpuPAddrToDevPAddr;
 	/*! Translate device physical address to CPU physical address */
 	DevPAddrToCpuPAddr	pfnDevPAddrToCpuPAddr;
+	/*! Return id of heap region to allocate from */
+	GetRegionId			pfnGetRegionId;
 } PHYS_HEAP_FUNCTIONS;
 
 typedef enum _PHYS_HEAP_TYPE_
@@ -72,21 +78,32 @@
 	PHYS_HEAP_TYPE_UNKNOWN = 0,
 	PHYS_HEAP_TYPE_UMA,
 	PHYS_HEAP_TYPE_LMA,
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	PHYS_HEAP_TYPE_DMA,
+#endif
 } PHYS_HEAP_TYPE;
 
+typedef struct _PHYS_HEAP_REGION_
+{
+	IMG_CPU_PHYADDR			sStartAddr;
+	IMG_DEV_PHYADDR			sCardBase;
+	IMG_UINT64				uiSize;
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	IMG_HANDLE				hPrivData;
+	IMG_BOOL				bDynAlloc;
+#endif
+} PHYS_HEAP_REGION;
+
 typedef struct _PHYS_HEAP_CONFIG_
 {
 	IMG_UINT32				ui32PhysHeapID;
 	PHYS_HEAP_TYPE			eType;
-	/*
-		Note:
-		sStartAddr, uiCardBase and uiSize are only required for LMA heaps
-	*/
-	IMG_CPU_PHYADDR			sStartAddr;
-	IMG_UINT64				uiCardBase;
-	IMG_UINT64				uiSize;
 	IMG_CHAR				*pszPDumpMemspaceName;
 	PHYS_HEAP_FUNCTIONS		*psMemFuncs;
+
+	PHYS_HEAP_REGION		*pasRegions;
+	IMG_UINT32				ui32NumOfRegions;
+
 	IMG_HANDLE				hPrivData;
 } PHYS_HEAP_CONFIG;
 
@@ -102,24 +119,39 @@
 
 PHYS_HEAP_TYPE PhysHeapGetType(PHYS_HEAP *psPhysHeap);
 
-PVRSRV_ERROR PhysHeapGetAddress(PHYS_HEAP *psPhysHeap,
+PVRSRV_ERROR PhysHeapRegionGetCpuPAddr(PHYS_HEAP *psPhysHeap,
+									   IMG_UINT32 ui32RegionId,
 								IMG_CPU_PHYADDR *psCpuPAddr);
 
-PVRSRV_ERROR PhysHeapGetBase(PHYS_HEAP *psPhysHeap,
-							IMG_UINT64 *puiBase);
 
-PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
+PVRSRV_ERROR PhysHeapRegionGetSize(PHYS_HEAP *psPhysHeap,
+							IMG_UINT32 ui32RegionId,
 						     IMG_UINT64 *puiSize);
 
+PVRSRV_ERROR PhysHeapRegionGetDevPAddr(PHYS_HEAP *psPhysHeap,
+									   IMG_UINT32 ui32RegionId,
+							 		   IMG_DEV_PHYADDR *psDevPAddr);
+
+PVRSRV_ERROR PhysHeapRegionGetSize(PHYS_HEAP *psPhysHeap,
+								   IMG_UINT32 ui32RegionId,
+						     	   IMG_UINT64 *puiSize);
+
+IMG_UINT32 PhysHeapNumberOfRegions(PHYS_HEAP *psPhysHeap);
+
 void PhysHeapCpuPAddrToDevPAddr(PHYS_HEAP *psPhysHeap,
 								IMG_UINT32 ui32NumOfAddr,
 								IMG_DEV_PHYADDR *psDevPAddr,
 								IMG_CPU_PHYADDR *psCpuPAddr);
+
 void PhysHeapDevPAddrToCpuPAddr(PHYS_HEAP *psPhysHeap,
 								IMG_UINT32 ui32NumOfAddr,
 								IMG_CPU_PHYADDR *psCpuPAddr,
 								IMG_DEV_PHYADDR *psDevPAddr);
 
+IMG_UINT32 PhysHeapGetRegionId(PHYS_HEAP *psPhysHeap,
+						PVRSRV_MEMALLOCFLAGS_T uiAllocFlags);
+
+
 IMG_CHAR *PhysHeapPDumpMemspaceName(PHYS_HEAP *psPhysHeap);
 
 PVRSRV_ERROR PhysHeapInit(void);
diff --git a/drivers/staging/imgtec/rogue/physmem.c b/drivers/staging/imgtec/rogue/physmem.c
index c12752e..2175166 100644
--- a/drivers/staging/imgtec/rogue/physmem.c
+++ b/drivers/staging/imgtec/rogue/physmem.c
@@ -49,7 +49,7 @@
 #include "osfunc.h"
 #include "pdump_physmem.h"
 #include "pdump_km.h"
-
+#include "rgx_heaps.h"
 
 #if defined(DEBUG)
 IMG_UINT32 gPMRAllocFail = 0;
@@ -96,6 +96,8 @@
 								ui32MemSize,
 								ui32PageSize,
 								IMG_FALSE,
+								0,
+								IMG_FALSE,
 								phHandlePtr);
 	if(PVRSRV_OK != eError)
 	{
@@ -120,10 +122,12 @@
 		}
 
 		/*Fill the memory with given content */
-		OSMemSet(pvCpuVAddr, u8Value, ui32MemSize);
+		/*NOTE: Wrong for the LMA + ARM64 combination, but this is unlikely */
+		OSCachedMemSet(pvCpuVAddr, u8Value, ui32MemSize);
 
 		/*Map the page to the CPU VA space */
-		eError = psDevNode->pfnDevPxClean(psMemHandle,
+		eError = psDevNode->pfnDevPxClean(psDevNode,
+		                                  psMemHandle,
 		                                  0,
 		                                  ui32MemSize);
 		if(PVRSRV_OK != eError)
@@ -166,8 +170,8 @@
 										PDUMP_FLAGS_CONTINUOUS);
 			if(PVRSRV_OK != eError)
 			{
-				PDUMP_ERROR(eError, "Failed to write LDB statment to script file");
-				PVR_DPF((PVR_DBG_ERROR, "Failed to write LDB statment to script file, error %d", eError));
+				PDUMP_ERROR(eError, "Failed to write LDB statement to script file");
+				PVR_DPF((PVR_DBG_ERROR, "Failed to write LDB statement to script file, error %d", eError));
 			}
 
 		}
@@ -224,68 +228,71 @@
                        IMG_UINT32 *pui32MappingTable,
                        IMG_UINT32 uiLog2PageSize,
                        PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                       IMG_UINT32 uiAnnotationLength,
+                       const IMG_CHAR *pszAnnotation,
                        PMR **ppsPMRPtr)
 {
 	PVRSRV_DEVICE_PHYS_HEAP ePhysHeapIdx;
-	PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE pfnCheckMemAllocSize = \
-										psDevNode->psDevConfig->pfnCheckMemAllocSize;
-
-#if defined(DEBUG)	
-	static IMG_UINT32 ui32AllocCount = 1;
-
-	if (ui32NumVirtChunks > 1)
-	{	/* We don't currently support sparse memory with non OS page sized heaps */
-		PVR_ASSERT(uiLog2PageSize == OSGetPageShift());
-	}
-#endif /* defined(DEBUG) */
-
+	PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE pfnCheckMemAllocSize =
+		psDevNode->psDevConfig->pfnCheckMemAllocSize;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(uiAnnotationLength);
+
+	/* We don't currently support sparse memory with non OS page sized heaps */
+	if (ui32NumVirtChunks > 1 && (uiLog2PageSize != OSGetPageShift()))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"Requested page size for sparse 2^%u is not OS page size.",
+				uiLog2PageSize));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Protect against ridiculous page sizes */
+	if (uiLog2PageSize > RGX_HEAP_2MB_PAGE_SHIFT)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Page size is too big: 2^%u.", uiLog2PageSize));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
 
 	/* Lookup the requested physheap index to use for this PMR allocation */
-	ePhysHeapIdx = (uiFlags & PVRSRV_MEMALLOCFLAG_FW_LOCAL)  ? PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL  :
-				   (uiFlags & PVRSRV_MEMALLOCFLAG_CPU_LOCAL) ? PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL :
-						   	   	   	   	   	   	   	   	   	   PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL;
-
-	/********************************
-	 * Sanity check the cache flags *
-	 ********************************/
-	/* Check if we can honour cached cache-coherent allocations */
-	if ((PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT) &&
-		(!PVRSRVSystemHasCacheSnooping()))
+	if (PVRSRV_CHECK_FW_LOCAL(uiFlags))
 	{
+		ePhysHeapIdx = PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL;
+	}
+	else if (PVRSRV_CHECK_CPU_LOCAL(uiFlags))
+	{
+		ePhysHeapIdx = PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL;
+	}
+	else
+	{
+		ePhysHeapIdx = PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL;
+	}
+
+	/* Fail if requesting coherency on one side but uncached on the other */
+	if ( (PVRSRV_CHECK_CPU_CACHE_COHERENT(uiFlags) &&
+	         (PVRSRV_CHECK_GPU_UNCACHED(uiFlags) || PVRSRV_CHECK_GPU_WRITE_COMBINE(uiFlags))) )
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Request for CPU coherency but specifying GPU uncached "
+				"Please use GPU cached flags for coherency."));
 		return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE;
 	}
 
-	/* Both or neither have to be cache-coherent */
-	if ((PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) ^
-		(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT))
+	if ( (PVRSRV_CHECK_GPU_CACHE_COHERENT(uiFlags) &&
+	         (PVRSRV_CHECK_CPU_UNCACHED(uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(uiFlags))) )
 	{
+		PVR_DPF((PVR_DBG_ERROR, "Request for GPU coherency but specifying CPU uncached "
+				"Please use CPU cached flags for coherency."));
 		return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE;
 	}
 
-	if ((PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT) ^
-		(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT))
-	{
-		return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE;
-	}
-
-
-	if (uiLog2PageSize > OSGetPageShift())
-	{
-		/* If we do support it, this check must become a page size validation */
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRV currently does not support "
-		        "page sizes that are larger than OS page size. Requested 2^%u, OS 2^%u ",
-		        uiLog2PageSize,
-		        (IMG_UINT32) OSGetPageShift()));
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
 	/* Apply memory budgeting policy */
 	if (pfnCheckMemAllocSize)
 	{
-		PVRSRV_ERROR eError = \
-						pfnCheckMemAllocSize(psDevNode, (IMG_UINT64)uiChunkSize*ui32NumPhysChunks);
+		IMG_UINT64 uiMemSize = (IMG_UINT64)uiChunkSize * ui32NumPhysChunks;
+		PVRSRV_ERROR eError;
+
+		eError = pfnCheckMemAllocSize(psDevNode->psDevConfig->hSysData, uiMemSize);
 		if (eError != PVRSRV_OK)
 		{
 			return eError;
@@ -295,6 +302,8 @@
 #if defined(DEBUG)
 	if (gPMRAllocFail > 0)
 	{
+		static IMG_UINT32 ui32AllocCount = 1;
+
 		if (ui32AllocCount < gPMRAllocFail)
 		{
 			ui32AllocCount++;
@@ -316,6 +325,7 @@
 											pui32MappingTable,
 											uiLog2PageSize,
 											uiFlags,
+											pszAnnotation,
 											ppsPMRPtr);
 }
 
@@ -329,6 +339,8 @@
 							IMG_UINT32 *pui32MappingTable,
 							IMG_UINT32 uiLog2PageSize,
 							PVRSRV_MEMALLOCFLAGS_T uiFlags,
+							IMG_UINT32 uiAnnotationLength,
+							const IMG_CHAR *pszAnnotation,
 							PMR **ppsPMRPtr)
 {
 
@@ -342,11 +354,13 @@
 									pui32MappingTable,
 									uiLog2PageSize,
 									uiFlags,
+									uiAnnotationLength,
+									pszAnnotation,
 									ppsPMRPtr);
 
 	if (eError == PVRSRV_OK)
 	{
-		eError = PMRLockSysPhysAddresses(*ppsPMRPtr, uiLog2PageSize);
+		eError = PMRLockSysPhysAddresses(*ppsPMRPtr);
 	}
 
 	return eError;
diff --git a/drivers/staging/imgtec/rogue/physmem.h b/drivers/staging/imgtec/rogue/physmem.h
index 74864f1..a7b698e 100644
--- a/drivers/staging/imgtec/rogue/physmem.h
+++ b/drivers/staging/imgtec/rogue/physmem.h
@@ -65,13 +65,13 @@
 @Input 				bInitPage				Flag to control initialisation
 @Input         		pszDevSpace             PDUMP memory space in which the
 											allocation is to be done
-@Input 				pszSymbolicAddress		Symboic name of the allocation
+@Input 				pszSymbolicAddress		Symbolic name of the allocation
 @Input 				phHandlePtr				PDUMP handle to the allocation
 @Output      	    psMemHandle             Handle to the allocated memory
 @Output    		    psDevPhysAddr           Device Physical address of allocated
 											page
 
-@Return         PVRSRV_OK if the alloction is successfull
+@Return         PVRSRV_OK if the allocation is successful
 */
 /*****************************************************************************/
 extern PVRSRV_ERROR DevPhysMemAlloc(PVRSRV_DEVICE_NODE *psDevNode,
@@ -149,6 +149,8 @@
                        IMG_UINT32 *pui32MappingTable,
                        IMG_UINT32 uiLog2PageSize,
                        PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                       IMG_UINT32 uiAnnotationLength,
+                       const IMG_CHAR *pszAnnotation,
                        PMR **ppsPMROut);
 
 
@@ -177,6 +179,8 @@
                              IMG_UINT32 *pui32MappingTable,
                              IMG_UINT32 uiLog2PageSize,
                              PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                             IMG_UINT32 uiAnnotationLength,
+                             const IMG_CHAR *pszAnnotation,
                              PMR **ppsPMRPtr);
 
 #endif /* _SRVSRV_PHYSMEM_H_ */
diff --git a/drivers/staging/imgtec/rogue/physmem_dmabuf.c b/drivers/staging/imgtec/rogue/physmem_dmabuf.c
index a8b2330..991a242 100644
--- a/drivers/staging/imgtec/rogue/physmem_dmabuf.c
+++ b/drivers/staging/imgtec/rogue/physmem_dmabuf.c
@@ -48,11 +48,12 @@
 #include "pvrsrv.h"
 #include "pmr.h"
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) || defined(SUPPORT_ION) || defined(KERNEL_HAS_DMABUF_VMAP_MMAP)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) || defined(SUPPORT_ION) || defined(KERNEL_HAS_DMABUF_VMAP_MMAP)
 
-#if defined(SUPPORT_DRM)
-#include "pvr_drm.h"
-#endif
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/dma-buf.h>
+#include <linux/scatterlist.h>
 
 #include "img_types.h"
 #include "pvr_debug.h"
@@ -61,29 +62,16 @@
 
 #include "allocmem.h"
 #include "osfunc.h"
-#include "pdump_physmem.h"
 #include "pmr_impl.h"
 #include "hash.h"
 #include "private_data.h"
 #include "module_common.h"
 
-#if defined(SUPPORT_DRM)
-#include <drm/drmP.h>
-#endif
-
 #if defined(PVR_RI_DEBUG)
 #include "ri_server.h"
 #endif
 
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/dma-buf.h>
-#include <linux/scatterlist.h>
-
-#if defined(CHROMIUMOS_WORKAROUNDS_KERNEL318)
-#define dma_buf_begin_cpu_access(A,B,C,D) dma_buf_begin_cpu_access(A,D)
-#define dma_buf_end_cpu_access(A,B,C,D)   dma_buf_end_cpu_access(A,D)
-#endif
+#include "kernel_compatibility.h"
 
 /*
  * dma_buf_ops
@@ -150,12 +138,12 @@
 	struct dma_buf_attachment *psAttachment;
 	PFN_DESTROY_DMABUF_PMR pfnDestroy;
 	IMG_BOOL bPoisonOnFree;
-	IMG_HANDLE hPDumpAllocInfo;
 
 	/* Modified by PMR lock/unlock */
 	struct sg_table *psSgTable;
 	IMG_DEV_PHYADDR *pasDevPhysAddr;
-	IMG_UINT32 ui32PageCount;
+	IMG_UINT32 ui32PhysPageCount;
+	IMG_UINT32 ui32VirtPageCount;
 } PMR_DMA_BUF_DATA;
 
 /* Start size of the g_psDmaBufHash hash table */
@@ -203,24 +191,27 @@
 static PVRSRV_ERROR PMRFinalizeDmaBuf(PMR_IMPL_PRIVDATA pvPriv)
 {
 	PMR_DMA_BUF_DATA *psPrivData = pvPriv;
-	struct dma_buf *psDmaBuf = psPrivData->psAttachment->dmabuf;
+	struct dma_buf_attachment *psAttachment = psPrivData->psAttachment;
+	struct dma_buf *psDmaBuf = psAttachment->dmabuf;
+	struct sg_table *psSgTable = psPrivData->psSgTable;
 	PVRSRV_ERROR eError;
 
-	if (psPrivData->hPDumpAllocInfo)
-	{
-		PDumpFree(psPrivData->hPDumpAllocInfo);
-		psPrivData->hPDumpAllocInfo = NULL;
-	}
+	psPrivData->ui32PhysPageCount = 0;
+
+	dma_buf_unmap_attachment(psAttachment, psSgTable, DMA_BIDIRECTIONAL);
+
 
 	if (psPrivData->bPoisonOnFree)
 	{
 		void *pvKernAddr;
 		int i, err;
 
-		err = dma_buf_begin_cpu_access(psDmaBuf, 0, psDmaBuf->size, DMA_FROM_DEVICE);
+		err = dma_buf_begin_cpu_access(psDmaBuf, DMA_FROM_DEVICE);
 		if (err)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to begin cpu access for free poisoning", __func__));
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to begin cpu access for free poisoning (err=%d)",
+					 __func__, err));
 			PVR_ASSERT(IMG_FALSE);
 			goto exit;
 		}
@@ -230,7 +221,9 @@
 			pvKernAddr = dma_buf_kmap(psDmaBuf, i);
 			if (IS_ERR_OR_NULL(pvKernAddr))
 			{
-				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to poison allocation before free", __func__));
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: Failed to poison allocation before free (err=%ld)",
+						 __func__, pvKernAddr ? PTR_ERR(pvKernAddr) : -ENOMEM));
 				PVR_ASSERT(IMG_FALSE);
 				goto exit_end_access;
 			}
@@ -241,7 +234,9 @@
 		}
 
 exit_end_access:
-		dma_buf_end_cpu_access(psDmaBuf, 0, psDmaBuf->size, DMA_TO_DEVICE);
+		do {
+			err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
+		} while (err == -EAGAIN || err == -EINTR);
 	}
 
 exit:
@@ -254,100 +249,26 @@
 		}
 	}
 
+	OSFreeMem(psPrivData->pasDevPhysAddr);
 	OSFreeMem(psPrivData);
 
 	return PVRSRV_OK;
 }
 
-static PVRSRV_ERROR PMRLockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
-					       IMG_UINT32 uiLog2DevPageSize)
+static PVRSRV_ERROR PMRLockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv)
 {
-	PMR_DMA_BUF_DATA *psPrivData = pvPriv;
-	struct dma_buf_attachment *psAttachment = psPrivData->psAttachment;
-	IMG_DEV_PHYADDR *pasDevPhysAddr = NULL;
-	IMG_UINT32 ui32PageCount = 0;
-	struct scatterlist *sg;
-	struct sg_table *table;
-	PVRSRV_ERROR eError;
-	IMG_UINT32 i;
-
-	table = dma_buf_map_attachment(psAttachment, DMA_BIDIRECTIONAL);
-	if (!table)
-	{
-		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto fail_map;
-	}
-
-	/*
-	 * We do a two pass process, 1st workout how many pages there
-	 * are, 2nd fill in the data.
-	 */
-	for_each_sg(table->sgl, sg, table->nents, i)
-	{
-		ui32PageCount += PAGE_ALIGN(pvr_sg_length(sg)) / PAGE_SIZE;
-	}
-
-	if (WARN_ON(!ui32PageCount))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lock dmabuf with no pages",
-				 __func__));
-		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto fail_page_count;
-	}
-
-	pasDevPhysAddr = OSAllocMem(sizeof(*pasDevPhysAddr) * ui32PageCount);
-	if (!pasDevPhysAddr)
-	{
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto fail_alloc;
-	}
-
-	ui32PageCount = 0;
-
-	for_each_sg(table->sgl, sg, table->nents, i)
-	{
-		IMG_UINT32 j;
-
-		for (j = 0; j < pvr_sg_length(sg); j += PAGE_SIZE)
-		{
-			/* Pass 2: Get the page data */
-			pasDevPhysAddr[ui32PageCount].uiAddr = sg_dma_address(sg) + j;
-			ui32PageCount++;
-		}
-	}
-
-	psPrivData->pasDevPhysAddr = pasDevPhysAddr;
-	psPrivData->ui32PageCount = ui32PageCount;
-	psPrivData->psSgTable = table;
-
+	PVR_UNREFERENCED_PARAMETER(pvPriv);
 	return PVRSRV_OK;
-
-fail_alloc:
-fail_page_count:
-	dma_buf_unmap_attachment(psAttachment, table, DMA_BIDIRECTIONAL);
-
-fail_map:
-	PVR_ASSERT(eError!= PVRSRV_OK);
-	return eError;
 }
 
 static PVRSRV_ERROR PMRUnlockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv)
 {
-	PMR_DMA_BUF_DATA *psPrivData = pvPriv;
-	struct dma_buf_attachment *psAttachment = psPrivData->psAttachment;
-	struct sg_table *psSgTable = psPrivData->psSgTable;
-
-	OSFreeMem(psPrivData->pasDevPhysAddr);
-
-	psPrivData->pasDevPhysAddr = NULL;
-	psPrivData->ui32PageCount = 0;
-
-	dma_buf_unmap_attachment(psAttachment, psSgTable, DMA_BIDIRECTIONAL);
-
+	PVR_UNREFERENCED_PARAMETER(pvPriv);
 	return PVRSRV_OK;
 }
 
 static PVRSRV_ERROR PMRDevPhysAddrDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
+					 IMG_UINT32 ui32Log2PageSize,
 					 IMG_UINT32 ui32NumOfPages,
 					 IMG_DEVMEM_OFFSET_T *puiOffset,
 					 IMG_BOOL *pbValid,
@@ -357,6 +278,11 @@
 	IMG_UINT32 ui32PageIndex;
 	IMG_UINT32 idx;
 
+	if (ui32Log2PageSize != PAGE_SHIFT)
+	{
+		return PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+	}
+
 	for (idx=0; idx < ui32NumOfPages; idx++)
 	{
 		if (pbValid[idx])
@@ -366,13 +292,12 @@
 			ui32PageIndex = puiOffset[idx] >> PAGE_SHIFT;
 			ui32InPageOffset = puiOffset[idx] - ((IMG_DEVMEM_OFFSET_T)ui32PageIndex << PAGE_SHIFT);
 
-			PVR_ASSERT(ui32PageIndex < psPrivData->ui32PageCount);
-			PVR_ASSERT(ui32InPageOffset < PAGE_SIZE);
 
+			PVR_ASSERT(ui32PageIndex < psPrivData->ui32VirtPageCount);
+			PVR_ASSERT(ui32InPageOffset < PAGE_SIZE);
 			psDevPAddr[idx].uiAddr = psPrivData->pasDevPhysAddr[ui32PageIndex].uiAddr + ui32InPageOffset;
 		}
 	}
-
 	return PVRSRV_OK;
 }
 
@@ -390,7 +315,15 @@
 	PVRSRV_ERROR eError;
 	int err;
 
-	err = dma_buf_begin_cpu_access(psDmaBuf, 0, psDmaBuf->size, DMA_BIDIRECTIONAL);
+	if (psPrivData->ui32PhysPageCount != psPrivData->ui32VirtPageCount)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Kernel mappings for sparse DMABufs "
+				"are not allowed!", __func__));
+		eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
+		goto fail;
+	}
+
+	err = dma_buf_begin_cpu_access(psDmaBuf, DMA_BIDIRECTIONAL);
 	if (err)
 	{
 		eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
@@ -410,7 +343,9 @@
 	return PVRSRV_OK;
 
 fail_kmap:
-	dma_buf_end_cpu_access(psDmaBuf, 0, psDmaBuf->size, DMA_BIDIRECTIONAL);
+	do {
+		err = dma_buf_end_cpu_access(psDmaBuf, DMA_BIDIRECTIONAL);
+	} while (err == -EAGAIN || err == -EINTR);
 
 fail:
 	PVR_ASSERT(eError != PVRSRV_OK);
@@ -423,22 +358,31 @@
 	PMR_DMA_BUF_DATA *psPrivData = pvPriv;
 	struct dma_buf *psDmaBuf = psPrivData->psAttachment->dmabuf;
 	void *pvKernAddr = hHandle;
+	int err;
 
 	dma_buf_vunmap(psDmaBuf, pvKernAddr);
 
-	dma_buf_end_cpu_access(psDmaBuf, 0, psDmaBuf->size, DMA_BIDIRECTIONAL);
+	do {
+		err = dma_buf_end_cpu_access(psDmaBuf, DMA_BIDIRECTIONAL);
+	} while (err == -EAGAIN || err == -EINTR);
 }
 
 static PVRSRV_ERROR PMRMMapDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
-				  const PMR *psPMR,
-				  PMR_MMAP_DATA pOSMMapData)
+                                  PMR *psPMR,
+                                  PMR_MMAP_DATA pOSMMapData)
 {
 	PMR_DMA_BUF_DATA *psPrivData = pvPriv;
 	struct dma_buf *psDmaBuf = psPrivData->psAttachment->dmabuf;
 	struct vm_area_struct *psVma = pOSMMapData;
 	int err;
 
-	PVR_UNREFERENCED_PARAMETER(psPMR);
+	if (psPrivData->ui32PhysPageCount != psPrivData->ui32VirtPageCount)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Not possible to MMAP sparse DMABufs",
+				__func__));
+		return PVRSRV_ERROR_NOT_IMPLEMENTED;
+	}
 
 	err = dma_buf_mmap(psDmaBuf, psVma, 0);
 	if (err)
@@ -465,80 +409,78 @@
  *****************************************************************************/
 
 PVRSRV_ERROR
-PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap,
-				struct dma_buf_attachment *psAttachment,
-				PFN_DESTROY_DMABUF_PMR pfnDestroy,
-				PVRSRV_MEMALLOCFLAGS_T uiFlags,
-				PMR **ppsPMRPtr)
+PhysmemCreateNewDmaBufBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+                                PHYS_HEAP *psHeap,
+                                struct dma_buf_attachment *psAttachment,
+                                PFN_DESTROY_DMABUF_PMR pfnDestroy,
+                                PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                IMG_DEVMEM_SIZE_T uiChunkSize,
+                                IMG_UINT32 ui32NumPhysChunks,
+                                IMG_UINT32 ui32NumVirtChunks,
+                                IMG_UINT32 *pui32MappingTable,
+                                PMR **ppsPMRPtr)
 {
 	struct dma_buf *psDmaBuf = psAttachment->dmabuf;
 	PMR_DMA_BUF_DATA *psPrivData;
-	IMG_BOOL bMappingTable = IMG_TRUE;
 	PMR_FLAGS_T uiPMRFlags;
 	IMG_BOOL bZeroOnAlloc;
 	IMG_BOOL bPoisonOnAlloc;
 	IMG_BOOL bPoisonOnFree;
 	PVRSRV_ERROR eError;
+	IMG_UINT32 i, j;
+	IMG_UINT32 uiPagesPerChunk = uiChunkSize >> PAGE_SHIFT;
+	IMG_UINT32 ui32PageCount = 0;
+	struct scatterlist *sg;
+	struct sg_table *table;
+	IMG_UINT32 uiSglOffset;
 
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
-	{
-		bZeroOnAlloc = IMG_TRUE;
-	}
-	else
-	{
-		bZeroOnAlloc = IMG_FALSE;
-	}
-
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC)
-	{
-		bPoisonOnAlloc = IMG_TRUE;
-	}
-	else
-	{
-		bPoisonOnAlloc = IMG_FALSE;
-	}
-
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
-	{
-		bPoisonOnFree = IMG_TRUE;
-	}
-	else
-	{
-		bPoisonOnFree = IMG_FALSE;
-	}
+	bZeroOnAlloc = PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags);
+	bPoisonOnAlloc = PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags);
+	bPoisonOnFree = PVRSRV_CHECK_POISON_ON_FREE(uiFlags);
 
 	if (bZeroOnAlloc && bPoisonOnFree)
 	{
 		/* Zero on Alloc and Poison on Alloc are mutually exclusive */
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto fail_params;
+		goto errReturn;
 	}
 
 	psPrivData = OSAllocZMem(sizeof(*psPrivData));
 	if (psPrivData == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto fail_priv_alloc;
+		goto errReturn;
 	}
 
 	psPrivData->psPhysHeap = psHeap;
 	psPrivData->psAttachment = psAttachment;
 	psPrivData->pfnDestroy = pfnDestroy;
 	psPrivData->bPoisonOnFree = bPoisonOnFree;
+	psPrivData->ui32VirtPageCount =
+			(ui32NumVirtChunks * uiChunkSize) >> PAGE_SHIFT;
+
+	psPrivData->pasDevPhysAddr =
+			OSAllocZMem(sizeof(*(psPrivData->pasDevPhysAddr)) *
+			            psPrivData->ui32VirtPageCount);
+	if (!psPrivData->pasDevPhysAddr)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Failed to allocate buffer for physical addresses (oom)",
+				 __func__));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto errFreePrivData;
+	}
 
 	if (bZeroOnAlloc || bPoisonOnAlloc)
 	{
 		void *pvKernAddr;
 		int i, err;
 
-		err = dma_buf_begin_cpu_access(psDmaBuf,
-					       0,
-					       psDmaBuf->size,
-					       DMA_FROM_DEVICE);
+		err = dma_buf_begin_cpu_access(psDmaBuf, DMA_FROM_DEVICE);
 		if (err)
 		{
 			eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
-			goto fail_begin;
+			goto errFreePhysAddr;
 		}
 
 		for (i = 0; i < psDmaBuf->size / PAGE_SIZE; i++)
@@ -547,17 +489,16 @@
 			if (IS_ERR_OR_NULL(pvKernAddr))
 			{
 				PVR_DPF((PVR_DBG_ERROR,
-					 "%s: Failed to map page for %s",
-					 __func__,
-					 bZeroOnAlloc ? "zeroing" : "poisoning"));
+						 "%s: Failed to map page for %s (err=%ld)",
+						 __func__, bZeroOnAlloc ? "zeroing" : "poisoning",
+						 pvKernAddr ? PTR_ERR(pvKernAddr) : -ENOMEM));
 				eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
 
-				dma_buf_end_cpu_access(psDmaBuf,
-						       0,
-						       psDmaBuf->size,
-						       DMA_TO_DEVICE);
+				do {
+					err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
+				} while (err == -EAGAIN || err == -EINTR);
 
-				goto fail_kmap;
+				goto errFreePhysAddr;
 			}
 
 			if (bZeroOnAlloc)
@@ -572,10 +513,79 @@
 			dma_buf_kunmap(psDmaBuf, i, pvKernAddr);
 		}
 
-		dma_buf_end_cpu_access(psDmaBuf,
-				       0,
-				       psDmaBuf->size,
-				       DMA_TO_DEVICE);
+		do {
+			err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
+		} while (err == -EAGAIN || err == -EINTR);
+	}
+
+	table = dma_buf_map_attachment(psAttachment, DMA_BIDIRECTIONAL);
+	if (IS_ERR_OR_NULL(table))
+	{
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto errFreePhysAddr;
+	}
+
+	/*
+	 * We do a two pass process: first work out how many pages there
+	 * are and second, fill in the data.
+	 */
+	for_each_sg(table->sgl, sg, table->nents, i)
+	{
+		ui32PageCount += PAGE_ALIGN(pvr_sg_length(sg)) / PAGE_SIZE;
+	}
+
+	if (WARN_ON(!ui32PageCount))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Number of phys. pages must not be zero",
+				 __func__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto errUnmap;
+	}
+
+	if  (WARN_ON(ui32PageCount != ui32NumPhysChunks * uiPagesPerChunk))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Requested physical chunks and actual "
+				"number of physical dma buf pages don't match",
+				 __func__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto errUnmap;
+	}
+
+	psPrivData->ui32PhysPageCount = ui32PageCount;
+	psPrivData->psSgTable = table;
+	ui32PageCount = 0;
+	sg = table->sgl;
+	uiSglOffset = 0;
+
+
+	/* Fill physical address array */
+	for (i = 0; i < ui32NumPhysChunks; i++)
+	{
+		for (j = 0; j < uiPagesPerChunk; j++)
+		{
+			IMG_UINT32 uiIdx = pui32MappingTable[i] * uiPagesPerChunk + j;
+
+			psPrivData->pasDevPhysAddr[uiIdx].uiAddr =
+					sg_dma_address(sg) + uiSglOffset;
+
+			/* Get the next offset for the current sgl or the next sgl */
+			uiSglOffset += PAGE_SIZE;
+			if (uiSglOffset >= pvr_sg_length(sg))
+			{
+				sg = sg_next(sg);
+				uiSglOffset = 0;
+
+				/* Check that we haven't looped */
+				if (WARN_ON(sg == table->sgl))
+				{
+					PVR_DPF((PVR_DBG_ERROR, "%s: Failed to fill phys. address "
+							"array ",
+							 __func__));
+					eError = PVRSRV_ERROR_INVALID_PARAMS;
+					goto errUnmap;
+				}
+			}
+		}
 	}
 
 	uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
@@ -586,48 +596,37 @@
 	 */
 	PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
 
-	eError = PMRCreatePMR(psHeap,
-			      psDmaBuf->size,
-			      psDmaBuf->size,
-			      1,
-			      1,
-			      &bMappingTable,
+	eError = PMRCreatePMR(psDevNode,
+			      psHeap,
+			      ui32NumVirtChunks * uiChunkSize,
+			      uiChunkSize,
+			      ui32NumPhysChunks,
+			      ui32NumVirtChunks,
+			      pui32MappingTable,
 			      PAGE_SHIFT,
 			      uiPMRFlags,
-			      "PMRDMABUF",
+			      "IMPORTED_DMABUF",
 			      &_sPMRDmaBufFuncTab,
 			      psPrivData,
+			      PMR_TYPE_DMABUF,
 			      ppsPMRPtr,
-			      &psPrivData->hPDumpAllocInfo,
 			      IMG_FALSE);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create PMR", __func__));
-		goto fail_create_pmr;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create PMR (%s)",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
+		goto errFreePhysAddr;
 	}
 
-#if defined(PVR_RI_DEBUG)
-	eError = RIWritePMREntryKM(*ppsPMRPtr,
-				   sizeof("DMABUF"),
-				   "DMABUF",
-				   psDmaBuf->size);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_WARNING,
-			 "%s: Failed to write PMR entry (%s)",
-			 __func__, PVRSRVGetErrorStringKM(eError)));
-	}
-#endif
-
 	return PVRSRV_OK;
 
-fail_create_pmr:
-fail_kmap:
-fail_begin:
+errUnmap:
+	dma_buf_unmap_attachment(psAttachment, table, DMA_BIDIRECTIONAL);
+errFreePhysAddr:
+	OSFreeMem(psPrivData->pasDevPhysAddr);
+errFreePrivData:
 	OSFreeMem(psPrivData);
-
-fail_priv_alloc:
-fail_params:
+errReturn:
 	PVR_ASSERT(eError != PVRSRV_OK);
 	return eError;
 }
@@ -708,10 +707,8 @@
 
 	if (IS_ERR_OR_NULL(psDmaBuf))
 	{
-		PVR_DPF((PVR_DBG_ERROR,
-		         "%s: dma_buf_export failed (err=%ld)",
-		         __func__,
-		         PTR_ERR(psDmaBuf)));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to export buffer (err=%ld)",
+		         __func__, psDmaBuf ? PTR_ERR(psDmaBuf) : -ENOMEM));
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto fail_pmr_ref;
 	}
@@ -719,10 +716,8 @@
 	iFd = dma_buf_fd(psDmaBuf, O_RDWR);
 	if (iFd < 0)
 	{
-		PVR_DPF((PVR_DBG_ERROR,
-		         "%s: dma_buf_fd failed (err=%d)",
-		         __func__,
-		         iFd));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get dma-buf fd (err=%d)",
+		         __func__, iFd));
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto fail_dma_buf;
 	}
@@ -742,51 +737,99 @@
 
 PVRSRV_ERROR
 PhysmemImportDmaBuf(CONNECTION_DATA *psConnection,
-		    PVRSRV_DEVICE_NODE *psDevNode,
-		    IMG_INT fd,
-		    PVRSRV_MEMALLOCFLAGS_T uiFlags,
-		    PMR **ppsPMRPtr,
-		    IMG_DEVMEM_SIZE_T *puiSize,
-		    IMG_DEVMEM_ALIGN_T *puiAlign)
+                    PVRSRV_DEVICE_NODE *psDevNode,
+                    IMG_INT fd,
+                    PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                    PMR **ppsPMRPtr,
+                    IMG_DEVMEM_SIZE_T *puiSize,
+                    IMG_DEVMEM_ALIGN_T *puiAlign)
 {
-#if defined(SUPPORT_DRM)
-	struct file *psFile;
-	struct drm_file *psFilePriv;
-#endif
-	struct device *psDev;
+	IMG_DEVMEM_SIZE_T uiSize;
+	IMG_UINT32 ui32MappingTable = 0;
+	struct dma_buf *psDmaBuf;
+
+	/* Get the buffer handle */
+	psDmaBuf = dma_buf_get(fd);
+	if (IS_ERR_OR_NULL(psDmaBuf))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get dma-buf from fd (err=%ld)",
+				 __func__, psDmaBuf ? PTR_ERR(psDmaBuf) : -ENOMEM));
+		return PVRSRV_ERROR_BAD_MAPPING;
+
+	}
+
+	uiSize = psDmaBuf->size;
+
+	dma_buf_put(psDmaBuf);
+
+	return PhysmemImportSparseDmaBuf(psConnection,
+	                                 psDevNode,
+	                                 fd,
+	                                 uiFlags,
+	                                 uiSize,
+	                                 1,
+	                                 1,
+	                                 &ui32MappingTable,
+	                                 ppsPMRPtr,
+	                                 puiSize,
+	                                 puiAlign);
+
+
+}
+
+PVRSRV_ERROR
+PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_INT fd,
+                          PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                          IMG_DEVMEM_SIZE_T uiChunkSize,
+                          IMG_UINT32 ui32NumPhysChunks,
+                          IMG_UINT32 ui32NumVirtChunks,
+                          IMG_UINT32 *pui32MappingTable,
+                          PMR **ppsPMRPtr,
+                          IMG_DEVMEM_SIZE_T *puiSize,
+                          IMG_DEVMEM_ALIGN_T *puiAlign)
+{
 	PMR *psPMR = NULL;
 	struct dma_buf_attachment *psAttachment;
 	struct dma_buf *psDmaBuf;
 	PHYS_HEAP *psHeap;
 	PVRSRV_ERROR eError;
 
-	if (!psConnection)
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	if (!psDevNode)
 	{
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto fail_params;
+		goto errReturn;
 	}
 
-#if defined(SUPPORT_DRM)
-	psFile = LinuxFileFromConnection(psConnection);
-	psFilePriv = psFile->private_data;
-	psDev = psFilePriv->minor->dev->dev;
-#else
-	psDev = &gpsPVRLDMDev->dev;
-#endif
-
 	/* Get the buffer handle */
 	psDmaBuf = dma_buf_get(fd);
 	if (IS_ERR_OR_NULL(psDmaBuf))
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_get failed", __func__));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get dma-buf from fd (err=%ld)",
+				 __func__, psDmaBuf ? PTR_ERR(psDmaBuf) : -ENOMEM));
 		eError = PVRSRV_ERROR_BAD_MAPPING;
-		goto fail_dma_buf_get;
+		goto errReturn;
 	}
 
 	if (psDmaBuf->ops == &sPVRDmaBufOps)
 	{
+		PVRSRV_DEVICE_NODE *psPMRDevNode;
+
 		/* We exported this dma_buf, so we can just get its PMR */
 		psPMR = (PMR *) psDmaBuf->priv;
+
+		/* However, we can't import it if it belongs to a different device */
+		psPMRDevNode = PMR_DeviceNode(psPMR);
+		if (psPMRDevNode != psDevNode)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: PMR invalid for this device\n",
+					 __func__));
+			eError = PVRSRV_ERROR_PMR_NOT_PERMITTED;
+			goto errDMAPut;
+		}
 	}
 	else if (g_psDmaBufHash)
 	{
@@ -800,7 +843,7 @@
 		PMRRefPMR(psPMR);
 
 		*ppsPMRPtr = psPMR;
-		*puiSize = psDmaBuf->size;
+		PMR_LogicalSize(psPMR, puiSize);
 		*puiAlign = PAGE_SIZE;
 
 		dma_buf_put(psDmaBuf);
@@ -808,17 +851,74 @@
 		return PVRSRV_OK;
 	}
 
-	psAttachment = dma_buf_attach(psDmaBuf, psDev);
+	/* Do we want this to be a sparse PMR? */
+	if (ui32NumVirtChunks > 1)
+	{
+		IMG_UINT32 i;
+
+		/* Parameter validation */
+		if (psDmaBuf->size != (uiChunkSize * ui32NumPhysChunks) ||
+		    uiChunkSize != PAGE_SIZE ||
+		    ui32NumPhysChunks > ui32NumVirtChunks)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"%s: Requesting sparse buffer: "
+					"uiChunkSize ("IMG_DEVMEM_SIZE_FMTSPEC") must be equal to "
+					"OS page size (%lu). uiChunkSize * ui32NumPhysChunks "
+					"("IMG_DEVMEM_SIZE_FMTSPEC") must"
+					" be equal to the buffer size ("IMG_SIZE_FMTSPEC"). "
+					"ui32NumPhysChunks (%u) must be lesser or equal to "
+					"ui32NumVirtChunks (%u)",
+					 __func__,
+					uiChunkSize,
+					PAGE_SIZE,
+					uiChunkSize * ui32NumPhysChunks,
+					psDmaBuf->size,
+					ui32NumPhysChunks,
+					ui32NumVirtChunks));
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto errDMAPut;
+		}
+
+		/* Parameter validation - Mapping table entries*/
+		for (i = 0; i < ui32NumPhysChunks; i++)
+		{
+			if (pui32MappingTable[i] > ui32NumVirtChunks)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						"%s: Requesting sparse buffer: "
+						"Entry in mapping table (%u) is out of allocation "
+						"bounds (%u)",
+						 __func__,
+						 (IMG_UINT32) pui32MappingTable[i],
+						 (IMG_UINT32) ui32NumVirtChunks));
+				eError = PVRSRV_ERROR_INVALID_PARAMS;
+				goto errDMAPut;
+			}
+		}
+	}
+	else
+	{
+		/* Make sure parameters are valid for non-sparse allocations as well */
+		uiChunkSize = psDmaBuf->size;
+		ui32NumPhysChunks = 1;
+		ui32NumVirtChunks = 1;
+		pui32MappingTable[0] = 0;
+	}
+
+
+	psAttachment = dma_buf_attach(psDmaBuf, psDevNode->psDevConfig->pvOSDevice);
 	if (IS_ERR_OR_NULL(psAttachment))
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_get failed", __func__));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to attach to dma-buf (err=%ld)",
+				 __func__, psAttachment? PTR_ERR(psAttachment) : -ENOMEM));
 		eError = PVRSRV_ERROR_BAD_MAPPING;
-		goto fail_dma_buf_attach;
+		goto errDMAPut;
 	}
 
 	/*
 	 * Get the physical heap for this PMR
-	 *	
+	 *
 	 * Note:
 	 * While we have no way to determine the type of the buffer
 	 * we just assume that all dmabufs are from the same
@@ -827,18 +927,24 @@
 	eError = PhysHeapAcquire(DMABUF_IMPORT_PHYSHEAP_ID, &psHeap);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed PhysHeapAcquire", __func__));
-		goto fail_physheap;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire physical heap (%s)",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
+		goto errDMADetach;
 	}
 
-	eError = PhysmemCreateNewDmaBufBackedPMR(psHeap,
-						 psAttachment,
-						 PhysmemDestroyDmaBuf,
-						 uiFlags,
-						 &psPMR);
+	eError = PhysmemCreateNewDmaBufBackedPMR(psDevNode,
+	                                         psHeap,
+	                                         psAttachment,
+	                                         PhysmemDestroyDmaBuf,
+	                                         uiFlags,
+	                                         uiChunkSize,
+	                                         ui32NumPhysChunks,
+	                                         ui32NumVirtChunks,
+	                                         pui32MappingTable,
+	                                         &psPMR);
 	if (eError != PVRSRV_OK)
 	{
-		goto fail_create_new_pmr;
+		goto errHeapRelease;
 	}
 
 	if (!g_psDmaBufHash)
@@ -852,7 +958,7 @@
 		if (!g_psDmaBufHash)
 		{
 			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-			goto fail_hash_create;
+			goto errUnrefPMR;
 		}
 	}
 
@@ -861,25 +967,24 @@
 	g_ui32HashRefCount++;
 
 	*ppsPMRPtr = psPMR;
-	*puiSize = psDmaBuf->size;
+	*puiSize = ui32NumVirtChunks * uiChunkSize;
 	*puiAlign = PAGE_SIZE;
 
 	return PVRSRV_OK;
 
-fail_hash_create:
+errUnrefPMR:
 	PMRUnrefPMR(psPMR);
 
-fail_create_new_pmr:
+errHeapRelease:
 	PhysHeapRelease(psHeap);
 
-fail_physheap:
+errDMADetach:
 	dma_buf_detach(psDmaBuf, psAttachment);
 
-fail_dma_buf_attach:
+errDMAPut:
 	dma_buf_put(psDmaBuf);
 
-fail_dma_buf_get:
-fail_params:
+errReturn:
 	PVR_ASSERT(eError != PVRSRV_OK);
 	return eError;
 }
@@ -887,16 +992,26 @@
 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) || defined(SUPPORT_ION) */
 
 PVRSRV_ERROR
-PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap,
+PhysmemCreateNewDmaBufBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+                                PHYS_HEAP *psHeap,
                                 struct dma_buf_attachment *psAttachment,
                                 PFN_DESTROY_DMABUF_PMR pfnDestroy,
                                 PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                IMG_DEVMEM_SIZE_T uiChunkSize,
+                                IMG_UINT32 ui32NumPhysChunks,
+                                IMG_UINT32 ui32NumVirtChunks,
+                                IMG_UINT32 *pui32MappingTable,
                                 PMR **ppsPMRPtr)
 {
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(psHeap);
 	PVR_UNREFERENCED_PARAMETER(psAttachment);
 	PVR_UNREFERENCED_PARAMETER(pfnDestroy);
 	PVR_UNREFERENCED_PARAMETER(uiFlags);
+	PVR_UNREFERENCED_PARAMETER(uiChunkSize);
+	PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+	PVR_UNREFERENCED_PARAMETER(ui32NumVirtChunks);
+	PVR_UNREFERENCED_PARAMETER(pui32MappingTable);
 	PVR_UNREFERENCED_PARAMETER(ppsPMRPtr);
 
 	return PVRSRV_ERROR_NOT_SUPPORTED;
@@ -944,4 +1059,31 @@
 	return PVRSRV_ERROR_NOT_SUPPORTED;
 }
 
+PVRSRV_ERROR
+PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_INT fd,
+                          PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                          IMG_DEVMEM_SIZE_T uiChunkSize,
+                          IMG_UINT32 ui32NumPhysChunks,
+                          IMG_UINT32 ui32NumVirtChunks,
+                          IMG_UINT32 *pui32MappingTable,
+                          PMR **ppsPMRPtr,
+                          IMG_DEVMEM_SIZE_T *puiSize,
+                          IMG_DEVMEM_ALIGN_T *puiAlign)
+{
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
+	PVR_UNREFERENCED_PARAMETER(fd);
+	PVR_UNREFERENCED_PARAMETER(uiFlags);
+	PVR_UNREFERENCED_PARAMETER(ppsPMRPtr);
+	PVR_UNREFERENCED_PARAMETER(puiSize);
+	PVR_UNREFERENCED_PARAMETER(puiAlign);
+	PVR_UNREFERENCED_PARAMETER(uiChunkSize);
+	PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+	PVR_UNREFERENCED_PARAMETER(ui32NumVirtChunks);
+	PVR_UNREFERENCED_PARAMETER(pui32MappingTable);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) || defined(SUPPORT_ION) || defined(KERNEL_HAS_DMABUF_VMAP_MMAP) */
diff --git a/drivers/staging/imgtec/rogue/physmem_dmabuf.h b/drivers/staging/imgtec/rogue/physmem_dmabuf.h
index ab1b868..c3be373 100644
--- a/drivers/staging/imgtec/rogue/physmem_dmabuf.h
+++ b/drivers/staging/imgtec/rogue/physmem_dmabuf.h
@@ -47,6 +47,11 @@
 
 #include <linux/dma-buf.h>
 
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
 #include "pvrsrv_memallocflags.h"
@@ -58,10 +63,15 @@
                                                struct dma_buf_attachment *psAttachment);
 
 PVRSRV_ERROR
-PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap,
+PhysmemCreateNewDmaBufBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+                                PHYS_HEAP *psHeap,
                                 struct dma_buf_attachment *psAttachment,
                                 PFN_DESTROY_DMABUF_PMR pfnDestroy,
                                 PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                IMG_DEVMEM_SIZE_T uiChunkSize,
+                                IMG_UINT32 ui32NumPhysChunks,
+                                IMG_UINT32 ui32NumVirtChunks,
+                                IMG_UINT32 *pui32MappingTable,
                                 PMR **ppsPMRPtr);
 
 struct dma_buf *
@@ -82,4 +92,17 @@
                     IMG_DEVMEM_SIZE_T *puiSize,
                     IMG_DEVMEM_ALIGN_T *puiAlign);
 
+PVRSRV_ERROR
+PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_INT fd,
+                          PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                          IMG_DEVMEM_SIZE_T uiChunkSize,
+                          IMG_UINT32 ui32NumPhysChunks,
+                          IMG_UINT32 ui32NumVirtChunks,
+                          IMG_UINT32 *pui32MappingTable,
+                          PMR **ppsPMRPtr,
+                          IMG_DEVMEM_SIZE_T *puiSize,
+                          IMG_DEVMEM_ALIGN_T *puiAlign);
+
 #endif /* !defined(_PHYSMEM_DMABUF_H_) */
diff --git a/drivers/staging/imgtec/rogue/physmem_lma.c b/drivers/staging/imgtec/rogue/physmem_lma.c
index af5cd10..3dfe183 100644
--- a/drivers/staging/imgtec/rogue/physmem_lma.c
+++ b/drivers/staging/imgtec/rogue/physmem_lma.c
@@ -50,8 +50,8 @@
 #include "allocmem.h"
 #include "osfunc.h"
 #include "pvrsrv.h"
+#include "devicemem_server_utils.h"
 #include "physmem_lma.h"
-#include "pdump_physmem.h"
 #include "pdump_km.h"
 #include "pmr.h"
 #include "pmr_impl.h"
@@ -86,16 +86,16 @@
 	IMG_BOOL bOnDemand;
 
 	/*
-	  for pdump...
-	*/
-	IMG_BOOL bPDumpMalloced;
-	IMG_HANDLE hPDumpAllocInfo;
-
-	/*
 	  record at alloc time whether poisoning will be required when the
 	  PMR is freed.
 	*/
 	IMG_BOOL bPoisonOnFree;
+
+	/* Physical heap and arena pointers for this allocation */
+	PHYS_HEAP* psPhysHeap;
+	RA_ARENA* psArena;
+	PVRSRV_MEMALLOCFLAGS_T uiAllocFlags;
+
 } PMR_LMALLOCARRAY_DATA;
 
 static PVRSRV_ERROR _MapAlloc(PVRSRV_DEVICE_NODE *psDevNode, 
@@ -105,6 +105,7 @@
 							  PMR_FLAGS_T ulFlags,
 							  void **pvPtr)
 {
+	IMG_UINT32 ui32CPUCacheFlags = DevmemCPUCacheMode(psDevNode, ulFlags);
 	IMG_CPU_PHYADDR sCpuPAddr;
 	PHYS_HEAP *psPhysHeap;
 
@@ -119,7 +120,7 @@
 
 	PhysHeapDevPAddrToCpuPAddr(psPhysHeap, 1, &sCpuPAddr, psDevPAddr);
 
-	*pvPtr = OSMapPhysToLin(sCpuPAddr,	uiSize,	ulFlags);
+	*pvPtr = OSMapPhysToLin(sCpuPAddr, uiSize, ui32CPUCacheFlags);
 	if (*pvPtr == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -136,7 +137,7 @@
 						PMR_FLAGS_T ulFlags,
 						void *pvPtr)
 {
-	OSUnMapPhysToLin(pvPtr, uiSize, 0);
+	OSUnMapPhysToLin(pvPtr, uiSize, PVRSRV_CPU_CACHE_MODE(ulFlags));
 }
 
 static PVRSRV_ERROR
@@ -158,7 +159,7 @@
 					   psDevPAddr,
 					   uiAllocSize,
 					   bFwLocalAlloc,
-					   0,
+					   PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
 					   &pvKernLin);
 	if (eError != PVRSRV_OK)
 	{
@@ -199,14 +200,19 @@
 					   psDevPAddr,
 					   uiAllocSize,
 					   bFwLocalAlloc,
-					   0,
+					   PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
 					   &pvKernLin);
 	if (eError != PVRSRV_OK)
 	{
 		goto map_failed;
 	}
 
-	OSMemSet(pvKernLin, 0, uiAllocSize);
+	/* NOTE: 'CachedMemSet' means the operating system default memset, which
+	 *       we *assume* in the LMA code will be faster, and doesn't need to
+	 *       worry about ARM64.
+	 */
+	OSCachedMemSet(pvKernLin, 0, uiAllocSize);
+
 	_UnMapAlloc(psDevNode, uiAllocSize, bFwLocalAlloc, 0, pvKernLin);
 
 	return PVRSRV_OK;
@@ -227,7 +233,7 @@
 			  PMR_SIZE_T uiChunkSize,
 			  IMG_UINT32 ui32NumPhysChunks,
 			  IMG_UINT32 ui32NumVirtChunks,
-			  IMG_BOOL *pabMappingTable,
+			  IMG_UINT32 *pabMappingTable,
 			  IMG_UINT32 uiLog2PageSize,
 			  IMG_BOOL bZero,
 			  IMG_BOOL bPoisonOnAlloc,
@@ -235,6 +241,8 @@
 			  IMG_BOOL bContig,
 			  IMG_BOOL bOnDemand,
 			  IMG_BOOL bFwLocalAlloc,
+			  PHYS_HEAP* psPhysHeap,
+			  PVRSRV_MEMALLOCFLAGS_T uiAllocFlags,
 			  PMR_LMALLOCARRAY_DATA **ppsPageArrayDataPtr
 			  )
 {
@@ -259,13 +267,12 @@
 		goto errorOnParam;
 	}
 
-	psPageArrayData = OSAllocMem(sizeof(PMR_LMALLOCARRAY_DATA));
+	psPageArrayData = OSAllocZMem(sizeof(PMR_LMALLOCARRAY_DATA));
 	if (psPageArrayData == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto errorOnAllocArray;
 	}
-	OSMemSet(psPageArrayData, 0, sizeof(PMR_LMALLOCARRAY_DATA));
 
 	if (bContig)
 	{
@@ -304,14 +311,9 @@
 		goto errorOnAllocAddr;
 	}
 
-	OSMemSet(&psPageArrayData->pasDevPAddr[0], INVALID_PAGE, sizeof(IMG_DEV_PHYADDR)*
+	OSCachedMemSet(&psPageArrayData->pasDevPAddr[0], INVALID_PAGE, sizeof(IMG_DEV_PHYADDR)*
 												psPageArrayData->uiTotalNumPages);
 
-	/* N.B.  We have a window of opportunity where a failure in
-	   createPMR the finalize function can be called before the PMR
-	   MALLOC and thus the hPDumpAllocInfo won't be set.  So we have
-	   to conditionally call the PDumpFree function. */
-	psPageArrayData->bPDumpMalloced = IMG_FALSE;
     psPageArrayData->iNumPagesAllocated = 0;
     psPageArrayData->bZeroOnAlloc = bZero;
 	psPageArrayData->bPoisonOnAlloc = bPoisonOnAlloc;
@@ -319,6 +321,8 @@
  	psPageArrayData->bHasLMPages = IMG_FALSE;
  	psPageArrayData->bOnDemand = bOnDemand;
  	psPageArrayData->bFwLocalAlloc = bFwLocalAlloc;
+ 	psPageArrayData->psPhysHeap = psPhysHeap;
+ 	psPageArrayData->uiAllocFlags = uiAllocFlags;
 
 	*ppsPageArrayDataPtr = psPageArrayData;
 
@@ -342,33 +346,25 @@
 _AllocLMPages(PMR_LMALLOCARRAY_DATA *psPageArrayData, IMG_UINT32 *pui32MapTable)
 {
 	PVRSRV_ERROR eError;
-	IMG_BOOL bAllocResult;
 	RA_BASE_T uiCardAddr;
 	RA_LENGTH_T uiActualSize;
 	IMG_UINT32 i,ui32Index=0;
 	IMG_UINT32 uiAllocSize;
 	IMG_UINT32 uiLog2AllocSize;
+	IMG_UINT32 uiRegionId;
 	PVRSRV_DEVICE_NODE *psDevNode;
 	IMG_BOOL bPoisonOnAlloc;
 	IMG_BOOL bZeroOnAlloc;
 	RA_ARENA *pArena;
 
 	PVR_ASSERT(NULL != psPageArrayData);
-    PVR_ASSERT(0 <= psPageArrayData->iNumPagesAllocated);
+	PVR_ASSERT(0 <= psPageArrayData->iNumPagesAllocated);
 
-    uiAllocSize = psPageArrayData->uiAllocSize;
-    uiLog2AllocSize = psPageArrayData->uiLog2AllocSize;
-    psDevNode = psPageArrayData->psDevNode;
-    bPoisonOnAlloc = psPageArrayData->bPoisonOnAlloc;
-    bZeroOnAlloc = psPageArrayData->bZeroOnAlloc;
-    pArena = psDevNode->psLocalDevMemArena;
-
-    if(psPageArrayData->uiTotalNumPages < (psPageArrayData->iNumPagesAllocated + psPageArrayData->uiPagesToAlloc))
-    {
-    	PVR_DPF((PVR_DBG_ERROR,"Pages requested to allocate larger than original PMR alloc Size"));
-    	eError = PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE;
-    	return eError;
-    }
+	uiAllocSize = psPageArrayData->uiAllocSize;
+	uiLog2AllocSize = psPageArrayData->uiLog2AllocSize;
+	psDevNode = psPageArrayData->psDevNode;
+	bPoisonOnAlloc =  psPageArrayData->bPoisonOnAlloc;
+	bZeroOnAlloc =  psPageArrayData->bZeroOnAlloc;
 
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
 	if (psPageArrayData->bFwLocalAlloc)
@@ -377,23 +373,43 @@
 		pArena = psDevNode->psKernelFwMemArena[psDevNode->uiKernelFwRAIdx];
 		psDevNode->uiKernelFwRAIdx = 0;
 	}
+	else
 #endif
+	{
+		/* Get suitable local memory region for this allocation */
+		uiRegionId = PhysHeapGetRegionId(psPageArrayData->psPhysHeap, psPageArrayData->uiAllocFlags);
+
+		PVR_ASSERT(uiRegionId < psDevNode->ui32NumOfLocalMemArenas);
+		pArena = psDevNode->apsLocalDevMemArenas[uiRegionId];
+	}
+
+	if(psPageArrayData->uiTotalNumPages < (psPageArrayData->iNumPagesAllocated + psPageArrayData->uiPagesToAlloc))
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Pages requested to allocate larger than original PMR alloc Size"));
+		eError = PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE;
+		return eError;
+	}
+
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+	{
+		IMG_UINT32  ui32OSid=0, ui32OSidReg=0;
+		IMG_BOOL    bOSidAxiProt;
+		IMG_PID     pId;
+
+		pId=OSGetCurrentClientProcessIDKM();
+		RetrieveOSidsfromPidList(pId, &ui32OSid, &ui32OSidReg, &bOSidAxiProt);
+
+		pArena=psDevNode->psOSidSubArena[ui32OSid];
+		PVR_DPF((PVR_DBG_MESSAGE,"(GPU Virtualization Validation): Giving from OS slot %d",ui32OSid));
+	}
+#endif
+
+	psPageArrayData->psArena = pArena;
 
 	for(i=0;i<psPageArrayData->uiPagesToAlloc;i++)
 	{
 
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-{
-		IMG_UINT32  ui32OSid=0, ui32OSidReg=0;
-		IMG_PID     pId;
-
-		pId=OSGetCurrentClientProcessIDKM();
-		RetrieveOSidsfromPidList(pId, &ui32OSid, &ui32OSidReg);
-
-		pArena=psDevNode->psOSidSubArena[ui32OSid];
-		PVR_DPF((PVR_DBG_MESSAGE,"(GPU Virtualization Validation): Giving from OS slot %d",ui32OSid));
-}
-#endif
 		/*This part of index finding should happen before allocating page. Just avoiding intricate paths */
 		if(psPageArrayData->uiTotalNumPages == psPageArrayData->uiPagesToAlloc)
 		{
@@ -424,15 +440,15 @@
 			}
 		}
 
-		bAllocResult = RA_Alloc(pArena,
-								uiAllocSize,
-								RA_NO_IMPORT_MULTIPLIER,
-								0,                                      /* No flags */
-								1ULL << uiLog2AllocSize,
-								&uiCardAddr,
-								&uiActualSize,
-								NULL);                      /* No private handle */
-
+		eError = RA_Alloc(pArena,
+		                  uiAllocSize,
+		                  RA_NO_IMPORT_MULTIPLIER,
+		                  0,                       /* No flags */
+		                  1ULL << uiLog2AllocSize,
+		                  "LMA_Page_Alloc",
+		                  &uiCardAddr,
+		                  &uiActualSize,
+		                  NULL);                   /* No private handle */
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 {
@@ -440,7 +456,7 @@
 }
 #endif
 
-		if (!bAllocResult)
+		if (PVRSRV_OK != eError)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"Failed to Allocate the page @index:%d",ui32Index));
 			eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
@@ -528,7 +544,7 @@
 
 		if(ui32Index < psPageArrayData->uiTotalNumPages)
 		{
-			RA_Free(psDevNode->psLocalDevMemArena, psPageArrayData->pasDevPAddr[ui32Index].uiAddr);
+			RA_Free(pArena, psPageArrayData->pasDevPAddr[ui32Index].uiAddr);
 			psPageArrayData->pasDevPAddr[ui32Index].uiAddr = INVALID_PAGE;
 		}
 	}
@@ -553,10 +569,10 @@
 {
 	IMG_UINT32 uiAllocSize;
 	IMG_UINT32 i,ui32PagesToFree=0,ui32PagesFreed=0,ui32Index=0;
-	PVRSRV_DEVICE_NODE *psDevNode = psPageArrayData->psDevNode;
-	RA_ARENA *pArena = psDevNode->psLocalDevMemArena;
+	RA_ARENA *pArena = psPageArrayData->psArena;
 
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
+	PVRSRV_DEVICE_NODE *psDevNode = psPageArrayData->psDevNode;
 	if (psPageArrayData->bFwLocalAlloc)
 	{
 		PVR_ASSERT(psDevNode->uiKernelFwRAIdx < RGXFW_NUM_OS);
@@ -596,7 +612,6 @@
 			}
 
 			RA_Free(pArena,	psPageArrayData->pasDevPAddr[ui32Index].uiAddr);
-			psPageArrayData->pasDevPAddr[ui32Index].uiAddr = INVALID_PAGE;
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
@@ -604,10 +619,11 @@
 			PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, uiAllocSize);
 #else
 			{
-				PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, psPageArrayData->pasDevPAddr[i].uiAddr);
+				PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, psPageArrayData->pasDevPAddr[ui32Index].uiAddr);
 			}
 #endif
 #endif
+			psPageArrayData->pasDevPAddr[ui32Index].uiAddr = INVALID_PAGE;
 		}
 	}
 	psPageArrayData->iNumPagesAllocated -= ui32PagesFreed;
@@ -640,13 +656,6 @@
 
 	psLMAllocArrayData = pvPriv;
 
-	/* Conditionally do the PDump free, because if CreatePMR failed we
-	   won't have done the PDump MALLOC.  */
-	if (psLMAllocArrayData->bPDumpMalloced)
-	{
-		PDumpFree(psLMAllocArrayData->hPDumpAllocInfo);
-	}
-
 	/*  We can't free pages until now. */
 	if (psLMAllocArrayData->bHasLMPages)
 	{
@@ -663,8 +672,7 @@
 /* callback function for locking the system physical page addresses.
    As we are LMA there is nothing to do as we control physical memory. */
 static PVRSRV_ERROR
-PMRLockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
-							 IMG_UINT32 uiLog2DevPageSize)
+PMRLockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv)
 {
 
     PVRSRV_ERROR eError;
@@ -682,8 +690,6 @@
     	}
     }
 
-	PVR_UNREFERENCED_PARAMETER(uiLog2DevPageSize);
-
 	return PVRSRV_OK;
 
 }
@@ -714,6 +720,7 @@
 /* N.B.  It is assumed that PMRLockSysPhysAddressesLocalMem() is called _before_ this function! */
 static PVRSRV_ERROR
 PMRSysPhysAddrLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+					   IMG_UINT32 ui32Log2PageSize,
 					   IMG_UINT32 ui32NumOfPages,
 					   IMG_DEVMEM_OFFSET_T *puiOffset,
 					   IMG_BOOL *pbValid,
@@ -726,6 +733,16 @@
 	IMG_DEVMEM_OFFSET_T uiInAllocOffset;
 	PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = pvPriv;
 
+	if (psLMAllocArrayData->uiLog2AllocSize < ui32Log2PageSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Requested physical addresses from PMR "
+		         "for incompatible contiguity %u!",
+		         __FUNCTION__,
+		         ui32Log2PageSize));
+		return PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+	}
+
 	uiNumAllocs = psLMAllocArrayData->uiTotalNumPages;
 	if (uiNumAllocs > 1)
 	{
@@ -772,8 +789,7 @@
 	PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = NULL;
 	void *pvKernLinAddr = NULL;
 	IMG_UINT32 ui32PageIndex = 0;
-
-	PVR_UNREFERENCED_PARAMETER(ulFlags);
+	size_t uiOffsetMask = uiOffset;
 
 	psLMAllocArrayData = pvPriv;
 
@@ -793,6 +809,7 @@
 
 		/* Locate the desired physical page to map in */
 		ui32PageIndex = uiOffset >> psLMAllocArrayData->uiLog2AllocSize;
+		uiOffsetMask = (1U << psLMAllocArrayData->uiLog2AllocSize) - 1;
 	}
 
 	PVR_ASSERT(ui32PageIndex < psLMAllocArrayData->uiTotalNumPages);
@@ -804,7 +821,7 @@
 						ulFlags,
 						&pvKernLinAddr);
 
-	*ppvKernelAddressOut = ((IMG_CHAR *) pvKernLinAddr) + (uiOffset & ((1U << psLMAllocArrayData->uiLog2AllocSize) - 1));
+	*ppvKernelAddressOut = ((IMG_CHAR *) pvKernLinAddr) + (uiOffset & uiOffsetMask);
 	*phHandleOut = pvKernLinAddr;
 
 	return eError;
@@ -884,7 +901,7 @@
 								&psLMAllocArrayData->pasDevPAddr[uiAllocIndex],
 								psLMAllocArrayData->uiAllocSize,
 								psLMAllocArrayData->bFwLocalAlloc,
-								0,
+								PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
 								&pvMapping);
 			if (eError != PVRSRV_OK)
 			{
@@ -913,7 +930,7 @@
 								&psLMAllocArrayData->pasDevPAddr[0],
 								psLMAllocArrayData->uiAllocSize,
 								psLMAllocArrayData->bFwLocalAlloc,
-								0,
+								PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
 								&pvMapping);
 			if (eError != PVRSRV_OK)
 			{
@@ -941,7 +958,11 @@
 						 IMG_UINT8 *pcPMR,
 						 size_t uiSize)
 {
-	OSMemCopy(pcBuffer, pcPMR, uiSize);
+	/* NOTE: 'CachedMemCopy' means the operating system default memcpy, which
+	 *       we *assume* in the LMA code will be faster, and doesn't need to
+	 *       worry about ARM64.
+	 */
+	OSCachedMemCopy(pcBuffer, pcPMR, uiSize);
 }
 
 static PVRSRV_ERROR
@@ -963,7 +984,11 @@
 						  IMG_UINT8 *pcPMR,
 						  size_t uiSize)
 {
-	OSMemCopy(pcPMR, pcBuffer, uiSize);
+	/* NOTE: 'CachedMemCopy' means the operating system default memcpy, which
+	 *       we *assume* in the LMA code will be faster, and doesn't need to
+	 *       worry about ARM64.
+	 */
+	OSCachedMemCopy(pcPMR, pcBuffer, uiSize);
 }
 
 static PVRSRV_ERROR
@@ -989,59 +1014,79 @@
 */ /**************************************************************************/
 static PVRSRV_ERROR
 PMRChangeSparseMemLocalMem(PMR_IMPL_PRIVDATA pPriv,
-		const PMR *psPMR,
-		IMG_UINT32 ui32AllocPageCount,
-		IMG_UINT32 *pai32AllocIndices,
-		IMG_UINT32 ui32FreePageCount,
-		IMG_UINT32 *pai32FreeIndices,
-		IMG_UINT32	uiFlags,
-		IMG_UINT32	*pui32Status)
+                           const PMR *psPMR,
+                           IMG_UINT32 ui32AllocPageCount,
+                           IMG_UINT32 *pai32AllocIndices,
+                           IMG_UINT32 ui32FreePageCount,
+                           IMG_UINT32 *pai32FreeIndices,
+                           IMG_UINT32 uiFlags)
 {
-	IMG_UINT32 ui32AdtnlAllocPages=0, ui32AdtnlFreePages=0,ui32CommonRequstCount=0,ui32Loop=0;
+	PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+	IMG_UINT32 ui32AdtnlAllocPages = 0;
+	IMG_UINT32 ui32AdtnlFreePages = 0;
+	IMG_UINT32 ui32CommonRequstCount = 0;
+	IMG_UINT32 ui32Loop = 0;
+	IMG_UINT32 ui32Index = 0;
+	IMG_UINT32 uiAllocpgidx;
+	IMG_UINT32 uiFreepgidx;
+
 	PMR_LMALLOCARRAY_DATA *psPMRPageArrayData = (PMR_LMALLOCARRAY_DATA *)pPriv;
 	IMG_DEV_PHYADDR sPhyAddr;
-	PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
-	IMG_UINT32	ui32Index = 0,uiAllocpgidx,uiFreepgidx;
+
 #if defined(DEBUG)
-	IMG_BOOL bPoisonFail=IMG_FALSE, bZeroFail = IMG_FALSE;
+	IMG_BOOL bPoisonFail = IMG_FALSE;
+	IMG_BOOL bZeroFail = IMG_FALSE;
 #endif
 
-	/*Fetch the Page table array represented by the PMR */
+	/* Fetch the Page table array represented by the PMR */
 	IMG_DEV_PHYADDR *psPageArray = psPMRPageArrayData->pasDevPAddr;
 	PMR_MAPPING_TABLE *psPMRMapTable = PMR_GetMappigTable(psPMR);
 
-	/*The incoming request is classified in to two operations alloc & free pages, independent of each other
-	 * These operations can be combined with two mapping operations as well which are GPU & CPU space mapping
-	 * From the alloc and free page requests, net pages to be allocated or freed is computed.
-	 * And hence the order of operations are done in the following steps.
-	 * 1. Allocate net pages
-	 * 2. Move the free pages from free request to common alloc requests.
-	 * 3. Free net pages
-	 * */
+	/* The incoming request is classified into two operations independent of
+	 * each other: alloc & free pages.
+	 * These operations can be combined with two mapping operations as well
+	 * which are GPU & CPU space mappings.
+	 *
+	 * From the alloc and free page requests, the net amount of pages to be
+	 * allocated or freed is computed. Pages that were requested to be freed
+	 * will be reused to fulfil alloc requests.
+	 *
+	 * The order of operations is:
+	 * 1. Allocate new pages from the OS
+	 * 2. Move the free pages from free request to alloc positions.
+	 * 3. Free the rest of the pages not used for alloc
+	 *
+	 * Alloc parameters are validated at the time of allocation
+	 * and any error will be handled then. */
 
-	if(SPARSE_RESIZE_BOTH == (uiFlags & SPARSE_RESIZE_BOTH))
+	if (SPARSE_RESIZE_BOTH == (uiFlags & SPARSE_RESIZE_BOTH))
 	{
-		ui32CommonRequstCount = (ui32AllocPageCount > ui32FreePageCount)?ui32FreePageCount:ui32AllocPageCount;
-#ifdef PDUMP
-		PDUMP_PANIC(RGX, SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported ");
-#endif
+		ui32CommonRequstCount = (ui32AllocPageCount > ui32FreePageCount) ?
+				ui32FreePageCount : ui32AllocPageCount;
+
+		PDUMP_PANIC(SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported");
 	}
-	if(SPARSE_RESIZE_ALLOC == (uiFlags & SPARSE_RESIZE_ALLOC))
+
+	if (SPARSE_RESIZE_ALLOC == (uiFlags & SPARSE_RESIZE_ALLOC))
 	{
 		ui32AdtnlAllocPages = ui32AllocPageCount - ui32CommonRequstCount;
-	}else
+	}
+	else
 	{
 		ui32AllocPageCount = 0;
 	}
-	if(SPARSE_RESIZE_FREE == (uiFlags & SPARSE_RESIZE_FREE))
+
+	if (SPARSE_RESIZE_FREE == (uiFlags & SPARSE_RESIZE_FREE))
 	{
 		ui32AdtnlFreePages = ui32FreePageCount - ui32CommonRequstCount;
-	}else
+	}
+	else
 	{
 		ui32FreePageCount = 0;
 	}
 
-	if(0 == (ui32CommonRequstCount || ui32AdtnlAllocPages || ui32AdtnlFreePages))
+	if (0 == (ui32CommonRequstCount || ui32AdtnlAllocPages || ui32AdtnlFreePages))
 	{
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		return eError;
@@ -1049,22 +1094,24 @@
 
 	{
 		/* Validate the free page indices */
-		if(ui32FreePageCount)
+		if (ui32FreePageCount)
 		{
-			if(NULL != pai32FreeIndices)
+			if (NULL != pai32FreeIndices)
 			{
-				for(ui32Loop=0; ui32Loop<ui32FreePageCount; ui32Loop++)
+				for (ui32Loop = 0; ui32Loop < ui32FreePageCount; ui32Loop++)
 				{
 					uiFreepgidx = pai32FreeIndices[ui32Loop];
-					if((uiFreepgidx > psPMRPageArrayData->uiTotalNumPages))
+
+					if (uiFreepgidx > psPMRPageArrayData->uiTotalNumPages)
 					{
 						eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
-						goto SparseMemChangeFailed;
+						goto e0;
 					}
-					if(INVALID_PAGE == psPageArray[uiFreepgidx].uiAddr)
+
+					if (INVALID_PAGE == psPageArray[uiFreepgidx].uiAddr)
 					{
 						eError = PVRSRV_ERROR_INVALID_PARAMS;
-						goto SparseMemChangeFailed;
+						goto e0;
 					}
 				}
 			}else{
@@ -1074,65 +1121,75 @@
 		}
 
 		/*The following block of code verifies any issues with common alloc page indices */
-		for(ui32Loop=ui32AdtnlAllocPages; ui32Loop<ui32AllocPageCount; ui32Loop++)
+		for (ui32Loop = ui32AdtnlAllocPages; ui32Loop < ui32AllocPageCount; ui32Loop++)
 		{
 			uiAllocpgidx = pai32AllocIndices[ui32Loop];
-			if((uiAllocpgidx > psPMRPageArrayData->uiTotalNumPages))
+			if (uiAllocpgidx > psPMRPageArrayData->uiTotalNumPages)
 			{
 				eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
-				goto SparseMemChangeFailed;
+				goto e0;
 			}
-			if(SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
+
+			if (SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
 			{
-				if((INVALID_PAGE != psPageArray[uiAllocpgidx].uiAddr) || \
+				if ((INVALID_PAGE != psPageArray[uiAllocpgidx].uiAddr) ||
 						(TRANSLATION_INVALID != psPMRMapTable->aui32Translation[uiAllocpgidx]))
 				{
 					eError = PVRSRV_ERROR_INVALID_PARAMS;
-					goto SparseMemChangeFailed;
+					goto e0;
 				}
-			}else{
-				if(((INVALID_PAGE ==  psPageArray[uiAllocpgidx].uiAddr) || \
-						(TRANSLATION_INVALID == psPMRMapTable->aui32Translation[uiAllocpgidx])))
+			}
+			else
+			{
+				if ((INVALID_PAGE ==  psPageArray[uiAllocpgidx].uiAddr) ||
+				    (TRANSLATION_INVALID == psPMRMapTable->aui32Translation[uiAllocpgidx]))
 				{
 					eError = PVRSRV_ERROR_INVALID_PARAMS;
-					goto SparseMemChangeFailed;
+					goto e0;
 				}
 			}
 		}
 
-		/*Allocate the net additional pages computed */
+
 		ui32Loop = 0;
-		if(0 != ui32AdtnlAllocPages)
+
+		/* Allocate new pages */
+		if (0 != ui32AdtnlAllocPages)
 		{
-			/*Alloc pages*/
-			/*Say how many pages to allocate */
+			/* Say how many pages to allocate */
 			psPMRPageArrayData->uiPagesToAlloc = ui32AdtnlAllocPages;
 
 			eError = _AllocLMPages(psPMRPageArrayData, pai32AllocIndices);
-			if(PVRSRV_OK != eError)
+			if (PVRSRV_OK != eError)
 			{
-				PVR_DPF((PVR_DBG_ERROR, "%s: New Addtl Allocation of pages failed", __FUNCTION__));
-				goto SparseMemChangeFailed;
+				PVR_DPF((PVR_DBG_ERROR,
+				         "%s: New Addtl Allocation of pages failed",
+				         __FUNCTION__));
+				goto e0;
 			}
-			/*Mark the corresponding pages of translation table as valid */
-			for(ui32Loop=0;ui32Loop<ui32AdtnlAllocPages;ui32Loop++)
+
+			/* Mark the corresponding pages of translation table as valid */
+			for (ui32Loop = 0; ui32Loop < ui32AdtnlAllocPages; ui32Loop++)
 			{
 				psPMRMapTable->aui32Translation[pai32AllocIndices[ui32Loop]] = pai32AllocIndices[ui32Loop];
 			}
 		}
 
-		/*Move the corresponding free pages to alloc request */
 		ui32Index = ui32Loop;
-		for(ui32Loop=0; ui32Loop<ui32CommonRequstCount; ui32Loop++,ui32Index++)
+
+		/* Move the corresponding free pages to alloc request */
+		for (ui32Loop = 0; ui32Loop < ui32CommonRequstCount; ui32Loop++, ui32Index++)
 		{
 
 			uiAllocpgidx = pai32AllocIndices[ui32Index];
 			uiFreepgidx =  pai32FreeIndices[ui32Loop];
 			sPhyAddr = psPageArray[uiAllocpgidx];
 			psPageArray[uiAllocpgidx] = psPageArray[uiFreepgidx];
-			/*is remap mem used in real world scenario, should it be turned toa a debug feature ?
-			 * The condition check need to be out of look, for later though */
-			if(SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
+
+			/* Is remap mem used in real world scenario? Should it be turned to a
+			 *  debug feature? The condition check needs to be out of loop, will be
+			 *  done at later point though after some analysis */
+			if (SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
 			{
 				psPMRMapTable->aui32Translation[uiFreepgidx] = TRANSLATION_INVALID;
 				psPMRMapTable->aui32Translation[uiAllocpgidx] = uiAllocpgidx;
@@ -1145,21 +1202,20 @@
 				psPMRMapTable->aui32Translation[uiAllocpgidx] = uiAllocpgidx;
 			}
 
-			/*Be sure to honour the attributes associated with the allocation
-			 * such as zeroing, poisoning etc
-			 * */
+			/* Be sure to honour the attributes associated with the allocation
+			 * such as zeroing, poisoning etc. */
 			if (psPMRPageArrayData->bPoisonOnAlloc)
 			{
 				eError = _PoisonAlloc(psPMRPageArrayData->psDevNode,
-						  	  &psPMRPageArrayData->pasDevPAddr[uiAllocpgidx],
-						  	  psPMRPageArrayData->bFwLocalAlloc,
-						  	  psPMRPageArrayData->uiAllocSize,
-							  _AllocPoison,
-							  _AllocPoisonSize);
-				/*Consider this as a soft failure and go ahead but log error to kernel log */
-				if (eError !=PVRSRV_OK)
+				                      &psPMRPageArrayData->pasDevPAddr[uiAllocpgidx],
+				                      psPMRPageArrayData->bFwLocalAlloc,
+				                      psPMRPageArrayData->uiAllocSize,
+				                      _AllocPoison,
+				                      _AllocPoisonSize);
+
+				/* Consider this as a soft failure and go ahead but log error to kernel log */
+				if (eError != PVRSRV_OK)
 				{
-					*pui32Status = PVRSRV_ERROR_PMR_PAGE_POISONING_FAILED;
 #if defined(DEBUG)
 					bPoisonFail = IMG_TRUE;
 #endif
@@ -1170,13 +1226,12 @@
 				if (psPMRPageArrayData->bZeroOnAlloc)
 				{
 					eError = _ZeroAlloc(psPMRPageArrayData->psDevNode,
-										&psPMRPageArrayData->pasDevPAddr[uiAllocpgidx],
-										psPMRPageArrayData->bFwLocalAlloc,
-										psPMRPageArrayData->uiAllocSize);
-					/*Consider this as a soft failure and go ahead but log error to kernel log */
-					if (eError !=PVRSRV_OK)
+					                    &psPMRPageArrayData->pasDevPAddr[uiAllocpgidx],
+					                    psPMRPageArrayData->bFwLocalAlloc,
+					                    psPMRPageArrayData->uiAllocSize);
+					/* Consider this as a soft failure and go ahead but log error to kernel log */
+					if (eError != PVRSRV_OK)
 					{
-						*pui32Status = PVRSRV_ERROR_PMR_PAGE_POISONING_FAILED;
 #if defined(DEBUG)
 						/*Don't think we need to zero  any pages further*/
 						bZeroFail = IMG_TRUE;
@@ -1187,11 +1242,12 @@
 		}
 
 		/*Free the additional free pages */
-		if(0 != ui32AdtnlFreePages)
+		if (0 != ui32AdtnlFreePages)
 		{
 			ui32Index = ui32Loop;
 			_FreeLMPages(psPMRPageArrayData, &pai32FreeIndices[ui32Loop], ui32AdtnlFreePages);
 			ui32Loop = 0;
+
 			while(ui32Loop++ < ui32AdtnlFreePages)
 			{
 				/*Set the corresponding mapping table entry to invalid address */
@@ -1215,7 +1271,8 @@
 
 	/* Update the PMR memory holding information */
 	eError = PVRSRV_OK;
-SparseMemChangeFailed:
+
+e0:
 		return eError;
 
 }
@@ -1227,13 +1284,12 @@
 */ /**************************************************************************/
 static
 PVRSRV_ERROR PMRChangeSparseMemCPUMapLocalMem(PMR_IMPL_PRIVDATA pPriv,
-								const PMR *psPMR,
-								IMG_UINT64 sCpuVAddrBase,
-								IMG_UINT32	ui32AllocPageCount,
-								IMG_UINT32	*pai32AllocIndices,
-								IMG_UINT32	ui32FreePageCount,
-								IMG_UINT32	*pai32FreeIndices,
-								IMG_UINT32	*pui32Status)
+                                              const PMR *psPMR,
+                                              IMG_UINT64 sCpuVAddrBase,
+                                              IMG_UINT32 ui32AllocPageCount,
+                                              IMG_UINT32 *pai32AllocIndices,
+                                              IMG_UINT32 ui32FreePageCount,
+                                              IMG_UINT32 *pai32FreeIndices)
 {
 	IMG_DEV_PHYADDR *psPageArray;
 	PMR_LMALLOCARRAY_DATA *psPMRPageArrayData = (PMR_LMALLOCARRAY_DATA *)pPriv;
@@ -1243,27 +1299,25 @@
 
 	/*Get the base address of the heap */
 	PMR_CpuPhysAddr(psPMR,
-			psPMRPageArrayData->uiLog2AllocSize,
-            1,
-            0,	/* offset zero here mean first page in the PMR */
-            &sCpuAddrPtr,
-            &bValid);
+	                psPMRPageArrayData->uiLog2AllocSize,
+	                1,
+	                0,	/* offset zero here mean first page in the PMR */
+	                &sCpuAddrPtr,
+	                &bValid);
 
-	/* Phys address of heap is computed here by substracting the offset of this page
-	 * basically phys address of any page = Base address of heap + offset of the page
-	 */
+	/* Phys address of heap is computed here by subtracting the offset of this page
+	 * basically phys address of any page = Base address of heap + offset of the page */
 	sCpuAddrPtr.uiAddr -= psPMRPageArrayData->pasDevPAddr[0].uiAddr;
-
 	psPageArray = psPMRPageArrayData->pasDevPAddr;
+
 	return OSChangeSparseMemCPUAddrMap((void **)psPageArray,
-											sCpuVABase,
-											((uintptr_t)(sCpuAddrPtr.uiAddr)),
-											ui32AllocPageCount,
-											pai32AllocIndices,
-											ui32FreePageCount,
-											pai32FreeIndices,
-											pui32Status,
-											IMG_TRUE);
+	                                   sCpuVABase,
+	                                   sCpuAddrPtr,
+	                                   ui32AllocPageCount,
+	                                   pai32AllocIndices,
+	                                   ui32FreePageCount,
+	                                   pai32FreeIndices,
+	                                   IMG_TRUE);
 }
 
 
@@ -1274,12 +1328,16 @@
 	&PMRUnlockSysPhysAddressesLocalMem,
 	/* pfnDevPhysAddr */
 	&PMRSysPhysAddrLocalMem,
-	/* pfnPDumpSymbolicAddr */
-	NULL,
 	/* pfnAcquireKernelMappingData */
 	&PMRAcquireKernelMappingDataLocalMem,
 	/* pfnReleaseKernelMappingData */
 	&PMRReleaseKernelMappingDataLocalMem,
+#if defined(INTEGRITY_OS)
+	/* pfnMapMemoryObject */
+    NULL,
+	/* pfnUnmapMemoryObject */
+    NULL,
+#endif
 	/* pfnReadBytes */
 	&PMRReadBytesLocalMem,
 	/* pfnWriteBytes */
@@ -1307,60 +1365,41 @@
 							IMG_UINT32 *pui32MappingTable,
 							IMG_UINT32 uiLog2PageSize,
 							PVRSRV_MEMALLOCFLAGS_T uiFlags,
+							const IMG_CHAR *pszAnnotation,
 							PMR **ppsPMRPtr)
 {
 	PVRSRV_ERROR eError;
 	PVRSRV_ERROR eError2;
 	PMR *psPMR = NULL;
 	PMR_LMALLOCARRAY_DATA *psPrivData = NULL;
-	IMG_HANDLE hPDumpAllocInfo = NULL;
 	PMR_FLAGS_T uiPMRFlags;
 	PHYS_HEAP *psPhysHeap;
 	IMG_BOOL bZero;
 	IMG_BOOL bPoisonOnAlloc;
 	IMG_BOOL bPoisonOnFree;
-	IMG_BOOL bOnDemand = ((uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
+	IMG_BOOL bOnDemand;
 	IMG_BOOL bContig;
-	IMG_BOOL bFwLocalAlloc = uiFlags & PVRSRV_MEMALLOCFLAG_FW_LOCAL ? IMG_TRUE : IMG_FALSE;
+	IMG_BOOL bFwLocalAlloc;
+	IMG_BOOL bCpuLocalAlloc;
 
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+	if (PVRSRV_CHECK_KERNEL_CPU_MAPPABLE(uiFlags) &&
+		(ui32NumPhysChunks == ui32NumVirtChunks))
 	{
-		bZero = IMG_TRUE;
-	}
-	else
-	{
-		bZero = IMG_FALSE;
-	}
-
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC)
-	{
-		bPoisonOnAlloc = IMG_TRUE;
-	}
-	else
-	{
-		bPoisonOnAlloc = IMG_FALSE;
-	}
-
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
-	{
-		bPoisonOnFree = IMG_TRUE;
-	}
-	else
-	{
-		bPoisonOnFree = IMG_FALSE;
-	}
-
-	if (uiFlags & PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE)
-	{
-		bContig = (ui32NumPhysChunks == ui32NumVirtChunks)?IMG_TRUE:IMG_FALSE;
+		bContig = IMG_TRUE;
 	}
 	else
 	{
 		bContig = IMG_FALSE;
 	}
 
-	if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
-		(uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
+	bOnDemand = PVRSRV_CHECK_ON_DEMAND(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bFwLocalAlloc = PVRSRV_CHECK_FW_LOCAL(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bCpuLocalAlloc = PVRSRV_CHECK_CPU_LOCAL(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bZero = PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bPoisonOnAlloc = PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bPoisonOnFree = PVRSRV_CHECK_POISON_ON_FREE(uiFlags) ? IMG_TRUE : IMG_FALSE;
+
+	if (bZero && bPoisonOnAlloc)
 	{
 		/* Zero on Alloc and Poison on Alloc are mutually exclusive */
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
@@ -1375,21 +1414,47 @@
 		? OSGetPageShift()
 		: uiLog2PageSize;
 
+	/* In case we have a non-sparse allocation tolerate bad requests and round up.
+	 * For sparse allocations the users have to make sure to meet the right
+	 * requirements. */
+	if (ui32NumPhysChunks == ui32NumVirtChunks &&
+		ui32NumVirtChunks == 1)
+	{
+		/* Round up allocation size to at least a full OSGetPageSize() */
+		uiSize = PVR_ALIGN(uiSize, OSGetPageSize());
+		uiChunkSize = uiSize;
+	}
+
+	if (bFwLocalAlloc)
+	{
+		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL];
+	}
+	else if (bCpuLocalAlloc)
+	{
+		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL];
+	}
+	else
+	{
+		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL];
+	}
+
 	/* Create Array structure that holds the physical pages */
 	eError = _AllocLMPageArray(psDevNode,
-						   uiChunkSize * ui32NumVirtChunks,
-						   uiChunkSize,
-                           ui32NumPhysChunks,
-                           ui32NumVirtChunks,
-                           pui32MappingTable,
-						   uiLog2PageSize,
-						   bZero,
-						   bPoisonOnAlloc,
-						   bPoisonOnFree,
-						   bContig,
-						   bOnDemand,
-						   bFwLocalAlloc,
-						   &psPrivData);
+	                           uiChunkSize * ui32NumVirtChunks,
+	                           uiChunkSize,
+	                           ui32NumPhysChunks,
+	                           ui32NumVirtChunks,
+	                           pui32MappingTable,
+	                           uiLog2PageSize,
+	                           bZero,
+	                           bPoisonOnAlloc,
+	                           bPoisonOnFree,
+	                           bContig,
+	                           bOnDemand,
+	                           bFwLocalAlloc,
+	                           psPhysHeap,
+	                           uiFlags,
+	                           &psPrivData);
 	if (eError != PVRSRV_OK)
 	{
 		goto errorOnAllocPageArray;
@@ -1423,17 +1488,9 @@
     	PDUMPCOMMENT("Deferred Allocation PMR (LMA)");
     }
 
-    if (bFwLocalAlloc)
-    {
-		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL];
-    }
-    else
-    {
-    	psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL];
-    }
 
-
-	eError = PMRCreatePMR(psPhysHeap,
+	eError = PMRCreatePMR(psDevNode,
+						  psPhysHeap,
 						  uiSize,
                           uiChunkSize,
                           ui32NumPhysChunks,
@@ -1441,25 +1498,23 @@
                           pui32MappingTable,
 						  uiLog2PageSize,
 						  uiPMRFlags,
-						  "PMRLMA",
+						  pszAnnotation,
 						  &_sPMRLMAFuncTab,
 						  psPrivData,
+						  PMR_TYPE_LMA,
 						  &psPMR,
-						  &hPDumpAllocInfo,
 						  IMG_FALSE);
 	if (eError != PVRSRV_OK)
 	{
+		PVR_DPF((PVR_DBG_ERROR, "PhysmemNewLocalRamBackedPMR: Unable to create PMR (status=%d)", eError));
 		goto errorOnCreate;
 	}
 
-	psPrivData->hPDumpAllocInfo = hPDumpAllocInfo;
-	psPrivData->bPDumpMalloced = IMG_TRUE;
-
 	*ppsPMRPtr = psPMR;
 	return PVRSRV_OK;
 
 errorOnCreate:
-	if(!bOnDemand)
+	if(!bOnDemand && psPrivData->bHasLMPages)
 	{
 		eError2 = _FreeLMPages(psPrivData, NULL,0);
 		PVR_ASSERT(eError2 == PVRSRV_OK);
@@ -1482,6 +1537,7 @@
 	IMG_PID     pId;
 	IMG_UINT32  ui32OSid;
 	IMG_UINT32	ui32OSidReg;
+    IMG_BOOL    bOSidAxiProt;
 
 	struct PidOSidCouplingList *psNext;
 };
@@ -1490,11 +1546,12 @@
 static PidOSidCouplingList *psPidOSidHead=NULL;
 static PidOSidCouplingList *psPidOSidTail=NULL;
 
-void InsertPidOSidsCoupling(IMG_PID pId, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg)
+void InsertPidOSidsCoupling(IMG_PID pId, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg, IMG_BOOL bOSidAxiProt)
 {
 	PidOSidCouplingList *psTmp;
 
-	PVR_DPF((PVR_DBG_MESSAGE,"(GPU Virtualization Validation): Inserting (PID/ OSid/ OSidReg) (%d/ %d/ %d) into list",pId,ui32OSid, ui32OSidReg));
+    PVR_DPF((PVR_DBG_MESSAGE,"(GPU Virtualization Validation): Inserting (PID/ OSid/ OSidReg/ IsSecure) (%d/ %d/ %d/ %s) into list",
+                 pId,ui32OSid, ui32OSidReg, (bOSidAxiProt)?"Yes":"No"));
 
 	psTmp=OSAllocMem(sizeof(PidOSidCouplingList));
 
@@ -1507,6 +1564,7 @@
 	psTmp->pId=pId;
 	psTmp->ui32OSid=ui32OSid;
 	psTmp->ui32OSidReg=ui32OSidReg;
+    psTmp->bOSidAxiProt = bOSidAxiProt;
 
 	psTmp->psNext=NULL;
 	if (psPidOSidHead==NULL)
@@ -1523,7 +1581,7 @@
 	return ;
 }
 
-void RetrieveOSidsfromPidList(IMG_PID pId, IMG_UINT32 *pui32OSid, IMG_UINT32 * pui32OSidReg)
+void RetrieveOSidsfromPidList(IMG_PID pId, IMG_UINT32 *pui32OSid, IMG_UINT32 *pui32OSidReg, IMG_BOOL *pbOSidAxiProt)
 {
 	PidOSidCouplingList *psTmp;
 
@@ -1531,8 +1589,9 @@
 	{
 		if (psTmp->pId==pId)
 		{
-			(*pui32OSid) = psTmp->ui32OSid;
-			(*pui32OSidReg) = psTmp->ui32OSidReg;
+            (*pui32OSid)     = psTmp->ui32OSid;
+            (*pui32OSidReg)  = psTmp->ui32OSidReg;
+            (*pbOSidAxiProt) = psTmp->bOSidAxiProt;
 
 			return ;
 		}
@@ -1540,10 +1599,12 @@
 
 	(*pui32OSid)=0;
 	(*pui32OSidReg)=0;
+    (*pbOSidAxiProt) = IMG_FALSE;
+
 	return ;
 }
 
-void    RemovePidOSidCoupling(IMG_PID pId)
+void RemovePidOSidCoupling(IMG_PID pId)
 {
 	PidOSidCouplingList *psTmp, *psPrev=NULL;
 
diff --git a/drivers/staging/imgtec/rogue/physmem_lma.h b/drivers/staging/imgtec/rogue/physmem_lma.h
index a9f0b05..be7bef7 100644
--- a/drivers/staging/imgtec/rogue/physmem_lma.h
+++ b/drivers/staging/imgtec/rogue/physmem_lma.h
@@ -69,6 +69,7 @@
 							IMG_UINT32 *pui32MappingTable,
 							IMG_UINT32 uiLog2PageSize,
 							PVRSRV_MEMALLOCFLAGS_T uiFlags,
+							const IMG_CHAR *pszAnnotation,
 							PMR **ppsPMRPtr);
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
@@ -76,8 +77,8 @@
  * Define some helper list functions for the virtualization validation code
  */
 
-void	InsertPidOSidsCoupling(IMG_PID pId, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg);
-void	RetrieveOSidsfromPidList(IMG_PID pId, IMG_UINT32 *pui32OSid, IMG_UINT32 *pui32OSidReg);
+void	InsertPidOSidsCoupling(IMG_PID pId, IMG_UINT32 ui32OSid, IMG_UINT32 ui32OSidReg, IMG_BOOL bOSidAxiProt);
+void	RetrieveOSidsfromPidList(IMG_PID pId, IMG_UINT32 *pui32OSid, IMG_UINT32 *pui32OSidReg, IMG_BOOL *pbOSidAxiProt);
 void	RemovePidOSidCoupling(IMG_PID pId);
 #endif
 
diff --git a/drivers/staging/imgtec/rogue/physmem_osmem.h b/drivers/staging/imgtec/rogue/physmem_osmem.h
index 13f7e9d..6c7502c 100644
--- a/drivers/staging/imgtec/rogue/physmem_osmem.h
+++ b/drivers/staging/imgtec/rogue/physmem_osmem.h
@@ -64,15 +64,52 @@
 #include "pmr.h"
 #include "pmr_impl.h"
 
-/*
- * PhysmemNewOSRamBackedPMR
- *
- * To be overridden on a per-OS basis.
- *
- * This function will create a PMR using the default "OS supplied" physical pages
- * method, assuming such is available on a particular operating system.  (If not,
- * PVRSRV_ERROR_NOT_SUPPORTED should be returned)
- */
+/*************************************************************************/ /*!
+@Function       PhysmemNewOSRamBackedPMR
+@Description    Rogue Services will call this function to allocate GPU device 
+                memory from the PMR factory supported by the OS DDK port. This 
+                factory typically obtains physical memory from the kernel/OS 
+                API that allocates memory from the default heap of shared system 
+                memory available on the platform. The allocated memory must be 
+                page-aligned and be a whole number of pages. 
+                After allocating the required memory, the implementation must 
+                then call PMRCreatePMR() to obtain the PMR structure that 
+                describes this allocation to the upper layers of the Services.
+                memory management sub-system. 
+                NB. Implementation of this function is mandatory. If shared 
+                system memory is not to be used in the OS port then the 
+                implementation must return PVRSRV_ERROR_NOT_SUPPORTED.
+
+@Input          psDevNode        the device node
+@Input          uiSize           the size of the allocation
+                                 (must be a multiple of page size)
+@Input          uiChunkSize      when sparse allocations are requested,
+                                 this is the allocated chunk size.
+                                 For regular allocations, this will be
+                                 the same as uiSize.
+                                 (must be a multiple of page size)
+@Input          ui32NumPhysChunks  when sparse allocations are requested,
+                                   this is the number of physical chunks
+                                   to be allocated.
+                                   For regular allocations, this will be 1.
+@Input          ui32NumVirtChunks  when sparse allocations are requested,
+                                   this is the number of virtual chunks
+                                   covering the sparse allocation.
+                                   For regular allocations, this will be 1.
+@Input          pui32MappingTable  when sparse allocations are requested,
+                                   this is the list of the indices of
+                                   each physically-backed virtual chunk
+                                   For regular allocations, this will
+                                   be NULL.
+@Input          uiLog2PageSize   the physical pagesize in log2(bytes).
+@Input          uiFlags          the allocation flags.
+@Input          pszAnnotation    string describing the PMR (for debug).
+                                 This should be passed into the function
+                                 PMRCreatePMR().
+@Output         ppsPMROut        pointer to the PMR created for the
+                                 new allocation
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 extern PVRSRV_ERROR
 PhysmemNewOSRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
                          IMG_DEVMEM_SIZE_T uiSize,
@@ -82,6 +119,7 @@
 						 IMG_UINT32 *pui32MappingTable,
                          IMG_UINT32 uiLog2PageSize,
                          PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                         const IMG_CHAR *pszAnnotation,
                          PMR **ppsPMROut);
 
 #endif /* #ifndef _SRVSRV_PHYSMEM_OSMEM_H_ */
diff --git a/drivers/staging/imgtec/rogue/physmem_osmem_linux.c b/drivers/staging/imgtec/rogue/physmem_osmem_linux.c
index 32e6142..6b4a365b 100644
--- a/drivers/staging/imgtec/rogue/physmem_osmem_linux.c
+++ b/drivers/staging/imgtec/rogue/physmem_osmem_linux.c
@@ -42,37 +42,10 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-
-/* include5/ */
-#include "img_types.h"
-#include "pvr_debug.h"
-#include "pvrsrv_error.h"
-#include "pvrsrv_memallocflags.h"
-#include "rgx_pdump_panics.h"
-/* services/server/include/ */
-#include "allocmem.h"
-#include "osfunc.h"
-#include "pdump_physmem.h"
-#include "pdump_km.h"
-#include "pmr.h"
-#include "pmr_impl.h"
-#include "devicemem_server_utils.h"
-#include "syscommon.h"
-
-/* ourselves */
-#include "physmem_osmem.h"
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#include "process_stats.h"
-#endif
-
 #include <linux/version.h>
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/mm.h>
-#define PHYSMEM_SUPPORTS_SHRINKER
-#endif
-
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/mm_types.h>
@@ -85,20 +58,29 @@
 #include <asm/cacheflush.h>
 #endif
 
+/* include5/ */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+#include "rgx_pdump_panics.h"
+/* services/server/include/ */
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pdump_km.h"
+#include "pmr.h"
+#include "pmr_impl.h"
+#include "devicemem_server_utils.h"
+
+/* ourselves */
+#include "physmem_osmem.h"
 #include "physmem_osmem_linux.h"
 
-/* Provide SHRINK_STOP definition for kernel older than 3.12 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
-#define SHRINK_STOP (~0UL)
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
 #endif
-/* Defines how many pages should be mapped at once to the kernel */
-#define PVR_LINUX_PHYSMEM_MAX_KMAP_PAGES 1024 /* 4 MB */
 
-/* GFP_WAIT got renamed to GFP_RECLAIM in 4.4 */
-/* This allows our code to use the new name on older kernels */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
-#define __GFP_RECLAIM __GFP_WAIT
-#endif
+#include "kernel_compatibility.h"
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
 static IMG_UINT32 g_uiMaxOrder = PVR_LINUX_PHYSMEM_MAX_ALLOC_ORDER_NUM;
@@ -108,89 +90,114 @@
 #define PVR_LINUX_PHYSMEM_MAX_ALLOC_ORDER_NUM 0
 static IMG_UINT32 g_uiMaxOrder = 0;
 #endif
+/* Defines how many pages should be mapped at once to the kernel */
+#define PVR_LINUX_PHYSMEM_MAX_KMAP_PAGES 1024 /* 4 MB */
 
+/* Get/Set/Mask out alloc_page/dma_alloc flag */
+#define DMA_GET_ADDR(x)			(((x) >> 1) << 1)
+#define DMA_SET_ALLOCPG_ADDR(x)	((x) | ((dma_addr_t)0x01))
+#define DMA_IS_ALLOCPG_ADDR(x)	((x) & ((dma_addr_t)0x01))
 
-struct _PMR_OSPAGEARRAY_DATA_ {
+typedef struct _PMR_OSPAGEARRAY_DATA_ {
 	/* Device for which this allocation has been made */
 	PVRSRV_DEVICE_NODE *psDevNode;
 
-    /*
-     * iNumPagesAllocated:
-     * Number of pages allocated in this PMR so far.
-     * Don't think more 8G memory will be used in one PMR
-     */
-    IMG_INT32 iNumPagesAllocated;
+	/*
+	 * iNumPagesAllocated:
+	 * Number of pages allocated in this PMR so far.
+	 * This allows for up to (2^31 - 1) pages. With 4KB pages, that's 8TB of memory for each PMR.
+	 */
+	IMG_INT32 iNumPagesAllocated;
 
-    /*
-     * uiTotalNumPages:
-     * Total number of pages supported by this PMR. (Fixed as of now due the fixed Page table array size)
-     *  number of "pages" (a.k.a. macro pages, compound pages, higher order pages, etc...)
-     */
-    IMG_UINT32 uiTotalNumPages;
+	/*
+	 * uiTotalNumPages:
+	 * Total number of pages supported by this PMR. (Fixed as of now due the fixed Page table array size)
+	 *  number of "pages" (a.k.a. macro pages, compound pages, higher order pages, etc...)
+	 */
+	IMG_UINT32 uiTotalNumPages;
 
-    /*
-      uiLog2PageSize;
-
-      size of each "page" -- this would normally be the same as
-      PAGE_SHIFT, but we support the idea that we may allocate pages
-      in larger chunks for better contiguity, using order>0 in the
-      call to alloc_pages()
-    */
-    IMG_UINT32 uiLog2DevPageSize;
-
-    /*
-      the pages thusly allocated...  N.B.. One entry per compound page,
-      where compound pages are used.
-    */
-    struct page **pagearray;
-
-    /*
-      for pdump...
-    */
-    IMG_BOOL bPDumpMalloced;
-    IMG_HANDLE hPDumpAllocInfo;
-
-    /*
-      record at alloc time whether poisoning will be required when the
-      PMR is freed.
-    */
-    IMG_BOOL bZero;
-    IMG_BOOL bPoisonOnFree;
-    IMG_BOOL bPoisonOnAlloc;
-    IMG_BOOL bOnDemand;
-    IMG_BOOL bUnpinned; /* Should be protected by page pool lock */
-    /*
-	 The cache mode of the PMR (required at free time)
-	 Boolean used to track if we need to revert the cache attributes
-	 of the pages used in this allocation. Depends on OS/architecture.
+	/*
+	  uiLog2PageSize;
+	
+	  size of each "page" -- this would normally be the same as
+	  PAGE_SHIFT, but we support the idea that we may allocate pages
+	  in larger chunks for better contiguity, using order>0 in the
+	  call to alloc_pages()
 	*/
-    IMG_UINT32 ui32CPUCacheFlags;
+	IMG_UINT32 uiLog2DevPageSize;
+
+	/*
+	  For non DMA/CMA allocation, pagearray references the pages
+	  thus allocated; one entry per compound page when compound
+	  pages are used. In addition, for DMA/CMA allocations, we
+	  track the returned cpu virtual and device bus address.
+	*/
+	struct page **pagearray;
+	dma_addr_t *dmaphysarray;
+	void **dmavirtarray;
+
+
+	/*
+	  record at alloc time whether poisoning will be required when the
+	  PMR is freed.
+	*/
+	IMG_BOOL bZero;
+	IMG_BOOL bPoisonOnFree;
+	IMG_BOOL bPoisonOnAlloc;
+	IMG_BOOL bOnDemand;
+	IMG_BOOL bUnpinned; /* Should be protected by page pool lock */
+	IMG_BOOL bIsCMA; /* Is CMA memory allocated via DMA framework */
+
+	/*
+	  The cache mode of the PMR. Additionally carrying the CPU-Cache-Clean
+	  flag, advising us to do cache maintenance on behalf of the caller.
+	  NOTE: For DMA/CMA allocations, memory is _always_ uncached.
+
+	  Boolean used to track if we need to revert the cache attributes
+	  of the pages used in this allocation. Depends on OS/architecture.
+	*/
+	IMG_UINT32 ui32CPUCacheFlags;
 	IMG_BOOL bUnsetMemoryType;
-};
+} PMR_OSPAGEARRAY_DATA;
 
 /***********************************
  * Page pooling for uncached pages *
  ***********************************/
- 
+
+static INLINE void
+_FreeOSPage_CMA(struct device *dev,
+				size_t alloc_size,
+				IMG_UINT32 uiOrder,
+				void *virt_addr,
+				dma_addr_t dev_addr,
+				struct page *psPage);
+
 static void
 _FreeOSPage(IMG_UINT32 uiOrder,
 			IMG_BOOL bUnsetMemoryType,
 			struct page *psPage);
 
 static PVRSRV_ERROR
-_FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData,
-									IMG_UINT32 *pai32FreeIndices,
-									IMG_UINT32 ui32FreePageCount);
+_FreeOSPages(PMR_OSPAGEARRAY_DATA *psPageArrayData,
+			IMG_UINT32 *pai32FreeIndices,
+			IMG_UINT32 ui32FreePageCount);
 
 static PVRSRV_ERROR
 _FreePagesFromPoolUnlocked(IMG_UINT32 uiMaxPagesToFree,
 						   IMG_UINT32 *puiPagesFreed);
 
+static inline void
+_ApplyCacheMaintenance(PVRSRV_DEVICE_NODE *psDevNode,
+					struct page **ppsPage,
+					IMG_UINT32 uiNumPages,
+					IMG_BOOL bFlush);
+
 static inline PVRSRV_ERROR
-_ApplyOSPagesAttribute(struct page **ppsPage,
-					   IMG_UINT32 uiNumPages,
-					   IMG_BOOL bFlush,
-					   IMG_UINT32 ui32CPUCacheFlags);
+_ApplyOSPagesAttribute(PVRSRV_DEVICE_NODE *psDevNode,
+					struct page **ppsPage,
+					IMG_UINT32 uiNumPages,
+					IMG_BOOL bFlush,
+					IMG_UINT32 ui32CPUCacheFlags);
 
 static inline unsigned int
 _GetGFPFlags(IMG_BOOL bZero,
@@ -207,7 +214,7 @@
 	/* How many items are still in the page array */
 	IMG_UINT32 uiItemsRemaining;
 	/* Array of the actual pages */
-	struct page **ppsPageArray; 
+	struct page **ppsPageArray;
 
 } LinuxPagePoolEntry;
 
@@ -223,10 +230,9 @@
 typedef struct
 {
 	struct list_head sUnpinPoolItem;
-	struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayDataPtr;
+	PMR_OSPAGEARRAY_DATA *psPageArrayDataPtr;
 } LinuxUnpinEntry;
 
-
 /* Caches to hold page pool and page array structures */
 static struct kmem_cache *g_psLinuxPagePoolCache = NULL;
 static struct kmem_cache *g_psLinuxPageArray = NULL;
@@ -251,17 +257,17 @@
 #define PVR_LINUX_PHYSMEM_MAX_ASYNC_CLEAN_TASKS 128
 
 /* Defines how many pages the page cache should hold. */
-#if defined(PVR_LINUX_PHYSMEM_MAX_POOL_PAGES) && !defined(SUPPORT_PVRSRV_GPUVIRT)
+#if defined(PVR_LINUX_PHYSMEM_MAX_POOL_PAGES)
 static const IMG_UINT32 g_ui32PagePoolMaxEntries = PVR_LINUX_PHYSMEM_MAX_POOL_PAGES;
 #else
 static const IMG_UINT32 g_ui32PagePoolMaxEntries = 0;
 #endif
 
-/*	We double check if we would exceed this limit if we are below MAX_POOL_PAGES
+/* 	We double check if we would exceed this limit if we are below MAX_POOL_PAGES
 	and want to add an allocation to the pool.
 	This prevents big allocations being given back to the OS just because they
 	exceed the MAX_POOL_PAGES limit even though the pool is currently empty. */
-#if defined(PVR_LINUX_PHYSMEM_MAX_EXCESS_POOL_PAGES)  && !defined(SUPPORT_PVRSRV_GPUVIRT)
+#if defined(PVR_LINUX_PHYSMEM_MAX_EXCESS_POOL_PAGES)
 static const IMG_UINT32 g_ui32PagePoolMaxExcessEntries = PVR_LINUX_PHYSMEM_MAX_EXCESS_POOL_PAGES;
 #else
 static const IMG_UINT32 g_ui32PagePoolMaxExcessEntries = 0;
@@ -280,7 +286,6 @@
 };
 #endif
 
-
 /* Global structures we use to manage the page pool */
 static DEFINE_MUTEX(g_sPagePoolMutex);
 
@@ -318,11 +323,11 @@
 }
 
 static PVRSRV_ERROR
-_AddUnpinListEntryUnlocked(struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData)
+_AddUnpinListEntryUnlocked(PMR_OSPAGEARRAY_DATA *psOSPageArrayData)
 {
 	LinuxUnpinEntry *psUnpinEntry;
 
-	psUnpinEntry = OSAllocMem(sizeof(LinuxUnpinEntry));
+	psUnpinEntry = OSAllocMem(sizeof(*psUnpinEntry));
 	if (!psUnpinEntry)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
@@ -342,7 +347,7 @@
 }
 
 static void
-_RemoveUnpinListEntryUnlocked(struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData)
+_RemoveUnpinListEntryUnlocked(PMR_OSPAGEARRAY_DATA *psOSPageArrayData)
 {
 	LinuxUnpinEntry *psUnpinEntry, *psTempUnpinEntry;
 
@@ -364,13 +369,12 @@
 	g_ui32UnpinPageCount -= psOSPageArrayData->iNumPagesAllocated;
 }
 
-
 static inline IMG_BOOL
 _GetPoolListHead(IMG_UINT32 ui32CPUCacheFlags,
 				 struct list_head **ppsPoolHead,
 				 IMG_UINT32 **ppuiCounter)
 {
-	switch(ui32CPUCacheFlags)
+	switch(PVRSRV_CPU_CACHE_MODE(ui32CPUCacheFlags))
 	{
 		case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
 #if defined(CONFIG_X86)
@@ -403,11 +407,10 @@
 	return IMG_TRUE;
 }
 
-#if defined(PHYSMEM_SUPPORTS_SHRINKER)
 static struct shrinker g_sShrinker;
 
 /* Returning the number of pages that still reside in the page pool. */
-static unsigned long 
+static unsigned long
 _GetNumberOfPagesInPoolUnlocked(void)
 {
 	return _PagesInPoolUnlocked() + g_ui32UnpinPageCount;
@@ -460,11 +463,11 @@
 
 	/* Free unpinned memory, starting with LRU entries */
 	list_for_each_entry_safe(psUnpinEntry,
-	                         psTempUnpinEntry,
-	                         &g_sUnpinList,
-	                         sUnpinPoolItem)
+							 psTempUnpinEntry,
+							 &g_sUnpinList,
+							 sUnpinPoolItem)
 	{
-		struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayDataPtr = psUnpinEntry->psPageArrayDataPtr;
+		PMR_OSPAGEARRAY_DATA *psPageArrayDataPtr = psUnpinEntry->psPageArrayDataPtr;
 		IMG_UINT32 uiNumPages = (psPageArrayDataPtr->uiTotalNumPages > psPageArrayDataPtr->iNumPagesAllocated)?
 								psPageArrayDataPtr->iNumPagesAllocated:psPageArrayDataPtr->uiTotalNumPages;
 		PVRSRV_ERROR eError;
@@ -555,23 +558,19 @@
 	.seeks = DEFAULT_SEEKS
 };
 #endif
-#endif /* defined(PHYSMEM_SUPPORTS_SHRINKER) */
-
 
 /* Register the shrinker so Linux can reclaim cached pages */
 void LinuxInitPhysmem(void)
 {
-	g_psLinuxPageArray = kmem_cache_create("pvr-pa", sizeof(struct _PMR_OSPAGEARRAY_DATA_), 0, 0, NULL);
-	
+	g_psLinuxPageArray = kmem_cache_create("pvr-pa", sizeof(PMR_OSPAGEARRAY_DATA), 0, 0, NULL);
+
 	_PagePoolLock();
 	g_psLinuxPagePoolCache = kmem_cache_create("pvr-pp", sizeof(LinuxPagePoolEntry), 0, 0, NULL);
-#if defined(PHYSMEM_SUPPORTS_SHRINKER)
-	/* Only create the shrinker if we created the cache OK */
-		if (g_psLinuxPagePoolCache)
+	if (g_psLinuxPagePoolCache)
 	{
+		/* Only create the shrinker if we created the cache OK */
 		register_shrinker(&g_sShrinker);
 	}
-#endif
 	_PagePoolUnlock();
 
 	OSAtomicWrite(&g_iPoolCleanTasks, 0);
@@ -585,27 +584,25 @@
 	if (OSAtomicRead(&g_iPoolCleanTasks) > 0)
 	{
 		PVR_DPF((PVR_DBG_WARNING, "Still deferred cleanup tasks running "
-					"while deinitialising memory subsystem."));
+				"while deinitialising memory subsystem."));
 	}
 
 	_PagePoolLock();
 	if (_FreePagesFromPoolUnlocked(IMG_UINT32_MAX, &uiPagesFreed) != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "Unable to free all pages from page pool when "
-					"deinitialising memory subsystem."));
+				"deinitialising memory subsystem."));
 		PVR_ASSERT(0);
 	}
 
 	PVR_ASSERT(_PagesInPoolUnlocked() == 0);
-	
+
 	/* Free the page cache */
 	kmem_cache_destroy(g_psLinuxPagePoolCache);
-	
-#if defined(PHYSMEM_SUPPORTS_SHRINKER)
+
 	unregister_shrinker(&g_sShrinker);
-#endif
 	_PagePoolUnlock();
-	
+
 	kmem_cache_destroy(g_psLinuxPageArray);
 }
 
@@ -626,8 +623,7 @@
 	current->flags |= PF_DUMPCORE;
 }
 
-
-/* Prints out the addresses in a page array for debugging purposes 
+/* Prints out the addresses in a page array for debugging purposes
  * Define PHYSMEM_OSMEM_DEBUG_DUMP_PAGE_ARRAY locally to activate: */
 /* #define PHYSMEM_OSMEM_DEBUG_DUMP_PAGE_ARRAY 1 */
 static inline void
@@ -655,8 +651,8 @@
 }
 
 /* Debugging function that dumps out the number of pages for every
- * page array that is currently in the page pool. 
- * Not defined by default. Define locally to activate feature: */ 
+ * page array that is currently in the page pool.
+ * Not defined by default. Define locally to activate feature: */
 /* #define PHYSMEM_OSMEM_DEBUG_DUMP_PAGE_POOL 1 */
 static void
 _DumpPoolStructure(void)
@@ -693,7 +689,7 @@
 }
 
 /* Free a certain number of pages from the page pool.
- * Mainly used in error paths or at deinitialisation to 
+ * Mainly used in error paths or at deinitialisation to
  * empty the whole pool. */
 static PVRSRV_ERROR
 _FreePagesFromPoolUnlocked(IMG_UINT32 uiMaxPagesToFree,
@@ -740,7 +736,7 @@
 
 #if defined(CONFIG_X86)
 			/* Set the correct page caching attributes on x86 */
-			if (g_aui32CPUCacheFlags[j] != PVRSRV_MEMALLOCFLAG_CPU_CACHED)
+			if (!PVRSRV_CHECK_CPU_CACHED(g_aui32CPUCacheFlags[j]))
 			{
 				int ret;
 				ret = set_pages_array_wb(ppsPageArray, uiItemsToFree);
@@ -797,8 +793,7 @@
 	return eError;
 }
 
-
-/* Get a certain number of pages from the page pool and 
+/* Get a certain number of pages from the page pool and
  * copy them directly into a given page array. */
 static void
 _GetPagesFromPoolUnlocked(IMG_UINT32 ui32CPUCacheFlags,
@@ -806,58 +801,57 @@
 						  struct page **ppsPageArray,
 						  IMG_UINT32 *puiNumReceivedPages)
 {
-		LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
-		struct list_head *psPoolHead = NULL;
-		IMG_UINT32 i;
-		IMG_UINT32 *puiCounter;
+	LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+	struct list_head *psPoolHead = NULL;
+	IMG_UINT32 i;
+	IMG_UINT32 *puiCounter;
 
-		*puiNumReceivedPages = 0;
+	*puiNumReceivedPages = 0;
 
+	/* Get the correct list for this caching mode */
+	if (!_GetPoolListHead(ui32CPUCacheFlags, &psPoolHead, &puiCounter))
+	{
+		return;
+	}
 
-		/* Get the correct list for this caching mode */
-		if (!_GetPoolListHead(ui32CPUCacheFlags, &psPoolHead, &puiCounter))
+	/* Check if there are actually items in the list */
+	if (list_empty(psPoolHead))
+	{
+		return;
+	}
+
+	PVR_ASSERT(*puiCounter > 0);
+
+	/* Receive pages from the pool */
+	list_for_each_entry_safe(psPagePoolEntry,
+							 psTempPoolEntry,
+							 psPoolHead,
+							 sPagePoolItem)
+	{
+		/* Get the pages from this pool entry */
+		for (i = psPagePoolEntry->uiItemsRemaining; i != 0 && *puiNumReceivedPages < uiMaxNumPages; i--)
 		{
-			return;
+			ppsPageArray[*puiNumReceivedPages] = psPagePoolEntry->ppsPageArray[i-1];
+			(*puiNumReceivedPages)++;
+			psPagePoolEntry->uiItemsRemaining--;
 		}
 
-		/* Check if there are actually items in the list */
-		if (list_empty(psPoolHead))
+		/* Is this pool entry exhausted, delete it */
+		if (psPagePoolEntry->uiItemsRemaining == 0)
 		{
-			return;
+			OSFreeMemNoStats(psPagePoolEntry->ppsPageArray);
+			list_del(&psPagePoolEntry->sPagePoolItem);
+			kmem_cache_free(g_psLinuxPagePoolCache, psPagePoolEntry);
 		}
 
-		PVR_ASSERT(*puiCounter > 0);
-
-		/* Receive pages from the pool */
-		list_for_each_entry_safe(psPagePoolEntry,
-								 psTempPoolEntry,
-								 psPoolHead,
-								 sPagePoolItem)
+		/* Return if we have all our pages */
+		if (*puiNumReceivedPages == uiMaxNumPages)
 		{
-			/* Get the pages from this pool entry */
-			for (i = psPagePoolEntry->uiItemsRemaining; i != 0 && *puiNumReceivedPages < uiMaxNumPages; i--)
-			{
-				ppsPageArray[*puiNumReceivedPages] = psPagePoolEntry->ppsPageArray[i-1];
-				(*puiNumReceivedPages)++;
-				psPagePoolEntry->uiItemsRemaining--;
-			}
-
-			/* Is this pool entry exhausted, delete it */
-			if (psPagePoolEntry->uiItemsRemaining == 0)
-			{
-				OSFreeMemNoStats(psPagePoolEntry->ppsPageArray);
-				list_del(&psPagePoolEntry->sPagePoolItem);
-				kmem_cache_free(g_psLinuxPagePoolCache, psPagePoolEntry);
-			}
-
-			/* Return if we have all our pages */
-			if (*puiNumReceivedPages == uiMaxNumPages)
-			{
-				goto exit_ok;
-			}	
+			goto exit_ok;
 		}
+	}
 
-exit_ok:		
+exit_ok:
 
 	/* Update counters */
 	*puiCounter -= *puiNumReceivedPages;
@@ -871,15 +865,16 @@
 	 */
 	PVRSRVStatsDecrMemAllocPoolStat(PAGE_SIZE * (*puiNumReceivedPages));
 #endif
-	
+
 	_DumpPoolStructure();
 	return;
 }
 
-/* Same as _GetPagesFromPoolUnlocked but handles locking and 
+/* Same as _GetPagesFromPoolUnlocked but handles locking and
  * checks first whether pages from the pool are a valid option. */
 static inline void
-_GetPagesFromPoolLocked(IMG_UINT32 ui32CPUCacheFlags,
+_GetPagesFromPoolLocked(PVRSRV_DEVICE_NODE *psDevNode,
+						IMG_UINT32 ui32CPUCacheFlags,
 						IMG_UINT32 uiPagesToAlloc,
 						IMG_UINT32 uiOrder,
 						IMG_BOOL bZero,
@@ -887,38 +882,38 @@
 						IMG_UINT32 *puiPagesFromPool)
 {
 #if defined(PVR_LINUX_PHYSMEM_ZERO_ALL_PAGES)
-		PVR_UNREFERENCED_PARAMETER(bZero);
+	PVR_UNREFERENCED_PARAMETER(bZero);
 #else
-		/* Don't get pages from pool if it doesn't provide zeroed pages */
-		if (bZero)
-		{
-			return;
-		}
+	/* Don't get pages from pool if it doesn't provide zeroed pages */
+	if (bZero)
+	{
+		return;
+	}
 #endif
 
-	/* The page pool stores only order 0 pages. If we need zeroed memory we 
+	/* The page pool stores only order 0 pages. If we need zeroed memory we
 	 * directly allocate from the OS because it is faster than
-	 * doing it withing the driver. */
+	 * doing it within the driver. */
 	if (uiOrder == 0 &&
 	    !PVRSRV_CHECK_CPU_CACHED(ui32CPUCacheFlags))
 	{
+
 		_PagePoolLock();
-		
 		_GetPagesFromPoolUnlocked(ui32CPUCacheFlags,
 								  uiPagesToAlloc,
 								  ppsPageArray,
 								  puiPagesFromPool);
 		_PagePoolUnlock();
-	}	
-	
+	}
+
 	return;
 }
 
-/* Takes a page array and maps it into the kernel to write zeros */
+/* Takes a page array and maps it into the kernel to write zeros */ 
 static PVRSRV_ERROR
 _ZeroPageArray(IMG_UINT32 uiNumToClean,
-		               struct page **ppsCleanArray,
-					                  pgprot_t pgprot)
+               struct page **ppsCleanArray,
+               pgprot_t pgprot)
 {
 	IMG_CPU_VIRTADDR pvAddr;
 	IMG_UINT32 uiMaxPagesToMap = PVR_LINUX_PHYSMEM_MAX_KMAP_PAGES;
@@ -928,40 +923,39 @@
 	 * at a time. */
 	while (uiNumToClean != 0)
 	{
-			IMG_UINT32 uiToClean = (uiNumToClean >= uiMaxPagesToMap) ?
-			                        uiMaxPagesToMap :
-			                        uiNumToClean;
+		IMG_UINT32 uiToClean = (uiNumToClean >= uiMaxPagesToMap) ?
+		                        uiMaxPagesToMap :
+		                        uiNumToClean;
 
-			pvAddr = vm_map_ram(ppsCleanArray, uiToClean, -1, pgprot);
-			if (!pvAddr)
+		pvAddr = vm_map_ram(ppsCleanArray, uiToClean, -1, pgprot);
+		if (!pvAddr)
+		{
+			if (uiMaxPagesToMap <= 1)
 			{
-				if (uiMaxPagesToMap <= 1)
-				{
-					PVR_DPF((PVR_DBG_ERROR,
-								"%s: Out of vmalloc memory, "
-								"unable to map pages for zeroing.",
-								__func__));
-					return PVRSRV_ERROR_OUT_OF_MEMORY;
-				}
-				else
-				{
-					/* Half the pages to map at once and try again. */
-					uiMaxPagesToMap = uiMaxPagesToMap >> 1;
-					continue;
-				}
+				PVR_DPF((PVR_DBG_ERROR,
+						"%s: Out of vmalloc memory, "
+						"unable to map pages for zeroing.",
+						__func__));
+				return PVRSRV_ERROR_OUT_OF_MEMORY;
 			}
+			else
+			{
+				/* Half the pages to map at once and try again. */
+				uiMaxPagesToMap = uiMaxPagesToMap >> 1;
+				continue;
+			}
+		}
 
-			OSDeviceMemSet(pvAddr, 0, PAGE_SIZE * uiToClean);
-			vm_unmap_ram(pvAddr, uiToClean);
+		OSDeviceMemSet(pvAddr, 0, PAGE_SIZE * uiToClean);
+		vm_unmap_ram(pvAddr, uiToClean);
 
-			ppsCleanArray = &(ppsCleanArray[uiToClean]);
-			uiNumToClean -= uiToClean;
+		ppsCleanArray = &(ppsCleanArray[uiToClean]);
+		uiNumToClean -= uiToClean;
 	}
 
 	return PVRSRV_OK;
 }
 
-
 static PVRSRV_ERROR
 _CleanupThread_CleanPages(void *pvData)
 {
@@ -992,8 +986,8 @@
 
 		default:
 			PVR_DPF((PVR_DBG_ERROR,
-						"%s: Unknown caching mode to set page protection flags.",
-						__func__));
+					"%s: Unknown caching mode to set page protection flags.",
+					__func__));
 			eError = PVRSRV_ERROR_INVALID_PARAMS;
 			goto eExit;
 	}
@@ -1003,8 +997,8 @@
 	 * For large page arrays do it PVR_LINUX_PHYSMEM_MAX_KMAP_SIZE
 	 * at a time. */
 	eError = _ZeroPageArray(psPagePoolEntry->uiItemsRemaining,
-			psPagePoolEntry->ppsPageArray,
-			pgprot);
+	                        psPagePoolEntry->ppsPageArray,
+	                        pgprot);
 	if (eError != PVRSRV_OK)
 	{
 		goto eExit;
@@ -1034,8 +1028,8 @@
 		IMG_UINT32 i;
 
 		PVR_DPF((PVR_DBG_ERROR,
-					"%s: Deferred task error, freeing pages to OS.",
-					__func__));
+						"%s: Deferred task error, freeing pages to OS.",
+						__func__));
 		_PagePoolLock();
 
 		*puiCounter -= psPagePoolEntry->uiItemsRemaining;
@@ -1055,8 +1049,8 @@
 		for (i = 0; i < psCleanupData->psPoolEntry->uiItemsRemaining; i++)
 		{
 			_FreeOSPage(0,
-					IMG_TRUE,
-					psPagePoolEntry->ppsPageArray[i]);
+						IMG_TRUE,
+						psPagePoolEntry->ppsPageArray[i]);
 		}
 		OSFreeMemNoStats(psPagePoolEntry->ppsPageArray);
 		kmem_cache_free(g_psLinuxPagePoolCache, psPagePoolEntry);
@@ -1068,19 +1062,20 @@
 	return eError;
 }
 
-/* Put page array to the page pool.
+
+/* Put page array to the page pool. 
    Handles locking and checks whether the pages are
  * suitable to be stored in the pool. */
 static inline IMG_BOOL
 _PutPagesToPoolLocked(IMG_UINT32 ui32CPUCacheFlags,
 					  struct page **ppsPageArray,
-					  IMG_BOOL bUnpinned, 
+					  IMG_BOOL bUnpinned,
 					  IMG_UINT32 uiOrder,
 					  IMG_UINT32 uiNumPages)
 {
 	LinuxCleanupData *psCleanupData;
 	PVRSRV_CLEANUP_THREAD_WORK *psCleanupThreadFn;
-	
+
 	if (uiOrder == 0 &&
 		!bUnpinned &&
 		!PVRSRV_CHECK_CPU_CACHED(ui32CPUCacheFlags))
@@ -1095,10 +1090,10 @@
 		uiEntries = _PagesInPoolUnlocked();
 
 		/* Check for number of current page pool entries and whether
-		   we have other asynchronous tasks in-flight */
+		    we have other asynchronous tasks in-flight */
 		if ( (uiEntries < g_ui32PagePoolMaxEntries) &&
-				((uiEntries + uiNumPages) <
-				 (g_ui32PagePoolMaxEntries + g_ui32PagePoolMaxExcessEntries) ))
+		     ((uiEntries + uiNumPages) <
+		      (g_ui32PagePoolMaxEntries + g_ui32PagePoolMaxExcessEntries) ))
 		{
 			if (OSAtomicIncrement(&g_iPoolCleanTasks) <=
 					PVR_LINUX_PHYSMEM_MAX_ASYNC_CLEAN_TASKS)
@@ -1108,9 +1103,9 @@
 				if(!psCleanupData)
 				{
 					PVR_DPF((PVR_DBG_ERROR,
-								"%s: Failed to get memory for deferred page pool cleanup. "
-								"Trying to free pages immediately",
-								__FUNCTION__));
+							 "%s: Failed to get memory for deferred page pool cleanup. "
+							 "Trying to free pages immediately",
+							 __FUNCTION__));
 					goto eDecrement;
 				}
 
@@ -1121,17 +1116,17 @@
 				if(!psCleanupData->psPoolEntry)
 				{
 					PVR_DPF((PVR_DBG_ERROR,
-								"%s: Failed to get memory for deferred page pool cleanup. "
-								"Trying to free pages immediately",
-								__FUNCTION__));
+							 "%s: Failed to get memory for deferred page pool cleanup. "
+							 "Trying to free pages immediately",
+							 __FUNCTION__));
 					goto eFreeCleanupData;
 				}
 
 				if (!_GetPoolListHead(ui32CPUCacheFlags, &psPoolHead, &puiCounter))
 				{
 					PVR_DPF((PVR_DBG_ERROR,
-								"%s: Failed to get correct page pool",
-								__FUNCTION__));
+							 "%s: Failed to get correct page pool",
+							 __FUNCTION__));
 					goto eFreePoolEntry;
 				}
 
@@ -1144,7 +1139,8 @@
 				psCleanupThreadFn->pfnFree = _CleanupThread_CleanPages;
 				psCleanupThreadFn->pvData = psCleanupData;
 				psCleanupThreadFn->ui32RetryCount = CLEANUP_THREAD_RETRY_COUNT_DEFAULT;
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+				psCleanupThreadFn->bDependsOnHW = IMG_FALSE;
+	#if defined(PVRSRV_ENABLE_PROCESS_STATS)
 				/* MemStats usually relies on having the bridge lock held, however
 				 * the page pool code may call PVRSRVStatsIncrMemAllocPoolStat and
 				 * PVRSRVStatsDecrMemAllocPoolStat without the bridge lock held, so
@@ -1152,7 +1148,7 @@
 				 * exclusive
 				 */
 				PVRSRVStatsIncrMemAllocPoolStat(PAGE_SIZE * uiNumPages);
-#endif
+	#endif
 
 				/* We must not hold the pool lock when calling AddWork because it might call us back to
 				 * free pooled pages directly when unloading the driver	 */
@@ -1172,9 +1168,12 @@
 		{
 			goto eUnlock;
 		}
-	} else {
+	}
+	else
+	{
 		goto eExitFalse;
 	}
+
 	return IMG_TRUE;
 
 eFreePoolEntry:
@@ -1194,15 +1193,16 @@
 _GetGFPFlags(IMG_BOOL bZero,
              PVRSRV_DEVICE_NODE *psDevNode)
 {
+	struct device *psDev = psDevNode->psDevConfig->pvOSDevice;
 	unsigned int gfp_flags = 0;
 	gfp_flags = GFP_USER | __GFP_NOWARN | __GFP_NOMEMALLOC;
 
-	if (SysDevicePhysAddressMask() == SYS_PHYS_ADDRESS_32_BIT)
+	if (*psDev->dma_mask == DMA_BIT_MASK(32))
 	{
 		/* Limit to 32 bit.
 		 * Achieved by NOT setting __GFP_HIGHMEM for 32 bit systems and
          * setting __GFP_DMA32 for 64 bit systems */
-		gfp_flags |= __GFP_DMA32; 
+		gfp_flags |= __GFP_DMA32;
 	}
 	else
 	{
@@ -1221,35 +1221,35 @@
 /* Poison a page of order uiOrder with string taken from pacPoisonData*/
 static void
 _PoisonPages(struct page *page,
-             IMG_UINT32 uiOrder,
-             const IMG_CHAR *pacPoisonData,
-             size_t uiPoisonSize)
+			 IMG_UINT32 uiOrder,
+			 const IMG_CHAR *pacPoisonData,
+			 size_t uiPoisonSize)
 {
-    void *kvaddr;
-    IMG_UINT32 uiSrcByteIndex;
-    IMG_UINT32 uiDestByteIndex;
-    IMG_UINT32 uiSubPageIndex;
-    IMG_CHAR *pcDest;
+	void *kvaddr;
+	IMG_UINT32 uiSrcByteIndex;
+	IMG_UINT32 uiDestByteIndex;
+	IMG_UINT32 uiSubPageIndex;
+	IMG_CHAR *pcDest;
 
-    uiSrcByteIndex = 0;
-    for (uiSubPageIndex = 0; uiSubPageIndex < (1U << uiOrder); uiSubPageIndex++)
-    {
-        kvaddr = kmap(page + uiSubPageIndex);
+	uiSrcByteIndex = 0;
+	for (uiSubPageIndex = 0; uiSubPageIndex < (1U << uiOrder); uiSubPageIndex++)
+	{
+		kvaddr = kmap(page + uiSubPageIndex);
+		pcDest = kvaddr;
 
-        pcDest = kvaddr;
+		for(uiDestByteIndex=0; uiDestByteIndex<PAGE_SIZE; uiDestByteIndex++)
+		{
+			pcDest[uiDestByteIndex] = pacPoisonData[uiSrcByteIndex];
+			uiSrcByteIndex++;
+			if (uiSrcByteIndex == uiPoisonSize)
+			{
+				uiSrcByteIndex = 0;
+			}
+		}
 
-        for(uiDestByteIndex=0; uiDestByteIndex<PAGE_SIZE; uiDestByteIndex++)
-        {
-            pcDest[uiDestByteIndex] = pacPoisonData[uiSrcByteIndex];
-            uiSrcByteIndex++;
-            if (uiSrcByteIndex == uiPoisonSize)
-            {
-                uiSrcByteIndex = 0;
-            }
-        }
-        flush_dcache_page(page); 
-        kunmap(page + uiSubPageIndex);
-    }
+		flush_dcache_page(page);
+		kunmap(page + uiSubPageIndex);
+	}
 }
 
 static const IMG_CHAR _AllocPoison[] = "^PoIsOn";
@@ -1259,100 +1259,120 @@
 
 /* Allocate and initialise the structure to hold the metadata of the allocation */
 static PVRSRV_ERROR
-_AllocOSPageArray(PMR_SIZE_T uiChunkSize,
-        IMG_UINT32 ui32NumPhysChunks,
-        IMG_UINT32 ui32NumVirtChunks,
-        IMG_UINT32 uiLog2DevPageSize,
-        IMG_BOOL bZero,
-        IMG_BOOL bPoisonOnAlloc,
-        IMG_BOOL bPoisonOnFree,
-        IMG_BOOL bOnDemand,
-        IMG_UINT32 ui32CPUCacheFlags,
-		struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
+_AllocOSPageArray(PVRSRV_DEVICE_NODE *psDevNode,
+				  PMR_SIZE_T uiChunkSize,
+				  IMG_UINT32 ui32NumPhysChunks,
+				  IMG_UINT32 ui32NumVirtChunks,
+				  IMG_UINT32 uiLog2DevPageSize,
+				  IMG_BOOL bZero,
+				  IMG_BOOL bIsCMA,
+				  IMG_BOOL bPoisonOnAlloc,
+				  IMG_BOOL bPoisonOnFree,
+				  IMG_BOOL bOnDemand,
+				  IMG_UINT32 ui32CPUCacheFlags,
+				  PMR_OSPAGEARRAY_DATA **ppsPageArrayDataPtr)
 {
-    PVRSRV_ERROR eError;
-    PMR_SIZE_T uiSize = uiChunkSize * ui32NumVirtChunks;
-    IMG_UINT32 ui32NumVirtPages = 0;
+	PVRSRV_ERROR eError;
+	PMR_SIZE_T uiSize = uiChunkSize * ui32NumVirtChunks;
+	IMG_UINT32 uiNumOSPageSizeVirtPages;
+	IMG_UINT32 uiNumDevPageSizeVirtPages;
+	PMR_OSPAGEARRAY_DATA *psPageArrayData;
+	PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
 
-    struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData;
-    PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+	/* Sanity check of the alloc size */
+	if (uiSize >= 0x1000000000ULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Do you really want 64GB of physical memory in one go? "
+				 "This is likely a bug", __func__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto e_freed_none;
+	}
 
-    /* Sanity check of the alloc size */
-    if (uiSize >= 0x1000000000ULL)
-    {
-        PVR_DPF((PVR_DBG_ERROR,
-                 "%s: Do you really want 64GB of physical memory in one go? "
-                 "This is likely a bug", __func__));
-        eError = PVRSRV_ERROR_INVALID_PARAMS;
-        goto e_freed_psPageArrayData;
-    }
+	/* Check that we allocate the correct contiguity */
+	PVR_ASSERT(PAGE_SHIFT <= uiLog2DevPageSize);
+	if ((uiSize & ((1ULL << uiLog2DevPageSize) - 1)) != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"Allocation size " PMR_SIZE_FMTSPEC " is not multiple of page size 2^%u !",
+				 uiSize,
+				 uiLog2DevPageSize));
 
-    /* Check that we allocate the correct contiguitiy */
-    PVR_ASSERT(PAGE_SHIFT <= uiLog2DevPageSize);
-    if ((uiSize & ((1ULL << uiLog2DevPageSize) - 1)) != 0)
-    {
-    	PVR_DPF((PVR_DBG_ERROR,
-    			"Allocation size "PMR_SIZE_FMTSPEC" is not multiple of page size 2^%u !",
-                 uiSize,
-                 uiLog2DevPageSize));
+		eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+		goto e_freed_none;
+	}
 
-        eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
-        goto e_freed_psPageArrayData;
-    }
+	/* Use of cast below is justified by the assertion that follows to
+	   prove that no significant bits have been truncated */
+	uiNumOSPageSizeVirtPages = (IMG_UINT32) (((uiSize - 1) >> PAGE_SHIFT) + 1);
+	PVR_ASSERT(((PMR_SIZE_T) uiNumOSPageSizeVirtPages << PAGE_SHIFT) == uiSize);
+	uiNumDevPageSizeVirtPages = uiNumOSPageSizeVirtPages >> (uiLog2DevPageSize - PAGE_SHIFT);
 
-   /* Use of cast below is justified by the assertion that follows to
-       prove that no significant bits have been truncated */
-    ui32NumVirtPages = (IMG_UINT32) (((uiSize - 1) >> PAGE_SHIFT) + 1);
-    PVR_ASSERT(((PMR_SIZE_T) ui32NumVirtPages << PAGE_SHIFT) == uiSize);
+	/* Allocate the struct to hold the metadata */
+	psPageArrayData = kmem_cache_alloc(g_psLinuxPageArray, GFP_KERNEL);
+	if (psPageArrayData == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: OS refused the memory allocation for the private data.",
+				 __func__));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e_freed_none;
+	}
 
-    /* Allocate the struct to hold the metadata */
-    psPageArrayData = kmem_cache_alloc(g_psLinuxPageArray, GFP_KERNEL);
-    if (psPageArrayData == NULL)
-    {
-        PVR_DPF((PVR_DBG_ERROR,
-                 "%s: OS refused the memory allocation for the private data.",
-                 __func__));
-        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-        goto e_freed_psPageArrayData;
-    }
-
-	/* Allocate the page array.
+	/* 
+	 * Allocate the page array
 	 *
 	 * We avoid tracking this memory because this structure might go into the page pool.
 	 * The OS can drain the pool asynchronously and when doing that we have to avoid
 	 * any potential deadlocks.
+	 *
 	 * In one scenario the process stats vmalloc hash table lock is held and then
 	 * the oom-killer softirq is trying to call _ScanObjectsInPagePool(), it must not
 	 * try to acquire the vmalloc hash table lock again.
 	 */
-    psPageArrayData->pagearray = OSAllocZMemNoStats(sizeof(struct page *) * ui32NumVirtPages);
-    if (psPageArrayData->pagearray == NULL)
-    {
-        kmem_cache_free(g_psLinuxPageArray, psPageArrayData);
-        PVR_DPF((PVR_DBG_ERROR,
-                 "%s: OS refused the memory allocation for the page pointer table. "
-                 "Did you ask for too much?", 
-                 __func__));
-        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-        goto e_freed_psPageArrayData;
-    }
+	psPageArrayData->pagearray = OSAllocZMemNoStats(sizeof(struct page *) * uiNumDevPageSizeVirtPages);
+	if (psPageArrayData->pagearray == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e_free_kmem_cache;
+	}
+	else
+	{
+		if (bIsCMA)
+		{
+			/* Allocate additional DMA/CMA cpu kernel virtual address & device bus address array state */
+			psPageArrayData->dmavirtarray = OSAllocZMemNoStats(sizeof(void*) * uiNumDevPageSizeVirtPages);
+			if (psPageArrayData->dmavirtarray == NULL)
+			{
+				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto e_free_pagearray;
+			}
 
-    /* Init metadata */
-    psPageArrayData->iNumPagesAllocated = 0;
-    psPageArrayData->uiTotalNumPages = ui32NumVirtPages;
-    psPageArrayData->uiLog2DevPageSize = uiLog2DevPageSize;
-    
-    psPageArrayData->bPDumpMalloced = IMG_FALSE;
-    psPageArrayData->bZero = bZero;
- 	psPageArrayData->bPoisonOnFree = bPoisonOnFree;
- 	psPageArrayData->bPoisonOnAlloc = bPoisonOnAlloc;
- 	psPageArrayData->bOnDemand = bOnDemand;
- 	psPageArrayData->bUnpinned = IMG_FALSE;
-    psPageArrayData->ui32CPUCacheFlags = ui32CPUCacheFlags;
+			psPageArrayData->dmaphysarray = OSAllocZMemNoStats(sizeof(dma_addr_t) * uiNumDevPageSizeVirtPages);
+			if (psPageArrayData->dmaphysarray == NULL)
+			{
+				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto e_free_cpuvirtaddrarray;
+			}
+		}
+	}
+
+	/* Init metadata */
+	psPageArrayData->psDevNode = psDevNode;
+	psPageArrayData->iNumPagesAllocated = 0;
+	psPageArrayData->uiTotalNumPages = uiNumOSPageSizeVirtPages;
+	psPageArrayData->uiLog2DevPageSize = uiLog2DevPageSize;
+	psPageArrayData->bZero = bZero;
+	psPageArrayData->bIsCMA = bIsCMA;
+	psPageArrayData->bOnDemand = bOnDemand;
+	psPageArrayData->bUnpinned = IMG_FALSE;
+	psPageArrayData->bPoisonOnFree = bPoisonOnFree;
+	psPageArrayData->bPoisonOnAlloc = bPoisonOnAlloc;
+	psPageArrayData->ui32CPUCacheFlags = ui32CPUCacheFlags;
 
 	/* Indicate whether this is an allocation with default caching attribute (i.e cached) or not */
-	if (ui32CPUCacheFlags == PVRSRV_MEMALLOCFLAG_CPU_UNCACHED || 
-	    ui32CPUCacheFlags == PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE)
+	if (PVRSRV_CHECK_CPU_UNCACHED(ui32CPUCacheFlags) ||
+		PVRSRV_CHECK_CPU_WRITE_COMBINE(ui32CPUCacheFlags))
 	{
 		psPageArrayData->bUnsetMemoryType = IMG_TRUE;
 	}
@@ -1362,43 +1382,143 @@
 	}
 
 	*ppsPageArrayDataPtr = psPageArrayData;
-
 	return PVRSRV_OK;
 
-/* Error path */	
-e_freed_psPageArrayData:
-   PVR_ASSERT(eError != PVRSRV_OK);
-   return eError;
+/* Error path */
+e_free_cpuvirtaddrarray:
+	OSFreeMemNoStats(psPageArrayData->dmavirtarray);
+
+e_free_pagearray:
+	OSFreeMemNoStats(psPageArrayData->pagearray);
+
+e_free_kmem_cache:
+	kmem_cache_free(g_psLinuxPageArray, psPageArrayData);
+	PVR_DPF((PVR_DBG_ERROR,
+			 "%s: OS refused the memory allocation for the page pointer table. "
+			 "Did you ask for too much?", 
+			 __func__));
+
+e_freed_none:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
 }
 
-/* Change the caching attribute of pages on x86 systems 
- * (does cache maintainance as well). 
- * 
+static inline void
+_ApplyCacheMaintenance(PVRSRV_DEVICE_NODE *psDevNode,
+					   struct page **ppsPage,
+					   IMG_UINT32 uiNumPages,
+					   IMG_BOOL bFlush)
+{
+	PVRSRV_ERROR eError = PVRSRV_ERROR_RETRY;
+	void * pvAddr;
+
+
+	if ((uiNumPages << PAGE_SHIFT) >= PVR_DIRTY_BYTES_FLUSH_THRESHOLD)
+	{
+		/* May fail so fallback to range-based flush */
+		eError = OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
+	}
+
+
+	if (eError != PVRSRV_OK)
+	{
+
+		if (OSCPUCacheOpAddressType(PVRSRV_CACHE_OP_FLUSH) == PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL)
+		{
+			pgprot_t pgprot = PAGE_KERNEL;
+
+			IMG_UINT32 uiNumToClean = uiNumPages;
+			struct page **ppsCleanArray = ppsPage;
+
+			/* Map and flush page.
+			 * For large page arrays do it PVR_LINUX_PHYSMEM_MAX_KMAP_SIZE
+			 * at a time. */
+			while (uiNumToClean != 0)
+			{
+				IMG_UINT32 uiToClean = (uiNumToClean >= PVR_LINUX_PHYSMEM_MAX_KMAP_PAGES) ?
+											PVR_LINUX_PHYSMEM_MAX_KMAP_PAGES :
+											uiNumToClean;
+				IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
+
+				pvAddr = vm_map_ram(ppsCleanArray, uiToClean, -1, pgprot);
+				if (!pvAddr)
+				{
+					PVR_DPF((PVR_DBG_ERROR,
+							"Unable to flush page cache for new allocation, skipping flush."));
+					return;
+				}
+
+				OSFlushCPUCacheRangeKM(psDevNode,
+									   pvAddr,
+									   pvAddr + PAGE_SIZE,
+									   sCPUPhysAddrStart,
+									   sCPUPhysAddrEnd);
+
+				vm_unmap_ram(pvAddr, uiToClean);
+
+				ppsCleanArray = &(ppsCleanArray[uiToClean]);
+				uiNumToClean -= uiToClean;
+			}
+		}
+		else
+		{
+			IMG_UINT32 ui32Idx;
+
+			for (ui32Idx = 0; ui32Idx < uiNumPages;  ++ui32Idx)
+			{
+				IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
+
+				pvAddr = kmap(ppsPage[ui32Idx]);
+				sCPUPhysAddrStart.uiAddr = page_to_phys(ppsPage[ui32Idx]);
+				sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
+
+				/* If we're zeroing, we need to make sure the cleared memory is pushed out
+				   of the cache before the cache lines are invalidated */
+				OSFlushCPUCacheRangeKM(psDevNode,
+				                       pvAddr,
+				                       pvAddr + PAGE_SIZE,
+									   sCPUPhysAddrStart,
+									   sCPUPhysAddrEnd);
+
+				kunmap(ppsPage[ui32Idx]);
+			}
+		}
+
+	}
+}
+
+/* Change the caching attribute of pages on x86 systems and takes care of
+ * cache maintenance. This function is supposed to be called once for pages that
+ * came from alloc_pages().
+ *
  * Flush/Invalidate pages in case the allocation is not cached. Necessary to
  * remove pages from the cache that might be flushed later and corrupt memory. */
-static inline PVRSRV_ERROR 
-_ApplyOSPagesAttribute(struct page **ppsPage,
+static inline PVRSRV_ERROR
+_ApplyOSPagesAttribute(PVRSRV_DEVICE_NODE *psDevNode,
+					   struct page **ppsPage,
 					   IMG_UINT32 uiNumPages,
 					   IMG_BOOL bFlush,
 					   IMG_UINT32 ui32CPUCacheFlags)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
-	
+	IMG_BOOL bCPUCached = PVRSRV_CHECK_CPU_CACHED(ui32CPUCacheFlags);
+	IMG_BOOL bCPUUncached = PVRSRV_CHECK_CPU_UNCACHED(ui32CPUCacheFlags);
+	IMG_BOOL bCPUWriteCombine = PVRSRV_CHECK_CPU_WRITE_COMBINE(ui32CPUCacheFlags);
+
 	if (ppsPage != NULL)
 	{
-#if defined (CONFIG_X86)	
-		/* On x86 we have to set page cache attributes for non-cached pages. 
+#if defined (CONFIG_X86)
+		/* On x86 we have to set page cache attributes for non-cached pages.
 		 * The call is implicitly taking care of all flushing/invalidating
-		 * and therefore we can skip the usual cache maintainance after this. */
-		if (PVRSRV_CPU_CACHE_MODE(ui32CPUCacheFlags) == PVRSRV_MEMALLOCFLAG_CPU_UNCACHED ||
-			PVRSRV_CPU_CACHE_MODE(ui32CPUCacheFlags) == PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE)
+		 * and therefore we can skip the usual cache maintenance after this. */
+		if (bCPUUncached || bCPUWriteCombine)
 		{
 			/*  On X86 if we already have a mapping (e.g. low memory) we need to change the mode of
 				current mapping before we map it ourselves	*/
 			int ret = IMG_FALSE;
 			PVR_UNREFERENCED_PARAMETER(bFlush);
-	
-			switch (ui32CPUCacheFlags)
+
+			switch (PVRSRV_CPU_CACHE_MODE(ui32CPUCacheFlags))
 			{
 				case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
 					ret = set_pages_array_uc(ppsPage, uiNumPages);
@@ -1408,7 +1528,7 @@
 						PVR_DPF((PVR_DBG_ERROR, "Setting Linux page caching mode to UC failed, returned %d", ret));
 					}
 					break;
-	
+
 				case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
 					ret = set_pages_array_wc(ppsPage, uiNumPages);
 					if (ret)
@@ -1417,69 +1537,33 @@
 						PVR_DPF((PVR_DBG_ERROR, "Setting Linux page caching mode to WC failed, returned %d", ret));
 					}
 					break;
-	
+
 				case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
 					break;
-	
+
 				default:
 					break;
 			}
 		}
 		else
-#else
-	PVR_UNREFERENCED_PARAMETER(ui32CPUCacheFlags);
 #endif
 		{
-			/*  We can be given pages which still remain in the cache.
-				In order to make sure that the data we write through our mappings
-				doesn't get overwritten by later cache evictions we invalidate the
-				pages that are given to us.
-		
-				Note:
-				This still seems to be true if we request cold pages, it's just less
-				likely to be in the cache. */
-
-			IMG_UINT32 ui32Idx;
-
-			eError = PVRSRV_ERROR_RETRY;
-			if (uiNumPages >= PVR_DIRTY_PAGECOUNT_FLUSH_THRESHOLD)
+			if ( bFlush ||
+				 bCPUUncached || bCPUWriteCombine ||
+				 (bCPUCached && PVRSRV_CHECK_CPU_CACHE_CLEAN(ui32CPUCacheFlags)) )
 			{
-				/* May fail so fallback to range-based flush */
-				eError = OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
-			}
+				/*  We can be given pages which still remain in the cache.
+					In order to make sure that the data we write through our mappings
+					doesn't get overwritten by later cache evictions we invalidate the
+					pages that are given to us.
 
-			if (eError != PVRSRV_OK)
-			{
-				for (ui32Idx = 0; ui32Idx < uiNumPages;  ++ui32Idx)
-				{
-					IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
-					void *pvPageVAddr;
-
-					pvPageVAddr = kmap(ppsPage[ui32Idx]);
-					sCPUPhysAddrStart.uiAddr = page_to_phys(ppsPage[ui32Idx]);
-					sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
-
-					/* If we're zeroing, we need to make sure the cleared memory is pushed out
-					   of the cache before the cache lines are invalidated */
-					if (bFlush)
-					{
-						OSFlushCPUCacheRangeKM(pvPageVAddr,
-											   pvPageVAddr + PAGE_SIZE,
-											   sCPUPhysAddrStart,
-											   sCPUPhysAddrEnd);
-					}
-					else
-					{
-						OSInvalidateCPUCacheRangeKM(pvPageVAddr,
-													pvPageVAddr + PAGE_SIZE,
-													sCPUPhysAddrStart,
-													sCPUPhysAddrEnd);
-					}
-
-					kunmap(ppsPage[ui32Idx]);
-				}
-
-				eError = PVRSRV_OK;
+					Note:
+					This still seems to be true if we request cold pages, it's just less
+					likely to be in the cache. */
+				_ApplyCacheMaintenance(psDevNode,
+									   ppsPage,
+									   uiNumPages,
+									   bFlush);
 			}
 		}
 	}
@@ -1487,18 +1571,77 @@
 	return eError;
 }
 
+/* Same as _AllocOSPage except it uses DMA framework to perform allocation */
+static PVRSRV_ERROR
+_AllocOSPage_CMA(PMR_OSPAGEARRAY_DATA *psPageArrayData,
+				unsigned int gfp_flags,
+				IMG_UINT32 ui32AllocOrder,
+				IMG_UINT32 ui32MinOrder,
+				IMG_UINT32 uiPageIndex)
+{
+	void *virt_addr;
+	struct page *page;
+	dma_addr_t bus_addr;
+	size_t alloc_size = PAGE_SIZE << ui32MinOrder;
+	PVR_UNREFERENCED_PARAMETER(ui32AllocOrder);
+	PVR_ASSERT(ui32AllocOrder == ui32MinOrder);
+
+	DisableOOMKiller();
+	virt_addr = dma_alloc_coherent(psPageArrayData->psDevNode->psDevConfig->pvOSDevice,
+								  alloc_size,
+								  &bus_addr,
+								  gfp_flags);
+	if (virt_addr == NULL)
+	{
+		/* The idea here is primarily to support some older kernels with
+		   broken or non-functioning DMA/CMA implementations (< Linux-3.4)
+		   and to also handle DMA/CMA allocation failures by attempting a
+		   normal page allocation though we expect dma_alloc_coherent()
+		   already attempts this internally also before failing but
+		   nonetheless it does no harm to retry allocation ourself */
+		page = alloc_pages(gfp_flags, ui32AllocOrder);
+		if (page)
+		{
+			/* Taint bus_addr as alloc_page, needed when freeing;
+			   also acquire the low memory page address only, this
+			   prevents mapping possible high memory pages into
+			   kernel virtual address space which might exhaust
+			   the VMALLOC address space */
+			bus_addr = DMA_SET_ALLOCPG_ADDR(page_to_phys(page));
+			virt_addr = page_address(page);
+		}
+		else
+		{
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+	}
+	else
+	{
+		page = pfn_to_page(bus_addr >> PAGE_SHIFT);
+	}
+	EnableOOMKiller();
+
+	/* Convert OSPageSize-based index into DevicePageSize-based index */
+	psPageArrayData->dmavirtarray[uiPageIndex >> ui32MinOrder] = virt_addr;
+	psPageArrayData->dmaphysarray[uiPageIndex >> ui32MinOrder] = bus_addr;
+	psPageArrayData->pagearray[uiPageIndex >> ui32MinOrder] = page;
+
+	return PVRSRV_OK;
+}
+
 /* Allocate a page of order uiAllocOrder and stores it in the page array ppsPage at
  * position uiPageIndex.
- * 
- * If the order is higher than 0, it splits the page into multiples and 
+ *
+ * If the order is higher than 0, it splits the page into multiples and
  * stores them at position uiPageIndex to uiPageIndex+(1<<uiAllocOrder). */
 static PVRSRV_ERROR
-_AllocOSPage(unsigned int gfp_flags,
-             IMG_UINT32 uiAllocOrder,
-             struct page **ppsPage,
-             IMG_UINT32 uiPageIndex)
+_AllocOSPage(PMR_OSPAGEARRAY_DATA *psPageArrayData,
+			unsigned int gfp_flags,
+			IMG_UINT32 uiAllocOrder,
+			IMG_UINT32 uiMinOrder,
+			IMG_UINT32 uiPageIndex)
 {
-	struct page *psPage = NULL;
+	struct page *psPage;
 	IMG_UINT32 ui32Count;
 
 	/* Allocate the page */
@@ -1506,49 +1649,51 @@
 	psPage = alloc_pages(gfp_flags, uiAllocOrder);
 	EnableOOMKiller();
 
-	if(psPage == NULL)
+	if (psPage == NULL)
 	{
-		return PVRSRV_ERROR_OUT_OF_MEMORY; 
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
-	/* In case we need to, split the higher order page */
+	/* In case we need to, split the higher order page;
+	   this should only be used for order-0 allocations
+	   as higher order allocations should use DMA/CMA */
 	if (uiAllocOrder != 0)
 	{
 		split_page(psPage, uiAllocOrder);
 	}
 #endif
 
-	/* Store the page (or multiple splittet pages) in the page array */
+	/* Store the page (or multiple split pages) in the page array */
 	for (ui32Count = 0; ui32Count < (1 << uiAllocOrder); ui32Count++)
-	{	
-		ppsPage[uiPageIndex + ui32Count] = &(psPage[ui32Count]);
+	{
+		psPageArrayData->pagearray[uiPageIndex + ui32Count] = &(psPage[ui32Count]);
 	}
 
 	return PVRSRV_OK;
 }
 
-/* Allocation of OS pages: We may allocate N^order pages at a time for two reasons.
- * Firstly to support device pages which are larger the OS. By asking the OS for 2^Order
- * OS pages at a time we guarantee the device page is contiguous. Secondly for performance
- * where we may ask for N^order pages to reduce the number of calls to alloc_pages, and
- * thus reduce time for huge allocations. Regardless of page order requested, we need to
- * break them down to track _OS pages. The maximum order requested is increased if all
- * max order allocations were successful. If any request fails we reduce the max order.
- * In addition, we must also handle sparse allocations: allocations which provide only a
- * proportion of sparse physical backing within the total virtual range. Currently
- * we only support sparse allocations on device pages that are OS page sized.
+/* Allocation of OS pages: We may allocate 2^N order pages at a time for two reasons.
+ *
+ * Firstly to support device pages which are larger than OS. By asking the OS for 2^N
+ * order OS pages at a time we guarantee the device page is contiguous.
+ *
+ * Secondly for performance where we may ask for 2^N order pages to reduce the number
+ * of calls to alloc_pages, and thus reduce time for huge allocations.
+ *
+ * Regardless of page order requested, we need to break them down to track _OS pages.
+ * The maximum order requested is increased if all max order allocations were successful.
+ * If any request fails we reduce the max order.
  */
 static PVRSRV_ERROR
-_AllocOSPages_Fast(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData,
-				   IMG_UINT32 ui32CPUCacheFlags)
+_AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
 {
 	PVRSRV_ERROR eError;
 	IMG_UINT32 uiArrayIndex = 0;
 	IMG_UINT32 ui32Order;
 	IMG_UINT32 ui32MinOrder = psPageArrayData->uiLog2DevPageSize - PAGE_SHIFT;
 	IMG_BOOL bIncreaseMaxOrder = IMG_TRUE;
-	
+
 	IMG_UINT32 ui32NumPageReq;
 	IMG_UINT32 uiPagesToAlloc;
 	IMG_UINT32 uiPagesFromPool = 0;
@@ -1563,8 +1708,11 @@
 
 	uiPagesToAlloc = psPageArrayData->uiTotalNumPages;
 
-	/* Try to get pages from the pool since it is faster */
-	_GetPagesFromPoolLocked(ui32CPUCacheFlags,
+	/* Try to get pages from the pool since it is faster;
+	   the page pool currently only supports zero-order pages
+	   thus currently excludes all DMA/CMA allocated memory */
+	_GetPagesFromPoolLocked(psPageArrayData->psDevNode,
+							psPageArrayData->ui32CPUCacheFlags,
 							uiPagesToAlloc,
 							ui32MinOrder,
 							psPageArrayData->bZero,
@@ -1579,8 +1727,20 @@
 		bIncreaseMaxOrder = IMG_FALSE;
 	}
 	else
-	{	/* Large allocations: Ask for many device pages at a time */
+	{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
+		/* Large zero-order or none zero-order allocations, ask for
+		   MAX(max-order,min-order) order pages at a time; alloc
+		   failures throttles this down to ZeroOrder allocations */
 		ui32Order = MAX(g_uiMaxOrder, ui32MinOrder);
+#else
+		/* Because split_pages() is not available on older kernels
+		   we cannot mix-and-match any-order pages in the PMR;
+		   only same-order pages must be present in page array.
+		   So we unconditionally force it to use ui32MinOrder on
+		   these older kernels */
+		ui32Order = ui32MinOrder;
+#endif
 	}
 
 	/* Only if asking for more contiguity than we actually need, let it fail */
@@ -1592,17 +1752,43 @@
 		IMG_UINT32 ui32PageRemain = uiPagesToAlloc - uiArrayIndex;
 
 		while (ui32NumPageReq > ui32PageRemain)
-		{	/* Pages to request is larger than that remaining. Ask for less */
+		{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
+			/* Pages to request is larger than that remaining
+			   so ask for less so never over allocate */
 			ui32Order = MAX(ui32Order >> 1,ui32MinOrder);
+#else
+			/* Pages to request is larger than that remaining so
+			   do nothing thus over allocate as we do not support
+			   mix/match of any-order pages in PMR page-array in
+			   older kernels (simplifies page free logic) */
+			PVR_ASSERT(ui32Order == ui32MinOrder);
+#endif
 			ui32NumPageReq = (1 << ui32Order);
 			ui32GfpFlags = (ui32Order > ui32MinOrder) ? ui32HighOrderGfpFlags : gfp_flags;
 		}
 
-		/* Alloc uiOrder pages at uiArrayIndex */
-		eError = _AllocOSPage(ui32GfpFlags,
-							  ui32Order,
-							  ppsPageArray,
-							  uiArrayIndex);
+		if (psPageArrayData->bIsCMA)
+		{
+			/* As the DMA/CMA framework rounds-up request to the
+			   next power-of-two, we request multiple uiMinOrder
+			   pages to satisfy allocation request in order to
+			   minimise wasting memory */
+			eError =  _AllocOSPage_CMA(psPageArrayData,
+									   ui32GfpFlags,
+									   ui32Order,
+									   ui32MinOrder,
+									   uiArrayIndex);
+		}
+		else
+		{
+			/* Allocate uiOrder pages at uiArrayIndex */
+			eError = _AllocOSPage(psPageArrayData,
+								  ui32GfpFlags,
+								  ui32Order,
+								  ui32MinOrder,
+								  uiArrayIndex);
+		}
 
 		if (eError == PVRSRV_OK)
 		{
@@ -1619,16 +1805,22 @@
 				ui32NumPageReq = (1 << ui32Order);
 				ui32GfpFlags = (ui32Order > ui32MinOrder) ? ui32HighOrderGfpFlags : gfp_flags;
 				g_uiMaxOrder = ui32Order;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
+				/* We should not trigger this code path in older kernels,
+				   this is enforced by ensuring ui32Order == ui32MinOrder */
+				PVR_ASSERT(ui32Order == ui32MinOrder);
+#endif
 			}
 			else
 			{
 				/* Failed to alloc pages at required contiguity. Failed allocation */
-				PVR_DPF((PVR_DBG_ERROR, "%s: alloc_pages failed to honour request at %d of %d (%s)",
+				PVR_DPF((PVR_DBG_ERROR, "%s: alloc_pages failed to honour request at %u of %u, flags = %x, order = %u (%s)",
 								__FUNCTION__,
 								uiArrayIndex,
 								uiPagesToAlloc,
+								ui32GfpFlags,
+								ui32Order,
 								PVRSRVGetErrorStringKM(eError)));
-				
 				eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
 				goto e_free_pages;
 			}
@@ -1642,6 +1834,29 @@
 
 	/* Construct table of page pointers to apply attributes */
 	ppsPageAttributeArray = &ppsPageArray[uiPagesFromPool];
+	if (psPageArrayData->bIsCMA)
+	{
+		IMG_UINT32 uiIdx, uiIdy, uiIdz;
+
+		ppsPageAttributeArray = OSAllocMem(sizeof(struct page *) * uiPagesToAlloc);
+		if (ppsPageAttributeArray == NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Failed OSAllocMem() for page attributes table"));
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e_free_pages;
+		}
+
+		for (uiIdx = 0; uiIdx < uiPagesToAlloc; uiIdx += ui32NumPageReq)
+		{
+			uiIdy = uiIdx >> ui32Order;
+			for (uiIdz = 0; uiIdz < ui32NumPageReq; uiIdz++)
+			{
+				ppsPageAttributeArray[uiIdx+uiIdz] = psPageArrayData->pagearray[uiIdy];
+				ppsPageAttributeArray[uiIdx+uiIdz] += uiIdz;
+			}
+		}
+	}
+
 	if (psPageArrayData->bZero && ui32MinOrder == 0)
 	{
 		eError = _ZeroPageArray(uiPagesToAlloc - uiPagesFromPool,
@@ -1656,53 +1871,88 @@
 
 
 	/* Do the cache management as required */
-	eError = _ApplyOSPagesAttribute (&ppsPageArray[uiPagesFromPool],
-									 uiPagesToAlloc - uiPagesFromPool,
-									 psPageArrayData->bZero,
-									 ui32CPUCacheFlags);
-	
+	eError = _ApplyOSPagesAttribute(psPageArrayData->psDevNode,
+									ppsPageAttributeArray,
+									uiPagesToAlloc - uiPagesFromPool,
+									psPageArrayData->bZero,
+									psPageArrayData->ui32CPUCacheFlags);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Failed to to set page attributes"));
+		PVR_DPF((PVR_DBG_ERROR, "Failed to set page attributes"));
 		goto e_free_pages;
 	}
-	
+	else
+	{
+		if (psPageArrayData->bIsCMA)
+		{
+			OSFreeMem(ppsPageAttributeArray);
+		}
+	}
+
 	/* Update metadata */
 	psPageArrayData->iNumPagesAllocated = psPageArrayData->uiTotalNumPages;
-	
 	return PVRSRV_OK;
-	
+
 /* Error path */
 e_free_pages:
 	{
 		IMG_UINT32 ui32PageToFree;
-		
-		/* Free the pages we got from the pool */
-		for(ui32PageToFree = 0; ui32PageToFree < uiPagesFromPool; ui32PageToFree++)
+
+		if (psPageArrayData->bIsCMA)
 		{
-			_FreeOSPage(ui32MinOrder,
-						psPageArrayData->bUnsetMemoryType,
-						ppsPageArray[ui32PageToFree]);
-			ppsPageArray[ui32PageToFree] = INVALID_PAGE;
-		}	
-	
-		/* Free the pages we just allocated from the OS */
-		for(ui32PageToFree = uiPagesFromPool; ui32PageToFree < uiArrayIndex; ui32PageToFree++)
-		{
-			_FreeOSPage(ui32MinOrder,
-						IMG_FALSE,
-						ppsPageArray[ui32PageToFree]);
-			ppsPageArray[ui32PageToFree] = INVALID_PAGE;
+			IMG_UINT32 uiDevArrayIndex = uiArrayIndex >> ui32Order;
+			IMG_UINT32 uiDevPageSize = PAGE_SIZE << ui32Order;
+			PVR_ASSERT(ui32Order == ui32MinOrder);
+
+			if (ppsPageAttributeArray)
+			{
+				OSFreeMem(ppsPageAttributeArray);
+			}
+
+			for (ui32PageToFree = 0; ui32PageToFree < uiDevArrayIndex; ui32PageToFree++)
+			{
+				_FreeOSPage_CMA(psPageArrayData->psDevNode->psDevConfig->pvOSDevice,
+								uiDevPageSize,
+								ui32MinOrder,
+								psPageArrayData->dmavirtarray[ui32PageToFree],
+								psPageArrayData->dmaphysarray[ui32PageToFree],
+								ppsPageArray[ui32PageToFree]);
+				psPageArrayData->dmaphysarray[ui32PageToFree]= (dma_addr_t)0;
+				psPageArrayData->dmavirtarray[ui32PageToFree] = NULL;
+				ppsPageArray[ui32PageToFree] = INVALID_PAGE;
+			}
 		}
-	
+		else
+		{
+			/* Free the pages we got from the pool */
+			for(ui32PageToFree = 0; ui32PageToFree < uiPagesFromPool; ui32PageToFree++)
+			{
+				_FreeOSPage(ui32MinOrder,
+							psPageArrayData->bUnsetMemoryType,
+							ppsPageArray[ui32PageToFree]);
+				ppsPageArray[ui32PageToFree] = INVALID_PAGE;
+			}
+
+			for (ui32PageToFree = uiPagesFromPool; ui32PageToFree < uiArrayIndex; ui32PageToFree++)
+			{
+				_FreeOSPage(ui32MinOrder, IMG_FALSE, ppsPageArray[ui32PageToFree]);	
+				ppsPageArray[ui32PageToFree] = INVALID_PAGE;
+			}
+		}
+
 		return eError;
 	}
 }
 
+/* Allocation of OS pages: This function is used for sparse allocations.
+ *
+ * Sparse allocations provide only a proportion of sparse physical backing within the total
+ * virtual range. Currently we only support sparse allocations on device pages that are OS
+ * page sized.
+*/
 static PVRSRV_ERROR
-_AllocOSPages_Sparse(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData,
-					 IMG_UINT32 ui32CPUCacheFlags,
-					 IMG_UINT32 *puiAllocIndicies,
+_AllocOSPages_Sparse(PMR_OSPAGEARRAY_DATA *psPageArrayData,
+					 IMG_UINT32 *puiAllocIndices,
 					 IMG_UINT32 uiPagesToAlloc)
 {
 	PVRSRV_ERROR eError;
@@ -1717,7 +1967,7 @@
 	 * store pages that need their cache attribute changed on x86*/
 	struct page **ppsTempPageArray;
 	IMG_UINT32 uiTempPageArrayIndex = 0;
-	
+
 	/* Allocate the temporary page array that we need here to receive pages
 	 * from the pool and to store pages that need their caching attributes changed */
 	ppsTempPageArray = OSAllocMem(sizeof(struct page*) * uiPagesToAlloc);
@@ -1727,14 +1977,12 @@
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto e_exit;
 	}
-	
-	ui32CPUCacheFlags = psPageArrayData->ui32CPUCacheFlags;
-	
+
 	/* Check the requested number of pages if they fit in the page array */
 	if(psPageArrayData->uiTotalNumPages < \
 				(psPageArrayData->iNumPagesAllocated + uiPagesToAlloc))
 	{
-		PVR_DPF((PVR_DBG_ERROR, 
+		PVR_DPF((PVR_DBG_ERROR,
 				 "%s: Trying to allocate more pages than this buffer can handle, "
 				 "Request + Allocated < Max! Request %u, Allocated %u, Max %u.",
 				 __FUNCTION__,
@@ -1746,67 +1994,70 @@
 	}
 
 	/* Try to get pages from the pool since it is faster */
-	_GetPagesFromPoolLocked(ui32CPUCacheFlags,
+	_GetPagesFromPoolLocked(psPageArrayData->psDevNode,
+							psPageArrayData->ui32CPUCacheFlags,
 							uiPagesToAlloc,
 							uiOrder,
 							psPageArrayData->bZero,
 							ppsTempPageArray,
-							&uiPagesFromPool);	
-	
-	/* Allocate pages from the OS or move the pages that we got from the pool 
+							&uiPagesFromPool);
+
+	/* Allocate pages from the OS or move the pages that we got from the pool
 	 * to the page array */
 	DisableOOMKiller();
 	for (i = 0; i < uiPagesToAlloc; i++)
 	{
-		/* Check if the indicies we are allocating are in range */
-		if (puiAllocIndicies[i] >= psPageArrayData->uiTotalNumPages)
+		/* Check if the indices we are allocating are in range */
+		if (puiAllocIndices[i] >= psPageArrayData->uiTotalNumPages)
 		{
-			PVR_DPF((PVR_DBG_ERROR, 
+			PVR_DPF((PVR_DBG_ERROR,
 					 "%s: Given alloc index %u at %u is larger than page array %u.",
 					 __FUNCTION__,
 					 i,
-					 puiAllocIndicies[i],
+					 puiAllocIndices[i],
 					 psPageArrayData->uiTotalNumPages));
 			eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
 			goto e_free_pages;
 		}
 
 		/* Check if there is not already a page allocated at this position */
-		if (INVALID_PAGE != ppsPageArray[puiAllocIndicies[i]])
+		if (INVALID_PAGE != ppsPageArray[puiAllocIndices[i]])
 		{
 			PVR_DPF((PVR_DBG_ERROR,
 					 "%s: Mapping number %u at page array index %u already exists",
 					 __func__,
 					 i,
-					 puiAllocIndicies[i]));
+					 puiAllocIndices[i]));
 			eError = PVRSRV_ERROR_PMR_MAPPING_ALREADY_EXISTS;
 			goto e_free_pages;
 		}
 
-		/* Finally asign a page to the array. 
+		/* Finally assign a page to the array.
 		 * Either from the pool or allocate a new one. */
 		if (uiPagesFromPool != 0)
 		{
 			uiPagesFromPool--;
-			ppsPageArray[puiAllocIndicies[i]] =  ppsTempPageArray[uiPagesFromPool];
+			ppsPageArray[puiAllocIndices[i]] =  ppsTempPageArray[uiPagesFromPool];
 		}
 		else
 		{
-			ppsPageArray[puiAllocIndicies[i]] = alloc_pages(gfp_flags, uiOrder);
-			if(ppsPageArray[puiAllocIndicies[i]] != NULL)
+			ppsPageArray[puiAllocIndices[i]] = alloc_pages(gfp_flags, uiOrder);
+			if(ppsPageArray[puiAllocIndices[i]] != NULL)
 			{
 				/* Reusing the temp page array if it has no pool pages anymore */
-				ppsTempPageArray[uiTempPageArrayIndex] = ppsPageArray[puiAllocIndicies[i]];
+				ppsTempPageArray[uiTempPageArrayIndex] = ppsPageArray[puiAllocIndices[i]];
 				uiTempPageArrayIndex++;
 			}
 			else
 			{
 				/* Failed to alloc pages at required contiguity. Failed allocation */
-				PVR_DPF((PVR_DBG_ERROR, 
-						 "%s: alloc_pages failed to honour request at %d of %d",
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: alloc_pages failed to honour request at %u of %u, flags = %x, order = %u",
 						 __FUNCTION__,
 						 i,
-						 uiPagesToAlloc));
+						 uiPagesToAlloc,
+						 gfp_flags,
+						 uiOrder));
 				eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
 				goto e_free_pages;
 			}
@@ -1827,111 +2078,111 @@
 	}
 
 	/* Do the cache management as required */
-	eError = _ApplyOSPagesAttribute (ppsTempPageArray,
-									 uiTempPageArrayIndex,
-									 psPageArrayData->bZero,
-									 ui32CPUCacheFlags);
+	eError = _ApplyOSPagesAttribute(psPageArrayData->psDevNode,
+									ppsTempPageArray,
+									uiTempPageArrayIndex,
+									psPageArrayData->bZero,
+									psPageArrayData->ui32CPUCacheFlags);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Failed to to set page attributes"));
+		PVR_DPF((PVR_DBG_ERROR, "Failed to set page attributes"));
 		goto e_free_pages;
 	}
-	
+
 	/* Update metadata */
 	psPageArrayData->iNumPagesAllocated += uiPagesToAlloc;
-	
+
 	/* Free temporary page array */
 	OSFreeMem(ppsTempPageArray);
-
 	return PVRSRV_OK;
 
-/* Error path */	
+/* Error path */
 e_free_pages:
 	{
 		IMG_UINT32 ui32PageToFree;
-	
+
 		EnableOOMKiller();
-		
+
 		/* Free the pages we got from the pool */
 		for(ui32PageToFree = 0; ui32PageToFree < uiPagesFromPool; ui32PageToFree++)
 		{
 			_FreeOSPage(0,
 						psPageArrayData->bUnsetMemoryType,
 						ppsTempPageArray[ui32PageToFree]);
-		}	
-		
+		}
+
 		/* Free the pages we just allocated from the OS */
 		for(ui32PageToFree = uiPagesFromPool; ui32PageToFree < i; ui32PageToFree++)
 		{
 			_FreeOSPage(0,
 						IMG_FALSE,
-						ppsPageArray[puiAllocIndicies[ui32PageToFree]]);
-	
-			ppsPageArray[puiAllocIndicies[ui32PageToFree]] = (struct page *) INVALID_PAGE;
+						ppsPageArray[puiAllocIndices[ui32PageToFree]]);
+
+			ppsPageArray[puiAllocIndices[ui32PageToFree]] = (struct page *) INVALID_PAGE;
 		}
 	}
 
 e_free_temp_array:
 	OSFreeMem(ppsTempPageArray);
-	
+
 e_exit:
 	return eError;
 }
 
-/* Allocate pages for a given page array. 
- * 
- * The executed allocation path depends whether an array with allocation 
- * indicies has been passed or not */
+/* Allocate pages for a given page array.
+ *
+ * The executed allocation path depends whether an array with allocation
+ * indices has been passed or not */
 static PVRSRV_ERROR
-_AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr,
-			  IMG_UINT32 *puiAllocIndicies,
+_AllocOSPages(PMR_OSPAGEARRAY_DATA *psPageArrayData,
+			  IMG_UINT32 *puiAllocIndices,
 			  IMG_UINT32 uiPagesToAlloc)
 {
 	PVRSRV_ERROR eError;
 	IMG_UINT32 i;
-	struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData = *ppsPageArrayDataPtr;
 	struct page **ppsPageArray;
-	IMG_UINT32 ui32CPUCacheFlags;
 
-    /* Sanity checks */
-    PVR_ASSERT(NULL != psPageArrayData);
-    PVR_ASSERT(NULL != psPageArrayData->pagearray);
-    PVR_ASSERT(0 <= psPageArrayData->iNumPagesAllocated);
+	/* Sanity checks */
+	PVR_ASSERT(NULL != psPageArrayData);
+	if (psPageArrayData->bIsCMA)
+	{
+		PVR_ASSERT(psPageArrayData->dmaphysarray != NULL);
+		PVR_ASSERT(psPageArrayData->dmavirtarray != NULL);
+	}
+	PVR_ASSERT(psPageArrayData->pagearray != NULL);
+	PVR_ASSERT(0 <= psPageArrayData->iNumPagesAllocated);
 
-	ui32CPUCacheFlags = psPageArrayData->ui32CPUCacheFlags;
-    ppsPageArray = psPageArrayData->pagearray;
-	
-	/* Go the sparse alloc path if we have an array with alloc indicies.*/
-	if (puiAllocIndicies != NULL)
+	ppsPageArray = psPageArrayData->pagearray;
+
+	/* Go the sparse alloc path if we have an array with alloc indices.*/
+	if (puiAllocIndices != NULL)
 	{
 		eError =  _AllocOSPages_Sparse(psPageArrayData,
-									   ui32CPUCacheFlags,
-									   puiAllocIndicies,
+									   puiAllocIndices,
 									   uiPagesToAlloc);
 	}
 	else
 	{
-		eError =  _AllocOSPages_Fast(psPageArrayData,
-									 ui32CPUCacheFlags);
+		eError =  _AllocOSPages_Fast(psPageArrayData);
 	}
 
 	if (eError != PVRSRV_OK)
 	{
 		goto e_exit;
 	}
-	
+
 	if (psPageArrayData->bPoisonOnAlloc)
 	{
 		for (i = 0; i < uiPagesToAlloc; i++)
 		{
-			IMG_UINT32 uiIdx = puiAllocIndicies ? puiAllocIndicies[i] : i;
+			IMG_UINT32 uiIdx = puiAllocIndices ? puiAllocIndices[i] : i;
 			_PoisonPages(ppsPageArray[uiIdx],
 						 0,
 						 _AllocPoison,
 						 _AllocPoisonSize);
 		}
 	}
-	
+
 	_DumpPageArray(ppsPageArray, psPageArrayData->uiTotalNumPages);
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
@@ -1940,13 +2191,13 @@
 		for (i = 0; i < uiPagesToAlloc; i++)
 		{
 			IMG_CPU_PHYADDR sCPUPhysAddr;
-			IMG_UINT32 uiIdx = puiAllocIndicies ? puiAllocIndicies[i] : i;
+			IMG_UINT32 uiIdx = puiAllocIndices ? puiAllocIndices[i] : i;
 
 			sCPUPhysAddr.uiAddr = page_to_phys(ppsPageArray[uiIdx]);
 			PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES,
 										 NULL,
 										 sCPUPhysAddr,
-										 PAGE_SIZE,
+										 1 << psPageArrayData->uiLog2DevPageSize,
 										 NULL);
 		}
 	}
@@ -1956,25 +2207,55 @@
 #endif
 
 	PVR_DPF((PVR_DBG_MESSAGE, "physmem_osmem_linux.c: allocated OS memory for PMR @0x%p", psPageArrayData));
-
 	return PVRSRV_OK;
 
 e_exit:
 	return eError;
 }
 
+/* Same as _FreeOSPage except free memory using DMA framework */
+static INLINE void
+_FreeOSPage_CMA(struct device *dev,
+				size_t alloc_size,
+				IMG_UINT32 uiOrder,
+				void *virt_addr,
+				dma_addr_t dev_addr,
+				struct page *psPage)
+{
+	if (DMA_IS_ALLOCPG_ADDR(dev_addr))
+	{
+#if defined(CONFIG_X86)
+		void *pvPageVAddr = page_address(psPage);
+		if (pvPageVAddr)
+		{
+			int ret = set_memory_wb((unsigned long)pvPageVAddr, 1);
+			if (ret)
+			{
+				PVR_DPF((PVR_DBG_ERROR, 
+						"%s: Failed to reset page attribute",
+						__FUNCTION__));
+			}
+		}
+#endif
+		__free_pages(psPage, uiOrder);
+	}
+	else
+	{
+		dma_free_coherent(dev, alloc_size, virt_addr, DMA_GET_ADDR(dev_addr));
+	}
+}
 
-/* Free a single page back to the OS. 
+/* Free a single page back to the OS.
  * Make sure the cache type is set back to the default value.
- * 
+ *
  * Note:
  * We must _only_ check bUnsetMemoryType in the case where we need to free
  * the page back to the OS since we may have to revert the cache properties
  * of the page to the default as given by the OS when it was allocated. */
 static void
 _FreeOSPage(IMG_UINT32 uiOrder,
-            IMG_BOOL bUnsetMemoryType,
-            struct page *psPage)
+			IMG_BOOL bUnsetMemoryType,
+			struct page *psPage)
 {
 
 #if defined(CONFIG_X86)
@@ -1999,11 +2280,11 @@
 
 /* Free the struct holding the metadata */
 static PVRSRV_ERROR
-_FreeOSPagesArray(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
+_FreeOSPagesArray(PMR_OSPAGEARRAY_DATA *psPageArrayData)
 {
 	PVR_DPF((PVR_DBG_MESSAGE, "physmem_osmem_linux.c: freed OS memory for PMR @0x%p", psPageArrayData));
-	
-	/* Check if the page array actually still exists. 
+
+	/* Check if the page array actually still exists.
 	 * It might be the case that has been moved to the page pool */
 	if (psPageArrayData->pagearray != NULL)
 	{
@@ -2018,9 +2299,9 @@
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 /* _FreeOSPages_MemStats: Depends on the bridge lock already being held */
 static void
-_FreeOSPages_MemStats(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData,
-							IMG_UINT32 *pai32FreeIndices,
-							IMG_UINT32 ui32NumPages)
+_FreeOSPages_MemStats(PMR_OSPAGEARRAY_DATA *psPageArrayData,
+					IMG_UINT32 *pai32FreeIndices,
+					IMG_UINT32 ui32NumPages)
 {
 	struct page **ppsPageArray;
 	#if defined(PVRSRV_ENABLE_MEMORY_STATS)
@@ -2032,10 +2313,10 @@
 
 	ppsPageArray = psPageArrayData->pagearray;
 
-	#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-	#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
 		PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, ui32NumPages * PAGE_SIZE);
-	#else
+#else
 		for(ui32PageIndex = 0; ui32PageIndex < ui32NumPages; ui32PageIndex++)
 		{
 			IMG_CPU_PHYADDR sCPUPhysAddr;
@@ -2044,14 +2325,14 @@
 			sCPUPhysAddr.uiAddr = page_to_phys(ppsPageArray[uiArrayIndex]);
 			PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, sCPUPhysAddr.uiAddr);
 		}
-	#endif
-	#endif
+#endif
+#endif
 }
 #endif /* PVRSRV_ENABLE_PROCESS_STATS */
 
 /* Free all or some pages from a sparse page array */
 static PVRSRV_ERROR
-_FreeOSPages_Sparse(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData,
+_FreeOSPages_Sparse(PMR_OSPAGEARRAY_DATA *psPageArrayData,
 					IMG_UINT32 *pai32FreeIndices,
 					IMG_UINT32 ui32FreePageCount)
 {
@@ -2063,9 +2344,9 @@
 
 	struct page **ppsTempPageArray;
 	IMG_UINT32 uiTempArraySize;
-	
+
 	/* We really should have something to free before we call this */
-	PVR_ASSERT(psPageArrayData->iNumPagesAllocated != 0); 
+	PVR_ASSERT(psPageArrayData->iNumPagesAllocated != 0);
 
 	if(pai32FreeIndices == NULL)
 	{
@@ -2078,7 +2359,7 @@
 		uiTempArraySize = ui32FreePageCount;
 	}
 
-	/* OSAllocMemstatMem required because this code may be run without the bridge lock held */
+	/* OSAllocMemNoStats required because this code may be run without the bridge lock held */
 	ppsTempPageArray = OSAllocMemNoStats(sizeof(struct page*) * uiTempArraySize);
 	if (ppsTempPageArray == NULL)
 	{
@@ -2101,7 +2382,7 @@
 			ppsPageArray[uiPageIndex] = (struct page *) INVALID_PAGE;
 		}
 	}
-	
+
 	/* Try to move the temp page array to the pool */
 	bSuccess = _PutPagesToPoolLocked(psPageArrayData->ui32CPUCacheFlags,
 									 ppsTempPageArray,
@@ -2112,19 +2393,16 @@
 	{
 		goto exit_ok;
 	}
-		
+
 	/* Poison if necessary */
 	if (psPageArrayData->bPoisonOnFree)
 	{
-		for (i  = 0; i  < uiNumPages; i ++)
+		for (i  = 0; i  < uiTempIdx; i ++)
 		{
-
-			uiPageIndex = pai32FreeIndices ? pai32FreeIndices[i] : i ;
-
-			_PoisonPages(ppsPageArray[uiPageIndex],
-						 0,
-						 _FreePoison,
-						 _FreePoisonSize);
+				_PoisonPages(ppsTempPageArray[i],
+							 0,
+							 _FreePoison,
+							 _FreePoisonSize);
 		}
 	}
 
@@ -2141,28 +2419,26 @@
 		}
 	}
 #endif
-	
+
 	/* Free the pages */
 	for (i = 0; i < uiTempIdx; i++)
 	{
 		__free_pages(ppsTempPageArray[i], uiOrder);
 	}
-	
+
 	/* Free the temp page array here if it did not move to the pool */
 	OSFreeMemNoStats(ppsTempPageArray);
-	
-exit_ok:    
-    
-    /* Update metadata */
-    psPageArrayData->iNumPagesAllocated -= uiTempIdx;
-    PVR_ASSERT(0 <= psPageArrayData->iNumPagesAllocated);
 
-    return PVRSRV_OK;
+exit_ok:
+	/* Update metadata */
+	psPageArrayData->iNumPagesAllocated -= uiTempIdx;
+	PVR_ASSERT(0 <= psPageArrayData->iNumPagesAllocated);
+	return PVRSRV_OK;
 }
 
 /* Free all the pages in a page array */
 static PVRSRV_ERROR
-_FreeOSPages_Fast(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
+_FreeOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
 {
 	IMG_BOOL bSuccess;
 	IMG_UINT32 uiOrder;
@@ -2194,43 +2470,62 @@
 		for (i = 0; i < uiNumPages; i++)
 		{
 			_PoisonPages(ppsPageArray[i],
-					0,
-					_FreePoison,
-					_FreePoisonSize);
+						 0,
+						 _FreePoison,
+						 _FreePoisonSize);
 		}
 	}
 
-#if defined(CONFIG_X86)
-	if (psPageArrayData->bUnsetMemoryType == IMG_TRUE)
+	if (psPageArrayData->bIsCMA)
 	{
-		int ret;
-		ret = set_pages_array_wb(ppsPageArray, uiNumPages);
-		if (ret)
+		IMG_UINT32 uiDevNumPages = uiNumPages >> uiOrder;
+		IMG_UINT32 uiDevPageSize = PAGE_SIZE << uiOrder;
+
+		for (i = 0; i < uiDevNumPages; i++)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to reset page attributes", __FUNCTION__));
+			_FreeOSPage_CMA(psPageArrayData->psDevNode->psDevConfig->pvOSDevice,
+							uiDevPageSize,
+							uiOrder,
+							psPageArrayData->dmavirtarray[i],
+							psPageArrayData->dmaphysarray[i],
+							ppsPageArray[i]);
+  			psPageArrayData->dmaphysarray[i] = (dma_addr_t)0;
+			psPageArrayData->dmavirtarray[i] = NULL;
+			ppsPageArray[i] = INVALID_PAGE;
 		}
 	}
+	else
+	{
+#if defined(CONFIG_X86)
+		if (psPageArrayData->bUnsetMemoryType == IMG_TRUE)
+		{
+			int ret;
+
+			ret = set_pages_array_wb(ppsPageArray, uiNumPages);
+			if (ret)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to reset page attributes", __FUNCTION__));
+			}
+		}
 #endif
 
-	/* Free the pages */
-	for (i = 0; i < uiNumPages; i++)
-	{
-		__free_pages(ppsPageArray[i], uiOrder);
-		ppsPageArray[i] = INVALID_PAGE;
-
+		for (i = 0; i < uiNumPages; i++)
+		{
+			_FreeOSPage(uiOrder, IMG_FALSE, ppsPageArray[i]);
+			ppsPageArray[i] = INVALID_PAGE;
+		}
 	}
 
 exit_ok:
 	/* Update metadata */
 	psPageArrayData->iNumPagesAllocated = 0;
-
 	return PVRSRV_OK;
 }
 
-/* Free pages from a page array. 
+/* Free pages from a page array.
  * Takes care of mem stats and chooses correct free path depending on parameters. */
 static PVRSRV_ERROR
-_FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData,
+_FreeOSPages(PMR_OSPAGEARRAY_DATA *psPageArrayData,
 			 IMG_UINT32 *pai32FreeIndices,
 			 IMG_UINT32 ui32FreePageCount)
 {
@@ -2250,7 +2545,7 @@
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
  	_FreeOSPages_MemStats(psPageArrayData, pai32FreeIndices, uiNumPages);
 #endif
-	
+
 	/* Go the sparse or non-sparse path */
 	if (psPageArrayData->iNumPagesAllocated != psPageArrayData->uiTotalNumPages
 		|| pai32FreeIndices != NULL)
@@ -2268,10 +2563,10 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_FreePages failed"));
 	}
-	
+
 	_DumpPageArray(psPageArrayData->pagearray, psPageArrayData->uiTotalNumPages);
 
-    return eError;
+	return eError;
 }
 
 /*
@@ -2283,21 +2578,11 @@
 /* destructor func is called after last reference disappears, but
    before PMR itself is freed. */
 static PVRSRV_ERROR
-PMRFinalizeOSMem(PMR_IMPL_PRIVDATA pvPriv
-                 //struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData
-                 )
+PMRFinalizeOSMem(PMR_IMPL_PRIVDATA pvPriv)
 {
-    PVRSRV_ERROR eError;
-    struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+	PVRSRV_ERROR eError;
+	PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv;
 
-    psOSPageArrayData = pvPriv;
-
-    /* Conditionally do the PDump free, because if CreatePMR failed we
-       won't have done the PDump MALLOC.  */
-    if (psOSPageArrayData->bPDumpMalloced)
-    {
-        PDumpFree(psOSPageArrayData->hPDumpAllocInfo);
-    }
 
 	/*  We can't free pages until now. */
 	if (psOSPageArrayData->iNumPagesAllocated != 0)
@@ -2317,113 +2602,95 @@
 
 	eError = _FreeOSPagesArray(psOSPageArrayData);
 	PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
-
-
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 }
 
 /* callback function for locking the system physical page addresses.
    This function must be called before the lookup address func. */
 static PVRSRV_ERROR
-PMRLockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv,
-                             // struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData,
-                             IMG_UINT32 uiLog2DevPageSize)
+PMRLockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv)
 {
-    PVRSRV_ERROR eError;
-    struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+	PVRSRV_ERROR eError;
+	PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv;
 
-    psOSPageArrayData = pvPriv;
-
-    if (psOSPageArrayData->bOnDemand)
-    {
+	if (psOSPageArrayData->bOnDemand)
+	{
 		/* Allocate Memory for deferred allocation */
-    	eError = _AllocOSPages(&psOSPageArrayData, NULL, psOSPageArrayData->uiTotalNumPages);
-    	if (eError != PVRSRV_OK)
-    	{
-    		return eError;
-    	}
-    }
+		eError = _AllocOSPages(psOSPageArrayData, NULL, psOSPageArrayData->uiTotalNumPages);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
 
-    /* Physical page addresses are already locked down in this
-       implementation, so there is no need to acquire physical
-       addresses.  We do need to verify that the physical contiguity
-       requested by the caller (i.e. page size of the device they
-       intend to map this memory into) is compatible with (i.e. not of
-       coarser granularity than) our already known physicial
-       contiguity of the pages */
-    if (uiLog2DevPageSize > psOSPageArrayData->uiLog2DevPageSize)
-    {
-        /* or NOT_MAPPABLE_TO_THIS_PAGE_SIZE ? */
-        eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
-        return eError;
-    }
-
-    eError = PVRSRV_OK;
-    return eError;
-
+	eError = PVRSRV_OK;
+	return eError;
 }
 
 static PVRSRV_ERROR
-PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv
-                               //struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData
-                               )
+PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv)
 {
-    /* Just drops the refcount. */
+	/* Just drops the refcount. */
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv;
 
-    PVRSRV_ERROR eError = PVRSRV_OK;
-    struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
-
-    psOSPageArrayData = pvPriv;
-
-
-    if (psOSPageArrayData->bOnDemand)
-    {
+	if (psOSPageArrayData->bOnDemand)
+	{
 		/* Free Memory for deferred allocation */
-    	eError = _FreeOSPages(psOSPageArrayData,
-                              NULL,
-                              0);
-    	if (eError != PVRSRV_OK)
-    	{
-    		return eError;
-    	}
-    }
+		eError = _FreeOSPages(psOSPageArrayData,
+							  NULL,
+							  0);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
 
-    PVR_ASSERT (eError == PVRSRV_OK);
-
-    return eError;
+	PVR_ASSERT (eError == PVRSRV_OK);
+	return eError;
 }
 
 /* N.B.  It is assumed that PMRLockSysPhysAddressesOSMem() is called _before_ this function! */
 static PVRSRV_ERROR
 PMRSysPhysAddrOSMem(PMR_IMPL_PRIVDATA pvPriv,
-                    IMG_UINT32 ui32NumOfPages,
-                    IMG_DEVMEM_OFFSET_T *puiOffset,
+					IMG_UINT32 ui32Log2PageSize,
+					IMG_UINT32 ui32NumOfPages,
+					IMG_DEVMEM_OFFSET_T *puiOffset,
 					IMG_BOOL *pbValid,
-                    IMG_DEV_PHYADDR *psDevPAddr)
+					IMG_DEV_PHYADDR *psDevPAddr)
 {
-    const struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData = pvPriv;
-    struct page **ppsPageArray = psOSPageArrayData->pagearray;
+	const PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv;
 	IMG_UINT32 uiPageSize = 1U << psOSPageArrayData->uiLog2DevPageSize;
-	IMG_UINT32 ui32Order = psOSPageArrayData->uiLog2DevPageSize - PAGE_SHIFT;
 	IMG_UINT32 uiInPageOffset;
-    IMG_UINT32 uiPageIndex;
-    IMG_UINT32 idx;
+	IMG_UINT32 uiPageIndex;
+	IMG_UINT32 uiIdx;
 
-    for (idx=0; idx < ui32NumOfPages; idx++)
-    {
-		if (pbValid[idx])
+	if (psOSPageArrayData->uiLog2DevPageSize < ui32Log2PageSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s: Requested physical addresses from PMR "
+		         "for incompatible contiguity %u!",
+		         __FUNCTION__,
+		         ui32Log2PageSize));
+		return PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+	}
+
+	for (uiIdx=0; uiIdx < ui32NumOfPages; uiIdx++)
+	{
+		if (pbValid[uiIdx])
 		{
-			uiPageIndex = puiOffset[idx] >> psOSPageArrayData->uiLog2DevPageSize;
-			uiInPageOffset = puiOffset[idx] - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << psOSPageArrayData->uiLog2DevPageSize);
+			uiPageIndex = puiOffset[uiIdx] >> psOSPageArrayData->uiLog2DevPageSize;
+			uiInPageOffset = puiOffset[uiIdx] - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << psOSPageArrayData->uiLog2DevPageSize);
 
 			PVR_ASSERT(uiPageIndex < psOSPageArrayData->uiTotalNumPages);
 			PVR_ASSERT(uiInPageOffset < uiPageSize);
 
-			psDevPAddr[idx].uiAddr = page_to_phys(ppsPageArray[uiPageIndex * (1 << ui32Order)]) + uiInPageOffset;
+			psDevPAddr[uiIdx].uiAddr = page_to_phys(psOSPageArrayData->pagearray[uiPageIndex]);
+			psDevPAddr[uiIdx].uiAddr += uiInPageOffset;
 		}
-    }
+	}
 
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 }
 
 typedef struct _PMR_OSPAGEARRAY_KERNMAP_DATA_ {
@@ -2433,22 +2700,21 @@
 
 static PVRSRV_ERROR
 PMRAcquireKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
-                                 size_t uiOffset,
-                                 size_t uiSize,
-                                 void **ppvKernelAddressOut,
-                                 IMG_HANDLE *phHandleOut,
-                                 PMR_FLAGS_T ulFlags)
+								 size_t uiOffset,
+								 size_t uiSize,
+								 void **ppvKernelAddressOut,
+								 IMG_HANDLE *phHandleOut,
+								 PMR_FLAGS_T ulFlags)
 {
-    PVRSRV_ERROR eError;
-    struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData = pvPriv;
-    void *pvAddress;
-    pgprot_t prot = PAGE_KERNEL;
-    IMG_UINT32 ui32CPUCacheFlags = DevmemCPUCacheMode(ulFlags);
-    IMG_UINT32 ui32PageOffset;
-    size_t uiMapOffset;
-    IMG_UINT32 ui32PageCount;
-    IMG_UINT32 uiLog2DevPageSize = psOSPageArrayData->uiLog2DevPageSize;
-    PMR_OSPAGEARRAY_KERNMAP_DATA *psData;
+	PVRSRV_ERROR eError;
+	PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv;
+	void *pvAddress;
+	pgprot_t prot = PAGE_KERNEL;
+	IMG_UINT32 ui32PageOffset;
+	size_t uiMapOffset;
+	IMG_UINT32 ui32PageCount;
+	IMG_UINT32 uiLog2DevPageSize = psOSPageArrayData->uiLog2DevPageSize;
+	PMR_OSPAGEARRAY_KERNMAP_DATA *psData;
 
 	/*
 		Zero offset and size as a special meaning which means map in the
@@ -2474,36 +2740,43 @@
 		ui32PageCount -= ui32PageOffset;
 	}
 
-	switch (ui32CPUCacheFlags)
+	if (psOSPageArrayData->bIsCMA)
 	{
-		case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
-				prot = pgprot_noncached(prot);
-				break;
-
-		case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
-				prot = pgprot_writecombine(prot);
-				break;
-
-		case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
-				break;
-
-		default:
-				eError = PVRSRV_ERROR_INVALID_PARAMS;
-				goto e0;
+		prot = pgprot_noncached(prot);
 	}
-	
-	psData = OSAllocMem(sizeof(PMR_OSPAGEARRAY_KERNMAP_DATA));
+	else
+	{
+		switch (PVRSRV_CPU_CACHE_MODE(psOSPageArrayData->ui32CPUCacheFlags))
+		{
+			case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+					prot = pgprot_noncached(prot);
+					break;
+
+			case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+					prot = pgprot_writecombine(prot);
+					break;
+
+			case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+					break;
+
+			default:
+					eError = PVRSRV_ERROR_INVALID_PARAMS;
+					goto e0;
+		}
+	}
+
+	psData = OSAllocMem(sizeof(*psData));
 	if (psData == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto e0;
 	}
-	
+
 #if !defined(CONFIG_64BIT) || defined(PVRSRV_FORCE_SLOWER_VMAP_ON_64BIT_BUILDS)
 	pvAddress = vmap(&psOSPageArrayData->pagearray[ui32PageOffset],
-	                 ui32PageCount,
-	                 VM_READ | VM_WRITE,
-	                 prot);
+					 ui32PageCount,
+					 VM_READ | VM_WRITE,
+					 prot);
 #else
 	pvAddress = vm_map_ram(&psOSPageArrayData->pagearray[ui32PageOffset],
 						   ui32PageCount,
@@ -2516,50 +2789,46 @@
 		goto e1;
 	}
 
-    *ppvKernelAddressOut = pvAddress + uiMapOffset;
-    psData->pvBase = pvAddress;
-    psData->ui32PageCount = ui32PageCount;
-    *phHandleOut = psData;
+	*ppvKernelAddressOut = pvAddress + uiMapOffset;
+	psData->pvBase = pvAddress;
+	psData->ui32PageCount = ui32PageCount;
+	*phHandleOut = psData;
 
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 
-    /*
-      error exit paths follow
-    */
+	/*
+	  error exit paths follow
+	*/
  e1:
-    OSFreeMem(psData);
+	OSFreeMem(psData);
  e0:
-    PVR_ASSERT(eError != PVRSRV_OK);
-    return eError;
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
 }
-static void PMRReleaseKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
-                                                 IMG_HANDLE hHandle)
-{
-    struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
-    PMR_OSPAGEARRAY_KERNMAP_DATA *psData;
 
-    psOSPageArrayData = pvPriv;
-    psData = hHandle;
+static void PMRReleaseKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
+											 IMG_HANDLE hHandle)
+{
+    PMR_OSPAGEARRAY_KERNMAP_DATA *psData = hHandle;
+	PVR_UNREFERENCED_PARAMETER(pvPriv);
+
 #if !defined(CONFIG_64BIT) || defined(PVRSRV_FORCE_SLOWER_VMAP_ON_64BIT_BUILDS)
-    vunmap(psData->pvBase);
+	vunmap(psData->pvBase);
 #else
-    vm_unmap_ram(psData->pvBase, psData->ui32PageCount);
+	vm_unmap_ram(psData->pvBase, psData->ui32PageCount);
 #endif
-    OSFreeMem(psData);
+	OSFreeMem(psData);
 }
 
 static
 PVRSRV_ERROR PMRUnpinOSMem(PMR_IMPL_PRIVDATA pPriv)
 {
-
-#if defined(PHYSMEM_SUPPORTS_SHRINKER)
-
-	struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData = pPriv;
+	PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pPriv;
 	PVRSRV_ERROR eError = PVRSRV_OK;
 
 	/* Lock down the pool and add the array to the unpin list */
 	_PagePoolLock();
-	
+
 	/* Sanity check */
 	PVR_ASSERT(psOSPageArrayData->bUnpinned == IMG_FALSE);
 	PVR_ASSERT(psOSPageArrayData->bOnDemand == IMG_FALSE);
@@ -2581,29 +2850,22 @@
 e_exit:
 	_PagePoolUnlock();
 	return eError;
-
-#else
-	PVR_UNREFERENCED_PARAMETER(pPriv);
-	return PVRSRV_OK;
-#endif
 }
 
 static
 PVRSRV_ERROR PMRPinOSMem(PMR_IMPL_PRIVDATA pPriv,
-							PMR_MAPPING_TABLE *psMappingTable)
+						PMR_MAPPING_TABLE *psMappingTable)
 {
-#if defined(PHYSMEM_SUPPORTS_SHRINKER)
-
 	PVRSRV_ERROR eError;
-	struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData = pPriv;
+	PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pPriv;
 	IMG_UINT32  *pui32MapTable = NULL;
 	IMG_UINT32 i,j=0, ui32Temp=0;
 
 	_PagePoolLock();
-	
+
 	/* Sanity check */
 	PVR_ASSERT(psOSPageArrayData->bUnpinned == IMG_TRUE);
-	
+
 	psOSPageArrayData->bUnpinned = IMG_FALSE;
 
 	/* If there are still pages in the array remove entries from the pool */
@@ -2619,11 +2881,13 @@
 
 	/* If pages were reclaimed we allocate new ones and
 	 * return PVRSRV_ERROR_PMR_NEW_MEMORY  */
-	if(1 == psMappingTable->ui32NumVirtChunks){
-		eError = _AllocOSPages(&psOSPageArrayData, NULL, psOSPageArrayData->uiTotalNumPages);
-	}else
+	if (psMappingTable->ui32NumVirtChunks == 1)
 	{
-		pui32MapTable = (IMG_UINT32 *)OSAllocMem(sizeof(IMG_UINT32) * psMappingTable->ui32NumPhysChunks);
+		eError = _AllocOSPages(psOSPageArrayData, NULL, psOSPageArrayData->uiTotalNumPages);
+	}
+	else
+	{
+		pui32MapTable = (IMG_UINT32 *)OSAllocMem(sizeof(*pui32MapTable) * psMappingTable->ui32NumPhysChunks);
 		if(NULL == pui32MapTable)
 		{
 			eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
@@ -2641,7 +2905,7 @@
 				pui32MapTable[j++] = ui32Temp;
 			}
 		}
-		eError = _AllocOSPages(&psOSPageArrayData, pui32MapTable, psMappingTable->ui32NumPhysChunks);
+		eError = _AllocOSPages(psOSPageArrayData, pui32MapTable, psMappingTable->ui32NumPhysChunks);
 	}
 
 	if (eError != PVRSRV_OK)
@@ -2665,11 +2929,6 @@
 	OSFreeMem(pui32MapTable);
 e_exit_mapalloc_failure:
 	return eError;
-
-#else
-	PVR_UNREFERENCED_PARAMETER(pPriv);
-	return PVRSRV_OK;
-#endif
 }
 
 /*************************************************************************/ /*!
@@ -2680,176 +2939,209 @@
 */ /**************************************************************************/
 static PVRSRV_ERROR
 PMRChangeSparseMemOSMem(PMR_IMPL_PRIVDATA pPriv,
-		const PMR *psPMR,
-		IMG_UINT32 ui32AllocPageCount,
-		IMG_UINT32 *pai32AllocIndices,
-		IMG_UINT32 ui32FreePageCount,
-		IMG_UINT32 *pai32FreeIndices,
-		IMG_UINT32	uiFlags,
-		IMG_UINT32	*pui32Status)
+						const PMR *psPMR,
+						IMG_UINT32 ui32AllocPageCount,
+						IMG_UINT32 *pai32AllocIndices,
+						IMG_UINT32 ui32FreePageCount,
+						IMG_UINT32 *pai32FreeIndices,
+						IMG_UINT32 uiFlags)
 {
-	IMG_UINT32 ui32AdtnlAllocPages=0, ui32AdtnlFreePages=0,ui32CommonRequstCount=0,ui32Loop=0;
-	struct _PMR_OSPAGEARRAY_DATA_ *psPMRPageArrayData = (struct _PMR_OSPAGEARRAY_DATA_ *)pPriv;
-	struct page *page;
-	PVRSRV_ERROR eError = ~PVRSRV_OK;
-	IMG_UINT32	ui32Index = 0,uiAllocpgidx,uiFreepgidx;
+	PVRSRV_ERROR eError;
 
-	/*Fetch the Page table array represented by the PMR */
-	struct page **psPageArray = psPMRPageArrayData->pagearray;
 	PMR_MAPPING_TABLE *psPMRMapTable = PMR_GetMappigTable(psPMR);
+	PMR_OSPAGEARRAY_DATA *psPMRPageArrayData = (PMR_OSPAGEARRAY_DATA *)pPriv;
+	struct page **psPageArray = psPMRPageArrayData->pagearray;
+	struct page *psPage;
 
-	if(SPARSE_RESIZE_BOTH == (uiFlags & SPARSE_RESIZE_BOTH))
+	IMG_UINT32 ui32AdtnlAllocPages = 0; /*<! Number of pages to alloc from the OS */
+	IMG_UINT32 ui32AdtnlFreePages = 0; /*<! Number of pages to free back to the OS */
+	IMG_UINT32 ui32CommonRequestCount = 0; /*<! Number of pages to move position in the page array */
+	IMG_UINT32 ui32Loop = 0;
+	IMG_UINT32 ui32Index = 0;
+	IMG_UINT32 uiAllocpgidx ;
+	IMG_UINT32 uiFreepgidx;
+
+
+	/* Check SPARSE flags and calculate pages to allocate and free */
+	if (SPARSE_RESIZE_BOTH == (uiFlags & SPARSE_RESIZE_BOTH))
 	{
-		ui32CommonRequstCount = (ui32AllocPageCount > ui32FreePageCount)?ui32FreePageCount:ui32AllocPageCount;
-#ifdef PDUMP
-		PDUMP_PANIC(RGX, SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported ");
-#endif
+		ui32CommonRequestCount = (ui32AllocPageCount > ui32FreePageCount) ?
+				ui32FreePageCount : ui32AllocPageCount;
+
+		PDUMP_PANIC(SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported");
 	}
-	if(SPARSE_RESIZE_ALLOC == (uiFlags & SPARSE_RESIZE_ALLOC))
+
+	if (SPARSE_RESIZE_ALLOC == (uiFlags & SPARSE_RESIZE_ALLOC))
 	{
-		ui32AdtnlAllocPages = ui32AllocPageCount - ui32CommonRequstCount;
-	}else
+		ui32AdtnlAllocPages = ui32AllocPageCount - ui32CommonRequestCount;
+	}
+	else
 	{
 		ui32AllocPageCount = 0;
 	}
-	if(SPARSE_RESIZE_FREE == (uiFlags & SPARSE_RESIZE_FREE))
+
+	if (SPARSE_RESIZE_FREE == (uiFlags & SPARSE_RESIZE_FREE))
 	{
-		ui32AdtnlFreePages = ui32FreePageCount - ui32CommonRequstCount;
+		ui32AdtnlFreePages = ui32FreePageCount - ui32CommonRequestCount;
 	}
 	else
 	{
 		ui32FreePageCount = 0;
 	}
-	if(0 == (ui32CommonRequstCount || ui32AdtnlAllocPages || ui32AdtnlFreePages))
+
+	if (0 == (ui32CommonRequestCount || ui32AdtnlAllocPages || ui32AdtnlFreePages))
 	{
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		return eError;
 	}
 
-	/*The incoming request is classified in to two operations alloc & free pages, independent of each other
-	 * These operations can be combined with two mapping operations as well which are GPU & CPU space mapping
-	 * From the alloc and free page requests, net pages to be allocated or freed is computed.
-	 * And hence the order of operations are done in the following steps.
-	 * 1. Allocate net pages
-	 * 2. Move the free pages from free request to common alloc requests.
-	 * 3. Free net pages
-	 * */
+	/* The incoming request is classified into two operations independent of
+	 * each other: alloc & free pages.
+	 * These operations can be combined with two mapping operations as well
+	 * which are GPU & CPU space mappings.
+	 *
+	 * From the alloc and free page requests, the net amount of pages to be
+	 * allocated or freed is computed. Pages that were requested to be freed
+	 * will be reused to fulfil alloc requests.
+	 *
+	 * The order of operations is:
+	 * 1. Allocate new pages from the OS
+	 * 2. Move the free pages from free request to alloc positions.
+	 * 3. Free the rest of the pages not used for alloc
+	 *
+	 * Alloc parameters are validated at the time of allocation
+	 * and any error will be handled then. */
 
+	/* Validate the free indices */
+	if (ui32FreePageCount)
 	{
-		/*Alloc parameters are validated at the time of allocation
-		 * and any error will be handled then
-		 * */
-		/*Validate the free parameters*/
-		if(ui32FreePageCount)
-		{
-			if(NULL != pai32FreeIndices){
+		if (NULL != pai32FreeIndices){
 
-				for(ui32Loop=0; ui32Loop<ui32FreePageCount; ui32Loop++)
+			for (ui32Loop = 0; ui32Loop < ui32FreePageCount; ui32Loop++)
+			{
+				uiFreepgidx = pai32FreeIndices[ui32Loop];
+
+				if (uiFreepgidx > psPMRPageArrayData->uiTotalNumPages)
 				{
-					uiFreepgidx = pai32FreeIndices[ui32Loop];
-					if((uiFreepgidx > psPMRPageArrayData->uiTotalNumPages))
-					{
-						eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
-						goto SparseMemChangeFailed;
-					}
-					if(INVALID_PAGE == psPageArray[uiFreepgidx])
-					{
-						eError = PVRSRV_ERROR_INVALID_PARAMS;
-						goto SparseMemChangeFailed;
-					}
+					eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
+					goto e0;
 				}
-			}else{
+
+				if (INVALID_PAGE == psPageArray[uiFreepgidx])
+				{
+					eError = PVRSRV_ERROR_INVALID_PARAMS;
+					goto e0;
+				}
+			}
+		}
+		else
+		{
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			return eError;
+		}
+	}
+
+	/* Validate the alloc indices */
+	for (ui32Loop = ui32AdtnlAllocPages; ui32Loop < ui32AllocPageCount; ui32Loop++)
+	{
+		uiAllocpgidx = pai32AllocIndices[ui32Loop];
+
+		if (uiAllocpgidx > psPMRPageArrayData->uiTotalNumPages)
+		{
+			eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
+			goto e0;
+		}
+
+		if (SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
+		{
+			if ((INVALID_PAGE !=  psPageArray[uiAllocpgidx]) ||
+			    (TRANSLATION_INVALID != psPMRMapTable->aui32Translation[uiAllocpgidx]))
+			{
 				eError = PVRSRV_ERROR_INVALID_PARAMS;
-				return eError;
+				goto e0;
 			}
 		}
-
-		/*The following block of code verifies any issues with common alloc page indices */
-		for(ui32Loop=ui32AdtnlAllocPages; ui32Loop<ui32AllocPageCount; ui32Loop++)
+		else
 		{
-			uiAllocpgidx = pai32AllocIndices[ui32Loop];
-			if((uiAllocpgidx > psPMRPageArrayData->uiTotalNumPages))
+			if ((INVALID_PAGE ==  psPageArray[uiAllocpgidx]) ||
+			    (TRANSLATION_INVALID == psPMRMapTable->aui32Translation[uiAllocpgidx]) )
 			{
-				eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
-				goto SparseMemChangeFailed;
-			}
-			if(SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
-			{
-				if((INVALID_PAGE !=  psPageArray[uiAllocpgidx]) || \
-								(TRANSLATION_INVALID != psPMRMapTable->aui32Translation[uiAllocpgidx]))
-				{
-					eError = PVRSRV_ERROR_INVALID_PARAMS;
-					goto SparseMemChangeFailed;
-				}
-			}else{
-				if(((INVALID_PAGE ==  psPageArray[uiAllocpgidx]) || \
-						(TRANSLATION_INVALID == psPMRMapTable->aui32Translation[uiAllocpgidx])))
-				{
-					eError = PVRSRV_ERROR_INVALID_PARAMS;
-					goto SparseMemChangeFailed;
-				}
+				eError = PVRSRV_ERROR_INVALID_PARAMS;
+				goto e0;
 			}
 		}
+	}
 
-		ui32Loop = 0;
-		if(0 != ui32AdtnlAllocPages)
+	ui32Loop = 0;
+
+	/* Allocate new pages from the OS */
+	if (0 != ui32AdtnlAllocPages)
+	{
+			eError = _AllocOSPages(psPMRPageArrayData, pai32AllocIndices, ui32AdtnlAllocPages);
+			if (PVRSRV_OK != eError)
+			{
+				PVR_DPF((PVR_DBG_MESSAGE,
+				         "%s: New Addtl Allocation of pages failed",
+				         __FUNCTION__));
+				goto e0;
+			}
+
+			/*Mark the corresponding pages of translation table as valid */
+			for (ui32Loop = 0; ui32Loop < ui32AdtnlAllocPages; ui32Loop++)
+			{
+				psPMRMapTable->aui32Translation[pai32AllocIndices[ui32Loop]] = pai32AllocIndices[ui32Loop];
+			}
+	}
+
+
+	ui32Index = ui32Loop;
+
+	/* Move the corresponding free pages to alloc request */
+	for (ui32Loop = 0; ui32Loop < ui32CommonRequestCount; ui32Loop++, ui32Index++)
+	{
+		uiAllocpgidx = pai32AllocIndices[ui32Index];
+		uiFreepgidx =  pai32FreeIndices[ui32Loop];
+		psPage = psPageArray[uiAllocpgidx];
+		psPageArray[uiAllocpgidx] = psPageArray[uiFreepgidx];
+
+		/* Is remap mem used in real world scenario? Should it be turned to a
+		 *  debug feature? The condition check needs to be out of loop, will be
+		 *  done at later point though after some analysis */
+		if (SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
 		{
-
-				/*Alloc pages*/
-				eError = _AllocOSPages(&psPMRPageArrayData, pai32AllocIndices, ui32AdtnlAllocPages);
-				if(PVRSRV_OK != eError)
-				{
-					PVR_DPF((PVR_DBG_MESSAGE, "%s: New Addtl Allocation of pages failed", __FUNCTION__));
-					goto SparseMemChangeFailed;
-
-				}
-				/*Mark the corresponding pages of translation table as valid */
-				for(ui32Loop=0;ui32Loop<ui32AdtnlAllocPages;ui32Loop++)
-				{
-					psPMRMapTable->aui32Translation[pai32AllocIndices[ui32Loop]] = pai32AllocIndices[ui32Loop];
-				}
+			psPMRMapTable->aui32Translation[uiFreepgidx] = TRANSLATION_INVALID;
+			psPMRMapTable->aui32Translation[uiAllocpgidx] = uiAllocpgidx;
+			psPageArray[uiFreepgidx] = (struct page *)INVALID_PAGE;
 		}
-
-		/*Move the corresponding free pages to alloc request */
-		ui32Index = ui32Loop;
-		for(ui32Loop=0; ui32Loop<ui32CommonRequstCount; ui32Loop++,ui32Index++)
+		else
 		{
-			uiAllocpgidx = pai32AllocIndices[ui32Index];
-			uiFreepgidx =  pai32FreeIndices[ui32Loop];
-			page = psPageArray[uiAllocpgidx];
-			psPageArray[uiAllocpgidx] = psPageArray[uiFreepgidx];
-			/*is remap mem used in real world scenario? should it be turned to a debug feature ?
-			 * The condition check need to be out of loop, will be done at later point though after some analysis */
-			if(SPARSE_REMAP_MEM != (uiFlags & SPARSE_REMAP_MEM))
-			{
-				psPMRMapTable->aui32Translation[uiFreepgidx] = TRANSLATION_INVALID;
-				psPMRMapTable->aui32Translation[uiAllocpgidx] = uiAllocpgidx;
-				psPageArray[uiFreepgidx] = (struct page *)INVALID_PAGE;
-			}else{
-				psPageArray[uiFreepgidx] = page;
-				psPMRMapTable->aui32Translation[uiFreepgidx] = uiFreepgidx;
-				psPMRMapTable->aui32Translation[uiAllocpgidx] = uiAllocpgidx;
-			}
+			psPageArray[uiFreepgidx] = psPage;
+			psPMRMapTable->aui32Translation[uiFreepgidx] = uiFreepgidx;
+			psPMRMapTable->aui32Translation[uiAllocpgidx] = uiAllocpgidx;
 		}
+	}
 
-		/*Free the additional free pages */
-		if(0 != ui32AdtnlFreePages)
+	/* Free the additional free pages */
+	if (0 != ui32AdtnlFreePages)
+	{
+		eError = _FreeOSPages(psPMRPageArrayData,
+		                      &pai32FreeIndices[ui32Loop],
+		                      ui32AdtnlFreePages);
+		if (eError != PVRSRV_OK)
 		{
-			eError = _FreeOSPages(psPMRPageArrayData,
-								  &pai32FreeIndices[ui32Loop],
-								  ui32AdtnlFreePages);
-			while(ui32Loop < ui32FreePageCount)
-			{
-				psPMRMapTable->aui32Translation[pai32FreeIndices[ui32Loop]] = TRANSLATION_INVALID;
-				ui32Loop++;
-			}
+			goto e0;
 		}
-
+		while (ui32Loop < ui32FreePageCount)
+		{
+			psPMRMapTable->aui32Translation[pai32FreeIndices[ui32Loop]] = TRANSLATION_INVALID;
+			ui32Loop++;
+		}
 	}
 
 	eError = PVRSRV_OK;
-SparseMemChangeFailed:
-		return eError;
+
+e0:
+	return eError;
 }
 
 /*************************************************************************/ /*!
@@ -2859,29 +3151,28 @@
 */ /**************************************************************************/
 static
 PVRSRV_ERROR PMRChangeSparseMemCPUMapOSMem(PMR_IMPL_PRIVDATA pPriv,
-								const PMR *psPMR,
-								IMG_UINT64 sCpuVAddrBase,
-								IMG_UINT32	ui32AllocPageCount,
-								IMG_UINT32	*pai32AllocIndices,
-								IMG_UINT32	ui32FreePageCount,
-								IMG_UINT32	*pai32FreeIndices,
-								IMG_UINT32	*pui32Status)
+                                           const PMR *psPMR,
+                                           IMG_UINT64 sCpuVAddrBase,
+                                           IMG_UINT32 ui32AllocPageCount,
+                                           IMG_UINT32 *pai32AllocIndices,
+                                           IMG_UINT32 ui32FreePageCount,
+                                           IMG_UINT32 *pai32FreeIndices)
 {
 	struct page **psPageArray;
-	struct _PMR_OSPAGEARRAY_DATA_ *psPMRPageArrayData = (struct _PMR_OSPAGEARRAY_DATA_ *)pPriv;
-	PVRSRV_ERROR eError = ~PVRSRV_OK;
+	PMR_OSPAGEARRAY_DATA *psPMRPageArrayData = (PMR_OSPAGEARRAY_DATA *)pPriv;
+	IMG_CPU_PHYADDR sCPUPAddr;
 
+	sCPUPAddr.uiAddr = 0;
 	psPageArray = psPMRPageArrayData->pagearray;
+
 	return OSChangeSparseMemCPUAddrMap((void **)psPageArray,
-											sCpuVAddrBase,
-											0,
-											ui32AllocPageCount,
-											pai32AllocIndices,
-											ui32FreePageCount,
-											pai32FreeIndices,
-											pui32Status,
-											IMG_FALSE);
-	return eError;
+	                                   sCpuVAddrBase,
+	                                   sCPUPAddr,
+	                                   ui32AllocPageCount,
+	                                   pai32AllocIndices,
+	                                   ui32FreePageCount,
+	                                   pai32FreeIndices,
+	                                   IMG_FALSE);
 }
 
 static PMR_IMPL_FUNCTAB _sPMROSPFuncTab = {
@@ -2899,64 +3190,81 @@
     .pfnFinalize = &PMRFinalizeOSMem,
 };
 
-static PVRSRV_ERROR
-_NewOSAllocPagesPMR(PVRSRV_DEVICE_NODE *psDevNode,
-                    IMG_DEVMEM_SIZE_T uiSize,
-					IMG_DEVMEM_SIZE_T uiChunkSize,
-					IMG_UINT32 ui32NumPhysChunks,
-					IMG_UINT32 ui32NumVirtChunks,
-					IMG_UINT32 *puiAllocIndicies,
-                    IMG_UINT32 uiLog2DevPageSize,
-                    PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                    PMR **ppsPMRPtr)
+PVRSRV_ERROR
+PhysmemNewOSRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+						 IMG_DEVMEM_SIZE_T uiSize,
+						 IMG_DEVMEM_SIZE_T uiChunkSize,
+						 IMG_UINT32 ui32NumPhysChunks,
+						 IMG_UINT32 ui32NumVirtChunks,
+						 IMG_UINT32 *puiAllocIndices,
+						 IMG_UINT32 uiLog2PageSize,
+						 PVRSRV_MEMALLOCFLAGS_T uiFlags,
+						 const IMG_CHAR *pszAnnotation,
+						 PMR **ppsPMRPtr)
 {
-    PVRSRV_ERROR eError;
-    PVRSRV_ERROR eError2;
-    PMR *psPMR;
-    struct _PMR_OSPAGEARRAY_DATA_ *psPrivData;
-    IMG_HANDLE hPDumpAllocInfo = NULL;
-    PMR_FLAGS_T uiPMRFlags;
+	PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError2;
+	PMR *psPMR;
+	struct _PMR_OSPAGEARRAY_DATA_ *psPrivData;
+	PMR_FLAGS_T uiPMRFlags;
 	PHYS_HEAP *psPhysHeap;
-    IMG_BOOL bZero = IMG_FALSE;
-    IMG_BOOL bPoisonOnAlloc = IMG_FALSE;
-    IMG_BOOL bPoisonOnFree = IMG_FALSE;
-    IMG_BOOL bOnDemand = ((uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
-	IMG_BOOL bCpuLocal = ((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_LOCAL) > 0);
-	IMG_UINT32 ui32CPUCacheFlags = (IMG_UINT32) DevmemCPUCacheMode(uiFlags);
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	IMG_BOOL bFwLocalAlloc = uiFlags & PVRSRV_MEMALLOCFLAG_FW_LOCAL ? IMG_TRUE : IMG_FALSE;
-	PVR_ASSERT(bFwLocalAlloc == 0);
+	IMG_BOOL bZero;
+	IMG_BOOL bIsCMA;
+	IMG_BOOL bPoisonOnAlloc;
+	IMG_BOOL bPoisonOnFree;
+	IMG_BOOL bOnDemand;
+	IMG_BOOL bCpuLocal;
+	IMG_BOOL bFwLocal;
+	IMG_UINT32 ui32CPUCacheFlags = DevmemCPUCacheMode(psDevNode, uiFlags);
+	if (PVRSRV_CHECK_CPU_CACHE_CLEAN(uiFlags))
+	{
+		ui32CPUCacheFlags |= PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN;
+	}
+
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/*
+	 * The host driver (but not guest) can still use this factory for firmware
+	 * allocations
+	 */
+	PVR_ASSERT(!PVRSRV_CHECK_FW_LOCAL(uiFlags));
 #endif
 
-    if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
-    {
-        bZero = IMG_TRUE;
-    }
+	/*
+	 * Silently round up alignment/pagesize if request was less that PAGE_SHIFT
+	 * because it would never be harmful for memory to be _more_ contiguous that
+	 * was desired.
+	 */
+	uiLog2PageSize = PAGE_SHIFT > uiLog2PageSize ? PAGE_SHIFT : uiLog2PageSize;
 
-    if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC)
-    {
-        bPoisonOnAlloc = IMG_TRUE;
-    }
+	/* In case we have a non-sparse allocation tolerate bad requests and round up.
+	 * For sparse allocations the users have to make sure to meet the right
+	 * requirements. */
+	if (ui32NumPhysChunks == ui32NumVirtChunks &&
+		ui32NumVirtChunks == 1)
+	{
+		/* Round up allocation size to at least a full PAGE_SIZE */
+		uiSize = PVR_ALIGN(uiSize, PAGE_SIZE);
+		uiChunkSize = uiSize;
+	}
 
-    if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
-    {
-        bPoisonOnFree = IMG_TRUE;
-    }
+	/* 
+	 * Use CMA framework if order is greater than OS page size; please note
+	 * that OSMMapPMRGeneric() has the same expectation as well.
+	 */
+	bIsCMA = uiLog2PageSize > PAGE_SHIFT ? IMG_TRUE : IMG_FALSE;
+	bOnDemand = PVRSRV_CHECK_ON_DEMAND(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bCpuLocal = PVRSRV_CHECK_CPU_LOCAL(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bFwLocal = PVRSRV_CHECK_FW_LOCAL(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bZero = PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bPoisonOnAlloc = PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags) ? IMG_TRUE : IMG_FALSE;
+	bPoisonOnFree = PVRSRV_CHECK_POISON_ON_FREE(uiFlags) ? IMG_TRUE : IMG_FALSE;
 
-    if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
-        (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
-    {
-        /* Zero on Alloc and Poison on Alloc are mutually exclusive */
-        eError = PVRSRV_ERROR_INVALID_PARAMS;
-        goto errorOnParam;
-    }
-
-	/* Silently round up alignment/pagesize if request was less that
-	   PAGE_SHIFT, because it would never be harmful for memory to be
-	   _more_ contiguous that was desired */
-	uiLog2DevPageSize = PAGE_SHIFT > uiLog2DevPageSize
-		? PAGE_SHIFT
-		: uiLog2DevPageSize;
+	if (bZero && bPoisonOnAlloc)
+	{
+		/* Zero on Alloc and Poison on Alloc are mutually exclusive */
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto errorOnParam;
+	}
 
 #if defined(PVR_LINUX_PHYSMEM_ZERO_ALL_PAGES)
 	/* Overwrite flags and always zero pages that could go back to UM */
@@ -2965,16 +3273,18 @@
 #endif
 
 	/* Create Array structure that hold the physical pages */
-	eError = _AllocOSPageArray(uiChunkSize,
-						   ui32NumPhysChunks,
-						   ui32NumVirtChunks,
-						   uiLog2DevPageSize,
-						   bZero,
-						   bPoisonOnAlloc,
-						   bPoisonOnFree,
-						   bOnDemand,
-						   ui32CPUCacheFlags,
-						   &psPrivData);
+	eError = _AllocOSPageArray(psDevNode,
+							   uiChunkSize,
+							   ui32NumPhysChunks,
+							   ui32NumVirtChunks,
+							   uiLog2PageSize,
+							   bZero,
+							   bIsCMA,
+							   bPoisonOnAlloc,
+							   bPoisonOnFree,
+							   bOnDemand,
+							   ui32CPUCacheFlags,
+							   &psPrivData);
 	if (eError != PVRSRV_OK)
 	{
 		goto errorOnAllocPageArray;
@@ -2983,89 +3293,99 @@
 	if (!bOnDemand)
 	{
 		/* Do we fill the whole page array or just parts (sparse)? */
-		if(ui32NumPhysChunks == ui32NumVirtChunks)
+		if (ui32NumPhysChunks == ui32NumVirtChunks)
 		{
 			/* Allocate the physical pages */
-			eError = _AllocOSPages(&psPrivData, NULL, psPrivData->uiTotalNumPages);
-
-		}else
+			eError = _AllocOSPages(psPrivData, NULL, psPrivData->uiTotalNumPages);
+		}
+		else
 		{
-			if(0 != ui32NumPhysChunks)
+			if (ui32NumPhysChunks != 0)
 			{
 				/* Calculate the number of pages we want to allocate */
-				IMG_UINT32 uiPagesToAlloc = 0;
-				uiPagesToAlloc = (IMG_UINT32) ( (((ui32NumPhysChunks * uiChunkSize) - 1) >> uiLog2DevPageSize) + 1 );
+				IMG_UINT32 uiPagesToAlloc =
+					(IMG_UINT32) ((((ui32NumPhysChunks * uiChunkSize) - 1) >> uiLog2PageSize) + 1);
+
 				/* Make sure calculation is correct */
-				PVR_ASSERT( ((PMR_SIZE_T) uiPagesToAlloc << uiLog2DevPageSize) == (ui32NumPhysChunks * uiChunkSize) );
+				PVR_ASSERT(((PMR_SIZE_T) uiPagesToAlloc << uiLog2PageSize) ==
+						   (ui32NumPhysChunks * uiChunkSize) );
 
 				/* Allocate the physical pages */
-				eError = _AllocOSPages(&psPrivData, puiAllocIndicies, uiPagesToAlloc);
+				eError = _AllocOSPages(psPrivData, puiAllocIndices,
+									   uiPagesToAlloc);
 			}
 		}
+
 		if (eError != PVRSRV_OK)
 		{
 			goto errorOnAllocPages;
 		}
 	}
 
-    /* In this instance, we simply pass flags straight through.
+	/*
+	 * In this instance, we simply pass flags straight through.
+	 *
+	 * Generically, uiFlags can include things that control the PMR factory, but
+	 * we don't need any such thing (at the time of writing!), and our caller
+	 * specifies all PMR flags so we don't need to meddle with what was given to
+	 * us.
+	 */
+	uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
 
-       Generically, uiFlags can include things that control the PMR
-       factory, but we don't need any such thing (at the time of
-       writing!), and our caller specifies all PMR flags so we don't
-       need to meddle with what was given to us.
-    */
-    uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
-    /* check no significant bits were lost in cast due to different
-       bit widths for flags */
-    PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+	/*
+	 * Check no significant bits were lost in cast due to different bit widths
+	 * for flags
+	 */
+	PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
 
-    if (bOnDemand)
-    {
-    	PDUMPCOMMENT("Deferred Allocation PMR (UMA)");
-    }
-    if (bCpuLocal)
-    {
-    	PDUMPCOMMENT("CPU_LOCAL allocation requested");
+	if (bOnDemand)
+	{
+		PDUMPCOMMENT("Deferred Allocation PMR (UMA)");
+	}
+
+	if (bFwLocal)
+	{
+		PDUMPCOMMENT("FW_LOCAL allocation requested");
+		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL];
+	}
+	else if (bCpuLocal)
+	{
+		PDUMPCOMMENT("CPU_LOCAL allocation requested");
 		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL];
-    }
+	}
 	else
 	{
 		psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL];
 	}
 
-    eError = PMRCreatePMR(psPhysHeap,
-                          uiSize,
-                          uiChunkSize,
-                          ui32NumPhysChunks,
-                          ui32NumVirtChunks,
-                          puiAllocIndicies,
-                          uiLog2DevPageSize,
-                          uiPMRFlags,
-                          "PMROSAP",
-                          &_sPMROSPFuncTab,
-                          psPrivData,
-                          &psPMR,
-                          &hPDumpAllocInfo,
-    					  IMG_FALSE);
-    if (eError != PVRSRV_OK)
-    {
-        goto errorOnCreate;
-    }
+	eError = PMRCreatePMR(psDevNode,
+						  psPhysHeap,
+						  uiSize,
+						  uiChunkSize,
+						  ui32NumPhysChunks,
+						  ui32NumVirtChunks,
+						  puiAllocIndices,
+						  uiLog2PageSize,
+						  uiPMRFlags,
+						  pszAnnotation,
+						  &_sPMROSPFuncTab,
+						  psPrivData,
+						  PMR_TYPE_OSMEM,
+						  &psPMR,
+						  IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		goto errorOnCreate;
+	}
 
+	*ppsPMRPtr = psPMR;
 
-	psPrivData->hPDumpAllocInfo = hPDumpAllocInfo;
-	psPrivData->bPDumpMalloced = IMG_TRUE;
-
-    *ppsPMRPtr = psPMR;
-    return PVRSRV_OK;
+	return PVRSRV_OK;
 
 errorOnCreate:
 	if (!bOnDemand)
 	{
-		eError2 = _FreeOSPages(psPrivData,
-							   NULL,
-							   0);
+		eError2 = _FreeOSPages(psPrivData, NULL, 0);
 		PVR_ASSERT(eError2 == PVRSRV_OK);
 	}
 
@@ -3075,28 +3395,6 @@
 
 errorOnAllocPageArray:
 errorOnParam:
-    PVR_ASSERT(eError != PVRSRV_OK);
-    return eError;
-}
-
-PVRSRV_ERROR
-PhysmemNewOSRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
-                         IMG_DEVMEM_SIZE_T uiSize,
-						 IMG_DEVMEM_SIZE_T uiChunkSize,
-						 IMG_UINT32 ui32NumPhysChunks,
-						 IMG_UINT32 ui32NumVirtChunks,
-						 IMG_UINT32 *puiAllocIndicies,
-                         IMG_UINT32 uiLog2PageSize,
-                         PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                         PMR **ppsPMRPtr)
-{
-    return _NewOSAllocPagesPMR(psDevNode,
-                               uiSize,
-                               uiChunkSize,
-                               ui32NumPhysChunks,
-                               ui32NumVirtChunks,
-                               puiAllocIndicies,
-                               uiLog2PageSize,
-                               uiFlags,
-                               ppsPMRPtr);
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
 }
diff --git a/drivers/staging/imgtec/rogue/physmem_osmem_linux.h b/drivers/staging/imgtec/rogue/physmem_osmem_linux.h
index c6cc2f8..3fac82d 100644
--- a/drivers/staging/imgtec/rogue/physmem_osmem_linux.h
+++ b/drivers/staging/imgtec/rogue/physmem_osmem_linux.h
@@ -47,4 +47,3 @@
 void LinuxDeinitPhysmem(void);
 
 #endif /* __PHYSMEM_OSMEM_LINUX_H__ */
- 
diff --git a/drivers/staging/imgtec/rogue/physmem_tdsecbuf.c b/drivers/staging/imgtec/rogue/physmem_tdsecbuf.c
index 7940c50..a379b88 100644
--- a/drivers/staging/imgtec/rogue/physmem_tdsecbuf.c
+++ b/drivers/staging/imgtec/rogue/physmem_tdsecbuf.c
@@ -4,9 +4,8 @@
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @Description    Part of the memory management. This module is responsible for
                 implementing the function callbacks for physical memory imported
-                from a trusted environment. This memory is not accessible from
-                within the driver, so the only purpose of this PMR is to
-                provide physical addresses for the MMU page tables.
+                from a trusted environment. The driver cannot acquire CPU
+                mappings for this secure memory.
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -58,12 +57,15 @@
 
 #if defined (SUPPORT_TRUSTED_DEVICE)
 
+#if !defined(NO_HARDWARE)
+
 typedef struct _PMR_TDSECBUF_DATA_ {
+	PVRSRV_DEVICE_NODE    *psDevNode;
 	PHYS_HEAP             *psTDSecBufPhysHeap;
-	PFN_TD_SECUREBUF_FREE pfnTDSecureBufFree;
 	IMG_CPU_PHYADDR       sCpuPAddr;
 	IMG_DEV_PHYADDR       sDevPAddr;
 	IMG_UINT64            ui64Size;
+	IMG_UINT32            ui32Log2PageSize;
 	IMG_UINT64            ui64SecBufHandle;
 } PMR_TDSECBUF_DATA;
 
@@ -73,6 +75,7 @@
  */
 
 static PVRSRV_ERROR PMRSysPhysAddrTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv,
+                                              IMG_UINT32 ui32Log2PageSize,
                                               IMG_UINT32 ui32NumOfPages,
                                               IMG_DEVMEM_OFFSET_T *puiOffset,
                                               IMG_BOOL *pbValid,
@@ -81,6 +84,11 @@
 	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
 	IMG_UINT32 i;
 
+	if (psPrivData->ui32Log2PageSize != ui32Log2PageSize)
+	{
+		return PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+	}
+
 	for (i = 0; i < ui32NumOfPages; i++)
 	{
 		psDevPAddr[i].uiAddr = psPrivData->sDevPAddr.uiAddr + puiOffset[i];
@@ -92,9 +100,11 @@
 static PVRSRV_ERROR PMRFinalizeTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv)
 {
 	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+	PVRSRV_DEVICE_CONFIG *psDevConfig = psPrivData->psDevNode->psDevConfig;
 	PVRSRV_ERROR eError;
 
-	eError = psPrivData->pfnTDSecureBufFree(psPrivData->ui64SecBufHandle);
+	eError = psDevConfig->pfnTDSecureBufFree(psDevConfig->hSysData,
+											 psPrivData->ui64SecBufHandle);
 	if (eError != PVRSRV_OK)
 	{
 		if (eError == PVRSRV_ERROR_NOT_IMPLEMENTED)
@@ -115,34 +125,8 @@
 }
 
 static PMR_IMPL_FUNCTAB _sPMRTDSecBufFuncTab = {
-	/* pfnLockPhysAddresses */
-	NULL,
-	/* pfnUnlockPhysAddresses */
-	NULL,
-	/* pfnDevPhysAddr */
-	&PMRSysPhysAddrTDSecBufMem,
-	/* pfnPDumpSymbolicAddr */
-	NULL,
-	/* pfnAcquireKernelMappingData */
-	NULL,
-	/* pfnReleaseKernelMappingData */
-	NULL,
-	/* pfnReadBytes */
-	NULL,
-	/* pfnWriteBytes */
-	NULL,
-	/* pfnUnpinMem */
-	NULL,
-	/* pfnPinMem */
-	NULL,
-	/* pfnChangeSparseMem */
-	NULL,
-	/* pfnChangeSparseMemCPUMap */
-	NULL,
-	/* pfnMMap */
-	NULL,
-	/* pfnFinalize */
-	&PMRFinalizeTDSecBufMem
+	.pfnDevPhysAddr = &PMRSysPhysAddrTDSecBufMem,
+	.pfnFinalize = &PMRFinalizeTDSecBufMem,
 };
 
 
@@ -152,8 +136,8 @@
 PVRSRV_ERROR PhysmemNewTDSecureBufPMR(CONNECTION_DATA *psConnection,
                                       PVRSRV_DEVICE_NODE *psDevNode,
                                       IMG_DEVMEM_SIZE_T uiSize,
+                                      PMR_LOG2ALIGN_T uiLog2Align,
                                       PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                                      IMG_UINT32 *pui32Align,
                                       PMR **ppsPMRPtr,
                                       IMG_UINT64 *pui64SecBufHandle)
 {
@@ -161,14 +145,13 @@
 	RGX_DATA *psRGXData = (RGX_DATA *)(psDevConfig->hDevData);
 	PMR_TDSECBUF_DATA *psPrivData = NULL;
 	PMR *psPMR = NULL;
-	IMG_HANDLE hPDumpAllocInfo = NULL;
-	PMR_LOG2ALIGN_T uiLog2PageSize = OSGetPageShift();
-	IMG_BOOL bMappingTable = IMG_TRUE;
+	IMG_UINT32 uiMappingTable = 0;
 	PMR_FLAGS_T uiPMRFlags;
 	PVRSRV_ERROR eError;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
+
 	/* In this instance, we simply pass flags straight through.
 	 * Generically, uiFlags can include things that control the PMR
 	 * factory, but we don't need any such thing (at the time of
@@ -214,17 +197,18 @@
 	{
 		PVRSRV_TD_SECBUF_PARAMS sTDSecBufParams;
 
-		psPrivData->pfnTDSecureBufFree = psDevConfig->pfnTDSecureBufFree;
+		psPrivData->psDevNode = psDevNode;
 
 		/* Ask the Trusted Device to allocate secure memory */
 		sTDSecBufParams.uiSize = uiSize;
-		sTDSecBufParams.uiAlign = 1 << uiLog2PageSize;
+		sTDSecBufParams.uiAlign = 1 << uiLog2Align;
 
 		/* These will be returned by pfnTDSecureBufAlloc on success */
 		sTDSecBufParams.psSecBufAddr = &psPrivData->sCpuPAddr;
 		sTDSecBufParams.pui64SecBufHandle = &psPrivData->ui64SecBufHandle;
 
-		eError = psDevConfig->pfnTDSecureBufAlloc(&sTDSecBufParams);
+		eError = psDevConfig->pfnTDSecureBufAlloc(psDevConfig->hSysData,
+												  &sTDSecBufParams);
 		if (eError != PVRSRV_OK)
 		{
 			if (eError == PVRSRV_ERROR_NOT_IMPLEMENTED)
@@ -250,28 +234,35 @@
 	                           &psPrivData->sDevPAddr,
 	                           &psPrivData->sCpuPAddr);
 
+	/* Check that the secure buffer has the requested alignment */
+	if ((((1ULL << uiLog2Align) - 1) & psPrivData->sCpuPAddr.uiAddr) != 0)
 	/* Check that the secure buffer is aligned to a Rogue cache line */
-	if ((psPrivData->sDevPAddr.uiAddr & (ROGUE_CACHE_LINE_SIZE - 1)) != 0)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Trusted Device physical heap not aligned to a Rogue cache line!"));
+		PVR_DPF((PVR_DBG_ERROR,
+				 "Trusted Device physical heap has the wrong alignment!"
+				 "Physical address 0x%llx, alignment mask 0x%llx",
+				 (unsigned long long) psPrivData->sCpuPAddr.uiAddr,
+				 ((1ULL << uiLog2Align) - 1)));
 		eError = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
 		goto errorOnCheckAlign;
 	}
 
+	psPrivData->ui32Log2PageSize = uiLog2Align;
 
-	eError = PMRCreatePMR(psPrivData->psTDSecBufPhysHeap,
+	eError = PMRCreatePMR(psDevNode,
+	                      psPrivData->psTDSecBufPhysHeap,
 	                      psPrivData->ui64Size,
 	                      psPrivData->ui64Size,
 	                      1,                 /* ui32NumPhysChunks */
 	                      1,                 /* ui32NumVirtChunks */
-	                      &bMappingTable,    /* pui32MappingTable (not used) */
-	                      uiLog2PageSize,
+	                      &uiMappingTable,   /* pui32MappingTable (not used) */
+	                      uiLog2Align,
 	                      uiPMRFlags,
-	                      "PMRTDSECUREBUF",
+	                      "TDSECUREBUF_PMR",
 	                      &_sPMRTDSecBufFuncTab,
 	                      psPrivData,
+	                      PMR_TYPE_TDSECBUF,
 	                      &psPMR,
-	                      &hPDumpAllocInfo,
 	                      IMG_FALSE);
 	if (eError != PVRSRV_OK)
 	{
@@ -291,7 +282,6 @@
 	}
 #endif
 
-	*pui32Align = 1 << uiLog2PageSize;
 	*ppsPMRPtr = psPMR;
 	*pui64SecBufHandle = psPrivData->ui64SecBufHandle;
 
@@ -300,7 +290,8 @@
 
 errorOnCreatePMR:
 errorOnCheckAlign:
-	eError = psDevConfig->pfnTDSecureBufFree(psPrivData->ui64SecBufHandle);
+	eError = psDevConfig->pfnTDSecureBufFree(psDevConfig->hSysData,
+											 psPrivData->ui64SecBufHandle);
 	if (eError != PVRSRV_OK)
 	{
 		if (eError == PVRSRV_ERROR_NOT_IMPLEMENTED)
@@ -323,21 +314,256 @@
 	return eError;
 }
 
+#else /* NO_HARDWARE */
+
+#include "physmem_osmem.h"
+
+typedef struct _PMR_TDSECBUF_DATA_ {
+	PHYS_HEAP  *psTDSecBufPhysHeap;
+	PMR        *psOSMemPMR;
+	IMG_UINT32 ui32Log2PageSize;
+} PMR_TDSECBUF_DATA;
+
+
+/*
+ * Implementation of callback functions
+ */
+
+static PVRSRV_ERROR
+PMRLockPhysAddressesTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv)
+{
+	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+
+	return PMRLockSysPhysAddresses(psPrivData->psOSMemPMR);
+}
+
+static PVRSRV_ERROR
+PMRUnlockPhysAddressesTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv)
+{
+	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+
+	return PMRUnlockSysPhysAddresses(psPrivData->psOSMemPMR);
+}
+
+static PVRSRV_ERROR
+PMRSysPhysAddrTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv,
+                          IMG_UINT32 ui32Log2PageSize,
+                          IMG_UINT32 ui32NumOfPages,
+                          IMG_DEVMEM_OFFSET_T *puiOffset,
+                          IMG_BOOL *pbValid,
+                          IMG_DEV_PHYADDR *psDevPAddr)
+{
+	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+
+	/* On the assumption that this PMR was created with
+	 * NumPhysChunks == NumVirtChunks then
+	 * puiOffset[0] == uiLogicalOffset
+	 */
+
+	return PMR_DevPhysAddr(psPrivData->psOSMemPMR,
+	                       ui32Log2PageSize,
+	                       ui32NumOfPages,
+	                       puiOffset[0],
+	                       psDevPAddr,
+	                       pbValid);
+}
+
+static PVRSRV_ERROR
+PMRAcquireKernelMappingDataTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv,
+                                       size_t uiOffset,
+                                       size_t uiSize,
+                                       void **ppvKernelAddressOut,
+                                       IMG_HANDLE *phHandleOut,
+                                       PMR_FLAGS_T ulFlags)
+{
+	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+	size_t uiLengthOut;
+
+	PVR_UNREFERENCED_PARAMETER(ulFlags);
+
+	return PMRAcquireKernelMappingData(psPrivData->psOSMemPMR,
+	                                   uiOffset,
+	                                   uiSize,
+	                                   ppvKernelAddressOut,
+	                                   &uiLengthOut,
+	                                   phHandleOut);
+}
+
+static void
+PMRReleaseKernelMappingDataTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv,
+                                       IMG_HANDLE hHandle)
+{
+	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+
+	PMRReleaseKernelMappingData(psPrivData->psOSMemPMR, hHandle);
+}
+
+static PVRSRV_ERROR PMRFinalizeTDSecBufMem(PMR_IMPL_PRIVDATA pvPriv)
+{
+	PMR_TDSECBUF_DATA *psPrivData = pvPriv;
+
+	PMRUnrefPMR(psPrivData->psOSMemPMR);
+	PhysHeapRelease(psPrivData->psTDSecBufPhysHeap);
+	OSFreeMem(psPrivData);
+
+	return PVRSRV_OK;
+}
+
+static PMR_IMPL_FUNCTAB _sPMRTDSecBufFuncTab = {
+	.pfnLockPhysAddresses = &PMRLockPhysAddressesTDSecBufMem,
+	.pfnUnlockPhysAddresses = &PMRUnlockPhysAddressesTDSecBufMem,
+	.pfnDevPhysAddr = &PMRSysPhysAddrTDSecBufMem,
+	.pfnAcquireKernelMappingData = &PMRAcquireKernelMappingDataTDSecBufMem,
+	.pfnReleaseKernelMappingData = &PMRReleaseKernelMappingDataTDSecBufMem,
+	.pfnFinalize = &PMRFinalizeTDSecBufMem,
+};
+
+
+/*
+ * Public functions
+ */
+PVRSRV_ERROR PhysmemNewTDSecureBufPMR(CONNECTION_DATA *psConnection,
+                                      PVRSRV_DEVICE_NODE *psDevNode,
+                                      IMG_DEVMEM_SIZE_T uiSize,
+                                      PMR_LOG2ALIGN_T uiLog2Align,
+                                      PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                      PMR **ppsPMRPtr,
+                                      IMG_UINT64 *pui64SecBufHandle)
+{
+	PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
+	RGX_DATA *psRGXData = (RGX_DATA *)(psDevConfig->hDevData);
+	PMR_TDSECBUF_DATA *psPrivData = NULL;
+	PMR *psPMR = NULL;
+	PMR *psOSPMR = NULL;
+	IMG_UINT32 uiMappingTable = 0;
+	PMR_FLAGS_T uiPMRFlags;
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	/* In this instance, we simply pass flags straight through.
+	 * Generically, uiFlags can include things that control the PMR
+	 * factory, but we don't need any such thing (at the time of
+	 * writing!), and our caller specifies all PMR flags so we don't
+	 * need to meddle with what was given to us.
+	 */
+	uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
+
+	/* Check no significant bits were lost in cast due to different bit widths for flags */
+	PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+
+	psPrivData = OSAllocZMem(sizeof(PMR_TDSECBUF_DATA));
+	if (psPrivData == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto errorOnAllocData;
+	}
+
+	/* Get required info for the TD Secure Buffer physical heap */
+	if (!psRGXData->bHasTDSecureBufPhysHeap)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Trusted Device physical heap not available!"));
+		eError = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
+		goto errorOnAcquireHeap;
+	}
+
+	eError = PhysHeapAcquire(psRGXData->uiTDSecureBufPhysHeapID,
+	                         &psPrivData->psTDSecBufPhysHeap);
+	if (eError != PVRSRV_OK) goto errorOnAcquireHeap;
+
+	psPrivData->ui32Log2PageSize = uiLog2Align;
+
+	/* Note that this PMR is only used to copy the FW blob to memory and
+	 * to dump this memory to pdump, it doesn't need to have the alignment
+	 * requested by the caller
+	 */
+	eError = PhysmemNewOSRamBackedPMR(psDevNode,
+	                                  uiSize,
+	                                  uiSize,
+	                                  1,                 /* ui32NumPhysChunks */
+	                                  1,                 /* ui32NumVirtChunks */
+	                                  &uiMappingTable,
+	                                  psPrivData->ui32Log2PageSize,
+	                                  uiFlags,
+	                                  "TDSECUREBUF_OSMEM",
+	                                  &psOSPMR);
+	if (eError != PVRSRV_OK)
+	{
+		goto errorOnCreateOSPMR;
+	}
+
+	/* This is the primary PMR dumped with correct memspace and alignment */
+	eError = PMRCreatePMR(psDevNode,
+	                      psPrivData->psTDSecBufPhysHeap,
+	                      uiSize,
+	                      uiSize,
+	                      1,               /* ui32NumPhysChunks */
+	                      1,               /* ui32NumVirtChunks */
+	                      &uiMappingTable, /* pui32MappingTable (not used) */
+	                      uiLog2Align,
+	                      uiPMRFlags,
+	                      "TDSECUREBUF_PMR",
+	                      &_sPMRTDSecBufFuncTab,
+	                      psPrivData,
+	                      PMR_TYPE_TDSECBUF,
+	                      &psPMR,
+	                      IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		goto errorOnCreateTDPMR;
+	}
+
+#if defined(PVR_RI_DEBUG)
+	eError = RIWritePMREntryKM(psPMR,
+	                           sizeof("TDSecureBuffer"),
+	                           "TDSecureBuffer",
+	                           psPrivData->ui64Size);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+		         "%s: Failed to write PMR entry (%s)",
+		         __func__, PVRSRVGetErrorStringKM(eError)));
+	}
+#endif
+
+	psPrivData->psOSMemPMR = psOSPMR;
+	*ppsPMRPtr = psPMR;
+	*pui64SecBufHandle = 0x0ULL;
+
+	return PVRSRV_OK;
+
+errorOnCreateTDPMR:
+	PMRUnrefPMR(psOSPMR);
+
+errorOnCreateOSPMR:
+	PhysHeapRelease(psPrivData->psTDSecBufPhysHeap);
+
+errorOnAcquireHeap:
+	OSFreeMem(psPrivData);
+
+errorOnAllocData:
+	PVR_ASSERT(eError != PVRSRV_OK);
+
+	return eError;
+}
+
+#endif /* NO_HARDWARE */
+
 #else /* SUPPORT_TRUSTED_DEVICE */
 
 PVRSRV_ERROR PhysmemNewTDSecureBufPMR(CONNECTION_DATA *psConnection,
                                       PVRSRV_DEVICE_NODE *psDevNode,
                                       IMG_DEVMEM_SIZE_T uiSize,
+                                      PMR_LOG2ALIGN_T uiLog2Align,
                                       PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                                      IMG_UINT32 *pui32Align,
                                       PMR **ppsPMRPtr,
                                       IMG_UINT64 *pui64SecBufHandle)
 {
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(uiSize);
+	PVR_UNREFERENCED_PARAMETER(uiLog2Align);
 	PVR_UNREFERENCED_PARAMETER(uiFlags);
-	PVR_UNREFERENCED_PARAMETER(pui32Align);
 	PVR_UNREFERENCED_PARAMETER(ppsPMRPtr);
 	PVR_UNREFERENCED_PARAMETER(pui64SecBufHandle);
 
@@ -349,16 +575,16 @@
 PVRSRV_ERROR PhysmemImportSecBuf(CONNECTION_DATA *psConnection,
                                  PVRSRV_DEVICE_NODE *psDevNode,
                                  IMG_DEVMEM_SIZE_T uiSize,
+                                 IMG_UINT32 ui32Log2Align,
                                  PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                                 IMG_UINT32 *pui32Align,
                                  PMR **ppsPMRPtr,
                                  IMG_UINT64 *pui64SecBufHandle)
 {
 	return PhysmemNewTDSecureBufPMR(psConnection,
 	                                psDevNode,
 	                                uiSize,
+	                                (PMR_LOG2ALIGN_T)ui32Log2Align,
 	                                uiFlags,
-	                                pui32Align,
 	                                ppsPMRPtr,
 	                                pui64SecBufHandle);
 };
diff --git a/drivers/staging/imgtec/rogue/physmem_tdsecbuf.h b/drivers/staging/imgtec/rogue/physmem_tdsecbuf.h
index 9adac4e..6d13802 100644
--- a/drivers/staging/imgtec/rogue/physmem_tdsecbuf.h
+++ b/drivers/staging/imgtec/rogue/physmem_tdsecbuf.h
@@ -67,16 +67,16 @@
 PVRSRV_ERROR PhysmemNewTDSecureBufPMR(CONNECTION_DATA *psConnection,
                                       PVRSRV_DEVICE_NODE *psDevNode,
                                       IMG_DEVMEM_SIZE_T uiSize,
+                                      PMR_LOG2ALIGN_T uiLog2Align,
                                       PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                                      IMG_UINT32 *pui32Align,
                                       PMR **ppsPMRPtr,
                                       IMG_UINT64 *pui64SecBufHandle);
 
 PVRSRV_ERROR PhysmemImportSecBuf(CONNECTION_DATA *psConnection,
                                  PVRSRV_DEVICE_NODE *psDevNode,
                                  IMG_DEVMEM_SIZE_T uiSize,
+                                 IMG_UINT32 ui32Log2Align,
                                  PVRSRV_MEMALLOCFLAGS_T uiFlags,
-                                 IMG_UINT32 *pui32Align,
                                  PMR **ppsPMRPtr,
                                  IMG_UINT64 *pui64SecBufHandle);
 
diff --git a/drivers/staging/imgtec/rogue/pmr.c b/drivers/staging/imgtec/rogue/pmr.c
index fb8c261..9e014af 100644
--- a/drivers/staging/imgtec/rogue/pmr.c
+++ b/drivers/staging/imgtec/rogue/pmr.c
@@ -58,6 +58,7 @@
 #include "pvrsrv_error.h"
 
 #include "pdump.h"
+#include "devicemem_server_utils.h"
 
 #include "osfunc.h"
 #include "pdump_km.h"
@@ -67,11 +68,6 @@
 #include "pvrsrv.h"
 
 #include "allocmem.h"
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC) && defined(LINUX)
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <asm/pgtable.h>
-#endif
 #include "lock.h"
 
 #if defined(SUPPORT_SECURE_EXPORT)
@@ -93,7 +89,7 @@
    There is almost certainly only one of these, ever, in the system.
    But, let's keep the notion of a context anyway, "just-in-case".
 */
-struct _PMR_CTX_
+static struct _PMR_CTX_
 {
     /* For debugging, and PDump, etc., let's issue a forever
        incrementing serial number to each allocation. */
@@ -139,6 +135,10 @@
        (thus it is normal for allocated and exported memory to have a refcount of 3)
        The object is destroyed when and only when the refcount reaches 0
     */
+
+	/* Device node on which this PMR was created and is valid */
+	PVRSRV_DEVICE_NODE *psDevNode;
+
     /*
        Physical address translation (device <> cpu) is done on a per device
        basis which means we need the physical heap info
@@ -173,9 +173,24 @@
     /* Data associated with the "subtype" */
     PMR_IMPL_PRIVDATA pvFlavourData;
 
+    /* What kind of PMR do we have? */
+    PMR_IMPL_TYPE eFlavour;
+
     /* And for pdump */
     const IMG_CHAR *pszPDumpDefaultMemspaceName;
-    const IMG_CHAR *pszPDumpFlavour;
+#if defined(PDUMP)
+    /* Allocation annotation */
+    IMG_CHAR *pszAnnotation;
+
+    IMG_HANDLE hPDumpAllocHandle;
+
+	/* Whether PDumping of this PMR must be persistent
+	 * (i.e. it must be present in every future PDump stream as well)
+	 */
+	IMG_BOOL	bForcePersistent;
+
+	IMG_UINT32 uiNumPDumpBlocks;
+#endif
 
     /* Logical size of allocation.  "logical", because a PMR can
        represent memory that will never physically exist.  This is the
@@ -236,11 +251,6 @@
 	 */
 	void		*hRIHandle;
 #endif
-
-	/* Whether PDumping of this PMR must be persistent
-	 * (i.e. it must be present in every future PDump stream as well)
-	 */
-	IMG_BOOL	bForcePersistent;
 };
 
 /* do we need a struct for the export handle?  I'll use one for now, but if nothing goes in it, we'll lose it */
@@ -257,40 +267,6 @@
 
 #define MIN3(a,b,c)	(((a) < (b)) ? (((a) < (c)) ? (a):(c)) : (((b) < (c)) ? (b):(c)))
 
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-#if defined(LINUX)
-static INLINE IMG_BOOL _IsVmallocAddr(const void *pvAddr)
-{
-	unsigned long lAddr = (unsigned long) pvAddr;
-	return (lAddr >= VMALLOC_START) && (lAddr < VMALLOC_END);
-}
-#endif
-
-static INLINE void *_AllocMem(const size_t size)
-{
-#if defined(LINUX)
-	if (size > OSGetPageSize())
-		return vmalloc(size);
-	else
-		return OSAllocMem(size);
-#else
-	return OSAllocMem(size);
-#endif
-}
-
-static INLINE void _FreeMem(void *pvAddr)
-{
-#if defined(LINUX)
-	if (_IsVmallocAddr(pvAddr))
-		vfree(pvAddr);
-	else
-		OSFreeMem(pvAddr);
-#else
-	OSFreeMem(pvAddr);
-#endif
-}
-#endif
-
 static PVRSRV_ERROR
 _PMRCreate(PMR_SIZE_T uiLogicalSize,
            PMR_SIZE_T uiChunkSize,
@@ -302,9 +278,6 @@
            PMR **ppsPMR)
 {
     void *pvPMRLinAddr;
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-    void *pvMapLinAddr;
-#endif
     PMR *psPMR;
     PMR_MAPPING_TABLE *psMappingTable;
     struct _PMR_CTX_ *psContext;
@@ -340,38 +313,19 @@
 		}
 	}
 
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-	pvPMRLinAddr = OSAllocMem(sizeof(*psPMR) + sizeof(*psMappingTable));
-#else
 	pvPMRLinAddr = OSAllocMem(sizeof(*psPMR) + sizeof(*psMappingTable) + sizeof(IMG_UINT32) * ui32NumVirtChunks);
-#endif
+
 	if (pvPMRLinAddr == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-	pvMapLinAddr = _AllocMem(sizeof(IMG_UINT32) * ui32NumVirtChunks);
-	if (pvMapLinAddr == NULL)
-	{
-		OSFreeMem(pvPMRLinAddr);
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
-	}
-
 	psPMR = (PMR *) pvPMRLinAddr;
 	psMappingTable = (PMR_MAPPING_TABLE *) (((IMG_CHAR *) pvPMRLinAddr) + sizeof(*psPMR));
-	psMappingTable->aui32Translation = (IMG_UINT32 *) pvMapLinAddr;
-#else
-	psPMR = (PMR *) pvPMRLinAddr;
-	psMappingTable = (PMR_MAPPING_TABLE *) (((IMG_CHAR *) pvPMRLinAddr) + sizeof(*psPMR));
-#endif
 
 	eError = OSLockCreate(&psPMR->hLock, LOCK_TYPE_PASSIVE);
 	if (eError != PVRSRV_OK)
 	{
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-		_FreeMem(psMappingTable->aui32Translation);
-#endif
 		OSFreeMem(psPMR);
 		return eError;
 	}
@@ -380,7 +334,7 @@
 	psMappingTable->uiChunkSize = uiChunkSize;
 	psMappingTable->ui32NumVirtChunks = ui32NumVirtChunks;
 	psMappingTable->ui32NumPhysChunks = ui32NumPhysChunks;
-	OSMemSet(&psMappingTable->aui32Translation[0], 0xFF, sizeof(psMappingTable->aui32Translation[0])*
+	OSCachedMemSet(&psMappingTable->aui32Translation[0], 0xFF, sizeof(psMappingTable->aui32Translation[0])*
 																	ui32NumVirtChunks);
 	for (i=0; i<ui32NumPhysChunks; i++)
 	{
@@ -423,13 +377,6 @@
 	/* We need to ensure that this function is always executed under
 	 * PMRLock. The only exception acceptable is the unloading of the driver.
 	 */
-#if defined(PVRSRV_DEBUG_PMR)
-	if ((!PVRSRVGetPVRSRVData()->bUnload) && !PMRIsLockedByMe())
-	{
-		PVR_DPF((PVR_DBG_ERROR, "_RefNoLock: call processed without PMRLock" ));
-		OSDumpStack();
-	}
-#endif
 	psPMR->uiRefCount++;
 	return psPMR->uiRefCount;
 }
@@ -441,13 +388,6 @@
 	/* We need to ensure that this function is always executed under
 	 * PMRLock. The only exception acceptable is the unloading of the driver.
 	 */
-#if defined(PVRSRV_DEBUG_PMR)
-	if ((!PVRSRVGetPVRSRVData()->bUnload) && !PMRIsLockedByMe())
-	{
-		PVR_DPF((PVR_DBG_ERROR, "_UnrefNoLock: call processed without PMRLock" ));
-		OSDumpStack();
-	}
-#endif
 	psPMR->uiRefCount--;
 	return psPMR->uiRefCount;
 }
@@ -463,57 +403,65 @@
 static void
 _UnrefAndMaybeDestroy(PMR *psPMR)
 {
-    PVRSRV_ERROR eError2;
-    struct _PMR_CTX_ *psCtx;
-    IMG_UINT32 uiRefCount;
+	PVRSRV_ERROR eError2;
+	struct _PMR_CTX_ *psCtx;
+	IMG_UINT32 uiRefCount;
 
-    PVR_ASSERT(psPMR != NULL);
-    PVR_ASSERT(psPMR->uiRefCount > 0);
+	PVR_ASSERT(psPMR != NULL);
+	PVR_ASSERT(psPMR->uiRefCount > 0);
 
-    OSLockAcquire(psPMR->hLock);
+	OSLockAcquire(psPMR->hLock);
 	uiRefCount = _UnrefNoLock(psPMR);
-    OSLockRelease(psPMR->hLock);
+	OSLockRelease(psPMR->hLock);
 
-    if (uiRefCount == 0)
-    {
-        if (psPMR->psFuncTab->pfnFinalize != NULL)
-        {
-            eError2 = psPMR->psFuncTab->pfnFinalize(psPMR->pvFlavourData);
-            PVR_ASSERT (eError2 == PVRSRV_OK); /* can we do better? */
-        }
+	if (uiRefCount == 0)
+	{
+#if defined(PDUMP)
+		PDumpPMRFreePMR(psPMR,
+		                psPMR->uiLogicalSize,
+		                (1 << psPMR->uiLog2ContiguityGuarantee),
+		                psPMR->uiLog2ContiguityGuarantee,
+		                psPMR->hPDumpAllocHandle);
+
+		OSFreeMem(psPMR->pszAnnotation);
+#endif
+
+		if (psPMR->psFuncTab->pfnFinalize != NULL)
+		{
+			eError2 = psPMR->psFuncTab->pfnFinalize(psPMR->pvFlavourData);
+			PVR_ASSERT (eError2 == PVRSRV_OK); /* can we do better? */
+		}
 
 #ifdef PVRSRV_NEED_PVR_ASSERT
-        OSLockAcquire(psPMR->hLock);
-        PVR_ASSERT(psPMR->uiLockCount == 0);
-        OSLockRelease(psPMR->hLock);
+		OSLockAcquire(psPMR->hLock);
+		PVR_ASSERT(psPMR->uiLockCount == 0);
+		OSLockRelease(psPMR->hLock);
 #endif
 
 #if defined(PVR_RI_DEBUG)
 		{
-            PVRSRV_ERROR eError;
+			PVRSRV_ERROR eError;
 
 			/* Delete RI entry */
-            if (psPMR->hRIHandle)
-            {
-            	eError = RIDeletePMREntryKM (psPMR->hRIHandle);
-            }
+			if (psPMR->hRIHandle)
+			{
+				eError = RIDeletePMREntryKM (psPMR->hRIHandle);
+			}
 		}
 #endif /* if defined(PVR_RI_DEBUG) */
 		psCtx = psPMR->psContext;
 
 		OSLockDestroy(psPMR->hLock);
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-		_FreeMem(psPMR->psMappingTable->aui32Translation);
-#endif
-        OSFreeMem(psPMR);
 
-        /* Decrement live PMR count.  Probably only of interest for debugging */
-        PVR_ASSERT(psCtx->uiNumLivePMRs > 0);
+		OSFreeMem(psPMR);
 
-        OSLockAcquire(psCtx->hLock);
-        psCtx->uiNumLivePMRs --;
-        OSLockRelease(psCtx->hLock);
-    }
+		/* Decrement live PMR count.  Probably only of interest for debugging */
+		PVR_ASSERT(psCtx->uiNumLivePMRs > 0);
+
+		OSLockAcquire(psCtx->hLock);
+		psCtx->uiNumLivePMRs --;
+		OSLockRelease(psCtx->hLock);
+	}
 }
 
 static IMG_BOOL _PMRIsSparse(const PMR *psPMR)
@@ -528,7 +476,8 @@
 }
 
 PVRSRV_ERROR
-PMRCreatePMR(PHYS_HEAP *psPhysHeap,
+PMRCreatePMR(PVRSRV_DEVICE_NODE *psDevNode,
+             PHYS_HEAP *psPhysHeap,
              PMR_SIZE_T uiLogicalSize,
              PMR_SIZE_T uiChunkSize,
              IMG_UINT32 ui32NumPhysChunks,
@@ -536,73 +485,104 @@
              IMG_UINT32 *pui32MappingTable,
              PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee,
              PMR_FLAGS_T uiFlags,
-             const IMG_CHAR *pszPDumpFlavour,
+             const IMG_CHAR *pszAnnotation,
              const PMR_IMPL_FUNCTAB *psFuncTab,
              PMR_IMPL_PRIVDATA pvPrivData,
+             PMR_IMPL_TYPE eType,
              PMR **ppsPMRPtr,
-             IMG_HANDLE *phPDumpAllocInfo,
              IMG_BOOL bForcePersistent)
 {
-    PMR *psPMR = NULL;
-    PVRSRV_ERROR eError;
+	PMR *psPMR = NULL;
+	PVRSRV_ERROR eError;
 
-    eError = _PMRCreate(uiLogicalSize,
-						uiChunkSize,
-						ui32NumPhysChunks,
-						ui32NumVirtChunks,
-						pui32MappingTable,
-						uiLog2ContiguityGuarantee,
-						uiFlags,
-                        &psPMR);
-    if (eError != PVRSRV_OK)
-    {
-        goto e0;
-    }
-
-    psPMR->psPhysHeap = psPhysHeap;
-    psPMR->psFuncTab = psFuncTab;
-    psPMR->pszPDumpDefaultMemspaceName = PhysHeapPDumpMemspaceName(psPhysHeap);
-    psPMR->pszPDumpFlavour = pszPDumpFlavour;
-    psPMR->pvFlavourData = pvPrivData;
-    psPMR->uiRefCount = 1;
-    psPMR->bForcePersistent = bForcePersistent;
-
-    *ppsPMRPtr = psPMR;
-
-
-	if (phPDumpAllocInfo)
+	eError = _PMRCreate(uiLogicalSize,
+	                    uiChunkSize,
+	                    ui32NumPhysChunks,
+	                    ui32NumVirtChunks,
+	                    pui32MappingTable,
+	                    uiLog2ContiguityGuarantee,
+	                    uiFlags,
+	                    &psPMR);
+	if (eError != PVRSRV_OK)
 	{
-		PDumpPMRMallocPMR(psPMR,
-						  (uiChunkSize * ui32NumVirtChunks),
-						  1ULL<<uiLog2ContiguityGuarantee,
-						  bForcePersistent,
-						  phPDumpAllocInfo);
+		goto e0;
 	}
 
-    return PVRSRV_OK;
+	psPMR->psDevNode = psDevNode;
+	psPMR->psPhysHeap = psPhysHeap;
+	psPMR->psFuncTab = psFuncTab;
+	psPMR->pszPDumpDefaultMemspaceName = PhysHeapPDumpMemspaceName(psPhysHeap);
+	psPMR->pvFlavourData = pvPrivData;
+        psPMR->eFlavour = eType;
+	psPMR->uiRefCount = 1;
 
-    /*
-      error exit paths follow
-    */
- e0:
-    PVR_ASSERT(eError != PVRSRV_OK);
-    return eError;
+#if defined(PDUMP)
+	{
+		PMR_FLAGS_T uiFlags = psPMR->uiFlags;
+		IMG_BOOL bInitialise =  IMG_FALSE;
+		IMG_UINT32 ui32InitValue = 0;
+
+		psPMR->bForcePersistent = bForcePersistent;
+
+		psPMR->pszAnnotation = OSAllocMem(sizeof(IMG_CHAR) * PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH);
+		if (psPMR->pszAnnotation == NULL)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e1;
+		}
+
+		OSStringNCopy(psPMR->pszAnnotation, pszAnnotation, PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH);
+
+		if (PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags))
+		{
+			bInitialise = IMG_TRUE;
+		}
+		else if(PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags))
+		{
+			ui32InitValue = 0xDEADBEEF;
+			bInitialise = IMG_TRUE;
+		}
+
+		PDumpPMRMallocPMR(psPMR,
+		                  (uiChunkSize * ui32NumVirtChunks),
+		                  1ULL<<uiLog2ContiguityGuarantee,
+		                  uiChunkSize,
+		                  ui32NumPhysChunks,
+		                  ui32NumVirtChunks,
+		                  pui32MappingTable,
+		                  uiLog2ContiguityGuarantee,
+		                  bInitialise,
+		                  ui32InitValue,
+		                  bForcePersistent,
+		                  &psPMR->hPDumpAllocHandle);
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(bForcePersistent);
+#endif
+
+	*ppsPMRPtr = psPMR;
+
+	return PVRSRV_OK;
+
+	/*
+	 * error exit paths follow
+	 */
+#if defined(PDUMP)
+e1:
+	PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate memory for PMR PDump Annotation, OOM.", __func__));
+#endif
+e0:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
 }
 
 PVRSRV_ERROR PMRLockSysPhysAddressesNested(PMR *psPMR,
-                        IMG_UINT32 uiLog2RequiredContiguity,
-                        IMG_UINT32 ui32NestingLevel)
+                                           IMG_UINT32 ui32NestingLevel)
 {
     PVRSRV_ERROR eError;
 
     PVR_ASSERT(psPMR != NULL);
 
-    if (uiLog2RequiredContiguity > psPMR->uiLog2ContiguityGuarantee)
-    {
-        eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
-        goto e0;
-    }
-
 	OSLockAcquireNested(psPMR->hLock, ui32NestingLevel);
     /* We also count the locks as references, so that the PMR is not
        freed while someone is using a physical address. */
@@ -625,8 +605,7 @@
             /* must always have lock and unlock in pairs! */
             PVR_ASSERT(psPMR->psFuncTab->pfnUnlockPhysAddresses != NULL);
 
-            eError = psPMR->psFuncTab->pfnLockPhysAddresses(psPMR->pvFlavourData,
-                                                            uiLog2RequiredContiguity);
+            eError = psPMR->psFuncTab->pfnLockPhysAddresses(psPMR->pvFlavourData);
 
             if (eError != PVRSRV_OK)
             {
@@ -643,16 +622,14 @@
     _UnrefNoLock(psPMR);
     PVR_ASSERT(psPMR->uiRefCount != 0);
     OSLockRelease(psPMR->hLock);
- e0:
     PVR_ASSERT(eError != PVRSRV_OK);
     return eError;
 }
 
 PVRSRV_ERROR
-PMRLockSysPhysAddresses(PMR *psPMR,
-                        IMG_UINT32 uiLog2RequiredContiguity)
+PMRLockSysPhysAddresses(PMR *psPMR)
 {
-	return PMRLockSysPhysAddressesNested(psPMR, uiLog2RequiredContiguity, 0);
+	return PMRLockSysPhysAddressesNested(psPMR, 0);
 }
 
 PVRSRV_ERROR
@@ -722,13 +699,6 @@
 	{
 		eError = psPMR->psFuncTab->pfnUnpinMem(psPMR->pvFlavourData);
 	}
-	else
-	{
-		eError = PVRSRV_ERROR_NOT_SUPPORTED;
-		PVR_DPF((PVR_DBG_ERROR,
-		         "%s: Unpinning is not supported by this PMR implementation",
-		         __func__));
-	}
 
 e_exit:
 	return eError;
@@ -746,13 +716,6 @@
 		eError = psPMR->psFuncTab->pfnPinMem(psPMR->pvFlavourData,
 											psPMR->psMappingTable);
 	}
-	else
-	{
-		eError = PVRSRV_ERROR_NOT_SUPPORTED;
-		PVR_DPF((PVR_DBG_ERROR,
-		         "%s: Pinning is not supported by this PMR implementation",
-		         __func__));
-	}
 
 	return eError;
 }
@@ -839,6 +802,7 @@
 PVRSRV_ERROR
 PMRUnexportPMR(PMR_EXPORT *psPMRExport)
 {
+    /* FIXME: probably shouldn't be assertions? */
     PVR_ASSERT(psPMRExport != NULL);
     PVR_ASSERT(psPMRExport->psPMR != NULL);
     PVR_ASSERT(psPMRExport->psPMR->uiRefCount > 0);
@@ -852,7 +816,9 @@
 
 
 PVRSRV_ERROR
-PMRImportPMR(PMR_EXPORT *psPMRExport,
+PMRImportPMR(CONNECTION_DATA *psConnection,
+             PVRSRV_DEVICE_NODE *psDevNode,
+             PMR_EXPORT *psPMRExport,
              PMR_PASSWORD_T uiPassword,
              PMR_SIZE_T uiSize,
              PMR_LOG2ALIGN_T uiLog2Contig,
@@ -860,12 +826,21 @@
 {
     PMR *psPMR;
 
+    PVR_UNREFERENCED_PARAMETER(psConnection);
+
+    /* FIXME: probably shouldn't be assertions? */
     PVR_ASSERT(psPMRExport != NULL);
     PVR_ASSERT(psPMRExport->psPMR != NULL);
     PVR_ASSERT(psPMRExport->psPMR->uiRefCount > 0);
 
     psPMR = psPMRExport->psPMR;
 
+    if (psPMR->psDevNode != psDevNode)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: PMR invalid for this device\n", __func__));
+        return PVRSRV_ERROR_PMR_NOT_PERMITTED;
+    }
+
     if (psPMR->uiKey != uiPassword)
     {
         PVR_DPF((PVR_DBG_ERROR,
@@ -923,12 +898,16 @@
 
 
 PVRSRV_ERROR
-PMRImportPMR(PMR_EXPORT *psPMRExport,
+PMRImportPMR(CONNECTION_DATA *psConnection,
+             PVRSRV_DEVICE_NODE *psDevNode,
+             PMR_EXPORT *psPMRExport,
              PMR_PASSWORD_T uiPassword,
              PMR_SIZE_T uiSize,
              PMR_LOG2ALIGN_T uiLog2Contig,
              PMR **ppsPMR)
 {
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(psPMRExport);
 	PVR_UNREFERENCED_PARAMETER(uiPassword);
 	PVR_UNREFERENCED_PARAMETER(uiSize);
@@ -988,7 +967,9 @@
 	return PVRSRV_OK;
 }
 
-PVRSRV_ERROR PMRSecureImportPMR(IMG_SECURE_TYPE hSecure,
+PVRSRV_ERROR PMRSecureImportPMR(CONNECTION_DATA *psConnection,
+								PVRSRV_DEVICE_NODE *psDevNode,
+								IMG_SECURE_TYPE hSecure,
 								PMR **ppsPMR,
 								IMG_DEVMEM_SIZE_T *puiSize,
 								IMG_DEVMEM_ALIGN_T *puiAlign)
@@ -996,12 +977,20 @@
 	PVRSRV_ERROR eError;
 	PMR *psPMR;
 
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
 	eError = OSSecureImport(hSecure, (void **) &psPMR);
 	if (eError != PVRSRV_OK)
 	{
 		goto e0;
 	}
 
+	if (psPMR->psDevNode != psDevNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PMR invalid for this device\n", __func__));
+		return PVRSRV_ERROR_PMR_NOT_PERMITTED;
+	}
+
 	_Ref(psPMR);
 
 	/* Return the PMR */
@@ -1045,7 +1034,6 @@
     PVRSRV_ERROR eError;
     void *pvKernelAddress;
     IMG_HANDLE hPriv;
-    PMR_FLAGS_T ulFlags;
 
     PVR_ASSERT(psPMR != NULL);
 
@@ -1071,14 +1059,12 @@
     }
     PVR_ASSERT (psPMR->psFuncTab->pfnReleaseKernelMappingData != NULL);
 
-    ulFlags = PMR_Flags(psPMR);
-
     eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
                                                            uiLogicalOffset,
                                                            uiSize,
                                                            &pvKernelAddress,
                                                            &hPriv,
-                                                           ulFlags);
+                                                           psPMR->uiFlags);
     if (eError != PVRSRV_OK)
     {
         goto e0;
@@ -1156,6 +1142,44 @@
     return PVRSRV_OK;
 }
 
+#if defined(INTEGRITY_OS)
+
+PVRSRV_ERROR
+PMRMapMemoryObject(PMR *psPMR,
+                   IMG_HANDLE *phMemObj,
+                   IMG_HANDLE hPriv)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT (psPMR->psFuncTab->pfnMapMemoryObject != NULL);
+
+	eError = psPMR->psFuncTab->pfnMapMemoryObject(hPriv, phMemObj);
+
+	return eError;
+}
+
+PVRSRV_ERROR
+PMRUnmapMemoryObject(PMR *psPMR,
+                   IMG_HANDLE hPriv)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT (psPMR->psFuncTab->pfnMapMemoryObject != NULL);
+
+	eError = psPMR->psFuncTab->pfnUnmapMemoryObject(hPriv);
+
+	return eError;
+}
+
+#if defined(USING_HYPERVISOR)
+IMG_HANDLE PMRGetPmr(PMR *psPMR, size_t ulOffset)
+{
+    PVR_ASSERT(psPMR->psFuncTab->pfnGetPmr != NULL);
+    return psPMR->psFuncTab->pfnGetPmr(psPMR->pvFlavourData, ulOffset);
+}
+#endif
+#endif /* INTEGRITY_OS */
+
 /*
 	_PMRLogicalOffsetToPhysicalOffset
 
@@ -1217,7 +1241,7 @@
 					uiOffset,
 					TRUNCATE_64BITS_TO_32BITS(psMappingTable->uiChunkSize),
 					&ui32Remain);
-
+			
 			if (psMappingTable->aui32Translation[ui64ChunkIndex] == TRANSLATION_INVALID)
 			{
 				bValid[idx] = IMG_FALSE;
@@ -1240,7 +1264,7 @@
 				}
 
 				puiPhysicalOffset[idx] = (psMappingTable->aui32Translation[ui64ChunkIndex] * psMappingTable->uiChunkSize) +	 ui32Remain;
-				
+
 				/* initial offset may not be page aligned, round down */
 				uiOffset &= ~(uiPageSize-1);
 			}
@@ -1266,8 +1290,7 @@
     {
         /* defer to callback if present */
 
-        eError = PMRLockSysPhysAddresses(psPMR,
-                                         psPMR->uiLog2ContiguityGuarantee);
+        eError = PMRLockSysPhysAddresses(psPMR);
         if (eError != PVRSRV_OK)
         {
             goto e0;
@@ -1290,20 +1313,23 @@
 
         IMG_HANDLE hKernelMappingHandle;
         IMG_UINT8 *pcKernelAddress;
-        PMR_FLAGS_T ulFlags = PMR_Flags(psPMR);
 
         eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
                                                                (size_t) uiPhysicalOffset,
                                                                uiBufSz,
                                                                (void **)&pcKernelAddress,
                                                                &hKernelMappingHandle,
-                                                               ulFlags);
+                                                               psPMR->uiFlags);
         if (eError != PVRSRV_OK)
         {
             goto e0;
         }
 
-        OSMemCopy(&pcBuffer[0], pcKernelAddress, uiBufSz);
+        /* Use the conservative 'DeviceMemCopy' here because we can't know
+         * if this PMR will be mapped cached.
+         */
+
+        OSDeviceMemCopy(&pcBuffer[0], pcKernelAddress, uiBufSz);
         *puiNumBytes = uiBufSz;
 
         psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
@@ -1385,7 +1411,7 @@
 			if ((eError != PVRSRV_OK) || (uiRead != uiBytesToCopy))
 			{
 				PVR_DPF((PVR_DBG_ERROR,
-						 "%s: Failed to read chunk (eError = %s, uiRead = "IMG_SIZE_FMTSPEC" uiBytesToCopy = "IMG_SIZE_FMTSPEC")",
+						 "%s: Failed to read chunk (eError = %s, uiRead = " IMG_SIZE_FMTSPEC " uiBytesToCopy = " IMG_SIZE_FMTSPEC ")",
 						 __FUNCTION__,
 						 PVRSRVGetErrorStringKM(eError),
 						 uiRead,
@@ -1396,9 +1422,15 @@
 		}
 		else
 		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"%s: Invalid phys offset at logical offset (" IMG_DEVMEM_OFFSET_FMTSPEC ") logical size (" IMG_DEVMEM_OFFSET_FMTSPEC ")",
+					__FUNCTION__,
+					uiLogicalOffset,
+					psPMR->uiLogicalSize));
 			/* Fill invalid chunks with 0 */
-			OSMemSet(&pcBuffer[uiBytesCopied], 0, uiBytesToCopy);
+			OSCachedMemSet(&pcBuffer[uiBytesCopied], 0, uiBytesToCopy);
 			uiRead = uiBytesToCopy;
+			eError = PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR;
 		}
 		uiLogicalOffset += uiRead;
 		uiBytesCopied += uiRead;
@@ -1421,8 +1453,7 @@
     {
         /* defer to callback if present */
 
-        eError = PMRLockSysPhysAddresses(psPMR,
-                                         psPMR->uiLog2ContiguityGuarantee);
+        eError = PMRLockSysPhysAddresses(psPMR);
         if (eError != PVRSRV_OK)
         {
             goto e0;
@@ -1445,20 +1476,23 @@
 
         IMG_HANDLE hKernelMappingHandle;
         IMG_UINT8 *pcKernelAddress;
-        PMR_FLAGS_T ulFlags = PMR_Flags(psPMR);
 
         eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
                                                                (size_t) uiPhysicalOffset,
                                                                uiBufSz,
                                                                (void **)&pcKernelAddress,
                                                                &hKernelMappingHandle,
-                                                               ulFlags);
+                                                               psPMR->uiFlags);
         if (eError != PVRSRV_OK)
         {
             goto e0;
         }
 
-		OSMemCopy(pcKernelAddress, &pcBuffer[0], uiBufSz);
+		/* Use the conservative 'DeviceMemCopy' here because we can't know
+		 * if this PMR will be mapped cached.
+		 */
+
+		OSDeviceMemCopy(pcKernelAddress, &pcBuffer[0], uiBufSz);
         *puiNumBytes = uiBufSz;
 
         psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
@@ -1495,16 +1529,12 @@
                size_t *puiNumBytes)
 {
     PVRSRV_ERROR eError = PVRSRV_OK;
-	#if 0
-    PMR_FLAGS_T uiFlags;
-	#endif
     IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
     size_t uiBytesCopied = 0;
 
+	/* FIXME: When we honour CPU mapping flags remove the #if 0*/
 	#if 0
-	/* Check that writes are allowed */
-    uiFlags = PMR_Flags(psPMR);
-	if (!(uiFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE))
+	if (!PVRSRV_CHECK_CPU_WRITEABLE(psPMR->uiFlags))
 	{
 		return PVRSRV_ERROR_PMR_NOT_PERMITTED;
 	}
@@ -1557,7 +1587,7 @@
 			if ((eError != PVRSRV_OK) || (uiWrite != uiBytesToCopy))
 			{
 				PVR_DPF((PVR_DBG_ERROR,
-						 "%s: Failed to read chunk (eError = %s, uiWrite = "IMG_SIZE_FMTSPEC" uiBytesToCopy = "IMG_SIZE_FMTSPEC")",
+						 "%s: Failed to read chunk (eError = %s, uiWrite = " IMG_SIZE_FMTSPEC " uiBytesToCopy = " IMG_SIZE_FMTSPEC ")",
 						 __FUNCTION__,
 						 PVRSRVGetErrorStringKM(eError),
 						 uiWrite,
@@ -1614,6 +1644,14 @@
 	return PVRSRV_OK;
 }
 
+PVRSRV_DEVICE_NODE *
+PMR_DeviceNode(const PMR *psPMR)
+{
+    PVR_ASSERT(psPMR != NULL);
+
+    return psPMR->psDevNode;
+}
+
 PMR_FLAGS_T
 PMR_Flags(const PMR *psPMR)
 {
@@ -1641,24 +1679,65 @@
     return PVRSRV_OK;
 }
 
-void
-PMR_IsOffsetValid(const PMR *psPMR,
-                IMG_DEVMEM_OFFSET_T uiLogicalOffset,
-                IMG_BOOL *pbValid)
+PHYS_HEAP *
+PMR_PhysHeap(const PMR *psPMR)
 {
-	IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
-    IMG_UINT32 ui32BytesRemain;
+	return psPMR->psPhysHeap;
+}
 
-    PVR_ASSERT(psPMR != NULL);
-    PVR_ASSERT(psPMR->uiLogicalSize >= uiLogicalOffset);
+PVRSRV_ERROR
+PMR_IsOffsetValid(const PMR *psPMR,
+				IMG_UINT32 ui32Log2PageSize,
+				IMG_UINT32 ui32NumOfPages,
+				IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+				IMG_BOOL *pbValid)
+{
+	IMG_DEVMEM_OFFSET_T auiPhysicalOffset[PMR_MAX_TRANSLATION_STACK_ALLOC];
+	IMG_UINT32 aui32BytesRemain[PMR_MAX_TRANSLATION_STACK_ALLOC];
+	IMG_DEVMEM_OFFSET_T *puiPhysicalOffset = auiPhysicalOffset;
+	IMG_UINT32 *pui32BytesRemain = aui32BytesRemain;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(psPMR != NULL);
+	PVR_ASSERT(psPMR->uiLogicalSize >= uiLogicalOffset);
+
+	if (ui32NumOfPages > PMR_MAX_TRANSLATION_STACK_ALLOC)
+	{
+		puiPhysicalOffset = OSAllocMem(ui32NumOfPages * sizeof(IMG_DEVMEM_OFFSET_T));
+		if (puiPhysicalOffset == NULL)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e0;
+		}
+
+		pui32BytesRemain = OSAllocMem(ui32NumOfPages * sizeof(IMG_UINT32));
+		if (pui32BytesRemain == NULL)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e0;
+		}
+	}
 
 	_PMRLogicalOffsetToPhysicalOffset(psPMR,
-	                                  0,
-	                                  1,
-	                                  uiLogicalOffset,
-	                                  &uiPhysicalOffset,
-	                                  &ui32BytesRemain,
-	                                  pbValid);
+									ui32Log2PageSize,
+									ui32NumOfPages,
+									uiLogicalOffset,
+									puiPhysicalOffset,
+									pui32BytesRemain,
+									pbValid);
+
+e0:
+	if (puiPhysicalOffset != auiPhysicalOffset && puiPhysicalOffset != NULL)
+	{
+		OSFreeMem(puiPhysicalOffset);
+	}
+
+	if (pui32BytesRemain != aui32BytesRemain && pui32BytesRemain != NULL)
+	{
+		OSFreeMem(pui32BytesRemain);
+	}
+
+	return eError;
 }
 
 PMR_MAPPING_TABLE *
@@ -1669,39 +1748,53 @@
 
 }
 
+IMG_UINT32
+PMR_GetLog2Contiguity(const PMR *psPMR)
+{
+	PVR_ASSERT(psPMR != NULL);
+	return psPMR->uiLog2ContiguityGuarantee;
+}
+
+PMR_IMPL_TYPE
+PMR_GetType(const PMR *psPMR)
+{
+	PVR_ASSERT(psPMR != NULL);
+	return psPMR->eFlavour;
+}
+
 /* must have called PMRLockSysPhysAddresses() before calling this! */
 PVRSRV_ERROR
 PMR_DevPhysAddr(const PMR *psPMR,
 				IMG_UINT32 ui32Log2PageSize,
 				IMG_UINT32 ui32NumOfPages,
-                IMG_DEVMEM_OFFSET_T uiLogicalOffset,
-                IMG_DEV_PHYADDR *psDevAddrPtr,
-                IMG_BOOL *pbValid)
+				IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+				IMG_DEV_PHYADDR *psDevAddrPtr,
+				IMG_BOOL *pbValid)
 {
 	IMG_UINT32 ui32Remain;	
-    PVRSRV_ERROR eError = PVRSRV_OK;
-    IMG_DEVMEM_OFFSET_T auiPhysicalOffset[PMR_MAX_TRANSLATION_STACK_ALLOC];
-    IMG_DEVMEM_OFFSET_T *puiPhysicalOffset = auiPhysicalOffset;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_DEVMEM_OFFSET_T auiPhysicalOffset[PMR_MAX_TRANSLATION_STACK_ALLOC];
+	IMG_DEVMEM_OFFSET_T *puiPhysicalOffset = auiPhysicalOffset;
 
-    PVR_ASSERT(psPMR != NULL);
-    PVR_ASSERT(ui32NumOfPages > 0);
-    PVR_ASSERT(psPMR->psFuncTab->pfnDevPhysAddr != NULL);
+	PVR_ASSERT(psPMR != NULL);
+	PVR_ASSERT(ui32NumOfPages > 0);
+	PVR_ASSERT(psPMR->psFuncTab->pfnDevPhysAddr != NULL);
 
 #ifdef PVRSRV_NEED_PVR_ASSERT
-    OSLockAcquire(psPMR->hLock);
-    PVR_ASSERT(psPMR->uiLockCount > 0);
-    OSLockRelease(psPMR->hLock);
+	OSLockAcquire(psPMR->hLock);
+	PVR_ASSERT(psPMR->uiLockCount > 0);
+	OSLockRelease(psPMR->hLock);
 #endif
 
-    if (ui32NumOfPages > PMR_MAX_TRANSLATION_STACK_ALLOC)
-    {
-    	puiPhysicalOffset = OSAllocMem(ui32NumOfPages * sizeof(IMG_DEVMEM_OFFSET_T));
+	if (ui32NumOfPages > PMR_MAX_TRANSLATION_STACK_ALLOC)
+	{
+		puiPhysicalOffset = OSAllocMem(ui32NumOfPages * sizeof(IMG_DEVMEM_OFFSET_T));
 		if (puiPhysicalOffset == NULL)
-    	{
-    		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-    		goto e0;
-    	}
-    }
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e0;
+		}
+	}
 
 	_PMRLogicalOffsetToPhysicalOffset(psPMR,
 									 ui32Log2PageSize,
@@ -1714,10 +1807,43 @@
 	{
 		/* Sparse PMR may not always have the first page valid */
 		eError = psPMR->psFuncTab->pfnDevPhysAddr(psPMR->pvFlavourData,
+												  ui32Log2PageSize,
 												  ui32NumOfPages,
 												  puiPhysicalOffset,
 												  pbValid,
 												  psDevAddrPtr);
+#if defined(PLATO_MEMORY_CONFIG)
+    /* Currently excluded from the default build because of performance concerns.
+     *
+     * We do not need this part in other systems because the GPU has the same address view of system RAM as the CPU.
+     * Ideally this should be directly part of the PMR factories and they should always return 
+     * the device physical address and not CPU physical or even better they should return the
+	 * DMA bus address. */
+
+		if (PhysHeapGetType(psPMR->psPhysHeap) == PHYS_HEAP_TYPE_UMA)
+		{
+			IMG_DEV_PHYADDR *psDevPAddrCorrected = OSAllocMem(ui32NumOfPages * sizeof(IMG_DEV_PHYADDR));
+			if (psDevPAddrCorrected == NULL)
+			{
+				if (puiPhysicalOffset != auiPhysicalOffset)
+				{
+					OSFreeMem(puiPhysicalOffset);
+				}
+				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto e0;
+			}
+
+			PhysHeapCpuPAddrToDevPAddr(psPMR->psPhysHeap,
+									   ui32NumOfPages,
+									   psDevPAddrCorrected,
+									   (IMG_CPU_PHYADDR *) psDevAddrPtr);
+
+			/* Copy the translated addresses to the correct array */
+			memcpy(psDevAddrPtr, psDevPAddrCorrected, ui32NumOfPages * sizeof(IMG_DEV_PHYADDR));
+
+			OSFreeMem(psDevPAddrCorrected);
+		}
+#endif
 	}
 
 	if (puiPhysicalOffset != auiPhysicalOffset)
@@ -1784,56 +1910,92 @@
 }
 
 PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR,
-		IMG_UINT32 ui32AllocPageCount,
-		IMG_UINT32 *pai32AllocIndices,
-		IMG_UINT32 ui32FreePageCount,
-		IMG_UINT32 *pai32FreeIndices,
-		IMG_UINT32	uiFlags,
-		IMG_UINT32	*pui32Status)
+                                 IMG_UINT32 ui32AllocPageCount,
+                                 IMG_UINT32 *pai32AllocIndices,
+                                 IMG_UINT32 ui32FreePageCount,
+                                 IMG_UINT32 *pai32FreeIndices,
+                                 IMG_UINT32 uiFlags)
 {
 	PVRSRV_ERROR eError;
 
-	if(NULL == psPMR->psFuncTab->pfnChangeSparseMem)
+	if (NULL == psPMR->psFuncTab->pfnChangeSparseMem)
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "%s: This type of sparse PMR cannot be changed.",
+		         __func__));
 		return PVRSRV_ERROR_NOT_IMPLEMENTED;
 	}
 
 	eError = psPMR->psFuncTab->pfnChangeSparseMem(psPMR->pvFlavourData,
-															psPMR,
-															ui32AllocPageCount,
-															pai32AllocIndices,
-															ui32FreePageCount,
-															pai32FreeIndices,
-															uiFlags,
-															pui32Status);
+	                                              psPMR,
+	                                              ui32AllocPageCount,
+	                                              pai32AllocIndices,
+	                                              ui32FreePageCount,
+	                                              pai32FreeIndices,
+	                                              uiFlags);
+	if (eError != PVRSRV_OK)
+	{
+		goto e0;
+	}
 
+#if defined(PDUMP)
+	{
+		IMG_BOOL bInitialise = IMG_FALSE;
+		IMG_UINT32 ui32InitValue = 0;
+
+		if (PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags))
+		{
+			bInitialise = IMG_TRUE;
+		}
+		else if(PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags))
+		{
+			ui32InitValue = 0xDEADBEEF;
+			bInitialise = IMG_TRUE;
+		}
+
+		PDumpPMRChangeSparsePMR(psPMR,
+		                        1 << psPMR->uiLog2ContiguityGuarantee,
+		                        ui32AllocPageCount,
+		                        pai32AllocIndices,
+		                        ui32FreePageCount,
+		                        pai32FreeIndices,
+		                        bInitialise,
+		                        ui32InitValue,
+		                        &psPMR->hPDumpAllocHandle);
+	}
+
+#endif
+
+e0:
 	return eError;
 }
 
 
 PVRSRV_ERROR PMR_ChangeSparseMemCPUMap(PMR *psPMR,
-											IMG_UINT64 sCpuVAddrBase,
-											IMG_UINT32	ui32AllocPageCount,
-											IMG_UINT32	*pai32AllocIndices,
-											IMG_UINT32	ui32FreePageCount,
-											IMG_UINT32	*pai32FreeIndices,
-											IMG_UINT32	*pui32Status)
+                                       IMG_UINT64 sCpuVAddrBase,
+                                       IMG_UINT32 ui32AllocPageCount,
+                                       IMG_UINT32 *pai32AllocIndices,
+                                       IMG_UINT32 ui32FreePageCount,
+                                       IMG_UINT32 *pai32FreeIndices)
 {
 	PVRSRV_ERROR eError;
 
-	if((NULL == psPMR->psFuncTab) || (NULL == psPMR->psFuncTab->pfnChangeSparseMemCPUMap))
+	if ((NULL == psPMR->psFuncTab) ||
+	    (NULL == psPMR->psFuncTab->pfnChangeSparseMemCPUMap))
 	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "%s: This type of sparse PMR cannot be changed.",
+		         __func__));
 		return PVRSRV_ERROR_NOT_IMPLEMENTED;
 	}
 
 	eError = psPMR->psFuncTab->pfnChangeSparseMemCPUMap(psPMR->pvFlavourData,
-															psPMR,
-															sCpuVAddrBase,
-															ui32AllocPageCount,
-															pai32AllocIndices,
-															ui32FreePageCount,
-															pai32FreeIndices,
-															pui32Status);
+	                                                    psPMR,
+	                                                    sCpuVAddrBase,
+	                                                    ui32AllocPageCount,
+	                                                    pai32AllocIndices,
+	                                                    ui32FreePageCount,
+	                                                    pai32FreeIndices);
 
 	return eError;
 }
@@ -1852,40 +2014,35 @@
                                IMG_DEVMEM_OFFSET_T *puiNewOffset,
                                IMG_DEVMEM_OFFSET_T *puiNextSymName)
 {
-	const IMG_CHAR *pszPrefix;
+	if (DevmemCPUCacheCoherency(psPMR->psDevNode, psPMR->uiFlags) ||
+		DevmemDeviceCacheCoherency(psPMR->psDevNode, psPMR->uiFlags))
+	{
+		OSSNPrintf(pszMemspaceName,
+		           ui32MemspaceNameLen,
+		           PMR_MEMSPACE_CACHE_COHERENT_FMTSPEC,
+		           psPMR->pszPDumpDefaultMemspaceName);
+	}
+	else
+	{
+		OSSNPrintf(pszMemspaceName, ui32MemspaceNameLen, PMR_MEMSPACE_FMTSPEC,
+		           psPMR->pszPDumpDefaultMemspaceName);
+	}
 
-    if (psPMR->psFuncTab->pfnPDumpSymbolicAddr != NULL)
-    {
-        /* defer to callback if present */
-        return psPMR->psFuncTab->pfnPDumpSymbolicAddr(psPMR->pvFlavourData,
-                                                      uiPhysicalOffset,
-                                                      pszMemspaceName,
-                                                      ui32MemspaceNameLen,
-                                                      pszSymbolicAddr,
-                                                      ui32SymbolicAddrLen,
-                                                      puiNewOffset,
-                                                      puiNextSymName);
-    }
-    else
-    {
-        OSSNPrintf(pszMemspaceName, ui32MemspaceNameLen, "%s",
-                   psPMR->pszPDumpDefaultMemspaceName);
+	OSSNPrintf(pszSymbolicAddr,
+	           ui32SymbolicAddrLen,
+	           PMR_SYMBOLICADDR_FMTSPEC,
+	           PMR_DEFAULT_PREFIX,
+	           psPMR->uiSerialNum,
+	           uiPhysicalOffset >> PMR_GetLog2Contiguity(psPMR),
+	           psPMR->pszAnnotation ? psPMR->pszAnnotation : "");
+		PDumpMakeStringValid(pszSymbolicAddr, OSStringLength(pszSymbolicAddr));
 
-        if (psPMR->pszPDumpFlavour != NULL)
-        {
-            pszPrefix = psPMR->pszPDumpFlavour;
-        }
-        else
-        {
-            pszPrefix = PMR_DEFAULT_PREFIX;
-        }
-        OSSNPrintf(pszSymbolicAddr, ui32SymbolicAddrLen, PMR_SYMBOLICADDR_FMTSPEC,
-                   pszPrefix, psPMR->uiSerialNum);
-        *puiNewOffset = uiPhysicalOffset;
-        *puiNextSymName = (IMG_DEVMEM_OFFSET_T) psPMR->uiLogicalSize;
 
-        return PVRSRV_OK;
-    }
+	*puiNewOffset = uiPhysicalOffset & ((1 << PMR_GetLog2Contiguity(psPMR))-1);
+	*puiNextSymName = (IMG_DEVMEM_OFFSET_T) (((uiPhysicalOffset >> PMR_GetLog2Contiguity(psPMR))+1) 
+	                                          << PMR_GetLog2Contiguity(psPMR));
+
+	return PVRSRV_OK;
 }
 
 
@@ -1951,15 +2108,18 @@
                      PDUMP_FLAGS_T uiPDumpFlags)
 {
     PVRSRV_ERROR eError;
-    IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-    IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+    IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+    IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
     IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
     IMG_DEVMEM_OFFSET_T uiNextSymName;
+    IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
-    PVR_ASSERT(uiLogicalOffset + sizeof(IMG_UINT32) <= psPMR->uiLogicalSize);
+    PVR_ASSERT(uiLogicalOffset + sizeof(ui32Value) <= psPMR->uiLogicalSize);
+    /* Especially make sure to not cross a block boundary */
+    PVR_ASSERT(( ((uiLogicalOffset & (uiPMRPageSize-1)) + sizeof(ui32Value))
+               < uiPMRPageSize));
 
-    eError = PMRLockSysPhysAddresses(psPMR,
-                                     psPMR->uiLog2ContiguityGuarantee);
+    eError = PMRLockSysPhysAddresses(psPMR);
     PVR_ASSERT(eError == PVRSRV_OK);
 
 	/* Get the symbolic address of the PMR */
@@ -2004,15 +2164,20 @@
                      PDUMP_FLAGS_T uiPDumpFlags)
 {
     PVRSRV_ERROR eError;
-    IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-    IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+    IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+    IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
     IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
     IMG_DEVMEM_OFFSET_T uiNextSymName;
+    IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
-    PVR_ASSERT(uiLogicalOffset + sizeof(IMG_UINT64) <= psPMR->uiLogicalSize);
 
-    eError = PMRLockSysPhysAddresses(psPMR,
-                                     psPMR->uiLog2ContiguityGuarantee);
+    PVR_ASSERT(uiLogicalOffset + sizeof(ui64Value) <= psPMR->uiLogicalSize);
+    /* Especially make sure to not cross a block boundary */
+    /* Especially make sure to not cross a block boundary */
+    PVR_ASSERT(( ((uiLogicalOffset & (uiPMRPageSize-1)) + sizeof(ui64Value))
+               < uiPMRPageSize));
+
+    eError = PMRLockSysPhysAddresses(psPMR);
     PVR_ASSERT(eError == PVRSRV_OK);
 
 	/* Get the symbolic address of the PMR */
@@ -2053,29 +2218,31 @@
  */
 PVRSRV_ERROR
 PMRPDumpLoadMem(PMR *psPMR,
-					IMG_DEVMEM_OFFSET_T uiLogicalOffset,
-					IMG_DEVMEM_SIZE_T uiSize,
-					PDUMP_FLAGS_T uiPDumpFlags,
-					IMG_BOOL bZero)
+                IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+                IMG_DEVMEM_SIZE_T uiSize,
+                PDUMP_FLAGS_T uiPDumpFlags,
+                IMG_BOOL bZero)
 {
-	/* common variables */
-	PVRSRV_ERROR eError = PVRSRV_OK;
-	IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-	IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
-	IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
-	PDUMP_FILEOFFSET_T uiParamStreamFileOffset;
-	size_t uiBufSz;
-	size_t uiNumBytes;
-	IMG_DEVMEM_OFFSET_T uiNextSymName;
+	PVRSRV_ERROR eError;
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_DEVMEM_OFFSET_T uiOutOffset;
+	IMG_DEVMEM_OFFSET_T uiCurrentOffset = uiLogicalOffset;
+	IMG_DEVMEM_OFFSET_T uiNextSymName = 0;
 	const IMG_CHAR *pszParamStreamFileName;
+	PDUMP_FILEOFFSET_T uiParamStreamFileOffset;
 
 	/* required when !bZero */
-	#define PMR_MAX_PDUMP_BUFSZ 16384
+	#define PMR_MAX_PDUMP_BUFSZ (1<<14)
 	IMG_CHAR aszParamStreamFilename[PDUMP_PARAM_MAX_FILE_NAME];
 	IMG_UINT8 *pcBuffer = NULL;
+	size_t uiBufSz;
+	size_t uiNumBytes;
+	IMG_BOOL bValid;
 
 	PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
 
+	/* Get the correct PDump stream file name */
 	if(bZero)
 	{
 		/* Check if this PMR needs to be persistent:
@@ -2089,136 +2256,115 @@
 			uiPDumpFlags = PDUMP_FLAGS_PERSISTENT;
 		}
 
-		PDumpCommentWithFlags(uiPDumpFlags, "Zeroing allocation (%llu bytes)",
-										(unsigned long long) uiSize);
+		PDumpCommentWithFlags(uiPDumpFlags,
+		                      "Zeroing allocation (%llu bytes)",
+		                      (unsigned long long) uiSize);
 
 		/* get the zero page information. it is constant for this function */
-		PDumpGetParameterZeroPageInfo(&uiParamStreamFileOffset, &uiBufSz, &pszParamStreamFileName);
+		PDumpGetParameterZeroPageInfo(&uiParamStreamFileOffset,
+		                              &uiBufSz,
+		                              &pszParamStreamFileName);
 	}
 	else
 	{
-		uiBufSz = PMR_MAX_PDUMP_BUFSZ;
-		if (uiBufSz > uiSize)
-		{
-			uiBufSz = TRUNCATE_64BITS_TO_SIZE_T(uiSize);
-		}
+
+		uiBufSz = 1 << PMR_GetLog2Contiguity(psPMR);
+		PVR_ASSERT((1 << PMR_GetLog2Contiguity(psPMR)) <= PMR_MAX_PDUMP_BUFSZ);
 
 		pcBuffer = OSAllocMem(uiBufSz);
 
 		PVR_LOGR_IF_NOMEM(pcBuffer, "OSAllocMem");
 
-		eError = PMRLockSysPhysAddresses(psPMR,
-								psPMR->uiLog2ContiguityGuarantee);
+		eError = PMRLockSysPhysAddresses(psPMR);
 		PVR_ASSERT(eError == PVRSRV_OK);
 
 		pszParamStreamFileName = aszParamStreamFilename;
 	}
 
-	while (uiSize > 0)
+	/* Loop over all touched symbolic addresses of the PMR and
+	 * emit LDBs to load the contents. */
+	while (uiCurrentOffset < (uiLogicalOffset + uiSize))
 	{
-		IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
-		IMG_UINT32 ui32Remain;
-		IMG_BOOL bValid;
+		/* Get the correct symbolic name for the current offset */
+		eError = PMR_PDumpSymbolicAddr(psPMR,
+		                               uiCurrentOffset,
+		                               sizeof(aszMemspaceName),
+		                               &aszMemspaceName[0],
+		                               sizeof(aszSymbolicName),
+		                               &aszSymbolicName[0],
+		                               &uiOutOffset,
+		                               &uiNextSymName);
+		PVR_ASSERT(eError == PVRSRV_OK);
+		PVR_ASSERT((uiNextSymName - uiCurrentOffset) <= uiBufSz);
 
-		_PMRLogicalOffsetToPhysicalOffset(psPMR,
- 										  0,
- 										  1,
-										  uiLogicalOffset,
-										  &uiPhysicalOffset,
-										  &ui32Remain,
-										  &bValid);
+		PMR_IsOffsetValid(psPMR,
+		                  0,
+		                  1,
+		                  uiCurrentOffset,
+		                  &bValid);
 
+		/* Either just LDB the zeros or read from the PMR and store that
+		 * in the pdump stream */
 		if (bValid)
 		{
-			eError = _PMR_PDumpSymbolicAddrPhysical(psPMR,
-													uiPhysicalOffset,
-													sizeof(aszMemspaceName),
-													&aszMemspaceName[0],
-													sizeof(aszSymbolicName),
-													&aszSymbolicName[0],
-													&uiPDumpSymbolicOffset,
-													&uiNextSymName);
-			if(eError != PVRSRV_OK)
-			{
-				goto err_unlock_phys;
-			}
-
 			if(bZero)
 			{
-				uiNumBytes = TRUNCATE_64BITS_TO_SIZE_T(MIN(uiSize, uiBufSz));
+				uiNumBytes = MIN(uiSize, uiNextSymName - uiCurrentOffset);
 			}
 			else
 			{
+				IMG_DEVMEM_OFFSET_T uiReadOffset;
+				uiReadOffset = ((uiNextSymName > (uiLogicalOffset + uiSize)) ?
+				                 uiLogicalOffset + uiSize - uiCurrentOffset :
+				                 uiNextSymName - uiCurrentOffset);
 
-				/* Reads enough to fill buffer, or until next chunk,
-				or until end of PMR, whichever comes first */
-				eError = _PMR_ReadBytesPhysical(psPMR,
-												uiPhysicalOffset,
-												pcBuffer,
-												TRUNCATE_64BITS_TO_SIZE_T(MIN3(uiBufSz, uiSize, ui32Remain)),
-												&uiNumBytes);
-				if(eError != PVRSRV_OK)
-				{
-				    goto err_unlock_phys;
-				}
-				PVR_ASSERT(uiNumBytes > 0);
+				eError = PMR_ReadBytes(psPMR,
+				                       uiCurrentOffset,
+				                       pcBuffer,
+				                       uiReadOffset,
+				                       &uiNumBytes);
+				PVR_ASSERT(eError == PVRSRV_OK);
 
 				eError = PDumpWriteBuffer(pcBuffer,
-							  uiNumBytes,
-							  uiPDumpFlags,
-							  &aszParamStreamFilename[0],
-							  sizeof(aszParamStreamFilename),
-							  &uiParamStreamFileOffset);
+				                          uiNumBytes,
+				                          uiPDumpFlags,
+				                          &aszParamStreamFilename[0],
+				                          sizeof(aszParamStreamFilename),
+				                          &uiParamStreamFileOffset);
 				if (eError == PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
 				{
 					/* Write to parameter file prevented under the flags and
 					 * current state of the driver so skip further writes.
 					 */
 					eError = PVRSRV_OK;
-					goto err_unlock_phys;
 				}
 				else if(eError != PVRSRV_OK)
 				{
 					PDUMP_ERROR(eError, "Failed to write PMR memory to parameter file");
-				    goto err_unlock_phys;
 				}
-				/* else OK and continue with script write */
 			}
 
+			/* Emit the LDB command to the current symbolic address*/
 			eError = PDumpPMRLDB(aszMemspaceName,
-									aszSymbolicName,
-									uiPDumpSymbolicOffset,
-									uiNumBytes,
-									pszParamStreamFileName,
-									uiParamStreamFileOffset,
-									uiPDumpFlags);
-
-			if(eError != PVRSRV_OK)
-			{
-				goto err_unlock_phys;
-			}
+			                     aszSymbolicName,
+			                     uiOutOffset,
+			                     uiNumBytes,
+			                     pszParamStreamFileName,
+			                     uiParamStreamFileOffset,
+			                     uiPDumpFlags);
 		}
-		else
-		{
-			/* Skip over invalid chunks */
-			uiNumBytes = TRUNCATE_64BITS_TO_SIZE_T(MIN(ui32Remain, uiSize));
-		}
-
-		 uiLogicalOffset += uiNumBytes;
-		 PVR_ASSERT(uiNumBytes <= uiSize);
-		 uiSize -= uiNumBytes;
+		uiCurrentOffset = uiNextSymName;
 	}
 
-err_unlock_phys:
-
-	if(!bZero)
+	if (!bZero)
 	{
-	    eError = PMRUnlockSysPhysAddresses(psPMR);
-	    PVR_ASSERT(eError == PVRSRV_OK);
+		eError = PMRUnlockSysPhysAddresses(psPMR);
+		PVR_ASSERT(eError == PVRSRV_OK);
 
-	    OSFreeMem(pcBuffer);
+		OSFreeMem(pcBuffer);
 	}
-    return eError;
+
+	return PVRSRV_OK;
 }
 
 
@@ -2231,15 +2377,68 @@
                    const IMG_CHAR *pszFilename,
                    IMG_UINT32 uiFileOffset)
 {
+	PVRSRV_ERROR eError;
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_DEVMEM_OFFSET_T uiOutOffset;
+	IMG_DEVMEM_OFFSET_T uiCurrentOffset = uiLogicalOffset;
+	IMG_DEVMEM_OFFSET_T uiNextSymName = 0;
+
+	PVR_UNREFERENCED_PARAMETER(uiArraySize);
+
+	PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
+
+	while (uiCurrentOffset < (uiLogicalOffset + uiSize))
+	{
+		IMG_DEVMEM_OFFSET_T uiReadOffset;
+
+		eError = PMR_PDumpSymbolicAddr(psPMR,
+		                               uiCurrentOffset,
+		                               sizeof(aszMemspaceName),
+		                               &aszMemspaceName[0],
+		                               sizeof(aszSymbolicName),
+		                               &aszSymbolicName[0],
+		                               &uiOutOffset,
+		                               &uiNextSymName);
+		PVR_ASSERT(eError == PVRSRV_OK);
+		PVR_ASSERT(uiNextSymName <= psPMR->uiLogicalSize);
+
+		uiReadOffset = ((uiNextSymName > (uiLogicalOffset + uiSize)) ?
+		                 uiLogicalOffset + uiSize - uiCurrentOffset :
+		                 uiNextSymName - uiCurrentOffset);
+
+		eError = PDumpPMRSAB(aszMemspaceName,
+		                     aszSymbolicName,
+		                     uiOutOffset,
+		                     uiReadOffset,
+		                     pszFilename,
+		                     uiFileOffset);
+		PVR_ASSERT(eError == PVRSRV_OK);
+
+		uiCurrentOffset = uiNextSymName;
+	}
+
+	return PVRSRV_OK;
+}
+
+extern PVRSRV_ERROR
+PMRPDumpPol32(const PMR *psPMR,
+              IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+              IMG_UINT32 ui32Value,
+              IMG_UINT32 ui32Mask,
+              PDUMP_POLL_OPERATOR eOperator,
+              PDUMP_FLAGS_T uiPDumpFlags)
+{
     PVRSRV_ERROR eError;
-    IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
-    IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
-    IMG_DEVMEM_OFFSET_T uiOutOffset;
+    IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+    IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+    IMG_DEVMEM_OFFSET_T uiPDumpOffset;
     IMG_DEVMEM_OFFSET_T uiNextSymName;
+    IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
-    PVR_UNREFERENCED_PARAMETER(uiArraySize);
-
-    PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
+    /* Make sure to not cross a block boundary */
+    PVR_ASSERT(( ((uiLogicalOffset & (uiPMRPageSize-1)) + sizeof(ui32Value))
+               < uiPMRPageSize));
 
     eError = PMR_PDumpSymbolicAddr(psPMR,
                                    uiLogicalOffset,
@@ -2247,29 +2446,270 @@
                                    &aszMemspaceName[0],
                                    sizeof(aszSymbolicName),
                                    &aszSymbolicName[0],
-                                   &uiOutOffset,
-				   &uiNextSymName);
-    PVR_ASSERT(eError == PVRSRV_OK);
-    PVR_ASSERT(uiLogicalOffset + uiSize <= uiNextSymName);
+                                   &uiPDumpOffset,
+                                   &uiNextSymName);
+    if (eError != PVRSRV_OK)
+    {
+        goto e0;
+    }
 
-    eError = PDumpPMRSAB(aszMemspaceName,
+#define _MEMPOLL_DELAY		(1000)
+#define _MEMPOLL_COUNT		(2000000000 / _MEMPOLL_DELAY)
+
+    eError = PDumpPMRPOL(aszMemspaceName,
                          aszSymbolicName,
-                         uiOutOffset,
-                         uiSize,
-                         pszFilename,
-                         uiFileOffset);
-    PVR_ASSERT(eError == PVRSRV_OK);
+                         uiPDumpOffset,
+                         ui32Value,
+                         ui32Mask,
+                         eOperator,
+                         _MEMPOLL_COUNT,
+                         _MEMPOLL_DELAY,
+                         uiPDumpFlags);
+    if (eError != PVRSRV_OK)
+    {
+        goto e0;
+    }
 
     return PVRSRV_OK;
+
+    /*
+      error exit paths follow
+    */
+
+ e0:
+    PVR_ASSERT(eError != PVRSRV_OK);
+    return eError;
+}
+
+PVRSRV_ERROR
+PMRPDumpCBP(const PMR *psPMR,
+            IMG_DEVMEM_OFFSET_T uiReadOffset,
+            IMG_DEVMEM_OFFSET_T uiWriteOffset,
+            IMG_DEVMEM_SIZE_T uiPacketSize,
+            IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+    PVRSRV_ERROR eError;
+    IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+    IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+    IMG_DEVMEM_OFFSET_T uiPDumpOffset;
+    IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+    eError = PMR_PDumpSymbolicAddr(psPMR,
+                                   uiReadOffset,
+                                   sizeof(aszMemspaceName),
+                                   &aszMemspaceName[0],
+                                   sizeof(aszSymbolicName),
+                                   &aszSymbolicName[0],
+                                   &uiPDumpOffset,
+                                   &uiNextSymName);
+    if (eError != PVRSRV_OK)
+    {
+        goto e0;
+    }
+
+    eError = PDumpPMRCBP(aszMemspaceName,
+                         aszSymbolicName,
+                         uiPDumpOffset,
+                         uiWriteOffset,
+                         uiPacketSize,
+                         uiBufferSize);
+    if (eError != PVRSRV_OK)
+    {
+        goto e0;
+    }
+
+    return PVRSRV_OK;
+
+    /*
+      error exit paths follow
+    */
+
+ e0:
+    PVR_ASSERT(eError != PVRSRV_OK);
+    return eError;
+}
+
+IMG_INTERNAL void
+PDumpPMRChangeSparsePMR(PMR *psPMR,
+                        IMG_UINT32 uiBlockSize,
+                        IMG_UINT32 ui32AllocPageCount,
+                        IMG_UINT32 *pai32AllocIndices,
+                        IMG_UINT32 ui32FreePageCount,
+                        IMG_UINT32 *pai32FreeIndices,
+                        IMG_BOOL bInitialise,
+                        IMG_UINT32 ui32InitValue,
+                        IMG_HANDLE *phPDumpAllocInfoOut)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE *phPDumpAllocInfo = (IMG_HANDLE*) psPMR->hPDumpAllocHandle;
+
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_DEVMEM_OFFSET_T uiOffset;
+	IMG_DEVMEM_OFFSET_T uiNextSymName;
+	IMG_UINT32 i, uiIndex;
+
+	/* Remove pages from the PMR */
+	for (i = 0; i < ui32FreePageCount; i++)
+	{
+		uiIndex = pai32FreeIndices[i];
+
+		eError = PDumpFree(phPDumpAllocInfo[uiIndex]);
+		PVR_ASSERT(eError == PVRSRV_OK);
+		phPDumpAllocInfo[uiIndex] = NULL;
+	}
+
+	/* Add new pages to the PMR */
+	for (i = 0; i < ui32AllocPageCount; i++)
+	{
+		uiIndex = pai32AllocIndices[i];
+
+		PVR_ASSERT(phPDumpAllocInfo[uiIndex] == NULL);
+
+		eError = PMR_PDumpSymbolicAddr(psPMR,
+		                               uiIndex * uiBlockSize,
+		                               sizeof(aszMemspaceName),
+		                               &aszMemspaceName[0],
+		                               sizeof(aszSymbolicName),
+		                               &aszSymbolicName[0],
+		                               &uiOffset,
+		                               &uiNextSymName);
+		PVR_ASSERT(eError == PVRSRV_OK);
+
+		eError = PDumpMalloc(aszMemspaceName,
+		                     aszSymbolicName,
+		                     uiBlockSize,
+		                     uiBlockSize,
+		                     bInitialise,
+		                     ui32InitValue,
+		                     psPMR->bForcePersistent,
+		                     &phPDumpAllocInfo[uiIndex]);
+		PVR_ASSERT(eError == PVRSRV_OK);
+	}
+
+	/* (IMG_HANDLE) <- (IMG_HANDLE*) */
+	*phPDumpAllocInfoOut = (IMG_HANDLE) phPDumpAllocInfo;
+}
+
+IMG_INTERNAL void
+PDumpPMRFreePMR(PMR *psPMR,
+                IMG_DEVMEM_SIZE_T uiSize,
+                IMG_DEVMEM_ALIGN_T uiBlockSize,
+                IMG_UINT32 uiLog2Contiguity,
+                IMG_HANDLE hPDumpAllocationInfoHandle)
+{
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+
+	/* (IMG_HANDLE*) <- (IMG_HANDLE) */
+	IMG_HANDLE *ahPDumpAllocHandleArray = (IMG_HANDLE*) hPDumpAllocationInfoHandle;
+
+	for (i = 0; i < psPMR->uiNumPDumpBlocks; i++)
+	{
+		if (ahPDumpAllocHandleArray[i] != NULL)
+		{
+			eError = PDumpFree(ahPDumpAllocHandleArray[i]);
+			PVR_ASSERT(eError == PVRSRV_OK);
+			ahPDumpAllocHandleArray[i] = NULL;
+		}
+	}
+
+	OSFreeMem(ahPDumpAllocHandleArray);
+}
+
+
+IMG_INTERNAL void
+PDumpPMRMallocPMR(PMR *psPMR,
+                  IMG_DEVMEM_SIZE_T uiSize,
+                  IMG_DEVMEM_ALIGN_T uiBlockSize,
+                  IMG_UINT32 ui32ChunkSize,
+                  IMG_UINT32 ui32NumPhysChunks,
+                  IMG_UINT32 ui32NumVirtChunks,
+                  IMG_UINT32 *puiMappingTable,
+                  IMG_UINT32 uiLog2Contiguity,
+                  IMG_BOOL bInitialise,
+                  IMG_UINT32 ui32InitValue,
+                  IMG_BOOL bForcePersistent,
+                  IMG_HANDLE *phPDumpAllocInfoOut)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE *phPDumpAllocInfo;
+
+	IMG_CHAR aszMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+	IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
+	IMG_DEVMEM_OFFSET_T uiOffset;
+	IMG_DEVMEM_OFFSET_T uiNextSymName;
+	IMG_UINT32 uiNumPhysBlocks;
+	IMG_UINT32 uiNumVirtBlocks;
+	IMG_UINT32 i, uiIndex;
+
+
+	if (PMR_IsSparse(psPMR))
+	{
+		uiNumPhysBlocks = (ui32ChunkSize * ui32NumPhysChunks) >> uiLog2Contiguity;
+		/* Make sure we did not cut off anything */
+		PVR_ASSERT(uiNumPhysBlocks << uiLog2Contiguity == (ui32ChunkSize * ui32NumPhysChunks));
+	}
+	else
+	{
+		uiNumPhysBlocks = uiSize >> uiLog2Contiguity;
+		/* Make sure we did not cut off anything */
+		PVR_ASSERT(uiNumPhysBlocks << uiLog2Contiguity == uiSize);
+	}
+
+	uiNumVirtBlocks = uiSize >> uiLog2Contiguity;
+	PVR_ASSERT(uiNumVirtBlocks << uiLog2Contiguity == uiSize);
+
+	psPMR->uiNumPDumpBlocks = uiNumVirtBlocks;
+
+	phPDumpAllocInfo = (IMG_HANDLE*) OSAllocZMem(uiNumVirtBlocks * sizeof(IMG_HANDLE));
+
+
+	for (i = 0; i < uiNumPhysBlocks; i++)
+	{
+		uiIndex = PMR_IsSparse(psPMR) ? puiMappingTable[i] : i;
+
+		eError = PMR_PDumpSymbolicAddr(psPMR,
+		                               uiIndex * uiBlockSize,
+		                               sizeof(aszMemspaceName),
+		                               &aszMemspaceName[0],
+		                               sizeof(aszSymbolicName),
+		                               &aszSymbolicName[0],
+		                               &uiOffset,
+		                               &uiNextSymName);
+		PVR_ASSERT(eError == PVRSRV_OK);
+
+		eError = PDumpMalloc(aszMemspaceName,
+		                     aszSymbolicName,
+		                     uiBlockSize,
+		                     uiBlockSize,
+		                     bInitialise,
+		                     ui32InitValue,
+		                     bForcePersistent,
+		                     &phPDumpAllocInfo[uiIndex]);
+		PVR_ASSERT(eError == PVRSRV_OK);
+	}
+
+	/* (IMG_HANDLE) <- (IMG_HANDLE*) */
+	*phPDumpAllocInfoOut = (IMG_HANDLE) phPDumpAllocInfo;
+
 }
 #endif	/* PDUMP */
 
+
+
+
+/*
+   FIXME: Find a better way to do this
+ */
+
 void *PMRGetPrivateDataHack(const PMR *psPMR,
                                 const PMR_IMPL_FUNCTAB *psFuncTab)
 {
     return (psFuncTab == psPMR->psFuncTab) ? psPMR->pvFlavourData : NULL;
 }
 
+
 PVRSRV_ERROR
 PMRWritePMPageList(/* Target PMR, offset, and length */
                    PMR *psPageListPMR,
@@ -2284,14 +2724,14 @@
     IMG_DEVMEM_SIZE_T uiWordSize;
     IMG_UINT32 uiNumPages;
     IMG_UINT32 uiPageIndex;
-    PMR_FLAGS_T uiFlags;
+    PMR_FLAGS_T uiFlags = psPageListPMR->uiFlags;
     PMR_PAGELIST *psPageList;
 #if defined(PDUMP)
-    IMG_CHAR aszTableEntryMemspaceName[100];
-    IMG_CHAR aszTableEntrySymbolicName[100];
+    IMG_CHAR aszTableEntryMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+    IMG_CHAR aszTableEntrySymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
     IMG_DEVMEM_OFFSET_T uiTableEntryPDumpOffset;
-    IMG_CHAR aszPageMemspaceName[100];
-    IMG_CHAR aszPageSymbolicName[100];
+    IMG_CHAR aszPageMemspaceName[PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH];
+    IMG_CHAR aszPageSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
     IMG_DEVMEM_OFFSET_T uiPagePDumpOffset;
     IMG_DEVMEM_OFFSET_T uiNextSymName;
 #endif
@@ -2307,6 +2747,7 @@
     IMG_UINT32 *pui32DataPtr = NULL;
     IMG_BOOL *pbPageIsValid;
 #endif
+    /* FIXME: should this be configurable? */
     uiWordSize = 4;
 
     /* check we're being asked to write the same number of 4-byte units as there are pages */
@@ -2339,8 +2780,7 @@
     }
 
     /* the PMR into which we are writing must not be user CPU mappable: */
-    uiFlags = PMR_Flags(psPageListPMR);
-    if ((uiFlags & (PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE)) != 0)
+	if (PVRSRV_CHECK_CPU_READABLE(uiFlags) || PVRSRV_CHECK_CPU_WRITEABLE(uiFlags))
     {
 		PVR_DPF((PVR_DBG_ERROR, "masked flags = 0x%08x", (uiFlags & (PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE))));
 		PVR_DPF((PVR_DBG_ERROR, "Page list PMR allows CPU mapping (0x%08x)", uiFlags));
@@ -2373,8 +2813,7 @@
 
     /* Need to lock down the physical addresses of the reference PMR */
     /* N.B.  This also checks that the requested "contiguity" is achievable */
-    eError = PMRLockSysPhysAddresses(psReferencePMR,
-                                     uiLog2PageSize);
+    eError = PMRLockSysPhysAddresses(psReferencePMR);
     if(eError != PVRSRV_OK)
     {
         goto e1;
@@ -2509,7 +2948,7 @@
 
         PVR_ASSERT(((pasDevAddrPtr[uiPageIndex].uiAddr >> uiLog2PageSize) & 0xFFFFFFFF00000000ll) == 0);
 
-        /* Write the physcial page index into the page list PMR */
+        /* Write the physical page index into the page list PMR */
         *pui32DataPtr++ = TRUNCATE_64BITS_TO_32BITS(pasDevAddrPtr[uiPageIndex].uiAddr >> uiLog2PageSize);
 
         /* Last page so unmap */
@@ -2551,7 +2990,7 @@
 }
 
 
-PVRSRV_ERROR
+PVRSRV_ERROR /* FIXME: should be void */
 PMRUnwritePMPageList(PMR_PAGELIST *psPageList)
 {
     PVRSRV_ERROR eError2;
@@ -2621,15 +3060,18 @@
         	goto MappingSize_Error;
         }
 
-        /* zeroing page content */
-        OSMemSet(pvKernAddr, 0, ui32PageSize);
+        /* Use the conservative 'DeviceMemSet' here because we can't know
+         * if this PMR will be mapped cached.
+         */
+
+        OSDeviceMemSet(pvKernAddr, 0, ui32PageSize);
 
         /* release mapping */
         PMRReleaseKernelMappingData(psPMR, hPrivData);
 
     }
 
-    PVR_DPF((PVR_DBG_WARNING,"PMRZeroingPMR: Zeroing PMR %p done (num pages %u, page size %u)",
+    PVR_DPF((PVR_DBG_MESSAGE,"PMRZeroingPMR: Zeroing PMR %p done (num pages %u, page size %u)",
     						psPMR,
     						uiNumPages,
     						ui32PageSize));
@@ -2726,111 +3168,6 @@
     return eError;
 }
 
-#if defined(PDUMP)
-extern PVRSRV_ERROR
-PMRPDumpPol32(const PMR *psPMR,
-              IMG_DEVMEM_OFFSET_T uiLogicalOffset,
-              IMG_UINT32 ui32Value,
-              IMG_UINT32 ui32Mask,
-              PDUMP_POLL_OPERATOR eOperator,
-              PDUMP_FLAGS_T uiPDumpFlags)
-{
-    PVRSRV_ERROR eError;
-    IMG_CHAR aszMemspaceName[100];
-    IMG_CHAR aszSymbolicName[100];
-    IMG_DEVMEM_OFFSET_T uiPDumpOffset;
-    IMG_DEVMEM_OFFSET_T uiNextSymName;
-
-    eError = PMR_PDumpSymbolicAddr(psPMR,
-                                   uiLogicalOffset,
-                                   sizeof(aszMemspaceName),
-                                   &aszMemspaceName[0],
-                                   sizeof(aszSymbolicName),
-                                   &aszSymbolicName[0],
-                                   &uiPDumpOffset,
-				   &uiNextSymName);
-    if (eError != PVRSRV_OK)
-    {
-        goto e0;
-    }
-
-#define _MEMPOLL_DELAY		(1000)
-#define _MEMPOLL_COUNT		(2000000000 / _MEMPOLL_DELAY)
-
-    eError = PDumpPMRPOL(aszMemspaceName,
-                         aszSymbolicName,
-                         uiPDumpOffset,
-                         ui32Value,
-                         ui32Mask,
-                         eOperator,
-                         _MEMPOLL_COUNT,
-                         _MEMPOLL_DELAY,
-                         uiPDumpFlags);
-    if (eError != PVRSRV_OK)
-    {
-        goto e0;
-    }
-
-    return PVRSRV_OK;
-
-    /*
-      error exit paths follow
-    */
-
- e0:
-    PVR_ASSERT(eError != PVRSRV_OK);
-    return eError;
-}
-
-PVRSRV_ERROR
-PMRPDumpCBP(const PMR *psPMR,
-            IMG_DEVMEM_OFFSET_T uiReadOffset,
-            IMG_DEVMEM_OFFSET_T uiWriteOffset,
-            IMG_DEVMEM_SIZE_T uiPacketSize,
-            IMG_DEVMEM_SIZE_T uiBufferSize)
-{
-    PVRSRV_ERROR eError;
-    IMG_CHAR aszMemspaceName[100];
-    IMG_CHAR aszSymbolicName[100];
-    IMG_DEVMEM_OFFSET_T uiPDumpOffset;
-    IMG_DEVMEM_OFFSET_T uiNextSymName;
-
-    eError = PMR_PDumpSymbolicAddr(psPMR,
-                                   uiReadOffset,
-                                   sizeof(aszMemspaceName),
-                                   &aszMemspaceName[0],
-                                   sizeof(aszSymbolicName),
-                                   &aszSymbolicName[0],
-                                   &uiPDumpOffset,
-                                   &uiNextSymName);
-    if (eError != PVRSRV_OK)
-    {
-        goto e0;
-    }
-
-    eError = PDumpPMRCBP(aszMemspaceName,
-                         aszSymbolicName,
-                         uiPDumpOffset,
-                         uiWriteOffset,
-                         uiPacketSize,
-                         uiBufferSize);
-    if (eError != PVRSRV_OK)
-    {
-        goto e0;
-    }
-
-    return PVRSRV_OK;
-
-    /*
-      error exit paths follow
-    */
-
- e0:
-    PVR_ASSERT(eError != PVRSRV_OK);
-    return eError;
-}
-#endif
-
 PVRSRV_ERROR
 PMRInit()
 {
@@ -2888,5 +3225,11 @@
 
     _gsSingletonPMRContext.bModuleInitialised = IMG_FALSE;
 
+    /*
+      FIXME:
+
+      should deinitialise the mutex here
+    */
+
     return PVRSRV_OK;
 }
diff --git a/drivers/staging/imgtec/rogue/pmr.h b/drivers/staging/imgtec/rogue/pmr.h
index c8c91fb..2e86c81 100644
--- a/drivers/staging/imgtec/rogue/pmr.h
+++ b/drivers/staging/imgtec/rogue/pmr.h
@@ -69,18 +69,7 @@
 /* services/server/include/ */
 #include "pmr_impl.h"
 #include "physheap.h"
-/* A typical symbolic address for physical memory may look like:
-   :MEMORYSPACE:SUBSYS_NNNNNN_0X1234567890_XYZ.  That example is quite
-   extreme, they are likely shorter than that.  We'll make the define
-   here plentiful, however, note that this is _advisory_ not
-   _mandatory_ - in other words, it's the allocator's responsibility
-   to choose the amount of memory to set aside, and it's up to us to
-   honour the size passed in by the caller.  i.e. this define is for
-   GUIDANCE ONLY.
-*/
-#define PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT		(60)
-#define PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT		(20)
-#define PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT	(PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT + PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT)
+
 #define PMR_MAX_TRANSLATION_STACK_ALLOC				(32)
 
 typedef IMG_UINT64 PMR_BASE_T;
@@ -91,18 +80,14 @@
 typedef IMG_UINT32 PMR_LOG2ALIGN_T;
 typedef IMG_UINT64 PMR_PASSWORD_T;
 
-typedef struct _PMR_MAPPING_TABLE_
+struct _PMR_MAPPING_TABLE_
 {
 	PMR_SIZE_T	uiChunkSize;			/*!< Size of a "chunk" */
 	IMG_UINT32 	ui32NumPhysChunks;		/*!< Number of physical chunks that are valid */
 	IMG_UINT32 	ui32NumVirtChunks;		/*!< Number of virtual chunks in the mapping */
 	/* Must be last */
-#if defined(PVRSRV_SPLIT_LARGE_OSMEM_ALLOC)
-	IMG_UINT32 	*aui32Translation;      /*!< Translation mapping for "logical" to physical */
-#else
 	IMG_UINT32 	aui32Translation[1];    /*!< Translation mapping for "logical" to physical */
-#endif
-} PMR_MAPPING_TABLE;
+};
 
 #define TRANSLATION_INVALID 0xFFFFFFFFUL
 #define INVALID_PAGE 0ULL
@@ -111,7 +96,8 @@
 
 typedef struct _PMR_PAGELIST_ PMR_PAGELIST;
 
-struct _PVRSRV_DEVICE_NODE_;
+typedef struct _CONNECTION_DATA_ CONNECTION_DATA;
+typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
 
 /*
  * PMRCreatePMR
@@ -150,22 +136,6 @@
  *
  *       (device MMU page size) <= 2**(uiLog2ContiguityGuarantee) <= (actual contiguity of physical memory)
  *
- *
- * Note also that the implementation may supply pszPDumpFlavour and
- * pszPDumpDefaultMemspaceName, which are irrelevant where the PMR
- * implementation overrides the default symbolic name construction
- * routine.  Where the function pointer for PDump symbolic name
- * derivation is not overridden (i.e. NULL appears in the relevant
- * entry of the functab) and default implementation shall be used
- * which will copy the PDumpDefaultMemspaceName into the namespace
- * argument, and create the symbolic name by concatenating the
- * "PDumpFlavour" and a numeric representation of the PMR's serial
- * number.
- *
- * The implementation must guarantee that the storage for these two
- * strings, and the function table, are maintained, as copies are not
- * made, the pointer is simply stored.
- *
  * The function table will contain the following callbacks which may
  * be overridden by the PMR implementation:
  *
@@ -194,15 +164,6 @@
  *      pmr.c abstraction will handle the refcounting for the whole
  *      PMR.
  *
- * pfnPDumpSymbolicAddr
- *
- *      Derives the PDump symbolic address for the given offset.  The
- *      default implementation will copy the PDumpDefaultMemspaceName
- *      into the namespace argument (or use SYSMEM if none was
- *      supplied), and create the symbolic name by concatenating the
- *      "PDumpFlavour" and a numeric representation of the PMR's
- *      serial number.
- *
  * pfnFinalize
  *
  *      Called when the PMR's refcount reaches zero and it gets
@@ -211,7 +172,8 @@
  *
  */
 extern PVRSRV_ERROR
-PMRCreatePMR(PHYS_HEAP *psPhysHeap,
+PMRCreatePMR(PVRSRV_DEVICE_NODE *psDevNode,
+             PHYS_HEAP *psPhysHeap,
              PMR_SIZE_T uiLogicalSize,
              PMR_SIZE_T uiChunkSize,
              IMG_UINT32 ui32NumPhysChunks,
@@ -219,11 +181,11 @@
              IMG_UINT32 *pui32MappingTable,
              PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee,
              PMR_FLAGS_T uiFlags,
-             const IMG_CHAR *pszPDumpFlavour,
+             const IMG_CHAR *pszAnnotation,
              const PMR_IMPL_FUNCTAB *psFuncTab,
              PMR_IMPL_PRIVDATA pvPrivData,
+             PMR_IMPL_TYPE eType,
              PMR **ppsPMRPtr,
-             IMG_HANDLE *phPDumpAllocInfo,
              IMG_BOOL bForcePersistent);
 
 /*
@@ -233,8 +195,7 @@
  *
  * Before this call, it is not valid to use any of the information
  * getting APIs: PMR_Flags(), PMR_SysPhysAddr(),
- * PMR_PDumpSymbolicAddr() [ see note below about lock/unlock
- * semantics ]
+ * [ see note below about lock/unlock semantics ]
  *
  * The caller of this function does not have to care about how the PMR
  * is implemented.  He only has to know that he is allowed access to
@@ -258,12 +219,10 @@
  */
 
 extern PVRSRV_ERROR
-PMRLockSysPhysAddresses(PMR *psPMR,
-                        IMG_UINT32 uiLog2DevPageSize);
+PMRLockSysPhysAddresses(PMR *psPMR);
 
 extern PVRSRV_ERROR
 PMRLockSysPhysAddressesNested(PMR *psPMR,
-                        IMG_UINT32 uiLog2DevPageSize,
                         IMG_UINT32 ui32NestingLevel);
 
 /*
@@ -323,7 +282,7 @@
  *
  * Given a PMR, creates a PMR "Export", which is a handle that
  * provides sufficient data to be able to "import" this PMR elsewhere.
- * The PMR Export is an object in its own right, whose existance
+ * The PMR Export is an object in its own right, whose existence
  * implies a reference on the PMR, thus the PMR cannot be destroyed
  * while the PMR Export exists.  The intention is that the PMR Export
  * will be wrapped in the devicemem layer by a cross process handle,
@@ -415,7 +374,9 @@
  * promising to later call PhysmemPMRUnimport()
  */
 extern PVRSRV_ERROR
-PMRImportPMR(PMR_EXPORT *psPMRExport,
+PMRImportPMR(CONNECTION_DATA *psConnection,
+             PVRSRV_DEVICE_NODE *psDevNode,
+             PMR_EXPORT *psPMRExport,
              PMR_PASSWORD_T uiPassword,
              PMR_SIZE_T uiSize,
              PMR_LOG2ALIGN_T uiLog2Contig,
@@ -460,6 +421,15 @@
 PMRReleaseKernelMappingData(PMR *psPMR,
                             IMG_HANDLE hPriv);
 
+#if defined(INTEGRITY_OS)
+extern PVRSRV_ERROR
+PMRMapMemoryObject(PMR *psPMR,
+                   IMG_HANDLE *phMemObj,
+                   IMG_HANDLE hPriv);
+extern PVRSRV_ERROR
+PMRUnmapMemoryObject(PMR *psPMR,
+                     IMG_HANDLE hPriv);
+#endif
 
 /*
  * PMR_ReadBytes()
@@ -545,6 +515,9 @@
 extern PVRSRV_ERROR
 PMRUnrefUnlockPMR(PMR *psPMR);
 
+extern PVRSRV_DEVICE_NODE *
+PMR_DeviceNode(const PMR *psPMR);
+
 /*
  * PMR_Flags()
  *
@@ -567,19 +540,29 @@
 PMR_LogicalSize(const PMR *psPMR,
 				IMG_DEVMEM_SIZE_T *puiLogicalSize);
 
+extern PHYS_HEAP *
+PMR_PhysHeap(const PMR *psPMR);
+
 extern PMR_MAPPING_TABLE *
 PMR_GetMappigTable(const PMR *psPMR);
 
+extern IMG_UINT32
+PMR_GetLog2Contiguity(const PMR *psPMR);
 /*
  * PMR_IsOffsetValid()
  *
  * Returns if an address offset inside a PMR has a valid
  * physical backing.
  */
-extern void
+extern PVRSRV_ERROR
 PMR_IsOffsetValid(const PMR *psPMR,
-                IMG_DEVMEM_OFFSET_T uiLogicalOffset,
-                IMG_BOOL *pbValid);
+				IMG_UINT32 ui32Log2PageSize,
+				IMG_UINT32 ui32NumOfPages,
+				IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+				IMG_BOOL *pbValid);
+
+extern PMR_IMPL_TYPE
+PMR_GetType(const PMR *psPMR);
 
 /*
  * PMR_SysPhysAddr()
@@ -627,7 +610,7 @@
 
 PVRSRV_ERROR
 PMRGetUID(PMR *psPMR,
-		  IMG_UINT64 *pui64UID);
+          IMG_UINT64 *pui64UID);
 /*
  * PMR_ChangeSparseMem()
  *
@@ -638,12 +621,11 @@
  *
  */
 PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR,
-								IMG_UINT32 ui32AllocPageCount,
-								IMG_UINT32 *pai32AllocIndices,
-								IMG_UINT32 ui32FreePageCount,
-								IMG_UINT32 *pai32FreeIndices,
-								IMG_UINT32	uiFlags,
-								IMG_UINT32	*pui32Status);
+                                 IMG_UINT32 ui32AllocPageCount,
+                                 IMG_UINT32 *pai32AllocIndices,
+                                 IMG_UINT32 ui32FreePageCount,
+                                 IMG_UINT32 *pai32FreeIndices,
+                                 IMG_UINT32	uiFlags);
 
 /*
  * PMR_ChangeSparseMemCPUMap()
@@ -655,16 +637,45 @@
  *
  */
 PVRSRV_ERROR PMR_ChangeSparseMemCPUMap(PMR *psPMR,
-											IMG_UINT64 sCpuVAddrBase,
-											IMG_UINT32	ui32AllocPageCount,
-											IMG_UINT32	*pai32AllocIndices,
-											IMG_UINT32	ui32FreePageCount,
-											IMG_UINT32	*pai32FreeIndices,
-											IMG_UINT32	*pui32Status);
-
-
+                                       IMG_UINT64 sCpuVAddrBase,
+                                       IMG_UINT32 ui32AllocPageCount,
+                                       IMG_UINT32 *pai32AllocIndices,
+                                       IMG_UINT32 ui32FreePageCount,
+                                       IMG_UINT32 *pai32FreeIndices);
 
 #if defined(PDUMP)
+
+extern void
+PDumpPMRMallocPMR(PMR *psPMR,
+                  IMG_DEVMEM_SIZE_T uiSize,
+                  IMG_DEVMEM_ALIGN_T uiBlockSize,
+                  IMG_UINT32 ui32ChunkSize,
+                  IMG_UINT32 ui32NumPhysChunks,
+                  IMG_UINT32 ui32NumVirtChunks,
+                  IMG_UINT32 *puiMappingTable,
+                  IMG_UINT32 uiLog2Contiguity,
+                  IMG_BOOL bInitialise,
+                  IMG_UINT32 ui32InitValue,
+                  IMG_BOOL bForcePersistent,
+                  IMG_HANDLE *phPDumpAllocInfoPtr);
+
+extern void
+PDumpPMRFreePMR(PMR *psPMR,
+                IMG_DEVMEM_SIZE_T uiSize,
+                IMG_DEVMEM_ALIGN_T uiBlockSize,
+                IMG_UINT32 uiLog2Contiguity,
+                IMG_HANDLE hPDumpAllocationInfoHandle);
+
+extern void
+PDumpPMRChangeSparsePMR(PMR *psPMR,
+                        IMG_UINT32 uiBlockSize,
+                        IMG_UINT32 ui32AllocPageCount,
+                        IMG_UINT32 *pai32AllocIndices,
+                        IMG_UINT32 ui32FreePageCount,
+                        IMG_UINT32 *pai32FreeIndices,
+                        IMG_BOOL bInitialise,
+                        IMG_UINT32 ui32InitValue,
+                        IMG_HANDLE *phPDumpAllocInfoOut);
 /*
  * PMR_PDumpSymbolicAddr()
  *
@@ -758,6 +769,76 @@
                    IMG_UINT32 uiFileOffset);
 #else	/* PDUMP */
 
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpPMRMallocPMR)
+#endif
+static INLINE void
+PDumpPMRMallocPMR(PMR *psPMR,
+                  IMG_DEVMEM_SIZE_T uiSize,
+                  IMG_DEVMEM_ALIGN_T uiBlockSize,
+                  IMG_UINT32 ui32NumPhysChunks,
+                  IMG_UINT32 ui32NumVirtChunks,
+                  IMG_UINT32 *puiMappingTable,
+                  IMG_UINT32 uiLog2Contiguity,
+                  IMG_BOOL bInitialise,
+                  IMG_UINT32 ui32InitValue,
+                  IMG_BOOL bForcePersistent,
+                  IMG_HANDLE *phPDumpAllocInfoPtr)
+{
+	PVR_UNREFERENCED_PARAMETER(psPMR);
+	PVR_UNREFERENCED_PARAMETER(uiSize);
+	PVR_UNREFERENCED_PARAMETER(uiBlockSize);
+	PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+	PVR_UNREFERENCED_PARAMETER(ui32NumVirtChunks);
+	PVR_UNREFERENCED_PARAMETER(puiMappingTable);
+	PVR_UNREFERENCED_PARAMETER(uiLog2Contiguity);
+	PVR_UNREFERENCED_PARAMETER(bInitialise);
+	PVR_UNREFERENCED_PARAMETER(ui32InitValue);
+	PVR_UNREFERENCED_PARAMETER(bForcePersistent);
+	PVR_UNREFERENCED_PARAMETER(phPDumpAllocInfoPtr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpPMRFreePMR)
+#endif
+static INLINE void
+PDumpPMRFreePMR(PMR *psPMR,
+                IMG_DEVMEM_SIZE_T uiSize,
+                IMG_DEVMEM_ALIGN_T uiBlockSize,
+                IMG_UINT32 uiLog2Contiguity,
+                IMG_HANDLE hPDumpAllocationInfoHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(psPMR);
+	PVR_UNREFERENCED_PARAMETER(uiSize);
+	PVR_UNREFERENCED_PARAMETER(uiBlockSize);
+	PVR_UNREFERENCED_PARAMETER(uiLog2Contiguity);
+	PVR_UNREFERENCED_PARAMETER(hPDumpAllocationInfoHandle);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpPMRChangeSparsePMR)
+#endif
+static INLINE void
+PDumpPMRChangeSparsePMR(PMR *psPMR,
+                        IMG_UINT32 uiBlockSize,
+                        IMG_UINT32 ui32AllocPageCount,
+                        IMG_UINT32 *pai32AllocIndices,
+                        IMG_UINT32 ui32FreePageCount,
+                        IMG_UINT32 *pai32FreeIndices,
+                        IMG_BOOL bInitialise,
+                        IMG_UINT32 ui32InitValue,
+                        IMG_HANDLE *phPDumpAllocInfoOut)
+{
+	PVR_UNREFERENCED_PARAMETER(psPMR);
+	PVR_UNREFERENCED_PARAMETER(uiBlockSize);
+	PVR_UNREFERENCED_PARAMETER(ui32AllocPageCount);
+	PVR_UNREFERENCED_PARAMETER(pai32AllocIndices);
+	PVR_UNREFERENCED_PARAMETER(ui32FreePageCount);
+	PVR_UNREFERENCED_PARAMETER(pai32FreeIndices);
+	PVR_UNREFERENCED_PARAMETER(bInitialise);
+	PVR_UNREFERENCED_PARAMETER(ui32InitValue);
+	PVR_UNREFERENCED_PARAMETER(phPDumpAllocInfoOut);
+}
 
 #ifdef INLINE_IS_PRAGMA
 #pragma inline(PMR_PDumpSymbolicAddr)
diff --git a/drivers/staging/imgtec/rogue/pmr_impl.h b/drivers/staging/imgtec/rogue/pmr_impl.h
index 401fe028..53da82b 100644
--- a/drivers/staging/imgtec/rogue/pmr_impl.h
+++ b/drivers/staging/imgtec/rogue/pmr_impl.h
@@ -1,11 +1,11 @@
 /**************************************************************************/ /*!
 @File
-@Title		Implementation Callbacks for Physmem (PMR) abstraction
+@Title          Implementation Callbacks for Physmem (PMR) abstraction
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description	Part of the memory management.  This file is for definitions that
-                are private to the world of PMRs, but that needs to be shared between
-                pmr.c itself and the modules that implement the callbacks for the
-                PMR.
+@Description    Part of the memory management.  This file is for definitions
+                that are private to the world of PMRs, but that need to be
+                shared between pmr.c itself and the modules that implement the
+                callbacks for the PMR.
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -59,185 +59,462 @@
 typedef struct _PMR_MAPPING_TABLE_ PMR_MAPPING_TABLE;
 typedef void *PMR_MMAP_DATA;
 
-typedef struct {
-    /*
-     * LockPhysAddresses() and UnlockPhysAddresses()
-     *
-     * locks down the physical addresses for the whole PMR.  If memory
-     * is "prefaulted", i.e. exists phsycally at PMR creation time,
-     * then there is no need to override this callback.  The default
-     * implementation is to simply increment a lock-count for
-     * debugging purposes.
-     *
-     * If overridden, this function will be called when someone first
-     * requires a physical addresses, and the UnlockPhysAddresses()
-     * counterpart will be called when the last such reference is
-     * released.
-     *
-     * The PMR implementation may assume that physical addresses will
-     * have been "locked" in this manner before any call is made to
-     * the pfnDevPhysAddr() callback
-     */
-    PVRSRV_ERROR (*pfnLockPhysAddresses)(PMR_IMPL_PRIVDATA pvPriv,
-                                         IMG_UINT32 uiLog2DevPageSize);
-    PVRSRV_ERROR (*pfnUnlockPhysAddresses)(PMR_IMPL_PRIVDATA pvPriv);
-    /*
-     * called iteratively or once to obtain page(s) physical address
-     * ("page" might be device mmu page, or host cpu mmu page, or
-     * something else entirely... the PMR implementation should
-     * make no assumption, and honour the request for a physical
-     * address of any byte in the PMR)
-     *
-     * [ it's the callers responsibility to ensure that no addresses
-     * are missed, by calling this at least as often as once per
-     * "1<<contiguityguarantee" ]
-     *
-     * the LockPhysAddresses callback (if overridden) is guaranteed to
-     * have been called prior to calling this one, and the caller
-     * promises not to rely on the physical address thus obtained
-     * after the UnlockPhysAddresses callback is called.
-     *
-     * Overriding this callback is mandatory in all PMR
-     * implementations.
-     */
-    PVRSRV_ERROR (*pfnDevPhysAddr)(PMR_IMPL_PRIVDATA pvPriv,
-                                   IMG_UINT32 ui32NumOfAddr,
-                                   IMG_DEVMEM_OFFSET_T *puiOffset,
-								   IMG_BOOL *pbValid,
-                                   IMG_DEV_PHYADDR *psDevAddrPtr);
-    /*
-     * Called iteratively to obtain PDump symbolic addresses.  Behaves
-     * just like pfnDevPhysAddr callback, except for returning Symbolic
-     * Addresses.
-     *
-     * It is optional to override this callback.  The default
-     * implementation will construct an address from the PMR type and
-     * serial number.
-     *
-     * If the PMR factory supports unpinning of memory the symbolic
-     * address must not be calculated depending on the physical
-     * addresses of the PMR because it can change!
-     */
-    PVRSRV_ERROR (*pfnPDumpSymbolicAddr)(PMR_IMPL_PRIVDATA pvPriv,
-                                         IMG_DEVMEM_OFFSET_T uiOffset,
-                                         IMG_CHAR *pszMemspaceName,
-                                         IMG_UINT32 ui32MemspaceNameLen,
-                                         IMG_CHAR *pszSymbolicAddr,
-                                         IMG_UINT32 ui32SymbolicAddrLen,
-                                         IMG_DEVMEM_OFFSET_T *puiNewOffset,
-                                         IMG_DEVMEM_OFFSET_T *puiNextSymName);
-    /*
-     * AcquireKernelMappingData()/ReleaseKernelMappingData()
-     *
-     * called to obtain a kernel virtual address for the PMR for use
-     * internally in services.
-     *
-     * It is not necessary to override this callback, but failure to
-     * do so will mean that kernel mappings will not be possible
-     */
-    PVRSRV_ERROR (*pfnAcquireKernelMappingData)(PMR_IMPL_PRIVDATA pvPriv,
-                                                size_t uiOffset,
-                                                size_t uiSize,
-                                                void **ppvKernelAddressOut,
-                                                IMG_HANDLE *phHandleOut,
-                                                PMR_FLAGS_T ulFlags);
-    void (*pfnReleaseKernelMappingData)(PMR_IMPL_PRIVDATA pvPriv,
-                                            IMG_HANDLE hHandle);
-    /*
-     * Read up to uiBufSz bytes from the PMR.
-     * The pmr will be already locked.
-     *
-     * Overriding this is optional.  The default implementation will
-     * acquire a kernel virtual address with
-     * pfnAcquireKernelMappingData and OSMemCopy the data directly
-     */
-    PVRSRV_ERROR (*pfnReadBytes)(PMR_IMPL_PRIVDATA pvPriv,
-                                 IMG_DEVMEM_OFFSET_T uiOffset,
-                                 IMG_UINT8 *pcBuffer,
-                                 size_t uiBufSz,
-                                 size_t *puiNumBytes);
+/**
+ *  Which PMR factory has created this PMR?
+ */
+typedef enum _PMR_IMPL_TYPE_
+{
+	PMR_TYPE_NONE = 0,
+	PMR_TYPE_OSMEM,
+	PMR_TYPE_LMA,
+	PMR_TYPE_DMABUF,
+	PMR_TYPE_EXTMEM,
+	PMR_TYPE_DC,
+	PMR_TYPE_TDFWCODE,
+	PMR_TYPE_TDSECBUF
+} PMR_IMPL_TYPE;
 
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_LOCK_PHYS_ADDRESSES_FN
+
+@Description    Called to lock down the physical addresses for all pages
+                allocated for a PMR.
+                The default implementation is to simply increment a
+                lock-count for debugging purposes.
+                If overridden, the PFN_LOCK_PHYS_ADDRESSES_FN function will
+                be called when someone first requires a physical address,
+                and the PFN_UNLOCK_PHYS_ADDRESSES_FN counterpart will be
+                called when the last such reference is released.
+                The PMR implementation may assume that physical addresses
+                will have been "locked" in this manner before any call is
+                made to the pfnDevPhysAddr() callback
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+
+@Return         PVRSRV_OK if the operation was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_LOCK_PHYS_ADDRESSES_FN)(PMR_IMPL_PRIVDATA pvPriv);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_UNLOCK_PHYS_ADDRESSES_FN
+
+@Description    Called to release the lock taken on the physical addresses
+                for all pages allocated for a PMR.
+                The default implementation is to simply decrement a
+                lock-count for debugging purposes.
+                If overridden, the PFN_UNLOCK_PHYS_ADDRESSES_FN will be
+                called when the last reference taken on the PMR is
+                released.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+
+@Return         PVRSRV_OK if the operation was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_UNLOCK_PHYS_ADDRESSES_FN)(PMR_IMPL_PRIVDATA pvPriv);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_DEV_PHYS_ADDR_FN
+
+@Description    Called to obtain one or more physical addresses for given
+                offsets within a PMR.
+
+                The PFN_LOCK_PHYS_ADDRESSES_FN callback (if overridden) is
+                guaranteed to have been called prior to calling the
+                PFN_DEV_PHYS_ADDR_FN callback and the caller promises not to
+                rely on the physical address thus obtained after the
+                PFN_UNLOCK_PHYS_ADDRESSES_FN callback is called.
+
+   Implementation of this callback is mandatory.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          ui32Log2PageSize          The log2 page size.
+@Input          ui32NumOfAddr             The number of addresses to be
+                                          returned
+@Input          puiOffset                 The offset from the start of the
+                                          PMR (in bytes) for which the
+                                          physical address is required.
+                                          Where multiple addresses are
+                                          requested, this will contain a
+                                          list of offsets.
+@Output         pbValid                   List of boolean flags indicating
+                                          which addresses in the returned
+                                          list (psDevAddrPtr) are valid
+                                          (for sparse allocations, not all
+                                          pages may have a physical backing)
+@Output         psDevAddrPtr              Returned list of physical addresses
+
+@Return         PVRSRV_OK if the operation was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_DEV_PHYS_ADDR_FN)(PMR_IMPL_PRIVDATA pvPriv,
+                      IMG_UINT32 ui32Log2PageSize,
+                      IMG_UINT32 ui32NumOfAddr,
+                      IMG_DEVMEM_OFFSET_T *puiOffset,
+                      IMG_BOOL *pbValid,
+                      IMG_DEV_PHYADDR *psDevAddrPtr);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN
+
+@Description    Called to obtain a kernel-accessible address (mapped to a
+                virtual address if required) for the PMR for use internally
+                in Services.
+
+    Implementation of this function for the (default) PMR factory providing
+    OS-allocations is mandatory (the driver will expect to be able to call
+    this function for OS-provided allocations).
+    For other PMR factories, implementation of this function is only necessary
+    where an MMU mapping is required for the Kernel to be able to access the
+    allocated memory.
+    If no mapping is needed, this function can remain unimplemented and the
+    pfn may be set to NULL.
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          uiOffset                  Offset from the beginning of
+                                          the PMR at which mapping is to
+                                          start
+@Input          uiSize                    Size of mapping (in bytes)
+@Output         ppvKernelAddressOut       Mapped kernel address
+@Output         phHandleOut	              Returned handle of the new mapping
+@Input          ulFlags                   Mapping flags
+
+@Return         PVRSRV_OK if the mapping was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN)(PMR_IMPL_PRIVDATA pvPriv,
+                      size_t uiOffset,
+                      size_t uiSize,
+                      void **ppvKernelAddressOut,
+                      IMG_HANDLE *phHandleOut,
+                      PMR_FLAGS_T ulFlags);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_RELEASE_KERNEL_MAPPING_DATA_FN
+
+@Description    Called to release a mapped kernel virtual address
+
+   Implementation of this callback is mandatory if PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN
+   is provided for the PMR factory, otherwise this function can remain unimplemented
+   and the pfn may be set to NULL.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          hHandle                   Handle of the mapping to be
+                                          released
+
+@Return         None
+*/
+/*****************************************************************************/
+typedef void (*PFN_RELEASE_KERNEL_MAPPING_DATA_FN)(PMR_IMPL_PRIVDATA pvPriv,
+              IMG_HANDLE hHandle);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_READ_BYTES_FN
+
+@Description    Called to read bytes from an unmapped allocation
+
+   Implementation of this callback is optional -
+   where it is not provided, the driver will use PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN
+   to map the entire PMR (if an MMU mapping is required for the Kernel to be
+   able to access the allocated memory).
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          uiOffset                  Offset from the beginning of
+                                          the PMR at which to begin
+                                          reading
+@Output         pcBuffer                  Buffer in which to return the
+                                          read data
+@Input          uiBufSz                   Number of bytes to be read
+@Output         puiNumBytes               Number of bytes actually read
+                                          (may be less than uiBufSz)
+
+@Return         PVRSRV_OK if the read was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_READ_BYTES_FN)(PMR_IMPL_PRIVDATA pvPriv,
+                      IMG_DEVMEM_OFFSET_T uiOffset,
+                      IMG_UINT8 *pcBuffer,
+                      size_t uiBufSz,
+                      size_t *puiNumBytes);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_WRITE_BYTES_FN
+
+@Description    Called to write bytes into an unmapped allocation
+
+   Implementation of this callback is optional -
+   where it is not provided, the driver will use PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN
+   to map the entire PMR (if an MMU mapping is required for the Kernel to be
+   able to access the allocated memory).
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          uiOffset                  Offset from the beginning of
+                                          the PMR at which to begin
+                                          writing
+@Input          pcBuffer                  Buffer containing the data to be
+                                          written
+@Input          uiBufSz                   Number of bytes to be written
+@Output         puiNumBytes               Number of bytes actually written
+                                          (may be less than uiBufSz)
+
+@Return         PVRSRV_OK if the write was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_WRITE_BYTES_FN)(PMR_IMPL_PRIVDATA pvPriv,
+                      IMG_DEVMEM_OFFSET_T uiOffset,
+                      IMG_UINT8 *pcBuffer,
+                      size_t uiBufSz,
+                      size_t *puiNumBytes);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_UNPIN_MEM_FN
+
+@Description    Called to unpin an allocation.
+                Once unpinned, the pages backing the allocation may be
+                re-used by the Operating System for another purpose.
+                When the pages are required again, they may be re-pinned
+                (by calling PFN_PIN_MEM_FN). The driver will try to return
+                same pages as before. The caller will be told if the
+                content of these returned pages has been modified or if
+                the pages returned are not the original pages.
+
+   Implementation of this callback is optional.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+
+@Return         PVRSRV_OK if the unpin was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_UNPIN_MEM_FN)(PMR_IMPL_PRIVDATA pPriv);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_PIN_MEM_FN
+
+@Description    Called to pin a previously unpinned allocation.
+                The driver will try to return same pages as were previously
+                assigned to the allocation. The caller will be told if the
+                content of these returned pages has been modified or if
+                the pages returned are not the original pages.
+
+   Implementation of this callback is optional.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+
+@Input          psMappingTable            Mapping table, which describes how
+                                          virtual 'chunks' are to be mapped to
+                                          physical 'chunks' for the allocation.
+
+@Return         PVRSRV_OK if the original pages were returned unmodified.
+                PVRSRV_ERROR_PMR_NEW_MEMORY if the memory returned was modified
+                or different pages were returned.
+                Another PVRSRV_ERROR code on failure.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_PIN_MEM_FN)(PMR_IMPL_PRIVDATA pPriv,
+                      PMR_MAPPING_TABLE *psMappingTable);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_CHANGE_SPARSE_MEM_FN
+
+@Description    Called to modify the physical backing for a given sparse
+                allocation.
+                The caller provides a list of the pages within the sparse
+                allocation which should be backed with a physical allocation
+                and a list of the pages which do not require backing.
+
+                Implementation of this callback is mandatory.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          psPMR                     The PMR of the sparse allocation
+                                          to be modified
+@Input          ui32AllocPageCount        The number of pages specified in
+                                          pai32AllocIndices
+@Input          pai32AllocIndices         The list of pages in the sparse
+                                          allocation that should be backed
+                                          with a physical allocation. Pages
+                                          are referenced by their index
+                                          within the sparse allocation
+                                          (e.g. in a 10 page allocation, pages
+                                          are denoted by indices 0 to 9)
+@Input          ui32FreePageCount         The number of pages specified in
+                                          pai32FreeIndices
+@Input          pai32FreeIndices          The list of pages in the sparse
+                                          allocation that do not require
+                                          a physical allocation.
+@Input          ui32Flags                 Allocation flags
+
+@Return         PVRSRV_OK if the sparse allocation physical backing was updated
+                successfully, an error code otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_CHANGE_SPARSE_MEM_FN)(PMR_IMPL_PRIVDATA pPriv,
+                      const PMR *psPMR,
+                      IMG_UINT32 ui32AllocPageCount,
+                      IMG_UINT32 *pai32AllocIndices,
+                      IMG_UINT32 ui32FreePageCount,
+                      IMG_UINT32 *pai32FreeIndices,
+                      IMG_UINT32 uiFlags);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_CHANGE_SPARSE_MEM_CPU_MAP_FN
+
+@Description    Called to modify which pages are mapped for a given sparse
+                allocation.
+                The caller provides a list of the pages within the sparse
+                allocation which should be given a CPU mapping and a list
+                of the pages which do not require a CPU mapping.
+
+   Implementation of this callback is mandatory.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          psPMR                     The PMR of the sparse allocation
+                                          to be modified
+@Input          sCpuVAddrBase             The virtual base address of the
+                                          sparse allocation
+@Input          ui32AllocPageCount        The number of pages specified in
+                                          pai32AllocIndices
+@Input          pai32AllocIndices         The list of pages in the sparse
+                                          allocation that should be given
+                                          a CPU mapping. Pages are referenced
+                                          by their index within the sparse
+                                          allocation (e.g. in a 10 page
+                                          allocation, pages are denoted by
+                                          indices 0 to 9)
+@Input          ui32FreePageCount         The number of pages specified in
+                                          pai32FreeIndices
+@Input          pai32FreeIndices          The list of pages in the sparse
+                                          allocation that do not require a CPU
+                                          mapping.
+
+@Return         PVRSRV_OK if the page mappings were updated successfully, an
+                error code otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_CHANGE_SPARSE_MEM_CPU_MAP_FN)(PMR_IMPL_PRIVDATA pPriv,
+                      const PMR *psPMR,
+                      IMG_UINT64 sCpuVAddrBase,
+                      IMG_UINT32 ui32AllocPageCount,
+                      IMG_UINT32 *pai32AllocIndices,
+                      IMG_UINT32 ui32FreePageCount,
+                      IMG_UINT32 *pai32FreeIndices);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_MMAP_FN
+
+@Description    Called to map pages in the specified PMR.
+
+   Implementation of this callback is optional.
+   Where it is provided, it will be used in place of OSMMapPMRGeneric().
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+@Input          psPMR                     The PMR of the allocation to be
+                                          mapped
+@Input          pMMapData                 OS-specific data to describe how
+                                          mapping should be performed
+
+@Return         PVRSRV_OK if the mapping was successful, an error code
+                otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_MMAP_FN)(PMR_IMPL_PRIVDATA pPriv,
+                                    PMR *psPMR,
+                                    PMR_MMAP_DATA pMMapData);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_FINALIZE_FN
+
+@Description    Called to destroy the PMR.
+                This callback will be called only when all references to
+                the PMR have been dropped.
+                The PMR was created via a call to PhysmemNewRamBackedPMR()
+                and is destroyed via this callback.
+
+   Implementation of this callback is mandatory.
+
+@Input          pvPriv                    Private data (which was generated
+                                          by the PMR factory when PMR was
+                                          created)
+
+@Return         PVRSRV_OK if the PMR destruction was successful, an error
+                code otherwise.
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PFN_FINALIZE_FN)(PMR_IMPL_PRIVDATA pvPriv);
+
+#if 1
+struct _PMR_IMPL_FUNCTAB_ {
+#else
+typedef struct _PMR_IMPL_FUNCTAB_ {
+#endif
+    PFN_LOCK_PHYS_ADDRESSES_FN pfnLockPhysAddresses;
+    PFN_UNLOCK_PHYS_ADDRESSES_FN pfnUnlockPhysAddresses;
+
+    PFN_DEV_PHYS_ADDR_FN pfnDevPhysAddr;
+
+    PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN pfnAcquireKernelMappingData;
+    PFN_RELEASE_KERNEL_MAPPING_DATA_FN pfnReleaseKernelMappingData;
+
+#if defined (INTEGRITY_OS)
     /*
-     * Write up to uiBufSz bytes into the PMR.
-     * The pmr will be already locked.
+     * MapMemoryObject()/UnmapMemoryObject()
      *
-     * Overriding this is optional.  The default implementation will
-     * acquire a kernel virtual address with
-     * pfnAcquireKernelMappingData and OSMemCopy the data directly
-     *
-     * Note:
-     * This function callback is optional and unlike pfnReadBytes
-     * isn't required if pfnAcquireKernelMappingData isn't provided
+     * called to map/unmap memory objects in Integrity OS
      */
-    PVRSRV_ERROR (*pfnWriteBytes)(PMR_IMPL_PRIVDATA pvPriv,
-                                  IMG_DEVMEM_OFFSET_T uiOffset,
-                                  IMG_UINT8 *pcBuffer,
-                                  size_t uiBufSz,
-                                  size_t *puiNumBytes);
 
-    /* Mark the PMR as unpinned so that the OS or whatever is
-     * responsible for the PMR factory can reclaim the physical
-     * memory of it and use it for something else.
-     *
-     * Expected return values:
-     *     - PVRSRV_OK if unpin was successful.
-     *     - PVRSRV_ERROR_NOT_SUPPORTED if unpinning is not supported
-     *       in this PMR factory.
-     *     - ... a different error for all other problems.
-     */
-    PVRSRV_ERROR (*pfnUnpinMem)(PMR_IMPL_PRIVDATA pPriv);
+    PVRSRV_ERROR (*pfnMapMemoryObject)(PMR_IMPL_PRIVDATA pvPriv,
+    											IMG_HANDLE *phMemObj);
+    PVRSRV_ERROR (*pfnUnmapMemoryObject)(PMR_IMPL_PRIVDATA pvPriv);
+	
+#if defined(USING_HYPERVISOR)
+    IMG_HANDLE (*pfnGetPmr)(PMR_IMPL_PRIVDATA pvPriv, size_t ulOffset);
+#endif
+#endif
+    
+    PFN_READ_BYTES_FN pfnReadBytes;
+    PFN_WRITE_BYTES_FN pfnWriteBytes;
 
-    /* Repins the PMR and checks if the physical memory
-     * was lost, in that case it allocates new pages and returns
-     * an error to indicate what happened.
-     *
-     * Expected return values:
-     *     - PVRSRV_OK if pin was successful.
-     *     - PVRSRV_ERROR_PMR_NEW_MEMORY if pin was successful but
-     *       the content of the physical memory is lost.
-     *     - PVRSRV_ERROR_NOT_SUPPORTED if pinning is not supported
-     *       in this PMR factory.
-     *     - ... a different error for all other problems.
-     * */
-    PVRSRV_ERROR (*pfnPinMem)(PMR_IMPL_PRIVDATA pPriv,
-    							PMR_MAPPING_TABLE *psMappingTable);
+    PFN_UNPIN_MEM_FN pfnUnpinMem;
+    PFN_PIN_MEM_FN pfnPinMem;
 
-    PVRSRV_ERROR (*pfnChangeSparseMem)(PMR_IMPL_PRIVDATA pPriv,
-    								const PMR *psPMR,
-    								IMG_UINT32 ui32AllocPageCount,
-    								IMG_UINT32 *pai32AllocIndices,
-    								IMG_UINT32 ui32FreePageCount,
-    								IMG_UINT32 *pai32FreeIndices,
-    								IMG_UINT32	uiFlags,
-    								IMG_UINT32	*pui32Status);
+    PFN_CHANGE_SPARSE_MEM_FN pfnChangeSparseMem;
+    PFN_CHANGE_SPARSE_MEM_CPU_MAP_FN pfnChangeSparseMemCPUMap;
 
-    PVRSRV_ERROR (*pfnChangeSparseMemCPUMap)(PMR_IMPL_PRIVDATA pPriv,
-    											const PMR *psPMR,
-    											IMG_UINT64 sCpuVAddrBase,
-    											IMG_UINT32	ui32AllocPageCount,
-    											IMG_UINT32	*pai32AllocIndices,
-    											IMG_UINT32	ui32FreePageCount,
-    											IMG_UINT32	*pai32FreeIndices,
-    											IMG_UINT32	*pui32Status);
+    PFN_MMAP_FN pfnMMap;
 
-	/*
-	 * Maps the PMR into a user process address space.
-	 *
-	 * This callback is optional; However, it is strongly recommended
-	 * that an implementation is provided and that it performs any
-	 * necessary reference counting on the PMR. When this is not the
-	 * case a generic implementation is used instead.
-	 */
-	PVRSRV_ERROR (*pfnMMap)(PMR_IMPL_PRIVDATA pPriv,
-				const PMR *psPMR,
-				PMR_MMAP_DATA pMMapData);
-    /*
-     * Finalize()
-     *
-     * This callback will be called once when the last reference to
-     * the PMR has disappeared.
-     */
-    PVRSRV_ERROR (*pfnFinalize)(PMR_IMPL_PRIVDATA pvPriv);
-} PMR_IMPL_FUNCTAB;
+    PFN_FINALIZE_FN pfnFinalize;
+} ;
+typedef struct _PMR_IMPL_FUNCTAB_ PMR_IMPL_FUNCTAB;
 
-#endif /* of #ifndef _SRVSRV_PHYSMEM_PRIV_H_ */
+
+#endif /* of #ifndef _SRVSRV_PMR_IMPL_H_ */
diff --git a/drivers/staging/imgtec/rogue/pmr_os.c b/drivers/staging/imgtec/rogue/pmr_os.c
index 06c2ce3..381a412 100644
--- a/drivers/staging/imgtec/rogue/pmr_os.c
+++ b/drivers/staging/imgtec/rogue/pmr_os.c
@@ -43,17 +43,20 @@
 #include <asm/io.h>
 #include <asm/page.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#if defined(CONFIG_L4)
+#include <asm/api-l4env/api.h>
+#endif
 #include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+#include <linux/pfn_t.h>
+#include <linux/pfn.h>
+#endif
 
 #include "img_defs.h"
 #include "pvr_debug.h"
 #include "allocmem.h"
 #include "devicemem_server_utils.h"
-
-#if defined(SUPPORT_DRM)
-#include "pvr_drm.h"
-#endif
-
 #include "pmr.h"
 #include "pmr_os.h"
 
@@ -61,6 +64,8 @@
 #include "process_stats.h"
 #endif
 
+#include "kernel_compatibility.h"
+
 /*
  * x86_32:
  * Use vm_insert_page because remap_pfn_range has issues when mapping HIGHMEM
@@ -74,7 +79,7 @@
  * Other platforms:
  * Use remap_pfn_range by default because it does not issue a cache flush.
  * It is known that ARM32 benefits from this. When other platforms become
- * available it has to be investigated if this asumption holds for them as well.
+ * available it has to be investigated if this assumption holds for them as well.
  *
  * Since vm_insert_page does more precise memory accounting we have the build
  * flag PVR_MMAP_USE_VM_INSERT that forces its use. This is useful as a debug
@@ -105,7 +110,7 @@
 	 * locking down the physical addresses. */
 	PMRRefPMR(psPMR);
 
-	if (PMRLockSysPhysAddresses(psPMR, PAGE_SHIFT) != PVRSRV_OK)
+	if (PMRLockSysPhysAddresses(psPMR) != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Could not lock down physical addresses, aborting.", __func__));
 		PMRUnrefPMR(psPMR);
@@ -116,8 +121,6 @@
 {
 	PMR *psPMR = ps_vma->vm_private_data;
 
-	PMRLock();
-
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if	defined(PVRSRV_ENABLE_MEMORY_STATS)
 	{
@@ -137,8 +140,6 @@
 
 	PMRUnlockSysPhysAddresses(psPMR);
 	PMRUnrefPMR(psPMR);
-
-	PMRUnlock();
 }
 
 /*
@@ -155,8 +156,6 @@
 	PVRSRV_ERROR eError;
 	int iRetVal = -EINVAL;
 
-	PMRLock();
-
 	if (write)
 	{
 		eError = PMR_WriteBytes(psPMR,
@@ -174,8 +173,6 @@
 				       &uiBytesCopied);
 	}
 
-	PMRUnlock();
-
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Error from %s (%d)",
@@ -191,83 +188,175 @@
 	return iRetVal;
 }
 
-static struct vm_operations_struct gsMMapOps =
+static const struct vm_operations_struct gsMMapOps =
 {
 	.open = &MMapPMROpen,
 	.close = &MMapPMRClose,
 	.access = MMapVAccess,
 };
 
+static INLINE int _OSMMapPMR(PVRSRV_DEVICE_NODE *psDevNode,
+							struct vm_area_struct *ps_vma,
+							IMG_DEVMEM_OFFSET_T uiOffset,
+							IMG_CPU_PHYADDR *psCpuPAddr,
+							IMG_UINT32 uiLog2PageSize,
+							IMG_BOOL bUseVMInsertPage,
+							IMG_BOOL bUseMixedMap)
+{
+	IMG_INT32 iStatus;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+	pfn_t sPFN;
+#else
+	unsigned long uiPFN;
+#endif
+
+#if defined(CONFIG_L4)
+	IMG_CPU_VIRTADDR pvCpuVAddr;
+
+	/* Use L4LINUX function, removes per-arch code-path */
+	pvCpuVAddr = l4x_phys_to_virt(psCpuPAddr->uiAddr);
+	if (pvCpuVAddr == NULL)
+	{
+		return -1;
+	}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+	sPFN = phys_to_pfn_t((uintptr_t)pvCpuVAddr, 0);
+#else
+	uiPFN = ((uintptr_t) pvCpuVAddr) >> PAGE_SHIFT;
+#endif
+#else /* defined(CONFIG_L4) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+	sPFN = phys_to_pfn_t(psCpuPAddr->uiAddr, 0);
+#else
+	uiPFN = psCpuPAddr->uiAddr >> PAGE_SHIFT;
+	PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == psCpuPAddr->uiAddr);
+#endif
+#endif
+
+	/*
+	 * vm_insert_page() allows insertion of individual pages into user
+	 * VMA space _only_ if page is a order-zero allocated page
+	 */
+	if (bUseVMInsertPage)
+	{
+		if (bUseMixedMap)
+		{
+			/*
+			 * This path is just for debugging. It should be
+			 * equivalent to the remap_pfn_range() path.
+			 */
+			iStatus = vm_insert_mixed(ps_vma,
+									  ps_vma->vm_start + uiOffset,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+									  sPFN);
+#else
+									  uiPFN);
+#endif
+		}
+		else
+		{
+			/* Since kernel 3.7 this sets VM_MIXEDMAP internally */
+			iStatus = vm_insert_page(ps_vma,
+									 ps_vma->vm_start + uiOffset,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+									 pfn_t_to_page(sPFN));
+#else
+									 pfn_to_page(uiPFN));
+#endif
+		}
+	}
+	else
+	{
+		/*
+		   NOTE: Regarding absence of dma_mmap_coherent() in _OSMMapPMR()
+
+		   The current services mmap model maps in a PMR's full-length size
+		   into the user VMA & applies any user specified offset to the kernel
+		   returned zero-offset based VA in services client; this essentially
+		   means services server ignores ps_vma->vm_pgoff (this houses hPMR)
+		   during a mmap call.
+
+		   Furthermore, during a DMA/CMA memory allocation, multiple order-n
+		   pages are used to satisfy an allocation request due to DMA/CMA
+		   framework rounding-up allocation size to next power-of-two which
+		   can lead to wasted memory (so we don't allocate using single call).
+
+		   The combination of the above two issues mean that we cannot use the
+		   dma_mmap_coherent() for a number of reasons outlined below:
+
+		     - Services mmap semantics does not fit with dma_mmap_coherent()
+		       which requires proper ps_vma->vm_pgoff; seeing this houses a
+		       hPMR handle value, calls into dma_mmap_coherent() fails. This
+		       could be avoided by forcing ps_vma->vm_pgoff to zero but the
+		       ps_vma->vm_pgoff is applied to DMA bus address PFN and not
+		       user VMA which is always mapped at ps_vma->vm_start.
+
+		     - As multiple order-n pages are used for DMA/CMA allocations, a
+		       single dma_mmap_coherent() call with a vma->vm_pgoff set to
+		       zero cannot (maybe) be used because there is no guarantee that
+		       all of the multiple order-n pages in the PMR are physically
+		       contiguous from the first entry to the last. Whilst this is
+		       highly likely to be the case, there is no guarantee that it
+		       will be so we cannot depend on this being the case.
+
+		   The solution is to manually mmap DMA/CMA pages into user VMA
+		   using remap_pfn_range() directly. Furthermore, accounting is
+		   always compromised for DMA/CMA allocations.
+		*/
+		size_t uiNumContiguousBytes = 1ULL << uiLog2PageSize;
+
+		iStatus = remap_pfn_range(ps_vma,
+								  ps_vma->vm_start + uiOffset,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+								  pfn_t_to_pfn(sPFN),
+#else
+								  uiPFN,
+#endif
+								  uiNumContiguousBytes,
+								  ps_vma->vm_page_prot);
+	}
+
+	return iStatus;
+}
+
 PVRSRV_ERROR
 OSMMapPMRGeneric(PMR *psPMR, PMR_MMAP_DATA pOSMMapData)
 {
 	struct vm_area_struct *ps_vma = pOSMMapData;
+	PVRSRV_DEVICE_NODE *psDevNode = PMR_DeviceNode(psPMR);
 	PVRSRV_ERROR eError;
 	size_t uiLength;
+	IMG_INT32 iStatus;
 	IMG_DEVMEM_OFFSET_T uiOffset;
-	unsigned long uiPFN=0;
-	PMR_FLAGS_T ulPMRFlags;
 	IMG_UINT32 ui32CPUCacheFlags;
-	unsigned long ulNewFlags = 0;
 	pgprot_t sPageProt;
 	IMG_CPU_PHYADDR asCpuPAddr[PMR_MAX_TRANSLATION_STACK_ALLOC];
 	IMG_BOOL abValid[PMR_MAX_TRANSLATION_STACK_ALLOC];
-	IMG_UINT32 uiOffsetIdx, uiNumOfPFNs;
+	IMG_UINT32 uiOffsetIdx;
+	IMG_UINT32 uiNumOfPFNs;
+	IMG_UINT32 uiLog2PageSize;
 	IMG_CPU_PHYADDR *psCpuPAddr;
 	IMG_BOOL *pbValid;
-#if defined(PMR_OS_USE_VM_INSERT_PAGE)
-	IMG_BOOL bMixedMap = IMG_FALSE;
-#endif
+	IMG_BOOL bUseMixedMap = IMG_FALSE;
+	IMG_BOOL bUseVMInsertPage = IMG_FALSE;
 
-	eError = PMRLockSysPhysAddresses(psPMR, PAGE_SHIFT);
+	eError = PMRLockSysPhysAddresses(psPMR);
 	if (eError != PVRSRV_OK)
 	{
 		goto e0;
 	}
 
 	if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
-	    ((ps_vma->vm_flags & VM_SHARED) == 0))
+		((ps_vma->vm_flags & VM_SHARED) == 0))
 	{
 		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		goto e0;
 	}
 
-	/*
-	 * We ought to call PMR_Flags() here to check the permissions
-	 * against the requested mode, and possibly to set up the cache
-	 * control protflags
-	 */
-	ulPMRFlags = PMR_Flags(psPMR);
+	sPageProt = vm_get_page_prot(ps_vma->vm_flags);
 
-	ulNewFlags = ps_vma->vm_flags;
-#if 0
-	/* Discard user read/write request, we will pull these flags from the PMR */
-	ulNewFlags &= ~(VM_READ | VM_WRITE);
-
-	if (ulPMRFlags & PVRSRV_MEMALLOCFLAG_CPU_READABLE)
-	{
-		ulNewFlags |= VM_READ;
-	}
-	if (ulPMRFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE)
-	{
-		ulNewFlags |= VM_WRITE;
-	}
-#endif
-
-	ps_vma->vm_flags = ulNewFlags;
-
-#if defined (CONFIG_ARM64)
-	sPageProt = __pgprot_modify(ps_vma->vm_page_prot, 0, vm_get_page_prot(ulNewFlags));
-#elif defined(CONFIG_ARM)
-	sPageProt = __pgprot_modify(ps_vma->vm_page_prot, L_PTE_MT_MASK, vm_get_page_prot(ulNewFlags));
-#elif defined(CONFIG_X86)
-	sPageProt = pgprot_modify(ps_vma->vm_page_prot, vm_get_page_prot(ulNewFlags));
-#elif defined(CONFIG_METAG) || defined(CONFIG_MIPS)
-	sPageProt = vm_get_page_prot(ulNewFlags);
-#else
-#error Please add pgprot_modify equivalent for your system
-#endif
-	ui32CPUCacheFlags = DevmemCPUCacheMode(ulPMRFlags);
+	ui32CPUCacheFlags = DevmemCPUCacheMode(psDevNode, PMR_Flags(psPMR));
 	switch (ui32CPUCacheFlags)
 	{
 		case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
@@ -279,7 +368,16 @@
 				break;
 
 		case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+		{
+/* Do not set to write-combine for plato */
+#if !defined(PLATO_MEMORY_CONFIG)
+				PHYS_HEAP *psPhysHeap = PMR_PhysHeap(psPMR);
+
+				if (PhysHeapGetType(psPhysHeap) == PHYS_HEAP_TYPE_LMA)
+					sPageProt = pgprot_writecombine(sPageProt);
+#endif
 				break;
+		}
 
 		default:
 				eError = PVRSRV_ERROR_INVALID_PARAMS;
@@ -287,16 +385,10 @@
 	}
 	ps_vma->vm_page_prot = sPageProt;
 
-	uiLength = ps_vma->vm_end - ps_vma->vm_start;
-
 	ps_vma->vm_flags |= VM_IO;
 
-/* Don't include the mapping in core dumps */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
+	/* Don't include the mapping in core dumps */
 	ps_vma->vm_flags |= VM_DONTDUMP;
-#else
-	ps_vma->vm_flags |= VM_RESERVED;
-#endif
 
 	/*
 	 * Disable mremap because our nopage handler assumes all
@@ -307,11 +399,20 @@
 	/* Don't allow mapping to be inherited across a process fork */
 	ps_vma->vm_flags |= VM_DONTCOPY;
 
+	uiLength = ps_vma->vm_end - ps_vma->vm_start;
+
+	/* Is this mmap targeting non order-zero pages or does it use pfn mappings?
+	 * If yes, don't use vm_insert_page */
+	uiLog2PageSize = PMR_GetLog2Contiguity(psPMR);
+#if defined(PMR_OS_USE_VM_INSERT_PAGE)
+	bUseVMInsertPage = (uiLog2PageSize == PAGE_SHIFT) && (PMR_GetType(psPMR) != PMR_TYPE_EXTMEM);
+#endif
+
 	/* Can we use stack allocations */
-	uiNumOfPFNs = uiLength >> PAGE_SHIFT;
+	uiNumOfPFNs = uiLength >> uiLog2PageSize;
 	if (uiNumOfPFNs > PMR_MAX_TRANSLATION_STACK_ALLOC)
 	{
-		psCpuPAddr = OSAllocMem(uiNumOfPFNs * sizeof(IMG_CPU_PHYADDR));
+		psCpuPAddr = OSAllocMem(uiNumOfPFNs * sizeof(*psCpuPAddr));
 		if (psCpuPAddr == NULL)
 		{
 			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -319,7 +420,7 @@
 		}
 
 		/* Should allocation fail, clean-up here before exiting */
-		pbValid = OSAllocMem(uiNumOfPFNs * sizeof(IMG_BOOL));
+		pbValid = OSAllocMem(uiNumOfPFNs * sizeof(*pbValid));
 		if (pbValid == NULL)
 		{
 			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -335,7 +436,7 @@
 
 	/* Obtain map range pfns */
 	eError = PMR_CpuPhysAddr(psPMR,
-				 PAGE_SHIFT,
+				 uiLog2PageSize,
 				 uiNumOfPFNs,
 				 0,
 				 psCpuPAddr,
@@ -345,43 +446,55 @@
 		goto e3;
 	}
 
-#if defined(PMR_OS_USE_VM_INSERT_PAGE)
 	/*
 	 * Scan the map range for pfns without struct page* handling. If
-	 * we find one, this is a mixed map, and we can't use
-	 * vm_insert_page()
+	 * we find one, this is a mixed map, and we can't use vm_insert_page()
+	 * NOTE: vm_insert_page() allows insertion of individual pages into user
+	 * VMA space _only_ if said page is an order-zero allocated page.
 	 */
-	for (uiOffsetIdx = 0; uiOffsetIdx < uiNumOfPFNs; ++uiOffsetIdx)
+	if (bUseVMInsertPage)
 	{
-		if (pbValid[uiOffsetIdx])
-		{
-			uiPFN = psCpuPAddr[uiOffsetIdx].uiAddr >> PAGE_SHIFT;
-			PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == psCpuPAddr[uiOffsetIdx].uiAddr);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+		pfn_t sPFN;
+#else
+		unsigned long uiPFN;
+#endif
 
-			if (!pfn_valid(uiPFN) || page_count(pfn_to_page(uiPFN)) == 0)
+		for (uiOffsetIdx = 0; uiOffsetIdx < uiNumOfPFNs; ++uiOffsetIdx)
+		{
+			if (pbValid[uiOffsetIdx])
 			{
-				bMixedMap = IMG_TRUE;
-				break;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
+				sPFN = phys_to_pfn_t(psCpuPAddr[uiOffsetIdx].uiAddr, 0);
+
+				if (!pfn_t_valid(sPFN) || page_count(pfn_t_to_page(sPFN)) == 0)
+#else
+				uiPFN = psCpuPAddr[uiOffsetIdx].uiAddr >> PAGE_SHIFT;
+				PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == psCpuPAddr[uiOffsetIdx].uiAddr);
+
+				if (!pfn_valid(uiPFN) || page_count(pfn_to_page(uiPFN)) == 0)
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
+				{
+					bUseMixedMap = IMG_TRUE;
+					break;
+				}
 			}
 		}
+
+		if (bUseMixedMap)
+		{
+			ps_vma->vm_flags |= VM_MIXEDMAP;
+		}
+	}
+	else
+	{
+		ps_vma->vm_flags |= VM_PFNMAP;
 	}
 
-	if (bMixedMap)
+	/* For each PMR page-size contiguous bytes, map page(s) into user VMA */
+	for (uiOffset = 0; uiOffset < uiLength; uiOffset += 1ULL<<uiLog2PageSize)
 	{
-		ps_vma->vm_flags |= VM_MIXEDMAP;
-	}
-#else
-	ps_vma->vm_flags |= VM_PFNMAP;
-#endif /* PMR_OS_USE_VM_INSERT_PAGE */
-
-	for (uiOffset = 0; uiOffset < uiLength; uiOffset += 1ULL<<PAGE_SHIFT)
-	{
-		size_t uiNumContiguousBytes;
-		IMG_INT32 iStatus;
-
-		uiNumContiguousBytes = 1ULL<<PAGE_SHIFT;
-		uiOffsetIdx = uiOffset >> PAGE_SHIFT;
-
+		uiOffsetIdx = uiOffset >> uiLog2PageSize;
 		/*
 		 * Only map in pages that are valid, any that aren't will be
 		 * picked up by the nopage handler which will return a zeroed
@@ -389,57 +502,34 @@
 		 */
 		if (pbValid[uiOffsetIdx])
 		{
-			uiPFN = psCpuPAddr[uiOffsetIdx].uiAddr >> PAGE_SHIFT;
-			PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == psCpuPAddr[uiOffsetIdx].uiAddr);
-
-#if defined(PMR_OS_USE_VM_INSERT_PAGE)
-			if (bMixedMap)
+			iStatus = _OSMMapPMR(psDevNode,
+								 ps_vma,
+								 uiOffset,
+								 &psCpuPAddr[uiOffsetIdx],
+								 uiLog2PageSize,
+								 bUseVMInsertPage,
+								 bUseMixedMap);
+			if (iStatus)
 			{
-				/*
-				 * This path is just for debugging. It should be
-				 * equivalent to the remap_pfn_range() path.
-				 */
-				iStatus = vm_insert_mixed(ps_vma,
-							  ps_vma->vm_start + uiOffset,
-							  uiPFN);
-			}
-			else
-			{
-				/* Since kernel 3.7 this sets VM_MIXEDMAP internally */
-				iStatus = vm_insert_page(ps_vma,
-							 ps_vma->vm_start + uiOffset,
-							 pfn_to_page(uiPFN));
-			}
-#else
-			iStatus = remap_pfn_range(ps_vma,
-						  ps_vma->vm_start + uiOffset,
-						  uiPFN,
-						  uiNumContiguousBytes,
-						  ps_vma->vm_page_prot);
-#endif  /* PMR_OS_USE_VM_INSERT_PAGE */
-
-			PVR_ASSERT(iStatus == 0);
-			if(iStatus)
-			{
-				/*
-				 * N.B. not the right error code but it doesn't
-				 * get propagated anyway :(
-				 */
-				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				/* Failure error code doesn't get propagated */
+				eError = PVRSRV_ERROR_PMR_CPU_PAGE_MAP_FAILED;
+				PVR_ASSERT(0);
 				goto e3;
 			}
 		}
 #if defined(PVRSRV_ENABLE_PROCESS_STATS) && defined(PVRSRV_ENABLE_MEMORY_STATS)
 		PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES,
-					     (void*)(uintptr_t)(ps_vma->vm_start + uiOffset),
-					     psCpuPAddr[uiOffsetIdx],
-					     PAGE_SIZE,
-					     NULL);
+									(void*)(uintptr_t)(ps_vma->vm_start + uiOffset),
+									psCpuPAddr[uiOffsetIdx],
+									1<<uiLog2PageSize,
+									NULL);
 #endif
 	}
+
 #if defined(PVRSRV_ENABLE_PROCESS_STATS) && !defined(PVRSRV_ENABLE_MEMORY_STATS)
-		PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES, uiNumOfPFNs * PAGE_SIZE);
+	PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES, uiNumOfPFNs * PAGE_SIZE);
 #endif
+
 	if (psCpuPAddr != asCpuPAddr)
 	{
 		OSFreeMem(psCpuPAddr);
diff --git a/drivers/staging/imgtec/rogue/pmr_os.h b/drivers/staging/imgtec/rogue/pmr_os.h
index c5f90ed..0dfbd49 100644
--- a/drivers/staging/imgtec/rogue/pmr_os.h
+++ b/drivers/staging/imgtec/rogue/pmr_os.h
@@ -46,6 +46,16 @@
 
 #include "pmr_impl.h"
 
+/*************************************************************************/ /*!
+@Function       OSMMapPMRGeneric
+@Description    Implements a generic PMR mapping function, which is used
+                to CPU map a PMR where the PMR does not have a mapping
+                function defined by the creating PMR factory.
+@Input          psPMR               the PMR to be mapped
+@Output         pOSMMapData         pointer to any private data
+                                    needed by the generic mapping function
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
 PVRSRV_ERROR
 OSMMapPMRGeneric(PMR *psPMR, PMR_MMAP_DATA pOSMMapData);
 
diff --git a/drivers/staging/imgtec/rogue/power.c b/drivers/staging/imgtec/rogue/power.c
index ed37460..af89076 100644
--- a/drivers/staging/imgtec/rogue/power.c
+++ b/drivers/staging/imgtec/rogue/power.c
@@ -52,6 +52,24 @@
 #include "process_stats.h"
 #endif
 
+struct _PVRSRV_POWER_DEV_TAG_
+{
+	PFN_PRE_POWER					pfnDevicePrePower;
+	PFN_POST_POWER					pfnDevicePostPower;
+	PFN_SYS_DEV_PRE_POWER			pfnSystemPrePower;
+	PFN_SYS_DEV_POST_POWER			pfnSystemPostPower;
+	PFN_PRE_CLOCKSPEED_CHANGE		pfnPreClockSpeedChange;
+	PFN_POST_CLOCKSPEED_CHANGE		pfnPostClockSpeedChange;
+	PFN_FORCED_IDLE_REQUEST			pfnForcedIdleRequest;
+	PFN_FORCED_IDLE_CANCEL_REQUEST	pfnForcedIdleCancelRequest;
+	PFN_DUST_COUNT_REQUEST			pfnDustCountRequest;
+	IMG_HANDLE						hSysData;
+	IMG_HANDLE						hDevCookie;
+	PVRSRV_DEV_POWER_STATE 			eDefaultPowerState;
+	PVRSRV_DEV_POWER_STATE 			eCurrentPowerState;
+};
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 static IMG_BOOL gbInitServerRunning = IMG_FALSE;
 static IMG_BOOL gbInitServerRan = IMG_FALSE;
 static IMG_BOOL gbInitSuccessful = IMG_FALSE;
@@ -86,7 +104,7 @@
 			break;
 		default:
 			PVR_DPF((PVR_DBG_ERROR,
-				"PVRSRVSetInitServerState : Unknown state %x", eInitServerState));
+					 "%s: Unknown state %x", __func__, eInitServerState));
 			return PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE;
 	}
 
@@ -123,12 +141,13 @@
 			break;
 		default:
 			PVR_DPF((PVR_DBG_ERROR,
-				"PVRSRVGetInitServerState : Unknown state %x", eInitServerState));
+					 "%s: Unknown state %x", __func__, eInitServerState));
 			bReturnVal = IMG_FALSE;
 	}
 
 	return bReturnVal;
 }
+#endif /* !defined(SUPPORT_KERNEL_SRVINIT) */
 
 /*!
 ******************************************************************************
@@ -160,23 +179,19 @@
 
 ******************************************************************************/
 IMG_EXPORT
-PVRSRV_ERROR PVRSRVPowerLock()
+PVRSRV_ERROR PVRSRVPowerLock(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	PVRSRV_ERROR	eError;
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
+	OSLockAcquire(psDeviceNode->hPowerLock);
 
 	/* Only allow to take powerlock when the system power is on */
-	if (_IsSystemStatePowered(psPVRSRVData->eCurrentPowerState))
+	if (_IsSystemStatePowered(psDeviceNode->eCurrentSysPowerState))
 	{
-		OSLockAcquire(psPVRSRVData->hPowerLock);
-		eError = PVRSRV_OK;
-	}
-	else
-	{
-		eError = PVRSRV_ERROR_RETRY;
+		return PVRSRV_OK;
 	}
 
-	return eError;
+	OSLockRelease(psDeviceNode->hPowerLock);
+
+	return PVRSRV_ERROR_RETRY;
 }
 
 /*!
@@ -191,10 +206,9 @@
 
 ******************************************************************************/
 IMG_EXPORT
-void PVRSRVForcedPowerLock()
+void PVRSRVForcedPowerLock(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
-	OSLockAcquire(psPVRSRVData->hPowerLock);
+	OSLockAcquire(psDeviceNode->hPowerLock);
 }
 
 
@@ -209,11 +223,9 @@
 
 ******************************************************************************/
 IMG_EXPORT
-void PVRSRVPowerUnlock()
+void PVRSRVPowerUnlock(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	PVRSRV_DATA	*psPVRSRVData = PVRSRVGetPVRSRVData();
-
-	OSLockRelease(psPVRSRVData->hPowerLock);
+	OSLockRelease(psDeviceNode->hPowerLock);
 }
 IMG_EXPORT
 IMG_BOOL PVRSRVDeviceIsDefaultStateOFF(PVRSRV_POWER_DEV *psPowerDevice)
@@ -224,148 +236,32 @@
 /*!
 ******************************************************************************
 
- @Function	PVRSRVDevicePrePowerStateKM_AnyVaCb
+ @Function      PVRSRVSetDeviceDefaultPowerState
 
- @Description
+ @Description   Set the default device power state to eNewPowerState
 
- Perform device-specific processing required before a power transition
+ @Input		    psDeviceNode : Device node
+ @Input         eNewPowerState : New power state
 
- @Input		psPowerDevice : the device
- @Input		va : variable argument list with:
- 				bAllDevices : IMG_TRUE - All devices
- 						  	  IMG_FALSE - Use ui32DeviceIndex
-				ui32DeviceIndex : device index
-				eNewPowerState : New power state
-
- @Return	PVRSRV_ERROR
+ @Return        PVRSRV_ERROR
 
 ******************************************************************************/
-static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+PVRSRV_ERROR PVRSRVSetDeviceDefaultPowerState(const PVRSRV_DEVICE_NODE *psDeviceNode,
+					PVRSRV_DEV_POWER_STATE eNewPowerState)
 {
-	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
-	PVRSRV_ERROR			eError;
+	PVRSRV_POWER_DEV *psPowerDevice;
 
-	/*Variable Argument variables*/
-	IMG_BOOL				bAllDevices;
-	IMG_UINT32				ui32DeviceIndex;
-	PVRSRV_DEV_POWER_STATE	eNewPowerState;
-	IMG_BOOL				bForced;
-	IMG_UINT64				ui64SysTimer1 = 0, ui64SysTimer2 = 0;
-	IMG_UINT64				ui64DevTimer1 = 0, ui64DevTimer2 = 0;
-
-	/*WARNING! if types were not aligned to 4 bytes, this could be dangerous!!!*/
-	bAllDevices = va_arg(va, IMG_BOOL);
-	ui32DeviceIndex = va_arg(va, IMG_UINT32);
-	eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
-	bForced = va_arg(va, IMG_BOOL);
-
-	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	psPowerDevice = psDeviceNode->psPowerDev;
+	if (psPowerDevice == NULL)
 	{
-		eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
-							psPowerDevice->eDefaultPowerState : eNewPowerState;
-
-		if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
-		{
-			if (psPowerDevice->pfnDevicePrePower != NULL)
-			{
-				/* Call the device's power callback. */
-
-				ui64DevTimer1 = OSClockns64();
-
-				eError = psPowerDevice->pfnDevicePrePower(psPowerDevice->hDevCookie,
-															eNewDevicePowerState,
-															psPowerDevice->eCurrentPowerState,
-															bForced);
-
-				ui64DevTimer2 = OSClockns64();
-
-				if (eError != PVRSRV_OK)
-				{
-					return eError;
-				}
-			}
-
-			/* Do any required system-layer processing. */
-			if (psPowerDevice->pfnSystemPrePower != NULL)
-			{
-
-				ui64SysTimer1 = OSClockns64();
-
-				eError = psPowerDevice->pfnSystemPrePower(eNewDevicePowerState,
-														  psPowerDevice->eCurrentPowerState,
-														  bForced);
-
-				ui64SysTimer2 = OSClockns64();
-
-				if (eError != PVRSRV_OK)
-				{
-					return eError;
-				}
-			}
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-			InsertPowerTimeStatistic(ui64SysTimer1, ui64SysTimer2,
-			                         ui64DevTimer1, ui64DevTimer2,
-			                         bForced,
-			                         eNewDevicePowerState == PVRSRV_DEV_POWER_STATE_ON,
-			                         IMG_TRUE);
-#endif
-
-		}
+		return PVRSRV_ERROR_INVALID_DEVICE;
 	}
 
-	return  PVRSRV_OK;
+	psPowerDevice->eDefaultPowerState = eNewPowerState;
+
+	return PVRSRV_OK;
 }
-/*!
-******************************************************************************
 
- @Function	PVRSRVDeviceIdleKM_AnyVaCb
-
- @Description
-
- Perform device-specific processing required to force the device idle.
-
- @Input		psPowerDevice : the device
- @Input		va : variable argument list with:
-				bAllDevices : 	IMG_TRUE - All devices
-						IMG_FALSE - Use ui32DeviceIndex
-				ui32DeviceIndex : device index
-				pfnCheckIdleReq : Filter function used to determine whether a forced idle is required for the device
-				bDeviceOffPermitted :	IMG_TRUE if the transition should not fail if device off
-							IMG_FALSE if the transition should fail if device off
-
- @Return	PVRSRV_ERROR
-
-******************************************************************************/
-static PVRSRV_ERROR PVRSRVDeviceIdleKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
-{
-	PVRSRV_ERROR			eError = PVRSRV_OK;
-
-	/*Variable Argument variables*/
-	IMG_BOOL				bAllDevices;
-	IMG_UINT32				ui32DeviceIndex;
-	PFN_SYS_DEV_IS_DEFAULT_STATE_OFF	pfnIsDefaultStateOff;
-	IMG_BOOL				bDeviceOffPermitted;
-
-	/*WARNING! if types were not aligned to 4 bytes, this could be dangerous!!!*/
-	bAllDevices = va_arg(va, IMG_BOOL);
-	ui32DeviceIndex = va_arg(va, IMG_UINT32);
-	pfnIsDefaultStateOff = va_arg(va, PFN_SYS_DEV_IS_DEFAULT_STATE_OFF);
-	bDeviceOffPermitted = va_arg(va, IMG_BOOL);
-
-	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
-	{
-		if (psPowerDevice->pfnForcedIdleRequest != NULL)
-		{
-			if ((pfnIsDefaultStateOff == NULL) || pfnIsDefaultStateOff(psPowerDevice))
-			{
-				eError = psPowerDevice->pfnForcedIdleRequest(psPowerDevice->hDevCookie, bDeviceOffPermitted);
-			}
-		}
-	}
-
-	return eError;
-}
 /*!
 ******************************************************************************
 
@@ -375,9 +271,7 @@
 
  Perform device-specific processing required to force the device idle.
 
- @Input		bAllDevices : 	IMG_TRUE - All devices
-				IMG_FALSE - Use ui32DeviceIndex
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
  @Input		pfnCheckIdleReq : Filter function used to determine whether a forced idle is required for the device
  @Input		bDeviceOffPermitted :	IMG_TRUE if the transition should not fail if device off
 					IMG_FALSE if the transition should fail if device off
@@ -386,62 +280,22 @@
 
 ******************************************************************************/
 IMG_EXPORT
-PVRSRV_ERROR PVRSRVDeviceIdleRequestKM(IMG_BOOL					bAllDevices,
-					IMG_UINT32				ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDeviceIdleRequestKM(PVRSRV_DEVICE_NODE *psDeviceNode,
 					PFN_SYS_DEV_IS_DEFAULT_STATE_OFF	pfnIsDefaultStateOff,
 					IMG_BOOL				bDeviceOffPermitted)
 {
-	PVRSRV_ERROR		eError;
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
+	PVRSRV_POWER_DEV *psPowerDev = psDeviceNode->psPowerDev;
 
-	/* Loop through the power devices. */
-	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList,
-								&PVRSRVDeviceIdleKM_AnyVaCb,
-								bAllDevices,
-								ui32DeviceIndex,
-								pfnIsDefaultStateOff,
-								bDeviceOffPermitted);
-
-	return eError;
-}
-/*!
-******************************************************************************
-
- @Function	PVRSRVDeviceIdleCancelKM_AnyVaCb
-
- @Description
-
- Perform device-specific processing required before a power transition
-
- @Input		psPowerDevice : the device
- @Input		va : variable argument list with:
-				bAllDevices : 	IMG_TRUE - All devices
-						IMG_FALSE - Use ui32DeviceIndex
-				ui32DeviceIndex : device index
-
- @Return	PVRSRV_ERROR
-
-******************************************************************************/
-static PVRSRV_ERROR PVRSRVDeviceIdleCancelKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
-{
-	/*Variable Argument variables*/
-	PVRSRV_ERROR		eError = PVRSRV_OK;
-	IMG_BOOL		bAllDevices;
-	IMG_UINT32		ui32DeviceIndex;
-
-	/*WARNING! if types were not aligned to 4 bytes, this could be dangerous!!!*/
-	bAllDevices = va_arg(va, IMG_BOOL);
-	ui32DeviceIndex = va_arg(va, IMG_UINT32);
-
-	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	if (psPowerDev && psPowerDev->pfnForcedIdleRequest)
 	{
-		if (psPowerDevice->pfnForcedIdleCancelRequest != NULL)
+		if (!pfnIsDefaultStateOff || pfnIsDefaultStateOff(psPowerDev))
 		{
-			eError = psPowerDevice->pfnForcedIdleCancelRequest(psPowerDevice->hDevCookie);
+			return psPowerDev->pfnForcedIdleRequest(psPowerDev->hDevCookie,
+													bDeviceOffPermitted);
 		}
 	}
 
-	return eError;
+	return PVRSRV_OK;
 }
 /*!
 ******************************************************************************
@@ -452,27 +306,22 @@
 
  Perform device-specific processing required to cancel the forced idle state on the device, returning to normal operation.
 
- @Input		bAllDevices : 	IMG_TRUE - All devices
-				IMG_FALSE - Use ui32DeviceIndex
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
 
  @Return	PVRSRV_ERROR
 
 ******************************************************************************/
 IMG_EXPORT
-PVRSRV_ERROR PVRSRVDeviceIdleCancelRequestKM(IMG_BOOL			bAllDevices,
-						IMG_UINT32		ui32DeviceIndex)
+PVRSRV_ERROR PVRSRVDeviceIdleCancelRequestKM(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	PVRSRV_ERROR		eError;
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
+	PVRSRV_POWER_DEV *psPowerDev = psDeviceNode->psPowerDev;
 
-	/* Loop through the power devices. */
-	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList,
-					&PVRSRVDeviceIdleCancelKM_AnyVaCb,
-					bAllDevices,
-					ui32DeviceIndex);
+	if (psPowerDev && psPowerDev->pfnForcedIdleCancelRequest)
+	{
+		return psPowerDev->pfnForcedIdleCancelRequest(psPowerDev->hDevCookie);
+	}
 
-	return eError;
+	return PVRSRV_OK;
 }
 /*!
 ******************************************************************************
@@ -483,9 +332,7 @@
 
  Perform device-specific processing required before a power transition
 
- @Input		bAllDevices : IMG_TRUE - All devices
- 						  IMG_FALSE - Use ui32DeviceIndex
- @Input		ui32DeviceIndex : device index
+ @Input		psPowerDevice : Power device
  @Input		eNewPowerState : New power state
  @Input		bForced : TRUE if the transition should not fail (e.g. OS request)
 
@@ -493,119 +340,58 @@
 
 ******************************************************************************/
 static
-PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL				bAllDevices,
-										 IMG_UINT32				ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV		*psPowerDevice,
 										 PVRSRV_DEV_POWER_STATE	eNewPowerState,
 										 IMG_BOOL				bForced)
 {
-	PVRSRV_ERROR		eError;
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
+	IMG_UINT64 ui64SysTimer1 = 0;
+	IMG_UINT64 ui64SysTimer2 = 0;
+	IMG_UINT64 ui64DevTimer1 = 0;
+	IMG_UINT64 ui64DevTimer2 = 0;
+	PVRSRV_ERROR eError;
 
-	/* Loop through the power devices. */
-	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList,
-														&PVRSRVDevicePrePowerStateKM_AnyVaCb,
-														bAllDevices,
-														ui32DeviceIndex,
-														eNewPowerState,
-														bForced);
+	PVR_ASSERT(eNewPowerState != PVRSRV_DEV_POWER_STATE_DEFAULT);
 
-	return eError;
-}
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVDevicePostPowerStateKM_AnyVaCb
-
- @Description
-
- Perform device-specific processing required after a power transition
-
- @Input		psPowerDevice : the device
- @Input		va : variable argument list with:
- 				bAllDevices : IMG_TRUE - All devices
- 						  	  IMG_FALSE - Use ui32DeviceIndex
-				ui32DeviceIndex : device index
-				eNewPowerState : New power state
-
- @Return	PVRSRV_ERROR
-
-******************************************************************************/
-static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
-{
-	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
-	PVRSRV_ERROR			eError;
-
-	/*Variable Argument variables*/
-	IMG_BOOL				bAllDevices;
-	IMG_UINT32				ui32DeviceIndex;
-	PVRSRV_DEV_POWER_STATE	eNewPowerState;
-	IMG_BOOL				bForced;
-	IMG_UINT64				ui64SysTimer1 = 0, ui64SysTimer2 = 0;
-	IMG_UINT64				ui64DevTimer1 = 0, ui64DevTimer2 = 0;
-
-	/*WARNING! if types were not aligned to 4 bytes, this could be dangerous!!!*/
-	bAllDevices = va_arg(va, IMG_BOOL);
-	ui32DeviceIndex = va_arg(va, IMG_UINT32);
-	eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
-	bForced = va_arg(va, IMG_BOOL);
-
-	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	if (psPowerDevice->pfnDevicePrePower != NULL)
 	{
-		eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
-								psPowerDevice->eDefaultPowerState : eNewPowerState;
+		/* Call the device's power callback. */
+		ui64DevTimer1 = OSClockns64();
+		eError = psPowerDevice->pfnDevicePrePower(psPowerDevice->hDevCookie,
+												  eNewPowerState,
+												  psPowerDevice->eCurrentPowerState,
+												  bForced);
+		ui64DevTimer2 = OSClockns64();
 
-		if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+		if (eError != PVRSRV_OK)
 		{
-			/* Do any required system-layer processing. */
-			if (psPowerDevice->pfnSystemPostPower != NULL)
-			{
-
-				ui64SysTimer1 = OSClockns64();
-
-				eError = psPowerDevice->pfnSystemPostPower(eNewDevicePowerState,
-														   psPowerDevice->eCurrentPowerState,
-														   bForced);
-
-				ui64SysTimer2 = OSClockns64();
-
-				if (eError != PVRSRV_OK)
-				{
-					return eError;
-				}
-			}
-
-			if (psPowerDevice->pfnDevicePostPower != NULL)
-			{
-				/* Call the device's power callback. */
-
-				ui64DevTimer1 = OSClockns64();
-
-				eError = psPowerDevice->pfnDevicePostPower(psPowerDevice->hDevCookie,
-														   eNewDevicePowerState,
-														   psPowerDevice->eCurrentPowerState,
-														   bForced);
-
-				ui64DevTimer2 = OSClockns64();
-
-				if (eError != PVRSRV_OK)
-				{
-					return eError;
-				}
-			}
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-			InsertPowerTimeStatistic(ui64SysTimer1, ui64SysTimer2,
-			                         ui64DevTimer1, ui64DevTimer2,
-			                         bForced,
-			                         eNewDevicePowerState == PVRSRV_DEV_POWER_STATE_ON,
-			                         IMG_FALSE);
-#endif
-
-			psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+			return eError;
 		}
 	}
 
+	/* Do any required system-layer processing. */
+	if (psPowerDevice->pfnSystemPrePower != NULL)
+	{
+		ui64SysTimer1 = OSClockns64();
+		eError = psPowerDevice->pfnSystemPrePower(psPowerDevice->hSysData,
+												  eNewPowerState,
+												  psPowerDevice->eCurrentPowerState,
+												  bForced);
+		ui64SysTimer2 = OSClockns64();
+
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+	InsertPowerTimeStatistic(ui64SysTimer1, ui64SysTimer2,
+							 ui64DevTimer1, ui64DevTimer2,
+							 bForced,
+							 eNewPowerState == PVRSRV_DEV_POWER_STATE_ON,
+							 IMG_TRUE);
+#endif
+
 	return PVRSRV_OK;
 }
 
@@ -618,35 +404,70 @@
 
  Perform device-specific processing required after a power transition
 
- @Input		bAllDevices : IMG_TRUE - All devices
- 						  IMG_FALSE - Use ui32DeviceIndex
- @Input		ui32DeviceIndex : device index
+ @Input		psPowerDevice : Power device
  @Input		eNewPowerState : New power state
+ @Input		bForced : TRUE if the transition should not fail (e.g. OS request)
 
  @Return	PVRSRV_ERROR
 
 ******************************************************************************/
 static
-PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL					bAllDevices,
-										  IMG_UINT32				ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(PVRSRV_POWER_DEV			*psPowerDevice,
 										  PVRSRV_DEV_POWER_STATE	eNewPowerState,
 										  IMG_BOOL					bForced)
 {
-	PVRSRV_ERROR		eError;
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
+	IMG_UINT64 ui64SysTimer1 = 0;
+	IMG_UINT64 ui64SysTimer2 = 0;
+	IMG_UINT64 ui64DevTimer1 = 0;
+	IMG_UINT64 ui64DevTimer2 = 0;
+	PVRSRV_ERROR eError;
 
-	/* Loop through the power devices. */
-	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList,
-														&PVRSRVDevicePostPowerStateKM_AnyVaCb,
-														bAllDevices,
-														ui32DeviceIndex,
-														eNewPowerState,
-														bForced);
+	PVR_ASSERT(eNewPowerState != PVRSRV_DEV_POWER_STATE_DEFAULT);
 
-	return eError;
+	/* Do any required system-layer processing. */
+	if (psPowerDevice->pfnSystemPostPower != NULL)
+	{
+		ui64SysTimer1 = OSClockns64();
+		eError = psPowerDevice->pfnSystemPostPower(psPowerDevice->hSysData,
+												   eNewPowerState,
+												   psPowerDevice->eCurrentPowerState,
+												   bForced);
+		ui64SysTimer2 = OSClockns64();
+
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	if (psPowerDevice->pfnDevicePostPower != NULL)
+	{
+		/* Call the device's power callback. */
+		ui64DevTimer1 = OSClockns64();
+		eError = psPowerDevice->pfnDevicePostPower(psPowerDevice->hDevCookie,
+												   eNewPowerState,
+												   psPowerDevice->eCurrentPowerState,
+												   bForced);
+		ui64DevTimer2 = OSClockns64();
+
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+	InsertPowerTimeStatistic(ui64SysTimer1, ui64SysTimer2,
+							 ui64DevTimer1, ui64DevTimer2,
+							 bForced,
+							 eNewPowerState == PVRSRV_DEV_POWER_STATE_ON,
+							 IMG_FALSE);
+#endif
+	psPowerDevice->eCurrentPowerState = eNewPowerState;
+
+	return PVRSRV_OK;
 }
 
-
 /*!
 ******************************************************************************
 
@@ -654,7 +475,7 @@
 
  @Description	Set the Device into a new state
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
  @Input		eNewPowerState : New power state
  @Input		bForced : TRUE if the transition should not fail (e.g. OS request)
 
@@ -662,84 +483,92 @@
 
 ******************************************************************************/
 IMG_EXPORT
-PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(PVRSRV_DEVICE_NODE		*psDeviceNode,
 										 PVRSRV_DEV_POWER_STATE	eNewPowerState,
 										 IMG_BOOL				bForced)
 {
 	PVRSRV_ERROR	eError;
 	PVRSRV_DATA*    psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_DEV_POWER_STATE eOldPowerState;
+	PVRSRV_POWER_DEV *psPowerDevice;
 
-	if (PVRSRV_SYS_POWER_STATE_ON != psPVRSRVData->eCurrentPowerState)
+	psPowerDevice = psDeviceNode->psPowerDev;
+	if (!psPowerDevice)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetDevicePowerStateKM: System power state is not ON"));
-		return PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED;
+		return PVRSRV_OK;
 	}
 
-	eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eOldPowerState);
-	if (eError != PVRSRV_OK)
+	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
 	{
-		PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM: Couldn't read power state."));
-		eOldPowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+		eNewPowerState = psPowerDevice->eDefaultPowerState;
 	}
 
-	eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced);
-	if(eError != PVRSRV_OK)
+	if (psPowerDevice->eCurrentPowerState != eNewPowerState)
 	{
-		goto Exit;
-	}
-
-	eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced);
-
-	/* Signal Device Watchdog Thread about power mode change. */
-	if (eOldPowerState != eNewPowerState && eNewPowerState == PVRSRV_DEV_POWER_STATE_ON)
-	{
-		psPVRSRVData->ui32DevicesWatchdogPwrTrans++;
-
-		if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT)
+		eError = PVRSRVDevicePrePowerStateKM(psPowerDevice,
+											 eNewPowerState,
+											 bForced);
+		if (eError != PVRSRV_OK)
 		{
-			if (psPVRSRVData->hDevicesWatchdogEvObj)
+			goto ErrorExit;
+		}
+
+		eError = PVRSRVDevicePostPowerStateKM(psPowerDevice,
+											  eNewPowerState,
+											  bForced);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+
+		/* Signal Device Watchdog Thread about power mode change. */
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_ON)
+		{
+			psPVRSRVData->ui32DevicesWatchdogPwrTrans++;
+
+			if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT)
 			{
-				eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
-				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+				if (psPVRSRVData->hDevicesWatchdogEvObj)
+				{
+					eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
+					PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+				}
 			}
 		}
 	}
 
-Exit:
+	return PVRSRV_OK;
+
+ErrorExit:
 
 	if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
 	{
 		PVR_DPF((PVR_DBG_MESSAGE,
-				"PVRSRVSetDevicePowerStateKM : Transition to %d was denied, Forced=%d", eNewPowerState, bForced));
+				 "%s: Transition to %d was denied, Forced=%d",
+				 __func__, eNewPowerState, bForced));
 	}
 	else if(eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_WARNING,
-				"PVRSRVSetDevicePowerStateKM : Transition to %d FAILED (%s)", eNewPowerState, PVRSRVGetErrorStringKM(eError)));
+				 "%s: Transition to %d FAILED (%s)",
+				 __func__, eNewPowerState, PVRSRVGetErrorStringKM(eError)));
 	}
 	
 	return eError;
 }
 
-/*!
-******************************************************************************
-
- @Function	PVRSRVSetPowerStateKM
-
- @Description	Set the system into a new state
-
- @Input		eNewPowerState :
- @Input		bForced : TRUE if the transition should not fail (e.g. OS request)
-
- @Return	PVRSRV_ERROR
-
-******************************************************************************/
+/*************************************************************************/ /*!
+@Function     PVRSRVSetDeviceSystemPowerState
+@Description  Set the device into a new power state based on the systems power
+              state
+@Input        psDeviceNode          Device node
+@Input        eNewSysPowerState  New system power state
+@Return       PVRSRV_ERROR       PVRSRV_OK on success or an error otherwise
+*/ /**************************************************************************/
 IMG_EXPORT
-PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState, IMG_BOOL bForced)
+PVRSRV_ERROR PVRSRVSetDeviceSystemPowerState(PVRSRV_DEVICE_NODE *psDeviceNode,
+											 PVRSRV_SYS_POWER_STATE eNewSysPowerState)
 {
 	PVRSRV_ERROR	eError;
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
 	IMG_UINT        uiStage = 0;
 
 	PVRSRV_DEV_POWER_STATE eNewDevicePowerState = 
@@ -751,29 +580,18 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-#if defined(PDUMP)
-	/* required because sending the idle command to the RGX FW includes
-	* pdumping a SyncPrimSet value and pdumping a CCB command.
-	* The PMR lock must be taken before the power lock, otherwise
-	* lockdep detects a AB-BA style locking scenario
-	*/
-	PMRLock();
-#endif
 	/* Prevent simultaneous SetPowerStateKM calls */
-	PVRSRVForcedPowerLock();
+	PVRSRVForcedPowerLock(psDeviceNode);
 
 	/* no power transition requested, so do nothing */
-	if (eNewSysPowerState == psPVRSRVData->eCurrentPowerState)
+	if (eNewSysPowerState == psDeviceNode->eCurrentSysPowerState)
 	{
-		PVRSRVPowerUnlock();
-#if defined(PDUMP)
-		PMRUnlock();
-#endif
+		PVRSRVPowerUnlock(psDeviceNode);
 		return PVRSRV_OK;
 	}
 
-	/* For a forced power down, all devices must be forced idle before being powered off */
-	if (bForced && ((eNewDevicePowerState == PVRSRV_DEV_POWER_STATE_OFF) || (eNewDevicePowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)))
+	if ((eNewDevicePowerState == PVRSRV_DEV_POWER_STATE_OFF) || 
+		(eNewDevicePowerState == PVRSRV_DEV_POWER_STATE_DEFAULT))
 	{
 		/* If setting devices to default state, selectively force idle all devices whose default state is off */
 		 PFN_SYS_DEV_IS_DEFAULT_STATE_OFF pfnIsDefaultStateOff =
@@ -781,7 +599,8 @@
 
 		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 		{
-			eError = PVRSRVDeviceIdleRequestKM(IMG_TRUE, 0, pfnIsDefaultStateOff, IMG_TRUE);
+			eError = PVRSRVDeviceIdleRequestKM(psDeviceNode,
+											   pfnIsDefaultStateOff, IMG_TRUE);
 
 			if (eError == PVRSRV_OK)
 			{
@@ -789,9 +608,9 @@
 			}
 			else if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
 			{
-				PVRSRVPowerUnlock();
+				PVRSRVPowerUnlock(psDeviceNode);
 				OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-				PVRSRVForcedPowerLock();
+				PVRSRVForcedPowerLock(psDeviceNode);
 			}
 			else
 			{
@@ -801,74 +620,35 @@
 		} END_LOOP_UNTIL_TIMEOUT();
 	}
 
-	/* Perform pre transitions: first device and then sys layer */
-	eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced);
-	if (eError != PVRSRV_OK)
-	{
-		uiStage++;
-		goto ErrorExit;
-	}
-	eError = PVRSRVSysPrePowerState(eNewSysPowerState, bForced);
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode, eNewDevicePowerState,
+										 IMG_TRUE);
 	if (eError != PVRSRV_OK)
 	{
 		uiStage++;
 		goto ErrorExit;
 	}
 
-	/* Perform system-specific post power transitions: first sys layer and then device */
-	eError = PVRSRVSysPostPowerState(eNewSysPowerState, bForced);
-	if (eError != PVRSRV_OK)
-	{
-		uiStage++;
-		goto ErrorExit;
-	}
-	eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced);
-	if (eError != PVRSRV_OK)
-	{
-		uiStage++;
-		goto ErrorExit;
-	}
+	psDeviceNode->eCurrentSysPowerState = eNewSysPowerState;
 
-	psPVRSRVData->eCurrentPowerState = eNewSysPowerState;
-	psPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
-
-	PVRSRVPowerUnlock();
-#if defined(PDUMP)
-		PMRUnlock();
-#endif
-
-	/*
-		Reprocess the devices' queues in case commands were blocked during
-		the power transition.
-	*/
-	if (_IsSystemStatePowered(eNewSysPowerState) &&
-			PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
-	{
-		PVRSRVCheckStatus(NULL);
-	}
+	PVRSRVPowerUnlock(psDeviceNode);
 
 	return PVRSRV_OK;
 
 ErrorExit:
-	/* save the power state for the re-attempt */
-	psPVRSRVData->eFailedPowerState = eNewSysPowerState;
-
-	PVRSRVPowerUnlock();
-#if defined(PDUMP)
-	PMRUnlock();
-#endif
+	PVRSRVPowerUnlock(psDeviceNode);
 
 	PVR_DPF((PVR_DBG_ERROR,
-			"PVRSRVSetPowerStateKM: Transition from %d to %d FAILED (%s) at stage %d, forced: %d. Dumping debug info.",
-			psPVRSRVData->eCurrentPowerState, eNewSysPowerState, PVRSRVGetErrorStringKM(eError), uiStage, bForced));
+			 "%s: Transition from %d to %d FAILED (%s) at stage %d. Dumping debug info.",
+			 __func__, psDeviceNode->eCurrentSysPowerState, eNewSysPowerState,
+			 PVRSRVGetErrorStringKM(eError), uiStage));
 
-	PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+	PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
 
 	return eError;
 }
 
 
-PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32					ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(PVRSRV_DEVICE_NODE			*psDeviceNode,
 									   PFN_PRE_POWER				pfnDevicePrePower,
 									   PFN_POST_POWER				pfnDevicePostPower,
 									   PFN_SYS_DEV_PRE_POWER		pfnSystemPrePower,
@@ -882,19 +662,18 @@
 									   PVRSRV_DEV_POWER_STATE		eCurrentPowerState,
 									   PVRSRV_DEV_POWER_STATE		eDefaultPowerState)
 {
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_POWER_DEV	*psPowerDevice;
+	PVRSRV_POWER_DEV *psPowerDevice;
 
-	if (pfnDevicePrePower == NULL &&
-		pfnDevicePostPower == NULL)
-	{
-		return PVRSRVRemovePowerDevice(ui32DeviceIndex);
-	}
+	PVR_ASSERT(!psDeviceNode->psPowerDev);
+
+	PVR_ASSERT(eCurrentPowerState != PVRSRV_DEV_POWER_STATE_DEFAULT);
+	PVR_ASSERT(eDefaultPowerState != PVRSRV_DEV_POWER_STATE_DEFAULT);
 
 	psPowerDevice = OSAllocMem(sizeof(PVRSRV_POWER_DEV));
 	if (psPowerDevice == NULL)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to alloc PVRSRV_POWER_DEV", __func__));
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
@@ -908,13 +687,12 @@
 	psPowerDevice->pfnForcedIdleRequest = pfnForcedIdleRequest;
 	psPowerDevice->pfnForcedIdleCancelRequest = pfnForcedIdleCancelRequest;
 	psPowerDevice->pfnDustCountRequest = pfnDustCountRequest;
+	psPowerDevice->hSysData = psDeviceNode->psDevConfig->hSysData;
 	psPowerDevice->hDevCookie = hDevCookie;
-	psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
 	psPowerDevice->eCurrentPowerState = eCurrentPowerState;
 	psPowerDevice->eDefaultPowerState = eDefaultPowerState;
 
-	/* insert into power device list */
-	List_PVRSRV_POWER_DEV_Insert(&(psPVRSRVData->psPowerDeviceList), psPowerDevice);
+	psDeviceNode->psPowerDev = psPowerDevice;
 
 	return (PVRSRV_OK);
 }
@@ -929,27 +707,17 @@
 
  Removes device from power management register. Device is located by Device Index
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
 
  @Return	PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+PVRSRV_ERROR PVRSRVRemovePowerDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_POWER_DEV	*psPowerDev;
-
-	/* find device in list and remove it */
-	psPowerDev = (PVRSRV_POWER_DEV*)
-					List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
-												 &MatchPowerDeviceIndex_AnyVaCb,
-												 ui32DeviceIndex);
-
-	if (psPowerDev)
+	if (psDeviceNode->psPowerDev)
 	{
-		List_PVRSRV_POWER_DEV_Remove(psPowerDev);
-		OSFreeMem(psPowerDev);
-		/*not nulling pointer, copy on stack*/
+		OSFreeMem(psDeviceNode->psPowerDev);
+		psDeviceNode->psPowerDev = NULL;
 	}
 
 	return (PVRSRV_OK);
@@ -965,22 +733,19 @@
 
 	Return the device power state
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
  @Output	psPowerState : Current power state 
 
  @Return	PVRSRV_ERROR_UNKNOWN_POWER_STATE if device could not be found. PVRSRV_OK otherwise.
 
 ******************************************************************************/
 IMG_EXPORT
-PVRSRV_ERROR PVRSRVGetDevicePowerState(IMG_UINT32 ui32DeviceIndex, PPVRSRV_DEV_POWER_STATE pePowerState)
+PVRSRV_ERROR PVRSRVGetDevicePowerState(PVRSRV_DEVICE_NODE *psDeviceNode,
+									   PPVRSRV_DEV_POWER_STATE pePowerState)
 {
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_POWER_DEV	*psPowerDevice;
+	PVRSRV_POWER_DEV *psPowerDevice;
 
-	psPowerDevice = (PVRSRV_POWER_DEV*)
-					List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
-												 &MatchPowerDeviceIndex_AnyVaCb,
-												 ui32DeviceIndex);
+	psPowerDevice = psDeviceNode->psPowerDev;
 	if (psPowerDevice == NULL)
 	{
 		return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
@@ -1000,23 +765,22 @@
 
 	Whether the device is powered, for the purposes of lockup detection.
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
 
  @Return	IMG_BOOL
 
 ******************************************************************************/
 IMG_EXPORT
-IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+IMG_BOOL PVRSRVIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	PVRSRV_DATA            *psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_DEV_POWER_STATE ePowerState;
 
-	if (OSLockIsLocked(psPVRSRVData->hPowerLock))
+	if (OSLockIsLocked(psDeviceNode->hPowerLock))
 	{
 		return IMG_FALSE;
 	}
 
-	if (PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState) != PVRSRV_OK)
+	if (PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState) != PVRSRV_OK)
 	{
 		return IMG_FALSE;
 	}
@@ -1034,19 +798,18 @@
 
 	Notification from system layer that a device clock speed change is about to happen.
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
  @Input		bIdleDevice : whether the device should be idled
  @Input		pvInfo
 
  @Return	void
 
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(PVRSRV_DEVICE_NODE *psDeviceNode,
 											 IMG_BOOL	bIdleDevice,
 											 void	*pvInfo)
 {
 	PVRSRV_ERROR		eError = PVRSRV_OK;
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_POWER_DEV	*psPowerDevice;
 	IMG_UINT64			ui64StartTimer, ui64StopTimer;
 
@@ -1055,28 +818,24 @@
 	ui64StartTimer = OSClockus();
 
 	/* This mutex is released in PVRSRVDevicePostClockSpeedChange. */
-	eError = PVRSRVPowerLock();
+	eError = PVRSRVPowerLock(psDeviceNode);
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: failed to acquire lock (%s)",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
 		return eError;
 	}
 
-	/*search the device and then do the pre clock speed change*/
-	psPowerDevice = (PVRSRV_POWER_DEV*)
-					List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
-												 &MatchPowerDeviceIndex_AnyVaCb,
-												 ui32DeviceIndex);
-
-
+	psPowerDevice = psDeviceNode->psPowerDev;
 	if (psPowerDevice)
 	{
 		if ((psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) && bIdleDevice)
 		{
 			LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 			{	/* We can change the clock speed if the device is either IDLE or OFF */
-				eError = PVRSRVDeviceIdleRequestKM(IMG_FALSE, ui32DeviceIndex, NULL, IMG_TRUE);
+				eError = PVRSRVDeviceIdleRequestKM(psDeviceNode, NULL, IMG_TRUE);
 
 				if (eError == PVRSRV_OK)
 				{
@@ -1086,41 +845,34 @@
 				{
 					PVRSRV_ERROR	eError2;
 
-					PVRSRVPowerUnlock();
+					PVRSRVPowerUnlock(psDeviceNode);
 					OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-					eError2 = PVRSRVPowerLock();
+					eError2 = PVRSRVPowerLock(psDeviceNode);
 
 					if (eError2 != PVRSRV_OK)
 					{
-						PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+						PVR_DPF((PVR_DBG_ERROR,
+								 "%s: failed to acquire lock (%s)",
+								 __func__, PVRSRVGetErrorStringKM(eError)));
 						return eError2;
 					}
 				}
 				else
 				{
-					PVRSRVPowerUnlock();
+					PVRSRVPowerUnlock(psDeviceNode);
 					return eError;
 				}
 			} END_LOOP_UNTIL_TIMEOUT();
+
+			if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
+			{
+				PVRSRVPowerUnlock(psDeviceNode);
+				return eError;
+			}
 		}
 
-		if (eError == PVRSRV_OK)
-		{
-			eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
-														   psPowerDevice->eCurrentPowerState);
-		}
-		else if (eError != PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
-		{
-			PVR_DPF((PVR_DBG_ERROR,
-					"PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x",
-					ui32DeviceIndex, eError));
-		}
-	}
-
-	if (eError != PVRSRV_OK)
-	{
-		PVRSRVPowerUnlock();
-		return eError;
+		eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+		                                               psPowerDevice->eCurrentPowerState);
 	}
 
 	ui64StopTimer = OSClockus();
@@ -1142,19 +894,18 @@
 
 	Notification from system layer that a device clock speed change has just happened.
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
  @Input		bIdleDevice : whether the device had been idled
  @Input		pvInfo
 
  @Return	void
 
 ******************************************************************************/
-void PVRSRVDevicePostClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+void PVRSRVDevicePostClockSpeedChange(PVRSRV_DEVICE_NODE *psDeviceNode,
 									  IMG_BOOL		bIdleDevice,
 									  void		*pvInfo)
 {
 	PVRSRV_ERROR		eError;
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_POWER_DEV	*psPowerDevice;
 	IMG_UINT64			ui64StartTimer, ui64StopTimer;
 
@@ -1162,36 +913,31 @@
 
 	ui64StartTimer = OSClockus();
 
-	/*search the device and then do the post clock speed change*/
-	psPowerDevice = (PVRSRV_POWER_DEV*)
-					List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
-												 &MatchPowerDeviceIndex_AnyVaCb,
-												 ui32DeviceIndex);
-
+	psPowerDevice = psDeviceNode->psPowerDev;
 	if (psPowerDevice)
 	{
 		eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
 														psPowerDevice->eCurrentPowerState);
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR,
-					"PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x",
-					ui32DeviceIndex, eError));
+			PVR_DPF((PVR_DBG_ERROR, "%s: Device %p failed (%s)",
+					 __func__, psDeviceNode, PVRSRVGetErrorStringKM(eError)));
 		}
 
-		if((psPowerDevice->eCurrentPowerState != PVRSRV_DEV_POWER_STATE_OFF) && bIdleDevice)
+		if ((psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) && bIdleDevice)
 		{
-			eError = PVRSRVDeviceIdleCancelRequestKM(IMG_FALSE, ui32DeviceIndex);
+			eError = PVRSRVDeviceIdleCancelRequestKM(psDeviceNode);
 
 			if (eError != PVRSRV_OK)
 			{
-				PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePostClockSpeedChange : Failed to cancel forced IDLE."));
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: Failed to cancel forced IDLE.", __func__));
 			}
 		}
 	}
 
 	/* This mutex was acquired in PVRSRVDevicePreClockSpeedChange. */
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 	ui64StopTimer = OSClockus();
 
@@ -1209,108 +955,74 @@
 
 	Request from system layer that a dust count change is requested.
 
- @Input		ui32DeviceIndex : device index
+ @Input		psDeviceNode : Device node
  @Input		ui32DustCount : dust count to be set
 
  @Return	PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVDeviceDustCountChange(IMG_UINT32	ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDeviceDustCountChange(PVRSRV_DEVICE_NODE *psDeviceNode,
 						IMG_UINT32	ui32DustCount)
 {
 	PVRSRV_ERROR		eError = PVRSRV_OK;
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_POWER_DEV	*psPowerDevice;
-	PVRSRV_DEV_POWER_STATE	eCurrentPowerState;
 
-	/*search the device and then do the pre clock speed change*/
-	psPowerDevice = (PVRSRV_POWER_DEV*)
-					List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
-												 &MatchPowerDeviceIndex_AnyVaCb,
-												 ui32DeviceIndex);
-
+	psPowerDevice = psDeviceNode->psPowerDev;
 	if (psPowerDevice)
 	{
-		eError = PVRSRVPowerLock();
+		PVRSRV_DEV_POWER_STATE eDevicePowerState;
+
+		eError = PVRSRVPowerLock(psDeviceNode);
 
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDeviceDustCountChange : failed to acquire lock, error:0x%x", eError));
-			goto ErrorExit;
+			PVR_DPF((PVR_DBG_ERROR, "%s: failed to acquire lock (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+			return eError;
 		}
 
-		eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eCurrentPowerState);
-		if (eError != PVRSRV_OK)
+		eDevicePowerState = psPowerDevice->eCurrentPowerState;
+		if (eDevicePowerState == PVRSRV_DEV_POWER_STATE_ON)
 		{
-			PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDeviceDustCountChange : failed to get current device power state, error:0x%x", eError));
-			goto ErrorExit;
-		}
-
-		if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
-		{
-			PVRSRV_ERROR eError2 = PVRSRV_ERROR_NOT_IMPLEMENTED;
-			if (psPowerDevice->pfnDustCountRequest != NULL)
+			/* Device must be idle to change dust count */
+			LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 			{
-				eError2 = psPowerDevice->pfnDustCountRequest(psPowerDevice->hDevCookie, ui32DustCount);
+				eError = PVRSRVDeviceIdleRequestKM(psDeviceNode, NULL, IMG_FALSE);
+				if (eError == PVRSRV_OK)
+				{
+					break;
+				}
+				else if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
+				{
+					PVRSRV_ERROR	eError2;
 
-				if (eError2 != PVRSRV_OK)
+					PVRSRVPowerUnlock(psDeviceNode);
+					OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+					eError2 = PVRSRVPowerLock(psDeviceNode);
+
+					if (eError2 != PVRSRV_OK)
+					{
+						PVR_DPF((PVR_DBG_ERROR, "%s: failed to acquire lock (%s)",
+								 __func__, PVRSRVGetErrorStringKM(eError)));
+						return eError2;
+					}
+				}
+				else
 				{
 					PVR_DPF((PVR_DBG_ERROR,
-							"PVRSRVDeviceDustCountChange : Device %u failed, error:0x%x",
-							ui32DeviceIndex, eError));
+							 "%s: error occurred whilst forcing idle (%s)",
+							 __func__, PVRSRVGetErrorStringKM(eError)));
+					goto ErrorExit;
 				}
-			}
-			PVRSRVPowerUnlock();
-			return eError2;
-		}
-
-		/* Device must be idle to change dust count  */
-		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
-		{
-			PDUMPPOWCMDSTART();
-			eError = PVRSRVSetDevicePowerStateKM(ui32DeviceIndex,
-								PVRSRV_DEV_POWER_STATE_ON,
-								IMG_FALSE);
-			PDUMPPOWCMDEND();
+			} END_LOOP_UNTIL_TIMEOUT();
 
 			if (eError != PVRSRV_OK)
 			{
-				PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceDustCountChange: failed to transition Rogue to ON (%s)",
-							PVRSRVGetErrorStringKM(eError)));
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: timeout occurred attempting to force idle (%s)",
+						 __func__, PVRSRVGetErrorStringKM(eError)));
 				goto ErrorExit;
 			}
-
-			eError = PVRSRVDeviceIdleRequestKM(IMG_FALSE, ui32DeviceIndex, NULL, IMG_FALSE);
-
-			if (eError == PVRSRV_OK)
-			{
-				break;
-			}
-			else if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
-			{
-				PVRSRV_ERROR	eError2;
-
-				PVRSRVPowerUnlock();
-				OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-				eError2 = PVRSRVPowerLock();
-
-				if (eError2 != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDeviceDustCountChange : failed to acquire lock, error:0x%x", eError));
-					return eError2;
-				}
-			}
-			else
-			{
-				PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDeviceDustCountChange : error occurred whilst forcing idle, error:0x%x", eError));
-				goto ErrorExit;
-			}
-		} END_LOOP_UNTIL_TIMEOUT();
-
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDeviceDustCountChange : timeout occurred attempting to force idle, error:0x%x", eError));
-			goto ErrorExit;
 		}
 
 		if (psPowerDevice->pfnDustCountRequest != NULL)
@@ -1319,27 +1031,30 @@
 
 			if (eError2 != PVRSRV_OK)
 			{
-				PVR_DPF((PVR_DBG_ERROR,
-						"PVRSRVDeviceDustCountChange : Device %u failed, error:0x%x",
-						ui32DeviceIndex, eError));
+				PVR_DPF((PVR_DBG_ERROR, "%s: Device %p failed (%s)",
+						 __func__, psDeviceNode,
+						 PVRSRVGetErrorStringKM(eError)));
 			}
 		}
 
-		eError = PVRSRVDeviceIdleCancelRequestKM(IMG_FALSE, ui32DeviceIndex);
-
-		if (eError != PVRSRV_OK)
+		if (eDevicePowerState == PVRSRV_DEV_POWER_STATE_ON)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePostClockSpeedChange : Failed to cancel forced IDLE."));
-			goto ErrorExit;
+			eError = PVRSRVDeviceIdleCancelRequestKM(psDeviceNode);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: Failed to cancel forced IDLE.", __func__));
+				goto ErrorExit;
+			}
 		}
 
-		PVRSRVPowerUnlock();
+		PVRSRVPowerUnlock(psDeviceNode);
 	}
 
 	return eError;
 
 ErrorExit:
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 	return eError;
 }
 
diff --git a/drivers/staging/imgtec/rogue/power.h b/drivers/staging/imgtec/rogue/power.h
index 41ac21d..c8b801b 100644
--- a/drivers/staging/imgtec/rogue/power.h
+++ b/drivers/staging/imgtec/rogue/power.h
@@ -43,34 +43,15 @@
 #ifndef POWER_H
 #define POWER_H
 
-
+#include "img_defs.h"
+#include "img_types.h"
 #include "pvrsrv_device.h"
+#include "pvrsrv_error.h"
+#include "servicesext.h"
 
-/*!
- *****************************************************************************
- *	Power management
- *****************************************************************************/
- 
-typedef struct _PVRSRV_POWER_DEV_TAG_
-{
-	PFN_PRE_POWER					pfnDevicePrePower;
-	PFN_POST_POWER					pfnDevicePostPower;
-	PFN_SYS_DEV_PRE_POWER			pfnSystemPrePower;
-	PFN_SYS_DEV_POST_POWER			pfnSystemPostPower;
-	PFN_PRE_CLOCKSPEED_CHANGE		pfnPreClockSpeedChange;
-	PFN_POST_CLOCKSPEED_CHANGE		pfnPostClockSpeedChange;
-	PFN_FORCED_IDLE_REQUEST			pfnForcedIdleRequest;
-	PFN_FORCED_IDLE_CANCEL_REQUEST		pfnForcedIdleCancelRequest;
-	PFN_DUST_COUNT_REQUEST			pfnDustCountRequest;
-	IMG_HANDLE						hDevCookie;
-	IMG_UINT32						ui32DeviceIndex;
-	PVRSRV_DEV_POWER_STATE 			eDefaultPowerState;
-	PVRSRV_DEV_POWER_STATE 			eCurrentPowerState;
-	struct _PVRSRV_POWER_DEV_TAG_	*psNext;
-	struct _PVRSRV_POWER_DEV_TAG_	**ppsThis;
+typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
 
-} PVRSRV_POWER_DEV;
-
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 typedef enum _PVRSRV_INIT_SERVER_STATE_
 {
 	PVRSRV_INIT_SERVER_Unspecified		= -1,	
@@ -78,37 +59,49 @@
 	PVRSRV_INIT_SERVER_RAN				= 1,	
 	PVRSRV_INIT_SERVER_SUCCESSFUL		= 2,	
 	PVRSRV_INIT_SERVER_NUM				= 3,	
-	PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
-
+	PVRSRV_INIT_SERVER_FORCE_I32		= 0x7fffffff
 } PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
 
+IMG_IMPORT IMG_BOOL
+PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState,
+						 IMG_BOOL bState);
+#endif /* !defined(SUPPORT_KERNEL_SRVINIT) */
+
+
+/*!
+ *****************************************************************************
+ *	Power management
+ *****************************************************************************/
+
+typedef struct _PVRSRV_POWER_DEV_TAG_ PVRSRV_POWER_DEV;
+
 typedef IMG_BOOL (*PFN_SYS_DEV_IS_DEFAULT_STATE_OFF)(PVRSRV_POWER_DEV *psPowerDevice);
 
-IMG_IMPORT
-IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE	eInitServerState);
 
-IMG_IMPORT
-PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE	eInitServerState, IMG_BOOL bState);
-
-
-
-IMG_IMPORT PVRSRV_ERROR PVRSRVPowerLock(void);
-IMG_IMPORT void PVRSRVForcedPowerLock(void);
-IMG_IMPORT void PVRSRVPowerUnlock(void);
+IMG_IMPORT PVRSRV_ERROR PVRSRVPowerLock(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_IMPORT void PVRSRVForcedPowerLock(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_IMPORT void PVRSRVPowerUnlock(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 IMG_IMPORT IMG_BOOL PVRSRVDeviceIsDefaultStateOFF(PVRSRV_POWER_DEV *psPowerDevice);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(PVRSRV_DEVICE_NODE		*psDeviceNode,
 										 PVRSRV_DEV_POWER_STATE	eNewPowerState,
 										 IMG_BOOL				bForced);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState, IMG_BOOL bForced);
+PVRSRV_ERROR PVRSRVSetDeviceSystemPowerState(PVRSRV_DEVICE_NODE *psDeviceNode,
+											 PVRSRV_SYS_POWER_STATE ePVRState);
+
+PVRSRV_ERROR PVRSRVSetDeviceDefaultPowerState(const PVRSRV_DEVICE_NODE *psDeviceNode,
+					PVRSRV_DEV_POWER_STATE eNewPowerState);
 
 /* Type PFN_DC_REGISTER_POWER */
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32					ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(PVRSRV_DEVICE_NODE			*psDeviceNode,
 									   PFN_PRE_POWER				pfnDevicePrePower,
 									   PFN_POST_POWER				pfnDevicePostPower,
 									   PFN_SYS_DEV_PRE_POWER		pfnSystemPrePower,
@@ -123,35 +116,34 @@
 									   PVRSRV_DEV_POWER_STATE		eDefaultPowerState);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+PVRSRV_ERROR PVRSRVRemovePowerDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVGetDevicePowerState(IMG_UINT32 ui32DeviceIndex, PPVRSRV_DEV_POWER_STATE pePowerState);
+PVRSRV_ERROR PVRSRVGetDevicePowerState(PVRSRV_DEVICE_NODE *psDeviceNode,
+									   PPVRSRV_DEV_POWER_STATE pePowerState);
 
 IMG_IMPORT
-IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+IMG_BOOL PVRSRVIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(PVRSRV_DEVICE_NODE *psDeviceNode,
 											 IMG_BOOL	bIdleDevice,
 											 void	*pvInfo);
 
 IMG_IMPORT
-void PVRSRVDevicePostClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+void PVRSRVDevicePostClockSpeedChange(PVRSRV_DEVICE_NODE *psDeviceNode,
 										  IMG_BOOL		bIdleDevice,
 										  void		*pvInfo);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVDeviceIdleRequestKM(IMG_BOOL					bAllDevices,
-					IMG_UINT32				ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDeviceIdleRequestKM(PVRSRV_DEVICE_NODE *psDeviceNode,
 					PFN_SYS_DEV_IS_DEFAULT_STATE_OFF	pfnCheckIdleReq,
 					IMG_BOOL				bDeviceOffPermitted);
 
 IMG_IMPORT
-PVRSRV_ERROR PVRSRVDeviceIdleCancelRequestKM(IMG_BOOL			bAllDevices,
-						IMG_UINT32		ui32DeviceIndex);
+PVRSRV_ERROR PVRSRVDeviceIdleCancelRequestKM(PVRSRV_DEVICE_NODE *psDeviceNode);
 
-PVRSRV_ERROR PVRSRVDeviceDustCountChange(IMG_UINT32	ui32DeviceIndex,
+PVRSRV_ERROR PVRSRVDeviceDustCountChange(PVRSRV_DEVICE_NODE *psDeviceNode,
 						IMG_UINT32	ui32DustCount);
 
 
diff --git a/drivers/staging/imgtec/rogue/process_stats.c b/drivers/staging/imgtec/rogue/process_stats.c
index 6e6a56f..67358be 100644
--- a/drivers/staging/imgtec/rogue/process_stats.c
+++ b/drivers/staging/imgtec/rogue/process_stats.c
@@ -57,13 +57,17 @@
 #include "connection_server.h"
 #include "pvrsrv.h"
 
+#if defined(DEBUG) || defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS) || \
+    defined(PVRSRV_ENABLE_MEMORY_STATS) || \
+	(defined(PVR_RI_DEBUG) && defined(PVR_RI_DEBUG_DEBUGFS))
+#define ENABLE_DEBUGFS
+#endif
 
 /*
  *  Maximum history of process statistics that will be kept.
  */
 #define MAX_DEAD_LIST_PROCESSES  (10)
 
-
 /*
  * Definition of all process based statistics and the strings used to
  * format them.
@@ -111,8 +115,7 @@
 	PVRSRV_PROCESS_STAT_TYPE_COUNT
 } PVRSRV_PROCESS_STAT_TYPE;
 
-
-static IMG_CHAR*  pszProcessStatFmt[PVRSRV_PROCESS_STAT_TYPE_COUNT] = {
+static const IMG_CHAR *const pszProcessStatFmt[PVRSRV_PROCESS_STAT_TYPE_COUNT] = {
 	"Connections                       %10d\n", /* PVRSRV_STAT_TYPE_CONNECTIONS */
 	"ConnectionsMax                    %10d\n", /* PVRSRV_STAT_TYPE_MAXCONNECTIONS */
 
@@ -131,7 +134,7 @@
 	"FreeListInitialPages              %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT */
 	"FreeListMaxPages                  %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES */
 #if !defined(PVR_DISABLE_KMALLOC_MEMSTATS)
-    "MemoryUsageKMalloc                %10d\n", /* PVRSRV_STAT_TYPE_KMALLOC */
+	"MemoryUsageKMalloc                %10d\n", /* PVRSRV_STAT_TYPE_KMALLOC */
 	"MemoryUsageKMallocMax             %10d\n", /* PVRSRV_STAT_TYPE_MAX_KMALLOC */
 	"MemoryUsageVMalloc                %10d\n", /* PVRSRV_STAT_TYPE_VMALLOC */
 	"MemoryUsageVMallocMax             %10d\n", /* PVRSRV_STAT_TYPE_MAX_VMALLOC */
@@ -154,21 +157,30 @@
 	"MemoryUsageMappedGPUMemUMA/LMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_MAP_UMA_LMA_PAGES */
 };
 
-/* structure used in hash table to track vmalloc statistic entries */
+/* structure used in hash table to track statistic entries */
 typedef struct{
 	size_t	   uiSizeInBytes;
 	IMG_PID	   uiPid;
-}_PVR_STATS_VMALLOC_HASH_ENTRY;
+}_PVR_STATS_TRACKING_HASH_ENTRY;
 
-/* Function used internally to decrement per-process vmalloc statistic entries */
-static void _StatsDecrMemVAllocStat(_PVR_STATS_VMALLOC_HASH_ENTRY *psVmallocHashEntry);
+/* Function used internally to decrement tracked per-process statistic entries */
+static void _StatsDecrMemTrackedStat(_PVR_STATS_TRACKING_HASH_ENTRY *psTrackingHashEntry,
+                                    PVRSRV_MEM_ALLOC_TYPE eAllocType);
 
 /*
  *  Functions for printing the information stored...
  */
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 void  ProcessStatsPrintElements(void *pvFile,
 								void *pvStatPtr,
 								OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
+#endif
+
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+void RawProcessStatsPrintElements(void *pvFile,
+                                  void *pvStatPtr,
+                                  OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
+#endif
 
 void  MemStatsPrintElements(void *pvFile,
 							void *pvStatPtr,
@@ -186,6 +198,9 @@
 							   void *pvStatPtr,
 							   OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
 
+void  CacheOpStatsPrintElements(void *pvFile,
+							  void *pvStatPtr,
+							  OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
 
 #if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
 static void StripBadChars( IMG_CHAR *psStr);
@@ -205,6 +220,9 @@
 #define DECREASE_STAT_VALUE(ptr,var,val)		do { if ((ptr)->i32StatValue[(var)] >= (val)) { (ptr)->i32StatValue[(var)] -= (val); } else { (ptr)->i32StatValue[(var)] = 0; } } while(0)
 #define DECREASE_GLOBAL_STAT_VALUE(var,val)		do { if ((var) >= (val)) { (var) -= (val); } else { (var) = 0; } } while(0)
 #endif
+#define MAX_CACHEOP_STAT 16
+#define INCREMENT_CACHEOP_STAT_IDX_WRAP(x) ((x+1) >= MAX_CACHEOP_STAT ? 0 : (x+1))
+#define DECREMENT_CACHEOP_STAT_IDX_WRAP(x) ((x-1) < 0 ? (MAX_CACHEOP_STAT-1) : (x-1))
 
 /*
  * Structures for holding statistics...
@@ -214,7 +232,8 @@
 	PVRSRV_STAT_STRUCTURE_PROCESS = 1,
 	PVRSRV_STAT_STRUCTURE_RENDER_CONTEXT = 2,
 	PVRSRV_STAT_STRUCTURE_MEMORY = 3,
-	PVRSRV_STAT_STRUCTURE_RIMEMORY = 4
+	PVRSRV_STAT_STRUCTURE_RIMEMORY = 4,
+	PVRSRV_STAT_STRUCTURE_CACHEOP = 5
 } PVRSRV_STAT_STRUCTURE_TYPE;
 
 #define MAX_PROC_NAME_LENGTH   (32)
@@ -239,14 +258,40 @@
 	/* Folder name used to store the statistic */
 	IMG_CHAR							szFolderName[MAX_PROC_NAME_LENGTH];
 
+#if defined(ENABLE_DEBUGFS)
 	/* OS specific data */
 	void								*pvOSPidFolderData;
+#endif
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 	void								*pvOSPidEntryData;
+#endif
 
 	/* Stats... */
 	IMG_INT32							i32StatValue[PVRSRV_PROCESS_STAT_TYPE_COUNT];
 	IMG_UINT32							ui32StatAllocFlags;
 
+#if defined(DEBUG)
+	struct _CACHEOP_STRUCT_  {
+		PVRSRV_CACHE_OP uiCacheOp;
+#if defined(PVR_RI_DEBUG)
+		IMG_DEV_VIRTADDR sDevVAddr;
+		RGXFWIF_DM eFenceOpType;
+#endif
+		IMG_DEVMEM_SIZE_T uiOffset;
+		IMG_DEVMEM_SIZE_T uiSize;
+		IMG_UINT64 ui64ExecuteTime;
+		IMG_BOOL bRangeBasedFlush;
+		IMG_BOOL bUserModeFlush;
+		IMG_UINT32 ui32OpSeqNum;
+		IMG_BOOL bHasTimeline;
+		IMG_BOOL bIsFence;
+		IMG_PID ownerPid;
+	} 									asCacheOp[MAX_CACHEOP_STAT];
+	IMG_INT32 							uiCacheOpWriteIndex;
+	struct _PVRSRV_CACHEOP_STATS_*		psCacheOpStats;
+#endif
+
 	/* Other statistics structures */
 	struct _PVRSRV_MEMORY_STATS_*		psMemoryStats;
 	struct _PVRSRV_RI_MEMORY_STATS_*	psRIMemoryStats;
@@ -287,16 +332,25 @@
 	/* OS level process ID */
 	IMG_PID						pid;
 
+#if defined(PVR_RI_DEBUG_DEBUGFS)
 	/* OS specific data */
 	void						*pvOSRIMemEntryData;
+#endif
 } PVRSRV_RI_MEMORY_STATS;
 
+typedef struct _PVRSRV_CACHEOP_STATS_ {
+	/* Structure type (must be first!) */
+	PVRSRV_STAT_STRUCTURE_TYPE  eStructureType;
+
+	/* OS specific data */
+	void						*pvOSCacheOpEntryData;
+} PVRSRV_CACHEOP_STATS;
+
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
 static IMPLEMENT_LIST_INSERT(PVRSRV_MEM_ALLOC_REC)
 static IMPLEMENT_LIST_REMOVE(PVRSRV_MEM_ALLOC_REC)
 #endif
 
-
 /*
  *  Global Boolean to flag when the statistics are ready to monitor
  *  memory allocations.
@@ -310,7 +364,7 @@
 static PVRSRV_PROCESS_STATS*  g_psLiveList = NULL;
 static PVRSRV_PROCESS_STATS*  g_psDeadList = NULL;
 
-POS_LOCK  g_psLinkedListLock = NULL;
+static POS_LOCK g_psLinkedListLock = NULL;
 /* Lockdep feature in the kernel cannot differentiate between different instances of same lock type.
  * This allows it to group all such instances of the same lock type under one class
  * The consequence of this is that, if lock acquisition is nested on different instances, it generates
@@ -319,13 +373,18 @@
 #define PROCESS_LOCK_SUBCLASS_CURRENT	1
 #define PROCESS_LOCK_SUBCLASS_PREV 		2
 #define PROCESS_LOCK_SUBCLASS_NEXT 		3
+#if defined(ENABLE_DEBUGFS)
 /*
  * Pointer to OS folder to hold PID folders.
  */
-IMG_CHAR*	pszOSLivePidFolderName = "pid";
-IMG_CHAR*	pszOSDeadPidFolderName = "pids_retired";
-void		*pvOSLivePidFolder	   = NULL;
-void		*pvOSDeadPidFolder	   = NULL;
+static IMG_CHAR *pszOSLivePidFolderName = "pid";
+static IMG_CHAR *pszOSDeadPidFolderName = "pids_retired";
+static void *pvOSLivePidFolder = NULL;
+static void *pvOSDeadPidFolder = NULL;
+#endif
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+static void *pvOSProcStats = NULL;
+#endif
 
 /* global driver-data folders */
 typedef struct _GLOBAL_STATS_
@@ -360,28 +419,32 @@
 #define HASH_INITIAL_SIZE 5
 /* A hash table used to store the size of any vmalloc'd allocation
  * against its address (not needed for kmallocs as we can use ksize()) */
-static HASH_TABLE* gpsVmallocSizeHashTable;
-static POS_LOCK	 gpsVmallocSizeHashTableLock;
+static HASH_TABLE* gpsSizeTrackingHashTable;
+static POS_LOCK	 gpsSizeTrackingHashTableLock;
 
 static void _AddProcessStatsToFrontOfDeadList(PVRSRV_PROCESS_STATS* psProcessStats);
 static void _AddProcessStatsToFrontOfLiveList(PVRSRV_PROCESS_STATS* psProcessStats);
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 static IMG_UINT32 _PVRSRVIncrMemStatRefCount(void *pvStatPtr);
 static IMG_UINT32 _PVRSRVDecrMemStatRefCount(void *pvStatPtr);
+#endif
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS) || !defined(ENABLE_DEBUGFS)
 static void _DestroyProcessStat(PVRSRV_PROCESS_STATS* psProcessStats);
+#endif
 static void _RemoveProcessStatsFromList(PVRSRV_PROCESS_STATS* psProcessStats);
+#if defined(ENABLE_DEBUGFS)
 static void _RemoveOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats);
 static void _CreateOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats, void *pvOSPidFolder);
-
-
+#endif
+static void _DecreaseProcStatValue(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+                                   PVRSRV_PROCESS_STATS* psProcessStats,
+                                   IMG_UINT32 uiBytes);
 /*
  * Power statistics related definitions
  */
 
-/* Averaging each new value with the previous accumulated knowledge.
- * There are many coefficients for that (e.g.) 50 / 50 but I chose 75 / 25
- * meaning that previous knowledge affects the weighted average more
- * than any new knowledge. As time goes by though eventually the number
- * converges to the most commonly used.
+/* For the mean time, use an exponentially weighted moving average with a
+ * 1/4 weighting for the new measurement. 
  */
 #define MEAN_TIME(A, B)     ( ((3*(A))/4) + ((1 * (B))/4) )
 
@@ -412,10 +475,8 @@
 #define NUM_POWER_STATS        (16)
 static IMG_UINT32 aui32PowerTimingStats[NUM_POWER_STATS];
 
-
 static void *pvOSPowerStatsEntryData = NULL;
 
-
 void InsertPowerTimeStatistic(IMG_UINT64 ui64SysStartTime, IMG_UINT64 ui64SysEndTime,
                               IMG_UINT64 ui64DevStartTime, IMG_UINT64 ui64DevEndTime,
                               IMG_BOOL bForced, IMG_BOOL bPowerOn, IMG_BOOL bPrePower)
@@ -484,7 +545,6 @@
 	return;
 }
 
-
 /*************************************************************************/ /*!
 @Function       _FindProcessStatsInLiveList
 @Description    Searches the Live Process List for a statistics structure that
@@ -510,7 +570,6 @@
 	return NULL;
 } /* _FindProcessStatsInLiveList */
 
-
 /*************************************************************************/ /*!
 @Function       _FindProcessStatsInDeadList
 @Description    Searches the Dead Process List for a statistics structure that
@@ -536,7 +595,6 @@
 	return NULL;
 } /* _FindProcessStatsInDeadList */
 
-
 /*************************************************************************/ /*!
 @Function       _FindProcessStats
 @Description    Searches the Live and Dead Process Lists for a statistics
@@ -557,7 +615,6 @@
 	return psProcessStats;
 } /* _FindProcessStats */
 
-
 /*************************************************************************/ /*!
 @Function       _CompressMemoryUsage
 @Description    Reduces memory usage by deleting old statistics data.
@@ -604,7 +661,11 @@
 		PVRSRV_PROCESS_STATS*  psNextProcessStats = psProcessStatsToBeFreed->psNext;
 
 		psProcessStatsToBeFreed->psNext = NULL;
+#if defined(ENABLE_DEBUGFS)
 		_RemoveOSStatisticEntries(psProcessStatsToBeFreed);
+#else
+		_DestroyProcessStat(psProcessStatsToBeFreed);
+#endif
 		psProcessStatsToBeFreed = psNextProcessStats;
 	}
 } /* _CompressMemoryUsage */
@@ -623,6 +684,7 @@
 	_AddProcessStatsToFrontOfDeadList(psProcessStats);
 } /* _MoveProcessToDeadList */
 
+#if defined(ENABLE_DEBUGFS)
 static void
 _MoveProcessToDeadListDebugFS(PVRSRV_PROCESS_STATS* psProcessStats)
 {
@@ -630,6 +692,7 @@
 	_RemoveOSStatisticEntries(psProcessStats);
 	_CreateOSStatisticEntries(psProcessStats, pvOSDeadPidFolder);
 } /* _MoveProcessToDeadListDebugFS */
+#endif
 
 /* These functions move the process stats from the dead to the live list.
  * _MoveProcessToLiveList moves the entry in the global lists and
@@ -645,6 +708,7 @@
 	_AddProcessStatsToFrontOfLiveList(psProcessStats);
 } /* _MoveProcessToLiveList */
 
+#if defined(ENABLE_DEBUGFS)
 static void
 _MoveProcessToLiveListDebugFS(PVRSRV_PROCESS_STATS* psProcessStats)
 {
@@ -652,6 +716,7 @@
 	_RemoveOSStatisticEntries(psProcessStats);
 	_CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
 } /* _MoveProcessToLiveListDebugFS */
+#endif
 
 /*************************************************************************/ /*!
 @Function       _AddProcessStatsToFrontOfLiveList
@@ -661,8 +726,7 @@
 static void
 _AddProcessStatsToFrontOfLiveList(PVRSRV_PROCESS_STATS* psProcessStats)
 {
-	/*This function should always be called under global list lock g_psLinkedListLock
-	 * So I can't think of any paths that modifies the lists without taking the global lock.
+	/* This function should always be called under global list lock g_psLinkedListLock.
 	 */
 	PVR_ASSERT(psProcessStats != NULL);
 
@@ -682,7 +746,6 @@
 	OSLockRelease(psProcessStats->hLock);
 } /* _AddProcessStatsToFrontOfLiveList */
 
-
 /*************************************************************************/ /*!
 @Function       _AddProcessStatsToFrontOfDeadList
 @Description    Add a statistic to the dead list head.
@@ -708,7 +771,6 @@
 	OSLockRelease(psProcessStats->hLock);
 } /* _AddProcessStatsToFrontOfDeadList */
 
-
 /*************************************************************************/ /*!
 @Function       _RemoveProcessStatsFromList
 @Description    Detaches a process from either the live or dead list.
@@ -777,7 +839,7 @@
 
 } /* _RemoveProcessStatsFromList */
 
-
+#if defined(ENABLE_DEBUGFS)
 /*************************************************************************/ /*!
 @Function       _CreateOSStatisticEntries
 @Description    Create all OS entries for this statistic.
@@ -789,56 +851,78 @@
 						  void *pvOSPidFolder)
 {
 	void								*pvOSPidFolderData;
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 	void								*pvOSPidEntryData;
+#endif
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
 	void								*pvOSMemEntryData;
 #endif
-#if defined(PVR_RI_DEBUG)
+#if defined(PVR_RI_DEBUG_DEBUGFS)
 	void								*pvOSRIMemEntryData;
 #endif
+#if defined(DEBUG)
+	void								*pvOSCacheOpEntryData;
+#endif
 
 	PVR_ASSERT(psProcessStats != NULL);
 
 	pvOSPidFolderData = OSCreateStatisticFolder(psProcessStats->szFolderName, pvOSPidFolder);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 	pvOSPidEntryData  = OSCreateStatisticEntry("process_stats",
-															   pvOSPidFolderData,
-															   ProcessStatsPrintElements,
-															   _PVRSRVIncrMemStatRefCount,
-															   _PVRSRVDecrMemStatRefCount,
-															   (void *) psProcessStats);
+												pvOSPidFolderData,
+												ProcessStatsPrintElements,
+												_PVRSRVIncrMemStatRefCount,
+												_PVRSRVDecrMemStatRefCount,
+												(void *) psProcessStats);
+#endif
 
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
 	pvOSMemEntryData = OSCreateStatisticEntry("mem_area",
-																			 pvOSPidFolderData,
-																			 MemStatsPrintElements,
-																			 NULL,
-																			 NULL,
-																			 (void *) psProcessStats->psMemoryStats);
+											  pvOSPidFolderData,
+											  MemStatsPrintElements,
+											  NULL,
+											  NULL,
+											  (void *) psProcessStats->psMemoryStats);
 #endif
 
-#if defined(PVR_RI_DEBUG)
+#if defined(PVR_RI_DEBUG_DEBUGFS)
 	pvOSRIMemEntryData = OSCreateStatisticEntry("ri_mem_area",
-																				 pvOSPidFolderData,
-																				 RIMemStatsPrintElements,
-																				 NULL,
-																				 NULL,
-																				 (void *) psProcessStats->psRIMemoryStats);
+												 pvOSPidFolderData,
+												 RIMemStatsPrintElements,
+												 NULL,
+												 NULL,
+												 (void *) psProcessStats->psRIMemoryStats);
+#endif
+
+#if defined(DEBUG)
+	pvOSCacheOpEntryData = OSCreateStatisticEntry("cache_ops_exec",
+												 pvOSPidFolderData,
+												 CacheOpStatsPrintElements,
+												 NULL,
+												 NULL,
+												 (void *) psProcessStats);
 #endif
 
 	OSLockAcquireNested(psProcessStats->hLock, PROCESS_LOCK_SUBCLASS_CURRENT);
 
 	psProcessStats->pvOSPidFolderData = pvOSPidFolderData;
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 	psProcessStats->pvOSPidEntryData  = pvOSPidEntryData;
+#endif
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
 	psProcessStats->psMemoryStats->pvOSMemEntryData = pvOSMemEntryData;
 #endif
-#if defined(PVR_RI_DEBUG)
+#if defined(PVR_RI_DEBUG_DEBUGFS)
 	psProcessStats->psRIMemoryStats->pvOSRIMemEntryData = pvOSRIMemEntryData;
 #endif
+#if defined(DEBUG)
+	psProcessStats->psCacheOpStats->pvOSCacheOpEntryData = pvOSCacheOpEntryData;
+#endif
+
 	OSLockRelease(psProcessStats->hLock);
 } /* _CreateOSStatisticEntries */
 
-
 /*************************************************************************/ /*!
 @Function       _RemoveOSStatisticEntries
 @Description    Removed all OS entries used by this statistic.
@@ -849,7 +933,11 @@
 {
 	PVR_ASSERT(psProcessStats != NULL);
 
-#if defined(PVR_RI_DEBUG)
+#if defined(DEBUG)
+	OSRemoveStatisticEntry(psProcessStats->psCacheOpStats->pvOSCacheOpEntryData);
+#endif
+
+#if defined(PVR_RI_DEBUG_DEBUGFS)
 	OSRemoveStatisticEntry(psProcessStats->psRIMemoryStats->pvOSRIMemEntryData);
 #endif
 
@@ -857,18 +945,21 @@
 	OSRemoveStatisticEntry(psProcessStats->psMemoryStats->pvOSMemEntryData);
 #endif
 
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 	if( psProcessStats->pvOSPidEntryData != NULL)
 	{
 		OSRemoveStatisticEntry(psProcessStats->pvOSPidEntryData);
 	}
+#endif
+
 	if( psProcessStats->pvOSPidFolderData != NULL)
 	{
 		OSRemoveStatisticFolder(&psProcessStats->pvOSPidFolderData);
 	}
-
 } /* _RemoveOSStatisticEntries */
+#endif /* defined(ENABLE_DEBUGFS) */
 
-
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS) || !defined(ENABLE_DEBUGFS)
 /*************************************************************************/ /*!
 @Function       _DestroyProcessStat
 @Description    Frees memory and resources held by a process statistic.
@@ -900,7 +991,9 @@
 	/* Free the memory... */
 	OSFreeMemNoStats(psProcessStats);
 } /* _DestroyProcessStat */
+#endif
 
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 static IMG_UINT32 _PVRSRVIncrMemStatRefCount(void *pvStatPtr)
 {
 	PVRSRV_STAT_STRUCTURE_TYPE*  peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
@@ -912,10 +1005,6 @@
 		case PVRSRV_STAT_STRUCTURE_PROCESS:
 		{
 			OSLockAcquireNested(psProcessStats->hLock, PROCESS_LOCK_SUBCLASS_CURRENT);
-			/* Increment stat memory refCount */
-			/* We should shift some of them to atomic variables,
-			 * but for not this should suffice as this is non critical path.
-			 * We need lock in process stats to cover the other water marks in it*/
 			ui32Res = ++psProcessStats->ui32MemRefCount;
 			OSLockRelease(psProcessStats->hLock);
 			break;
@@ -960,6 +1049,7 @@
 	}
 	return ui32Res;
 }
+#endif
 
 /*************************************************************************/ /*!
 @Function       PVRSRVStatsInitialise
@@ -974,15 +1064,15 @@
 	PVR_ASSERT(g_psLiveList == NULL);
 	PVR_ASSERT(g_psDeadList == NULL);
 	PVR_ASSERT(g_psLinkedListLock == NULL);
-	PVR_ASSERT(gpsVmallocSizeHashTable == NULL);
+	PVR_ASSERT(gpsSizeTrackingHashTable == NULL);
 	PVR_ASSERT(bProcessStatsInitialised == IMG_FALSE);
 
 	/* We need a lock to protect the linked lists... */
 	error = OSLockCreate(&g_psLinkedListLock, LOCK_TYPE_NONE);
 	if (error == PVRSRV_OK)
 	{
-		/* We also need a lock to protect the hash table used for vmalloc size tracking.. */
-		error = OSLockCreate(&gpsVmallocSizeHashTableLock, LOCK_TYPE_NONE);
+		/* We also need a lock to protect the hash table used for size tracking.. */
+		error = OSLockCreate(&gpsSizeTrackingHashTableLock, LOCK_TYPE_NONE);
 
 		if (error != PVRSRV_OK)
 		{
@@ -996,9 +1086,15 @@
 			goto e1;
 		}
 
+#if defined(ENABLE_DEBUGFS)
 		/* Create a pid folders for putting the PID files in... */
 		pvOSLivePidFolder = OSCreateStatisticFolder(pszOSLivePidFolderName, NULL);
 		pvOSDeadPidFolder = OSCreateStatisticFolder(pszOSDeadPidFolderName, NULL);
+#endif
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+		pvOSProcStats = OSCreateRawStatisticEntry("memtrack_stats", NULL,
+		                                          RawProcessStatsPrintElements);
+#endif
 
 		/* Create power stats entry... */
 		pvOSPowerStatsEntryData = OSCreateStatisticEntry("power_timing_stats",
@@ -1017,16 +1113,16 @@
 
 		/* Flag that we are ready to start monitoring memory allocations. */
 
-		gpsVmallocSizeHashTable = HASH_Create(HASH_INITIAL_SIZE);
+		gpsSizeTrackingHashTable = HASH_Create(HASH_INITIAL_SIZE);
 
-		OSMemSet(asClockSpeedChanges, 0, sizeof(asClockSpeedChanges));
+		OSCachedMemSet(asClockSpeedChanges, 0, sizeof(asClockSpeedChanges));
 
 		bProcessStatsInitialised = IMG_TRUE;
 	}
 	return error;
 e1:
-	OSLockDestroy(gpsVmallocSizeHashTableLock);
-	gpsVmallocSizeHashTableLock = NULL;
+	OSLockDestroy(gpsSizeTrackingHashTableLock);
+	gpsSizeTrackingHashTableLock = NULL;
 e0:
 	OSLockDestroy(g_psLinkedListLock);
 	g_psLinkedListLock = NULL;
@@ -1034,7 +1130,6 @@
 
 } /* PVRSRVStatsInitialise */
 
-
 /*************************************************************************/ /*!
 @Function       PVRSRVStatsDestroy
 @Description    Method for destroying the statistics module data.
@@ -1047,6 +1142,14 @@
 	/* Stop monitoring memory allocations... */
 	bProcessStatsInitialised = IMG_FALSE;
 
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+	if (pvOSProcStats)
+	{
+		OSRemoveRawStatisticEntry(pvOSProcStats);
+		pvOSProcStats = NULL;
+	}
+#endif
+
 	/* Destroy the power stats entry... */
 	if (pvOSPowerStatsEntryData!=NULL)
 	{
@@ -1074,7 +1177,11 @@
 		PVRSRV_PROCESS_STATS*  psProcessStats = g_psLiveList;
 
 		_RemoveProcessStatsFromList(psProcessStats);
+#if defined(ENABLE_DEBUGFS)
 		_RemoveOSStatisticEntries(psProcessStats);
+#else
+		_DestroyProcessStat(psProcessStats);
+#endif
 	}
 
 	while (g_psDeadList != NULL)
@@ -1082,22 +1189,28 @@
 		PVRSRV_PROCESS_STATS*  psProcessStats = g_psDeadList;
 
 		_RemoveProcessStatsFromList(psProcessStats);
+#if defined(ENABLE_DEBUGFS)
 		_RemoveOSStatisticEntries(psProcessStats);
+#else
+		_DestroyProcessStat(psProcessStats);
+#endif
 	}
 
+#if defined(ENABLE_DEBUGFS)
 	/* Remove the OS folders used by the PID folders...
 	 * OSRemoveStatisticFolder will NULL the pointers */
 	OSRemoveStatisticFolder(&pvOSLivePidFolder);
 	OSRemoveStatisticFolder(&pvOSDeadPidFolder);
+#endif
 
-	if (gpsVmallocSizeHashTable != NULL)
+	if (gpsSizeTrackingHashTable != NULL)
 	{
-		HASH_Delete(gpsVmallocSizeHashTable);
+		HASH_Delete(gpsSizeTrackingHashTable);
 	}
-	if (gpsVmallocSizeHashTableLock != NULL)
+	if (gpsSizeTrackingHashTableLock != NULL)
 	{
-		OSLockDestroy(gpsVmallocSizeHashTableLock);
-		gpsVmallocSizeHashTableLock = NULL;
+		OSLockDestroy(gpsSizeTrackingHashTableLock);
+		gpsSizeTrackingHashTableLock = NULL;
 	}
 
 	if(NULL != gsGlobalStats.hGlobalStatsLock)
@@ -1108,8 +1221,6 @@
 
 } /* PVRSRVStatsDestroy */
 
-
-
 static void _decrease_global_stat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
 								  size_t uiBytes)
 {
@@ -1228,7 +1339,6 @@
 	OSLockRelease(gsGlobalStats.hGlobalStatsLock);
 }
 
-
 /*************************************************************************/ /*!
 @Function       PVRSRVStatsRegisterProcess
 @Description    Register a process into the list statistics list.
@@ -1284,6 +1394,7 @@
 
 		*phProcessStats = psProcessStats;
 
+#if defined(ENABLE_DEBUGFS)
 		/* Check if we need to perform any OS operation */
 		if (bMoveProcess)
 		{
@@ -1291,6 +1402,7 @@
 			_RemoveOSStatisticEntries(psProcessStats);
 			_CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
 		}
+#endif
 
 		return PVRSRV_OK;
 	}
@@ -1341,11 +1453,24 @@
 	psProcessStats->psRIMemoryStats->pid            = currentPid;
 #endif
 
+#if defined(DEBUG)
+	psProcessStats->psCacheOpStats = OSAllocZMemNoStats(sizeof(PVRSRV_CACHEOP_STATS));
+	if (psProcessStats->psCacheOpStats == NULL)
+	{
+		OSLockDestroyNoStats(psProcessStats->hLock);
+		OSFreeMemNoStats(psProcessStats->psMemoryStats);
+		OSFreeMemNoStats(psProcessStats->psRIMemoryStats);
+		goto e0;
+	}
+	psProcessStats->psCacheOpStats->eStructureType = PVRSRV_STAT_STRUCTURE_CACHEOP;
+#endif
+
 	/* Add it to the live list... */
 	OSLockAcquire(g_psLinkedListLock);
 	_AddProcessStatsToFrontOfLiveList(psProcessStats);
 	OSLockRelease(g_psLinkedListLock);
 
+#if defined(ENABLE_DEBUGFS)
 	/* Create the process stat in the OS... */
 #if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
 	OSSNPrintf(psProcessStats->szFolderName, sizeof(psProcessStats->szFolderName),
@@ -1355,6 +1480,7 @@
 			   "%d", currentPid);
 #endif
 	_CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
+#endif
 
 	/* Done */
 	*phProcessStats = (IMG_HANDLE) psProcessStats;
@@ -1367,7 +1493,6 @@
 	return PVRSRV_ERROR_OUT_OF_MEMORY;
 } /* PVRSRVStatsRegisterProcess */
 
-
 /*************************************************************************/ /*!
 @Function       PVRSRVStatsDeregisterProcess
 @Input          hProcessStats  Handle to the process returned when registered.
@@ -1404,18 +1529,19 @@
 		}
 		OSLockRelease(g_psLinkedListLock);
 
+#if defined(ENABLE_DEBUGFS)
 		/* The OS calls need to be performed without g_psLinkedListLock */
 		if (bMoveProcess == IMG_TRUE)
 		{
 			_MoveProcessToDeadListDebugFS(psProcessStats);
 		}
+#endif
 
 		/* Check if the dead list needs to be reduced */
 		_CompressMemoryUsage();
 	}
 } /* PVRSRVStatsDeregisterProcess */
 
-
 void
 PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
 							 void *pvCpuVAddr,
@@ -1457,17 +1583,12 @@
 	 */
 
 	/* Allocate the memory record... */
-#if defined(__linux__)
-	psRecord = (PVRSRV_MEM_ALLOC_REC*)OSAllocMemNoStats(sizeof(PVRSRV_MEM_ALLOC_REC));
-#else
-	psRecord = (PVRSRV_MEM_ALLOC_REC*)OSAllocMem(sizeof(PVRSRV_MEM_ALLOC_REC));
-#endif
+	psRecord = OSAllocZMemNoStats(sizeof(PVRSRV_MEM_ALLOC_REC));
 	if (psRecord == NULL)
 	{
 		return;
 	}
 
-	OSMemSet(psRecord, 0, sizeof(PVRSRV_MEM_ALLOC_REC));
 	psRecord->eAllocType       = eAllocType;
 	psRecord->pvCpuVAddr       = pvCpuVAddr;
 	psRecord->sCpuPAddr.uiAddr = sCpuPAddr.uiAddr;
@@ -1523,7 +1644,6 @@
 		StripBadChars(acFolderName);
 
 		psProcessStats = OSAllocZMemNoStats(sizeof(PVRSRV_PROCESS_STATS));
-
 		if (psProcessStats == NULL)
 		{
 			OSLockRelease(g_psLinkedListLock);
@@ -1538,7 +1658,6 @@
 		psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS] = 1;
 
 		eError = OSLockCreateNoStats(&psProcessStats->hLock ,LOCK_TYPE_NONE);
-
 		if (eError != PVRSRV_OK)
 		{
 			goto e0;
@@ -1561,11 +1680,7 @@
 		psProcessStats->psRIMemoryStats = OSAllocZMemNoStats(sizeof(PVRSRV_RI_MEMORY_STATS));
 		if (psProcessStats->psRIMemoryStats == NULL)
 		{
-#if defined(__linux__)
 			OSFreeMemNoStats(psProcessStats->psMemoryStats);
-#else
-			OSFreeMem(psProcessStats->psMemoryStats);
-#endif
 			OSLockDestroyNoStats(psProcessStats->hLock);
 			psProcessStats->hLock = NULL;
 			OSLockRelease(g_psLinkedListLock);
@@ -1575,6 +1690,22 @@
 		psProcessStats->psRIMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_RIMEMORY;
 		psProcessStats->psRIMemoryStats->pid            = currentPid;
 #endif
+
+#if defined(DEBUG)
+		psProcessStats->psCacheOpStats = OSAllocZMemNoStats(sizeof(PVRSRV_CACHEOP_STATS));
+		if (psProcessStats->psCacheOpStats == NULL)
+		{
+			OSFreeMemNoStats(psProcessStats->psRIMemoryStats);
+			OSFreeMemNoStats(psProcessStats->psMemoryStats);
+			OSLockDestroyNoStats(psProcessStats->hLock);
+			OSLockRelease(g_psLinkedListLock);
+			psProcessStats->hLock = NULL;
+			goto e0;
+		}
+
+		psProcessStats->psCacheOpStats->eStructureType = PVRSRV_STAT_STRUCTURE_CACHEOP;
+#endif
+
 		OSLockRelease(g_psLinkedListLock);
 		/* Add it to the live list... */
 		_AddProcessStatsToFrontOfLiveList(psProcessStats);
@@ -1583,7 +1714,9 @@
 		OSSNPrintf(psProcessStats->szFolderName, sizeof(psProcessStats->szFolderName),
 				   "%d_%s", currentPid, acFolderName);
 
+#if defined(ENABLE_DEBUGFS)
 		_CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
+#endif
 #else  /* defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) */
 		OSLockRelease(g_psLinkedListLock);
 #endif /* defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) */
@@ -1596,15 +1729,11 @@
 	if (psProcessStats == NULL)
 	{
 #if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
-		PVR_DPF((PVR_DBG_ERROR, "%s UNABLE TO CREATE process_stats entry for pid %d [%s] ("IMG_SIZE_FMTSPEC " bytes)", __FUNCTION__, currentPid, OSGetCurrentProcessName(), uiBytes));
+		PVR_DPF((PVR_DBG_ERROR, "%s UNABLE TO CREATE process_stats entry for pid %d [%s] (" IMG_SIZE_FMTSPEC " bytes)", __FUNCTION__, currentPid, OSGetCurrentProcessName(), uiBytes));
 #endif
 		if (psRecord != NULL)
 		{
-#if defined(__linux__)
 			OSFreeMemNoStats(psRecord);
-#else
-			OSFreeMem(psRecord);
-#endif
 		}
 		return;
 	}
@@ -1655,7 +1784,7 @@
 #else
 		case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
 		case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
-			break;
+		break;
 #endif
 		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
 		{
@@ -1763,7 +1892,9 @@
 		OSLockAcquire(g_psLinkedListLock);
 		_MoveProcessToLiveList(psProcessStats);
 		OSLockRelease(g_psLinkedListLock);
+#if defined(ENABLE_DEBUGFS)
 		_MoveProcessToLiveListDebugFS(psProcessStats);
+#endif
 	}
 	return;
 
@@ -1776,7 +1907,6 @@
 #endif
 } /* PVRSRVStatsAddMemAllocRecord */
 
-
 void
 PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
 								IMG_UINT64 ui64Key)
@@ -1903,109 +2033,9 @@
 
 		OSLockAcquireNested(psProcessStats->hLock, PROCESS_LOCK_SUBCLASS_CURRENT);
 	
-		switch (eAllocType)
-		{
-#if !defined(PVR_DISABLE_KMALLOC_MEMSTATS)
-			case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_KMALLOC-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_VMALLOC-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-#else
-		case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
-		case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
-			break;
-#endif
-		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, (IMG_UINT32)psRecord->uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			default:
-			{
-				PVR_ASSERT(0);
-			}
-			break;
-		}
+		_DecreaseProcStatValue(eAllocType,
+		                       psProcessStats,
+		                       psRecord->uiBytes);
 
 		List_PVRSRV_MEM_ALLOC_REC_Remove(psRecord);
 		OSLockRelease(psProcessStats->hLock);
@@ -2018,7 +2048,9 @@
 			OSLockAcquire(g_psLinkedListLock);
 			_MoveProcessToDeadList(psProcessStats);
 			OSLockRelease(g_psLinkedListLock);
+#if defined(ENABLE_DEBUGFS)
 			_MoveProcessToDeadListDebugFS(psProcessStats);
+#endif
 
 			/* Check if the dead list needs to be reduced */
 			_CompressMemoryUsage();
@@ -2028,11 +2060,7 @@
 		 * Free the record outside the lock so we don't deadlock and so we
 		 * reduce the time the lock is held.
 		 */
-#if defined(__linux__)
 		OSFreeMemNoStats(psRecord);
-#else
-		OSFreeMem(psRecord);
-#endif
 	}
 	else
 	{
@@ -2051,30 +2079,27 @@
 									IMG_UINT64 uiCpuVAddr)
 {
 	IMG_BOOL bRes = IMG_FALSE;
-	_PVR_STATS_VMALLOC_HASH_ENTRY *psNewVmallocHashEntry = NULL;
+	_PVR_STATS_TRACKING_HASH_ENTRY *psNewTrackingHashEntry = NULL;
 
-	if (!bProcessStatsInitialised || (gpsVmallocSizeHashTable == NULL) )
+	if (!bProcessStatsInitialised || (gpsSizeTrackingHashTable == NULL) )
 	{
 		return;
 	}
 
 	/* Alloc untracked memory for the new hash table entry */
-#if defined(__linux__)
-	psNewVmallocHashEntry = (_PVR_STATS_VMALLOC_HASH_ENTRY *)OSAllocMemNoStats(sizeof(*psNewVmallocHashEntry));
-#else
-	psNewVmallocHashEntry = (_PVR_STATS_VMALLOC_HASH_ENTRY *)OSAllocMem(sizeof(*psNewVmallocHashEntry));
-#endif
-	if (psNewVmallocHashEntry)
+	psNewTrackingHashEntry = (_PVR_STATS_TRACKING_HASH_ENTRY *)OSAllocMemNoStats(sizeof(*psNewTrackingHashEntry));
+	if (psNewTrackingHashEntry)
 	{
-		/* Fill-in the size of the vmalloc and PID of the allocating process */
-		psNewVmallocHashEntry->uiSizeInBytes = uiBytes;
-		psNewVmallocHashEntry->uiPid = OSGetCurrentProcessID();
-		OSLockAcquire(gpsVmallocSizeHashTableLock);
+		/* Fill-in the size of the allocation and PID of the allocating process */
+		psNewTrackingHashEntry->uiSizeInBytes = uiBytes;
+		psNewTrackingHashEntry->uiPid = OSGetCurrentClientProcessIDKM();
+		OSLockAcquire(gpsSizeTrackingHashTableLock);
 		/* Insert address of the new struct into the hash table */
-		bRes = HASH_Insert(gpsVmallocSizeHashTable, uiCpuVAddr, (uintptr_t)psNewVmallocHashEntry);
-		OSLockRelease(gpsVmallocSizeHashTableLock);
+		bRes = HASH_Insert(gpsSizeTrackingHashTable, uiCpuVAddr, (uintptr_t)psNewTrackingHashEntry);
+		OSLockRelease(gpsSizeTrackingHashTableLock);
 	}
-	if (psNewVmallocHashEntry)
+
+	if (psNewTrackingHashEntry)
 	{
 		if (bRes)
 		{
@@ -2087,7 +2112,7 @@
 	}
 	else
 	{
-		PVR_DPF((PVR_DBG_ERROR, "*** %s : @ line %d Failed to alloc memory for psNewVmallocHashEntry!!", __FUNCTION__, __LINE__));
+		PVR_DPF((PVR_DBG_ERROR, "*** %s : @ line %d Failed to alloc memory for psNewTrackingHashEntry!!", __FUNCTION__, __LINE__));
 	}
 }
 
@@ -2136,7 +2161,8 @@
 		}
 	}
 
-	if(NULL == psProcessStats){
+	if (psProcessStats == NULL)
+	{
 #if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
 		PVRSRV_ERROR eError;
 		IMG_CHAR				acFolderName[30];
@@ -2148,23 +2174,25 @@
 		if (bProcessStatsInitialised)
 		{
 			psProcessStats = OSAllocZMemNoStats(sizeof(PVRSRV_PROCESS_STATS));
-
 			if (psProcessStats == NULL)
 			{
 				return;
 			}
+
 			psProcessStats->eStructureType  = PVRSRV_STAT_STRUCTURE_PROCESS;
 			psProcessStats->pid             = currentPid;
 			psProcessStats->ui32RefCount    = 1;
 			psProcessStats->ui32MemRefCount = 1;
 			psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS]     = 1;
 			psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS] = 1;
+
 			eError = OSLockCreateNoStats(&psProcessStats->hLock ,LOCK_TYPE_NONE);
 			if (eError != PVRSRV_OK)
 			{
 				OSFreeMemNoStats(psProcessStats);
 				return;
 			}
+
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
 			psProcessStats->psMemoryStats = OSAllocZMemNoStats(sizeof(PVRSRV_MEMORY_STATS));
 			if (psProcessStats->psMemoryStats == NULL)
@@ -2175,6 +2203,7 @@
 			}
 			psProcessStats->psMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_MEMORY;
 #endif
+
 #if defined(PVR_RI_DEBUG)
 			psProcessStats->psRIMemoryStats = OSAllocZMemNoStats(sizeof(PVRSRV_RI_MEMORY_STATS));
 			if (psProcessStats->psRIMemoryStats == NULL)
@@ -2187,14 +2216,30 @@
 			psProcessStats->psRIMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_RIMEMORY;
 			psProcessStats->psRIMemoryStats->pid            = currentPid;
 #endif
+
+#if defined(PVR_RI_DEBUG)
+			psProcessStats->psCacheOpStats = OSAllocZMemNoStats(sizeof(PVRSRV_CACHEOP_STATS));
+			if (psProcessStats->psCacheOpStats == NULL)
+			{
+				OSFreeMemNoStats(psProcessStats->psMemoryStats);
+				OSFreeMemNoStats(psProcessStats->psRIMemoryStats);
+				OSLockDestroyNoStats(psProcessStats->hLock);
+				OSFreeMemNoStats(psProcessStats);
+				return;
+			}
+			psProcessStats->psCacheOpStats->eStructureType = PVRSRV_STAT_STRUCTURE_CACHEOP;
+#endif
+
 			/* Add it to the live list... */
 			_AddProcessStatsToFrontOfLiveList(psProcessStats);
 
+#if define(ENABLE_DEBUGFS)
 			/* Create the process stat in the OS... */
 			OSSNPrintf(psProcessStats->szFolderName, sizeof(psProcessStats->szFolderName),
 					"%d_%s", currentPid, acFolderName);
 
 			_CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
+#endif
 		}
 #else
 		OSLockRelease(g_psLinkedListLock);
@@ -2293,11 +2338,168 @@
 			OSLockAcquire(g_psLinkedListLock);
 			_MoveProcessToLiveList(psProcessStats);
 			OSLockRelease(g_psLinkedListLock);
+#if defined(ENABLE_DEBUGFS)
 			_MoveProcessToLiveListDebugFS(psProcessStats);
+#endif
 		}
     }
 }
 
+static void
+_DecreaseProcStatValue(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+                       PVRSRV_PROCESS_STATS* psProcessStats,
+                       IMG_UINT32 uiBytes)
+{
+	switch (eAllocType)
+	{
+	#if !defined(PVR_DISABLE_KMALLOC_MEMSTATS)
+		case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_KMALLOC-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_VMALLOC-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+	#else
+		case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+		case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+		break;
+	#endif
+		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+		{
+			DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, (IMG_UINT32)uiBytes);
+			if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] == 0 )
+			{
+				psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
+			}
+		}
+		break;
+
+		default:
+		{
+			PVR_ASSERT(0);
+		}
+		break;
+	}
+
+}
+
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+void RawProcessStatsPrintElements(void *pvFile,
+                                  void *pvStatPtr,
+                                  OS_STATS_PRINTF_FUNC *pfnOSStatsPrintf)
+{
+	PVRSRV_PROCESS_STATS *psProcessStats;
+
+	if (pfnOSStatsPrintf == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: pfnOSStatsPrintf not set", __func__));
+		return;
+	}
+
+	pfnOSStatsPrintf(pvFile, "%s,%s,%s,%s,%s,%s\n",
+	                 "PID",
+	                 "MemoryUsageKMalloc",           // PVRSRV_PROCESS_STAT_TYPE_KMALLOC
+	                 "MemoryUsageAllocPTMemoryUMA",  // PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA
+	                 "MemoryUsageAllocPTMemoryLMA",  // PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA
+	                 "MemoryUsageAllocGPUMemLMA",    // PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES
+	                 "MemoryUsageAllocGPUMemUMA"     // PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES
+	                 );
+
+	OSLockAcquire(g_psLinkedListLock);
+
+	psProcessStats = g_psLiveList;
+
+	while (psProcessStats != NULL)
+	{
+		pfnOSStatsPrintf(pvFile, "%d,%d,%d,%d,%d,%d\n",
+		                 psProcessStats->pid,
+		                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC],
+		                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA],
+		                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA],
+		                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES],
+		                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES]
+		                 );
+
+		psProcessStats = psProcessStats->psNext;
+	}
+
+	OSLockRelease(g_psLinkedListLock);
+} /* RawProcessStatsPrintElements */
+#endif
+
 void
 PVRSRVStatsDecrMemKAllocStat(size_t uiBytes,
                              IMG_PID decrPID)
@@ -2328,9 +2530,9 @@
 }
 
 static void
-_StatsDecrMemVAllocStat(_PVR_STATS_VMALLOC_HASH_ENTRY *psVmallocHashEntry)
+_StatsDecrMemTrackedStat(_PVR_STATS_TRACKING_HASH_ENTRY *psTrackingHashEntry,
+                        PVRSRV_MEM_ALLOC_TYPE eAllocType)
 {
-#if !defined(PVR_DISABLE_KMALLOC_MEMSTATS)
 	PVRSRV_PROCESS_STATS*  psProcessStats;
 
 	/* Don't do anything if we are not initialised or we are shutting down! */
@@ -2339,44 +2541,41 @@
 		return;
 	}
 
-	_decrease_global_stat(PVRSRV_MEM_ALLOC_TYPE_VMALLOC, psVmallocHashEntry->uiSizeInBytes);
+	_decrease_global_stat(eAllocType, psTrackingHashEntry->uiSizeInBytes);
 
 	OSLockAcquire(g_psLinkedListLock);
 
-	psProcessStats = _FindProcessStats(psVmallocHashEntry->uiPid);
+	psProcessStats = _FindProcessStats(psTrackingHashEntry->uiPid);
 
 	if (psProcessStats != NULL)
 	{
-		/* Decrement the kmalloc memory stat... */
-		DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, psVmallocHashEntry->uiSizeInBytes);
+		/* Decrement the memory stat... */
+		_DecreaseProcStatValue(eAllocType,
+		                       psProcessStats,
+		                       psTrackingHashEntry->uiSizeInBytes);
 	}
 
 	OSLockRelease(g_psLinkedListLock);
-#endif
 }
 
 void
 PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
 									  IMG_UINT64 uiCpuVAddr)
 {
-	_PVR_STATS_VMALLOC_HASH_ENTRY *psVmallocHashEntry = NULL;
+	_PVR_STATS_TRACKING_HASH_ENTRY *psTrackingHashEntry = NULL;
 
-	if (!bProcessStatsInitialised || (gpsVmallocSizeHashTable == NULL) )
+	if (!bProcessStatsInitialised || (gpsSizeTrackingHashTable == NULL) )
 	{
 		return;
 	}
 
-	OSLockAcquire(gpsVmallocSizeHashTableLock);
-	psVmallocHashEntry = (_PVR_STATS_VMALLOC_HASH_ENTRY *)HASH_Remove(gpsVmallocSizeHashTable, uiCpuVAddr);
-	OSLockRelease(gpsVmallocSizeHashTableLock);
-	if (psVmallocHashEntry)
+	OSLockAcquire(gpsSizeTrackingHashTableLock);
+	psTrackingHashEntry = (_PVR_STATS_TRACKING_HASH_ENTRY *)HASH_Remove(gpsSizeTrackingHashTable, uiCpuVAddr);
+	OSLockRelease(gpsSizeTrackingHashTableLock);
+	if (psTrackingHashEntry)
 	{
-		_StatsDecrMemVAllocStat(psVmallocHashEntry);
-#if defined(__linux__)
-		OSFreeMemNoStats(psVmallocHashEntry);
-#else
-		OSFreeMem(psVmallocHashEntry);
-#endif
+		_StatsDecrMemTrackedStat(psTrackingHashEntry, eAllocType);
+		OSFreeMemNoStats(psTrackingHashEntry);
 	}
 }
 
@@ -2423,109 +2622,9 @@
 		 * this ensures if the process is in deadlist the entry cannot be deleted or modified */
 		OSLockRelease(g_psLinkedListLock);
 		/* Update the memory watermarks... */
-		switch (eAllocType)
-		{
-#if !defined(PVR_DISABLE_KMALLOC_MEMSTATS)
-			case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_KMALLOC-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_VMALLOC-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-#else
-			case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
-			case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
-			break;
-#endif
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
-			{
-				DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, (IMG_UINT32)uiBytes);
-				if( psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] == 0 )
-				{
-					psProcessStats->ui32StatAllocFlags &= ~(IMG_UINT32)(1 << (PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES-PVRSRV_PROCESS_STAT_TYPE_KMALLOC));
-				}
-			}
-			break;
-
-			default:
-			{
-				PVR_ASSERT(0);
-			}
-			break;
-		}
+		_DecreaseProcStatValue(eAllocType,
+		                       psProcessStats,
+		                       uiBytes);
 		OSLockRelease(psProcessStats->hLock);
 
 #if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
@@ -2535,7 +2634,9 @@
 			OSLockAcquire(g_psLinkedListLock);
 			_MoveProcessToDeadList(psProcessStats);
 			OSLockRelease(g_psLinkedListLock);
+#if defined(ENABLE_DEBUGFS)
 			_MoveProcessToDeadListDebugFS(psProcessStats);
+#endif
 
 			/* Check if the dead list needs to be reduced */
 			_CompressMemoryUsage();
@@ -2605,7 +2706,6 @@
 	OSLockRelease(g_psLinkedListLock);
 } /* PVRSRVStatsUpdateRenderContextStats */
 
-
 void
 PVRSRVStatsUpdateZSBufferStats(IMG_UINT32 ui32NumReqByApp,
 							   IMG_UINT32 ui32NumReqByFW,
@@ -2636,7 +2736,6 @@
 	OSLockRelease(g_psLinkedListLock);
 } /* PVRSRVStatsUpdateZSBufferStats */
 
-
 void
 PVRSRVStatsUpdateFreelistStats(IMG_UINT32 ui32NumGrowReqByApp,
 							   IMG_UINT32 ui32NumGrowReqByFW,
@@ -2688,7 +2787,7 @@
 	OSLockRelease(g_psLinkedListLock);
 } /* PVRSRVStatsUpdateFreelistStats */
 
-
+#if defined(PVRSRV_ENABLE_PROCESS_STATS_DEBUGFS)
 /*************************************************************************/ /*!
 @Function       ProcessStatsPrintElements
 @Description    Prints all elements for this process statistic record.
@@ -2729,7 +2828,317 @@
 		ui32StatNumber++;
 	}
 } /* ProcessStatsPrintElements */
+#endif
 
+#if defined(DEBUG)
+/* Divide a number by 10 using shifts only */
+static INLINE IMG_UINT64 DivBy10(IMG_UINT64 uiNum) 
+{
+	IMG_UINT64 uiQuot;
+	IMG_UINT64 uiRem;
+
+	uiQuot = (uiNum >> 1) + (uiNum >> 2);
+	uiQuot = uiQuot + (uiQuot >> 4);
+	uiQuot = uiQuot + (uiQuot >> 8);
+	uiQuot = uiQuot + (uiQuot >> 16);
+	uiQuot = uiQuot >> 3;
+	uiRem  = uiNum - (((uiQuot << 2) + uiQuot) << 1);
+
+	return uiQuot + (uiRem > 9);
+}
+
+void
+PVRSRVStatsUpdateCacheOpStats(PVRSRV_CACHE_OP uiCacheOp,
+							IMG_UINT32 ui32OpSeqNum,
+#if defined(PVR_RI_DEBUG)
+							IMG_DEV_VIRTADDR sDevVAddr,
+							IMG_UINT32 eFenceOpType,
+#endif
+							IMG_DEVMEM_SIZE_T uiOffset,
+							IMG_DEVMEM_SIZE_T uiSize,
+							IMG_UINT64 ui64ExecuteTime,
+							IMG_BOOL bRangeBasedFlush,
+							IMG_BOOL bUserModeFlush,
+							IMG_BOOL bHasTimeline,
+							IMG_BOOL bIsFence,
+							IMG_PID ownerPid)
+{
+	IMG_PID				   currentPid = (ownerPid!=0)?ownerPid:OSGetCurrentClientProcessIDKM();
+	PVRSRV_PROCESS_STATS*  psProcessStats;
+
+	/* Don't do anything if we are not initialised or we are shutting down! */
+	if (!bProcessStatsInitialised)
+	{
+		return;
+	}
+
+	/* Lock while we find the correct process and update the record... */
+	OSLockAcquire(g_psLinkedListLock);
+
+	psProcessStats = _FindProcessStats(currentPid);
+
+	if (psProcessStats != NULL)
+	{
+		IMG_INT32 Idx;
+
+		OSLockAcquireNested(psProcessStats->hLock, PROCESS_LOCK_SUBCLASS_CURRENT);
+
+		/* Look-up next buffer write index */
+		Idx = psProcessStats->uiCacheOpWriteIndex;
+		psProcessStats->uiCacheOpWriteIndex = INCREMENT_CACHEOP_STAT_IDX_WRAP(Idx);
+
+		/* Store all CacheOp meta-data */
+		psProcessStats->asCacheOp[Idx].uiCacheOp = uiCacheOp;
+#if defined(PVR_RI_DEBUG)
+		psProcessStats->asCacheOp[Idx].sDevVAddr = sDevVAddr;
+		psProcessStats->asCacheOp[Idx].eFenceOpType = eFenceOpType;
+#endif
+		psProcessStats->asCacheOp[Idx].uiOffset = uiOffset;
+		psProcessStats->asCacheOp[Idx].uiSize = uiSize;
+		psProcessStats->asCacheOp[Idx].bRangeBasedFlush = bRangeBasedFlush;
+		psProcessStats->asCacheOp[Idx].bUserModeFlush = bUserModeFlush;
+		psProcessStats->asCacheOp[Idx].ui64ExecuteTime = ui64ExecuteTime;
+		psProcessStats->asCacheOp[Idx].ui32OpSeqNum = ui32OpSeqNum;
+		psProcessStats->asCacheOp[Idx].bHasTimeline = bHasTimeline;
+		psProcessStats->asCacheOp[Idx].bIsFence = bIsFence;
+
+		OSLockRelease(psProcessStats->hLock);
+	}
+
+	OSLockRelease(g_psLinkedListLock);
+} /* PVRSRVStatsUpdateCacheOpStats */
+
+/*************************************************************************/ /*!
+@Function       CacheOpStatsPrintElements
+@Description    Prints all elements for this process statistic CacheOp record.
+@Input          pvStatPtr         Pointer to statistics structure.
+@Input          pfnOSStatsPrintf  Printf function to use for output.
+*/ /**************************************************************************/
+void
+CacheOpStatsPrintElements(void *pvFile,
+						  void *pvStatPtr,
+						  OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
+{
+	PVRSRV_STAT_STRUCTURE_TYPE*  peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
+	PVRSRV_PROCESS_STATS*		 psProcessStats  = (PVRSRV_PROCESS_STATS*) pvStatPtr;
+	IMG_CHAR					 *pszCacheOpType, *pszFlushType, *pszFlushMode;
+	IMG_INT32 					 i32WriteIdx, i32ReadIdx;
+
+#if defined(PVR_RI_DEBUG)
+	#define CACHEOP_RI_PRINTF_HEADER \
+		"%-10s %-10s %-5s %-16s %-10s %-10s %-12s %-12s\n"
+	#define CACHEOP_RI_PRINTF_FENCE	 \
+		"%-10s %-10s %-5s %-16s %-10s %-10s %-12llu 0x%-10x\n"
+	#define CACHEOP_RI_PRINTF		\
+		"%-10s %-10s %-5s 0x%-14llx 0x%-8llx 0x%-8llx %-12llu 0x%-10x\n"
+#else
+	#define CACHEOP_PRINTF_HEADER	\
+		"%-10s %-10s %-5s %-10s %-10s %-12s %-12s\n"
+	#define CACHEOP_PRINTF_FENCE	 \
+		"%-10s %-10s %-5s %-10s %-10s %-12llu 0x%-10x\n"
+	#define CACHEOP_PRINTF		 	\
+		"%-10s %-10s %-5s 0x%-8llx 0x%-8llx %-12llu 0x%-10x\n"
+#endif
+
+	if (peStructureType == NULL  ||
+		*peStructureType != PVRSRV_STAT_STRUCTURE_PROCESS ||
+		psProcessStats->psCacheOpStats->eStructureType != PVRSRV_STAT_STRUCTURE_CACHEOP)
+	{
+		PVR_ASSERT(peStructureType != NULL);
+		PVR_ASSERT(*peStructureType == PVRSRV_STAT_STRUCTURE_PROCESS);
+		PVR_ASSERT(psProcessStats->psCacheOpStats->eStructureType == PVRSRV_STAT_STRUCTURE_CACHEOP);
+		return;
+	}
+
+	if (pfnOSStatsPrintf == NULL)
+	{
+		return;
+	}
+
+	/* File header info */
+	pfnOSStatsPrintf(pvFile,
+#if defined(PVR_RI_DEBUG)
+					CACHEOP_RI_PRINTF_HEADER,
+#else
+					CACHEOP_PRINTF_HEADER,
+#endif
+					"CacheOp",
+					"Type",
+					"Mode",
+#if defined(PVR_RI_DEBUG)
+					"DevVAddr",
+#endif
+					"Offset",
+					"Size",
+					"Time (us)",
+					"SeqNo");
+
+	/* Take a snapshot of write index, read backwards in buffer 
+	   and wrap round at boundary */
+	i32WriteIdx = psProcessStats->uiCacheOpWriteIndex;
+	for (i32ReadIdx = DECREMENT_CACHEOP_STAT_IDX_WRAP(i32WriteIdx);
+		 i32ReadIdx != i32WriteIdx;
+		 i32ReadIdx = DECREMENT_CACHEOP_STAT_IDX_WRAP(i32ReadIdx))
+	{
+		IMG_UINT64 ui64ExecuteTime;
+
+		if (! psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum)
+		{
+			break;
+		}
+
+		/* Convert nano-seconds to micro-seconds */
+		ui64ExecuteTime = psProcessStats->asCacheOp[i32ReadIdx].ui64ExecuteTime;
+		ui64ExecuteTime = DivBy10(DivBy10(DivBy10(ui64ExecuteTime)));
+
+		if (psProcessStats->asCacheOp[i32ReadIdx].bIsFence)
+		{
+			IMG_CHAR *pszFenceType = "";
+			pszCacheOpType = "Fence";
+
+#if defined(PVR_RI_DEBUG)
+			switch (psProcessStats->asCacheOp[i32ReadIdx].eFenceOpType)
+			{
+				case RGXFWIF_DM_GP:
+					pszFenceType = "GP";
+					break;
+
+				case RGXFWIF_DM_TDM:
+					/* Also case RGXFWIF_DM_2D: */
+					pszFenceType = "TDM/2D";
+					break;
+	
+				case RGXFWIF_DM_TA:
+					pszFenceType = "TA";
+					break;
+
+				case RGXFWIF_DM_3D:
+					pszFenceType = "3D";
+					break;
+
+				case RGXFWIF_DM_CDM:
+					pszFenceType = "CDM";
+					break;
+
+				case RGXFWIF_DM_RTU:
+					pszFenceType = "RTU";
+					break;
+	
+				case RGXFWIF_DM_SHG:
+					pszFenceType = "SHG";
+					break;
+
+				default:
+					PVR_ASSERT(0);
+					break;
+			}
+#endif
+
+			pfnOSStatsPrintf(pvFile,
+#if defined(PVR_RI_DEBUG)
+							CACHEOP_RI_PRINTF_FENCE,
+#else
+							CACHEOP_PRINTF_FENCE,
+#endif
+							pszCacheOpType,
+							pszFenceType,
+							"",
+#if defined(PVR_RI_DEBUG)
+							"",
+#endif
+							"",
+							"",
+							ui64ExecuteTime,
+							psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum);
+		}
+		else if (psProcessStats->asCacheOp[i32ReadIdx].bHasTimeline)
+		{
+			pfnOSStatsPrintf(pvFile,
+#if defined(PVR_RI_DEBUG)
+							CACHEOP_RI_PRINTF_FENCE,
+#else
+							CACHEOP_PRINTF_FENCE,
+#endif
+							"Timeline",
+							"",
+							"",
+#if defined(PVR_RI_DEBUG)
+							"",
+#endif
+							"",
+							"",
+							ui64ExecuteTime,
+							psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum);
+		}
+		else
+		{
+			if (psProcessStats->asCacheOp[i32ReadIdx].bRangeBasedFlush)
+			{
+				IMG_DEVMEM_SIZE_T ui64NumOfPages;
+	
+				ui64NumOfPages = psProcessStats->asCacheOp[i32ReadIdx].uiSize >> OSGetPageShift();
+				if (ui64NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC)
+				{
+					pszFlushType = "RBF.Fast";
+				}
+				else
+				{
+					pszFlushType = "RBF.Slow";
+				}
+			}
+			else
+			{
+				pszFlushType = "GF";
+			}
+
+			if (psProcessStats->asCacheOp[i32ReadIdx].bUserModeFlush)
+			{
+				pszFlushMode = "UM";
+			}
+			else
+			{
+				pszFlushMode = "KM";
+			}
+
+			switch (psProcessStats->asCacheOp[i32ReadIdx].uiCacheOp)
+			{
+				case PVRSRV_CACHE_OP_NONE:
+					pszCacheOpType = "None";
+					break;
+				case PVRSRV_CACHE_OP_CLEAN:
+					pszCacheOpType = "Clean";
+					break;
+				case PVRSRV_CACHE_OP_INVALIDATE:
+					pszCacheOpType = "Invalidate";
+					break;
+				case PVRSRV_CACHE_OP_FLUSH:
+					pszCacheOpType = "Flush";
+					break;
+				default:
+					pszCacheOpType = "Unknown";
+					break;
+			}
+
+			pfnOSStatsPrintf(pvFile,
+#if defined(PVR_RI_DEBUG)
+							CACHEOP_RI_PRINTF,
+#else
+							CACHEOP_PRINTF,
+#endif
+							pszCacheOpType,
+							pszFlushType,
+							pszFlushMode,
+#if defined(PVR_RI_DEBUG)
+							psProcessStats->asCacheOp[i32ReadIdx].sDevVAddr.uiAddr,
+#endif
+							psProcessStats->asCacheOp[i32ReadIdx].uiOffset,
+							psProcessStats->asCacheOp[i32ReadIdx].uiSize,
+							ui64ExecuteTime,
+							psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum);
+		}
+	}
+} /* CacheOpStatsPrintElements */
+#endif
 
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
 /*************************************************************************/ /*!
@@ -2792,7 +3201,7 @@
 #else
 		case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
 		case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
-															bPrintStat = IMG_FALSE; break;
+														bPrintStat = IMG_FALSE; break;
 #endif
 		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:  pfnOSStatsPrintf(pvFile, "ALLOC_PAGES_PT_LMA  "); break;
 		case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:  pfnOSStatsPrintf(pvFile, "ALLOC_PAGES_PT_UMA  "); break;
@@ -2835,8 +3244,7 @@
 } /* MemStatsPrintElements */
 #endif
 
-
-#if defined(PVR_RI_DEBUG)
+#if defined(PVR_RI_DEBUG_DEBUGFS)
 /*************************************************************************/ /*!
 @Function       RIMemStatsPrintElements
 @Description    Prints all elements for the RI Memory record.
@@ -2876,7 +3284,6 @@
 } /* RIMemStatsPrintElements */
 #endif
 
-
 static IMG_UINT32	ui32FirmwareStartTimestamp=0;
 static IMG_UINT64	ui64FirmwareIdleDuration=0;
 
@@ -2890,7 +3297,6 @@
 	ui64FirmwareIdleDuration = UPDATE_TIME(ui64FirmwareIdleDuration, ui64Duration);
 }
 
-
 static INLINE void PowerStatsPrintGroup(IMG_UINT32 *pui32Stats,
                                         void *pvFile,
                                         OS_STATS_PRINTF_FUNC *pfnPrintf,
@@ -2960,7 +3366,6 @@
 
 } /* PowerStatsPrintElements */
 
-
 void GlobalStatsPrintElements(void *pvFile,
 							  void *pvStatPtr,
 							  OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf)
diff --git a/drivers/staging/imgtec/rogue/process_stats.h b/drivers/staging/imgtec/rogue/process_stats.h
index fce4ff2..2ef30cb 100644
--- a/drivers/staging/imgtec/rogue/process_stats.h
+++ b/drivers/staging/imgtec/rogue/process_stats.h
@@ -43,7 +43,10 @@
 #ifndef __PROCESS_STATS_H__
 #define __PROCESS_STATS_H__
 
+#include <powervr/mem_types.h>
+
 #include "pvrsrv_error.h"
+#include "cache_ops.h"
 
 /*
  *  The publishing of Process Stats is controlled by the
@@ -123,7 +126,7 @@
 								 size_t uiBytes);
 
 void PVRSRVStatsDecrMemKAllocStat(size_t uiBytes,
-        						  IMG_PID decrPID);
+								  IMG_PID decrPID);
 
 /*
  * Decrease the memory stat for eAllocType. Takes the allocation size value from the
@@ -156,6 +159,20 @@
 									 IMG_UINT32 ui32NumHighPages,
 									 IMG_PID	ownerPid);
 
+void  PVRSRVStatsUpdateCacheOpStats(PVRSRV_CACHE_OP uiCacheOp,
+									IMG_UINT32 ui32OpSeqNum,
+#if defined(PVR_RI_DEBUG)
+									IMG_DEV_VIRTADDR sDevVAddr,
+									IMG_UINT32 eFenceOpType,
+#endif
+									IMG_DEVMEM_SIZE_T uiOffset,
+									IMG_DEVMEM_SIZE_T uiSize,
+									IMG_UINT64 ui64ExecuteTimeMs,
+									IMG_BOOL bRangeBasedFlush,
+									IMG_BOOL bUserModeFlush,
+									IMG_BOOL bIsTimeline,
+									IMG_BOOL bIsFence,
+									IMG_PID ownerPid);
 
 /* Update pre/post power transition timing statistics */
 void InsertPowerTimeStatistic(IMG_UINT64 ui64SysStartTime, IMG_UINT64 ui64SysEndTime,
diff --git a/drivers/staging/imgtec/rogue/pvr_bridge.h b/drivers/staging/imgtec/rogue/pvr_bridge.h
index d30fcc5..f8c62a6 100644
--- a/drivers/staging/imgtec/rogue/pvr_bridge.h
+++ b/drivers/staging/imgtec/rogue/pvr_bridge.h
@@ -49,16 +49,22 @@
 #endif
 
 #include "pvrsrv_error.h"
-#include "common_cachegeneric_bridge.h"
-
 #if defined(SUPPORT_DISPLAY_CLASS)
 #include "common_dc_bridge.h"
+#  if defined(SUPPORT_DCPLAT_BRIDGE)
+#    include "common_dcplat_bridge.h"
+#  endif
 #endif
 #include "common_mm_bridge.h"
 #if defined(SUPPORT_MMPLAT_BRIDGE)
 #include "common_mmplat_bridge.h"
 #endif
+#if defined(SUPPORT_WRAP_EXTMEM)
+#include "common_mmextmem_bridge.h"
+#endif
+#if !defined(EXCLUDE_CMM_BRIDGE)
 #include "common_cmm_bridge.h"
+#endif
 #if defined(LINUX)
 #include "common_dmabuf_bridge.h"
 #endif
@@ -67,6 +73,7 @@
 #include "common_pdumpctrl_bridge.h"
 #include "common_pdumpmm_bridge.h"
 #endif
+#include "common_cache_bridge.h"
 #include "common_srvcore_bridge.h"
 #include "common_sync_bridge.h"
 #if defined(SUPPORT_SERVER_SYNC)
@@ -80,13 +87,15 @@
 #if defined(SUPPORT_SECURE_EXPORT)
 #include "common_smm_bridge.h"
 #endif
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 #include "common_htbuffer_bridge.h"
+#endif
 #include "common_pvrtl_bridge.h"
 #if defined(PVR_RI_DEBUG)
 #include "common_ri_bridge.h"
 #endif
 
-#if defined(SUPPORT_VALIDATION)
+#if defined(SUPPORT_VALIDATION_BRIDGE)
 #include "common_validation_bridge.h"
 #endif
 
@@ -94,10 +103,14 @@
 #include "common_tutils_bridge.h"
 #endif
 
-#if defined(SUPPORT_PAGE_FAULT_DEBUG)
+#if defined(SUPPORT_DEVICEMEMHISTORY_BRIDGE)
 #include "common_devicememhistory_bridge.h"
 #endif
 
+#if defined(SUPPORT_SYNCTRACKING_BRIDGE)
+#include "common_synctracking_bridge.h"
+#endif
+
 /* 
  * Bridge Cmd Ids
  */
@@ -119,6 +132,7 @@
  * the feature is not enabled (each bridge group retains its own ioctl number).
  */
 
+#define PVRSRV_BRIDGE_FIRST                                     0UL
 
 /*	 0:	Default handler */
 #define PVRSRV_BRIDGE_DEFAULT					0UL
@@ -181,8 +195,13 @@
 
 /*   8: Context Memory Management functions */
 #define PVRSRV_BRIDGE_CMM      				8UL
+#if !defined(EXCLUDE_CMM_BRIDGE)
 #define PVRSRV_BRIDGE_CMM_DISPATCH_FIRST	(PVRSRV_BRIDGE_MMPLAT_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_CMM_DISPATCH_LAST		(PVRSRV_BRIDGE_CMM_DISPATCH_FIRST + PVRSRV_BRIDGE_CMM_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_CMM_DISPATCH_FIRST 0
+#define PVRSRV_BRIDGE_CMM_DISPATCH_LAST	 (PVRSRV_BRIDGE_MMPLAT_DISPATCH_LAST)
+#endif
 
 /*   9: PDUMP Memory Management functions */
 #define PVRSRV_BRIDGE_PDUMPMM      			9UL
@@ -224,19 +243,19 @@
 #define PVRSRV_BRIDGE_DC_DISPATCH_LAST		(PVRSRV_BRIDGE_DMABUF_DISPATCH_LAST)
 #endif
 
-/*  13: Generic cache interface functions*/
-#define PVRSRV_BRIDGE_CACHEGENERIC			13UL
-#define PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_FIRST (PVRSRV_BRIDGE_DC_DISPATCH_LAST + 1)
-#define PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_LAST  (PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_FIRST + PVRSRV_BRIDGE_CACHEGENERIC_CMD_LAST)
+/*  13: Cache interface functions */
+#define PVRSRV_BRIDGE_CACHE					13UL
+#define PVRSRV_BRIDGE_CACHE_DISPATCH_FIRST (PVRSRV_BRIDGE_DC_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_CACHE_DISPATCH_LAST  (PVRSRV_BRIDGE_CACHE_DISPATCH_FIRST + PVRSRV_BRIDGE_CACHE_CMD_LAST)
 
 /*  14: Secure Memory Management functions*/
 #define PVRSRV_BRIDGE_SMM					14UL
 #if defined(SUPPORT_SECURE_EXPORT)
-#define PVRSRV_BRIDGE_SMM_DISPATCH_FIRST   (PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_SMM_DISPATCH_FIRST    (PVRSRV_BRIDGE_CACHE_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_SMM_DISPATCH_LAST  	(PVRSRV_BRIDGE_SMM_DISPATCH_FIRST + PVRSRV_BRIDGE_SMM_CMD_LAST)
 #else
 #define PVRSRV_BRIDGE_SMM_DISPATCH_FIRST   0
-#define PVRSRV_BRIDGE_SMM_DISPATCH_LAST  	(PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_LAST)
+#define PVRSRV_BRIDGE_SMM_DISPATCH_LAST  	(PVRSRV_BRIDGE_CACHE_DISPATCH_LAST)
 #endif
 
 /*  15: Transport Layer interface functions */
@@ -256,7 +275,7 @@
 
 /*  17: Validation interface functions */
 #define PVRSRV_BRIDGE_VALIDATION				17UL
-#if defined(SUPPORT_VALIDATION)
+#if defined(SUPPORT_VALIDATION_BRIDGE)
 #define PVRSRV_BRIDGE_VALIDATION_DISPATCH_FIRST (PVRSRV_BRIDGE_RI_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_VALIDATION_DISPATCH_LAST  (PVRSRV_BRIDGE_VALIDATION_DISPATCH_FIRST + PVRSRV_BRIDGE_VALIDATION_CMD_LAST)
 #else
@@ -276,7 +295,7 @@
 
 /*  19: DevMem history interface functions */
 #define PVRSRV_BRIDGE_DEVICEMEMHISTORY		19UL
-#if defined(SUPPORT_PAGE_FAULT_DEBUG)
+#if defined(SUPPORT_DEVICEMEMHISTORY_BRIDGE)
 #define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DISPATCH_FIRST (PVRSRV_BRIDGE_TUTILS_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_DEVICEMEMHISTORY_DISPATCH_LAST  (PVRSRV_BRIDGE_DEVICEMEMHISTORY_DISPATCH_FIRST + PVRSRV_BRIDGE_DEVICEMEMHISTORY_CMD_LAST)
 #else
@@ -286,17 +305,124 @@
 
 /*  20: Host Trace Buffer interface functions */
 #define PVRSRV_BRIDGE_HTBUFFER                 20UL
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 #define PVRSRV_BRIDGE_HTBUFFER_DISPATCH_FIRST  (PVRSRV_BRIDGE_DEVICEMEMHISTORY_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_HTBUFFER_DISPATCH_LAST   (PVRSRV_BRIDGE_HTBUFFER_DISPATCH_FIRST + PVRSRV_BRIDGE_HTBUFFER_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_HTBUFFER_DISPATCH_FIRST 0
+#define PVRSRV_BRIDGE_HTBUFFER_DISPATCH_LAST  (PVRSRV_BRIDGE_DEVICEMEMHISTORY_DISPATCH_LAST)
+#endif
+
+/*  21: Non-Linux Display functions */
+#define PVRSRV_BRIDGE_DCPLAT          		21UL
+#if defined(SUPPORT_DISPLAY_CLASS) && defined (SUPPORT_DCPLAT_BRIDGE)
+#define PVRSRV_BRIDGE_DCPLAT_DISPATCH_FIRST	(PVRSRV_BRIDGE_HTBUFFER_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_DCPLAT_DISPATCH_LAST	(PVRSRV_BRIDGE_DCPLAT_DISPATCH_FIRST + PVRSRV_BRIDGE_DCPLAT_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_DCPLAT_DISPATCH_FIRST 0
+#define PVRSRV_BRIDGE_DCPLAT_DISPATCH_LAST	(PVRSRV_BRIDGE_HTBUFFER_DISPATCH_LAST)
+#endif
+
+/*  22: Extmem functions */
+#define PVRSRV_BRIDGE_MMEXTMEM				   22UL
+#if defined(SUPPORT_WRAP_EXTMEM)
+#define PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_FIRST (PVRSRV_BRIDGE_DCPLAT_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_LAST  (PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_FIRST + PVRSRV_BRIDGE_MMEXTMEM_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_FIRST 0
+#define PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_LAST (PVRSRV_BRIDGE_DCPLAT_DISPATCH_LAST)
+#endif
+
+/*  23: Sync tracking functions */
+#define PVRSRV_BRIDGE_SYNCTRACKING				   23UL
+#if defined(SUPPORT_SYNCTRACKING_BRIDGE)
+#define PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_FIRST (PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_LAST  (PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_FIRST + PVRSRV_BRIDGE_SYNCTRACKING_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_FIRST 0
+#define PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_LAST (PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_LAST)
+#endif
 
 /* NB PVRSRV_BRIDGE_LAST below must be the last bridge group defined above (PVRSRV_BRIDGE_FEATURE) */
-#define PVRSRV_BRIDGE_LAST       			(PVRSRV_BRIDGE_HTBUFFER)
+#define PVRSRV_BRIDGE_LAST       			(PVRSRV_BRIDGE_SYNCTRACKING)
 /* NB PVRSRV_BRIDGE_DISPATCH LAST below must be the last dispatch entry defined above (PVRSRV_BRIDGE_FEATURE_DISPATCH_LAST) */
-#define PVRSRV_BRIDGE_DISPATCH_LAST			(PVRSRV_BRIDGE_HTBUFFER_DISPATCH_LAST)
+#define PVRSRV_BRIDGE_DISPATCH_LAST			(PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_LAST)
 
+/* bit mask representing the enabled PVR bridges */
+
+static const IMG_UINT32 gui32PVRBridges =
+	  (1U << (PVRSRV_BRIDGE_DEFAULT - PVRSRV_BRIDGE_FIRST))
+	| (1U << (PVRSRV_BRIDGE_SRVCORE - PVRSRV_BRIDGE_FIRST))
+	| (1U << (PVRSRV_BRIDGE_SYNC - PVRSRV_BRIDGE_FIRST))
+#if defined(SUPPORT_INSECURE_EXPORT) && defined(SUPPORT_SERVER_SYNC)
+	| (1U << (PVRSRV_BRIDGE_SYNCEXPORT - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_SECURE_EXPORT) && defined(SUPPORT_SERVER_SYNC)
+	| (1U << (PVRSRV_BRIDGE_SYNCSEXPORT - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(PDUMP)
+	| (1U << (PVRSRV_BRIDGE_PDUMPCTRL - PVRSRV_BRIDGE_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_MM - PVRSRV_BRIDGE_FIRST))
+#if defined(SUPPORT_MMPLAT_BRIDGE)
+	| (1U << (PVRSRV_BRIDGE_MMPLAT - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_CMM)
+	| (1U << (PVRSRV_BRIDGE_CMM - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(PDUMP)
+	| (1U << (PVRSRV_BRIDGE_PDUMPMM - PVRSRV_BRIDGE_FIRST))
+	| (1U << (PVRSRV_BRIDGE_PDUMP - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(LINUX)
+	| (1U << (PVRSRV_BRIDGE_DMABUF - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_DISPLAY_CLASS)
+	| (1U << (PVRSRV_BRIDGE_DC - PVRSRV_BRIDGE_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_CACHE - PVRSRV_BRIDGE_FIRST))
+#if defined(SUPPORT_SECURE_EXPORT)
+	| (1U << (PVRSRV_BRIDGE_SMM - PVRSRV_BRIDGE_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_PVRTL - PVRSRV_BRIDGE_FIRST))
+#if defined(PVR_RI_DEBUG)
+	| (1U << (PVRSRV_BRIDGE_RI - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_VALIDATION)
+	| (1U << (PVRSRV_BRIDGE_VALIDATION - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(PVR_TESTING_UTILS)
+	| (1U << (PVRSRV_BRIDGE_TUTILS - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_DEVICEMEMHISTORY_BRIDGE)
+	| (1U << (PVRSRV_BRIDGE_DEVICEMEMHISTORY - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_HTBUFFER)
+	| (1U << (PVRSRV_BRIDGE_HTBUFFER - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_DISPLAY_CLASS) && defined (SUPPORT_DCPLAT_BRIDGE)
+	| (1U << (PVRSRV_BRIDGE_DCPLAT - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_WRAP_EXTMEM)
+	| (1U << (PVRSRV_BRIDGE_MMEXTMEM - PVRSRV_BRIDGE_FIRST))
+#endif
+#if defined(SUPPORT_SYNCTRACKING_BRIDGE)
+	| (1U << (PVRSRV_BRIDGE_SYNCTRACKING - PVRSRV_BRIDGE_FIRST))
+#endif
+	;
+
+/* bit field representing which PVR bridge groups may optionally not
+ * be present in the server
+ */
+#define PVR_BRIDGES_OPTIONAL \
+	( \
+		(1U << (PVRSRV_BRIDGE_RI - PVRSRV_BRIDGE_FIRST)) | \
+		(1U << (PVRSRV_BRIDGE_DEVICEMEMHISTORY - PVRSRV_BRIDGE_FIRST)) | \
+		(1U << (PVRSRV_BRIDGE_SYNCTRACKING - PVRSRV_BRIDGE_FIRST)) \
+	)
 
 /******************************************************************************
- * Generic bridge structures 
+ * Generic bridge structures
  *****************************************************************************/
 
 
@@ -314,7 +440,6 @@
 	IMG_UINT32				ui32OutBufferSize;		/*!< size of output data buffer */
 }PVRSRV_BRIDGE_PACKAGE;
 
-
 #if defined (__cplusplus)
 }
 #endif
diff --git a/drivers/staging/imgtec/rogue/pvr_bridge_k.c b/drivers/staging/imgtec/rogue/pvr_bridge_k.c
index b8964b9..8a9daad 100644
--- a/drivers/staging/imgtec/rogue/pvr_bridge_k.c
+++ b/drivers/staging/imgtec/rogue/pvr_bridge_k.c
@@ -53,11 +53,14 @@
 #include "private_data.h"
 #include "linkage.h"
 #include "pmr.h"
+#include "rgx_bvnc_defs_km.h"
 
-#if defined(SUPPORT_DRM)
 #include <drm/drmP.h>
 #include "pvr_drm.h"
-#endif /* defined(SUPPORT_DRM) */
+#include "pvr_drv.h"
+
+#include "env_connection.h"
+#include <linux/sched.h>
 
 /* RGX: */
 #if defined(SUPPORT_RGX)
@@ -67,6 +70,12 @@
 #include "srvcore.h"
 #include "common_srvcore_bridge.h"
 
+#if defined(SUPPORT_DRM_EXT)
+#define CAST_BRIDGE_CMD_PTR_TO_PTR(ptr) (ptr)
+#else
+#define CAST_BRIDGE_CMD_PTR_TO_PTR(ptr) (void *)(uintptr_t)(ptr)
+#endif
+
 #if defined(MODULE_TEST)
 /************************************************************************/
 // additional includes for services testing
@@ -112,14 +121,17 @@
 #endif
 PVRSRV_ERROR InitMMBridge(void);
 PVRSRV_ERROR DeinitMMBridge(void);
+#if !defined(EXCLUDE_CMM_BRIDGE)
 PVRSRV_ERROR InitCMMBridge(void);
 PVRSRV_ERROR DeinitCMMBridge(void);
+#endif
 PVRSRV_ERROR InitPDUMPMMBridge(void);
 PVRSRV_ERROR DeinitPDUMPMMBridge(void);
 PVRSRV_ERROR InitSRVCOREBridge(void);
 PVRSRV_ERROR DeinitSRVCOREBridge(void);
 PVRSRV_ERROR InitSYNCBridge(void);
 PVRSRV_ERROR DeinitSYNCBridge(void);
+
 #if defined(SUPPORT_SERVER_SYNC)
 #if defined(SUPPORT_INSECURE_EXPORT)
 PVRSRV_ERROR InitSYNCEXPORTBridge(void);
@@ -130,40 +142,51 @@
 PVRSRV_ERROR DeinitSYNCSEXPORTBridge(void);
 #endif
 #endif /* defined(SUPPORT_SERVER_SYNC) */
+
 #if defined (SUPPORT_RGX)
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 PVRSRV_ERROR InitRGXINITBridge(void);
 PVRSRV_ERROR DeinitRGXINITBridge(void);
+#endif
 PVRSRV_ERROR InitRGXTA3DBridge(void);
 PVRSRV_ERROR DeinitRGXTA3DBridge(void);
 PVRSRV_ERROR InitRGXTQBridge(void);
 PVRSRV_ERROR DeinitRGXTQBridge(void);
+PVRSRV_ERROR InitRGXTQ2Bridge(void);
+PVRSRV_ERROR DeinitRGXTQ2Bridge(void);
 PVRSRV_ERROR InitRGXCMPBridge(void);
 PVRSRV_ERROR DeinitRGXCMPBridge(void);
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
 PVRSRV_ERROR InitBREAKPOINTBridge(void);
 PVRSRV_ERROR DeinitBREAKPOINTBridge(void);
+#endif
 PVRSRV_ERROR InitDEBUGMISCBridge(void);
 PVRSRV_ERROR DeinitDEBUGMISCBridge(void);
 PVRSRV_ERROR InitRGXHWPERFBridge(void);
 PVRSRV_ERROR DeinitRGXHWPERFBridge(void);
-#if defined(RGX_FEATURE_RAY_TRACING)
 PVRSRV_ERROR InitRGXRAYBridge(void);
 PVRSRV_ERROR DeinitRGXRAYBridge(void);
-#endif /* RGX_FEATURE_RAY_TRACING */
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
 PVRSRV_ERROR InitREGCONFIGBridge(void);
 PVRSRV_ERROR DeinitREGCONFIGBridge(void);
+#endif
 PVRSRV_ERROR InitTIMERQUERYBridge(void);
 PVRSRV_ERROR DeinitTIMERQUERYBridge(void);
 PVRSRV_ERROR InitRGXKICKSYNCBridge(void);
 PVRSRV_ERROR DeinitRGXKICKSYNCBridge(void);
+PVRSRV_ERROR InitRGXSIGNALSBridge(void);
+PVRSRV_ERROR DeinitRGXSIGNALSBridge(void);
 #endif /* SUPPORT_RGX */
-PVRSRV_ERROR InitCACHEGENERICBridge(void);
-PVRSRV_ERROR DeinitCACHEGENERICBridge(void);
+PVRSRV_ERROR InitCACHEBridge(void);
+PVRSRV_ERROR DeinitCACHEBridge(void);
 #if defined(SUPPORT_SECURE_EXPORT)
 PVRSRV_ERROR InitSMMBridge(void);
 PVRSRV_ERROR DeinitSMMBridge(void);
 #endif
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 PVRSRV_ERROR InitHTBUFFERBridge(void);
 PVRSRV_ERROR DeinitHTBUFFERBridge(void);
+#endif
 PVRSRV_ERROR InitPVRTLBridge(void);
 PVRSRV_ERROR DeinitPVRTLBridge(void);
 #if defined(PVR_RI_DEBUG)
@@ -176,13 +199,115 @@
 #endif
 PVRSRV_ERROR InitDMABUFBridge(void);
 PVRSRV_ERROR DeinitDMABUFBridge(void);
-#if defined(SUPPORT_VALIDATION)
+#if defined(SUPPORT_VALIDATION_BRIDGE)
 PVRSRV_ERROR InitVALIDATIONBridge(void);
 #endif
+
 #if defined(PVR_TESTING_UTILS)
 PVRSRV_ERROR InitTUTILSBridge(void);
 PVRSRV_ERROR DeinitTUTILSBridge(void);
 #endif
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+PVRSRV_ERROR InitSYNCTRACKINGBridge(void);
+PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void);
+#endif
+#if defined(SUPPORT_WRAP_EXTMEM)
+PVRSRV_ERROR InitMMEXTMEMBridge(void);
+PVRSRV_ERROR DeinitMMEXTMEMBridge(void);
+#endif
+
+PVRSRV_ERROR
+DeviceDepBridgeInit(IMG_UINT64 ui64Features)
+{
+	PVRSRV_ERROR eError;
+
+	if(ui64Features & RGX_FEATURE_COMPUTE_BIT_MASK)
+	{
+		eError = InitRGXCMPBridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+
+	if(ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK)
+	{
+		eError = InitRGXSIGNALSBridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	if(ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+	{
+		eError = InitRGXRAYBridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	if(ui64Features & RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
+	{
+		eError = InitRGXTQ2Bridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+DeviceDepBridgeDeInit(IMG_UINT64 ui64Features)
+{
+	PVRSRV_ERROR eError;
+
+	if(ui64Features & RGX_FEATURE_COMPUTE_BIT_MASK)
+	{
+		eError = DeinitRGXCMPBridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+
+	if(ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK)
+	{
+		eError = DeinitRGXSIGNALSBridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	if(ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+	{
+		eError = DeinitRGXRAYBridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	if(ui64Features & RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
+	{
+		eError = DeinitRGXTQ2Bridge();
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
 
 PVRSRV_ERROR
 LinuxBridgeInit(void)
@@ -249,11 +374,13 @@
 	{
 		return eError;
 	}
+#if !defined(EXCLUDE_CMM_BRIDGE)
 	eError = InitCMMBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 #if defined(PDUMP)
 	eError = InitPDUMPMMBridge();
@@ -282,7 +409,7 @@
 	}
 #endif
 
-	eError = InitCACHEGENERICBridge();
+	eError = InitCACHEBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
@@ -296,11 +423,13 @@
 	}
 #endif
 
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 	eError = InitHTBUFFERBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = InitPVRTLBridge();
 	if (eError != PVRSRV_OK)
@@ -316,7 +445,7 @@
 	}
 	#endif
 
-#if defined(SUPPORT_VALIDATION)
+#if defined(SUPPORT_VALIDATION_BRIDGE)
 	eError = InitVALIDATIONBridge();
 	if (eError != PVRSRV_OK)
 	{
@@ -340,26 +469,30 @@
 	}
 #endif
 
-	#if defined (SUPPORT_RGX)
-	eError = InitRGXTQBridge();
-	if (eError != PVRSRV_OK)
-	{
-		return eError;
-	}
 
-#if defined(RGX_FEATURE_COMPUTE)
-	eError = InitRGXCMPBridge();
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	eError = InitSYNCTRACKINGBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
 #endif
 
+	#if defined (SUPPORT_RGX)
+
+	eError = InitRGXTQBridge();
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 	eError = InitRGXINITBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = InitRGXTA3DBridge();
 	if (eError != PVRSRV_OK)
@@ -367,11 +500,13 @@
 		return eError;
 	}
 
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
 	eError = InitBREAKPOINTBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = InitDEBUGMISCBridge();
 	if (eError != PVRSRV_OK)
@@ -393,19 +528,13 @@
 		return eError;
 	}
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	eError = InitRGXRAYBridge();
-	if (eError != PVRSRV_OK)
-	{
-		return eError;
-	}
-#endif /* RGX_FEATURE_RAY_TRACING */
-
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
 	eError = InitREGCONFIGBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = InitTIMERQUERYBridge();
 	if (eError != PVRSRV_OK)
@@ -419,9 +548,16 @@
 		return eError;
 	}
 
-
 #endif /* SUPPORT_RGX */
 
+#if defined(SUPPORT_WRAP_EXTMEM)
+	eError = InitMMEXTMEMBridge();
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+#endif
+
 	return eError;
 }
 
@@ -429,6 +565,15 @@
 LinuxBridgeDeInit(void)
 {
 	PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_WRAP_EXTMEM)
+	eError = DeinitMMEXTMEMBridge();
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+#endif
+
 #if defined(DEBUG_BRIDGE_KM)
 	if (gpsPVRDebugFSBridgeStatsEntry != NULL)
 	{
@@ -478,11 +623,13 @@
 	{
 		return eError;
 	}
+#if !defined(EXCLUDE_CMM_BRIDGE)
 	eError = DeinitCMMBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 #if defined(PDUMP)
 	eError = DeinitPDUMPMMBridge();
@@ -519,7 +666,7 @@
 	}
 #endif
 
-	eError = DeinitCACHEGENERICBridge();
+	eError = DeinitCACHEBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
@@ -533,11 +680,13 @@
 	}
 #endif
 
+#if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 	eError = DeinitHTBUFFERBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = DeinitPVRTLBridge();
 	if (eError != PVRSRV_OK)
@@ -561,26 +710,31 @@
 	}
 #endif
 
-	#if defined (SUPPORT_RGX)
-	eError = DeinitRGXTQBridge();
-	if (eError != PVRSRV_OK)
-	{
-		return eError;
-	}
 
-#if defined(RGX_FEATURE_COMPUTE)
-	eError = DeinitRGXCMPBridge();
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	eError = DeinitSYNCTRACKINGBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
 #endif
 
+	#if defined (SUPPORT_RGX)
+
+	eError = DeinitRGXTQBridge();
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 	eError = DeinitRGXINITBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = DeinitRGXTA3DBridge();
 	if (eError != PVRSRV_OK)
@@ -588,11 +742,13 @@
 		return eError;
 	}
 
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
 	eError = DeinitBREAKPOINTBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = DeinitDEBUGMISCBridge();
 	if (eError != PVRSRV_OK)
@@ -614,19 +770,13 @@
 		return eError;
 	}
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	eError = DeinitRGXRAYBridge();
-	if (eError != PVRSRV_OK)
-	{
-		return eError;
-	}
-#endif /* RGX_FEATURE_RAY_TRACING */
-
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
 	eError = DeinitREGCONFIGBridge();
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
 	}
+#endif
 
 	eError = DeinitTIMERQUERYBridge();
 	if (eError != PVRSRV_OK)
@@ -640,7 +790,6 @@
 		return eError;
 	}
 
-
 #endif /* SUPPORT_RGX */
 
 	return eError;
@@ -703,29 +852,35 @@
 			   "Total number of bytes copied via copy_from_user = %u\n"
 			   "Total number of bytes copied via copy_to_user = %u\n"
 			   "Total number of bytes copied via copy_*_user = %u\n\n"
-			   "%-60s | %-48s | %10s | %20s | %10s\n",
+			   "%3s: %-60s | %-48s | %10s | %20s | %20s | %20s | %20s \n",
 			   g_BridgeGlobalStats.ui32IOCTLCount,
 			   g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
 			   g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
 			   g_BridgeGlobalStats.ui32TotalCopyFromUserBytes + g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
-			   "  #: Bridge Name",
+			   "#",
+			   "Bridge Name",
 			   "Wrapper Function",
 			   "Call Count",
-			   "copy_from_user Bytes",
-			   "copy_to_user Bytes");
+			   "copy_from_user (B)",
+			   "copy_to_user (B)",
+			   "Total Time (us)",
+			   "Max Time (us)");
 	}
 	else if (pvData != NULL)
 	{
 		PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = (	PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)pvData;
+		IMG_UINT32 ui32Remainder;
 
 		seq_printf(psSeqFile,
-			   "%3d: %-60s   %-48s   %-10u   %-20u   %-10u\n",
-			   (IMG_UINT32)(((size_t)psEntry-(size_t)g_BridgeDispatchTable)/sizeof(PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY)),
+			   "%3d: %-60s   %-48s   %-10u   %-20u   %-20u   %-20llu   %-20llu\n",
+			   (IMG_UINT32)(((size_t)psEntry-(size_t)g_BridgeDispatchTable)/sizeof(*g_BridgeDispatchTable)),
 			   psEntry->pszIOCName,
-			   psEntry->pszFunctionName,
+			   (psEntry->pfFunction != NULL) ? psEntry->pszFunctionName : "(null)",
 			   psEntry->ui32CallCount,
 			   psEntry->ui32CopyFromUserTotalBytes,
-			   psEntry->ui32CopyToUserTotalBytes);
+			   psEntry->ui32CopyToUserTotalBytes,
+			   (unsigned long long) OSDivide64r64(psEntry->ui64TotalTimeNS, 1000, &ui32Remainder),
+			   (unsigned long long) OSDivide64r64(psEntry->ui64MaxTimeNS, 1000, &ui32Remainder));
 	}
 
 	return 0;
@@ -740,23 +895,13 @@
 };
 #endif /* defined(DEBUG_BRIDGE_KM) */
 
-
-#if defined(SUPPORT_DRM)
 int
-PVRSRV_BridgeDispatchKM(struct drm_device unref__ *dev, void *arg, struct drm_file *pDRMFile)
-#else
-long
-PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int ioctlCmd, unsigned long arg)
-#endif
+PVRSRV_BridgeDispatchKM(struct drm_device __maybe_unused *dev, void *arg, struct drm_file *pDRMFile)
 {
-#if defined(SUPPORT_DRM)
-	struct file *pFile = PVR_FILE_FROM_DRM_FILE(pDRMFile);
-#else
-	PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
-	PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
-#endif
-	PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
-	CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
+	struct drm_pvr_srvkm_cmd *psSrvkmCmd = (struct drm_pvr_srvkm_cmd *) arg;
+	PVRSRV_BRIDGE_PACKAGE sBridgePackageKM = { 0 };
+	CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pDRMFile->filp);
+	PVRSRV_ERROR error;
 
 	if(psConnection == NULL)
 	{
@@ -769,138 +914,26 @@
 		return -EINTR;
 	}
 
-#if defined(SUPPORT_DRM)
-	psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
-	PVR_ASSERT(psBridgePackageKM != NULL);
-#else
+	PVR_ASSERT(psSrvkmCmd != NULL);
 
-	psBridgePackageKM = &sBridgePackageKM;
+	DRM_DEBUG("tgid=%d, tgid_connection=%d, bridge_id=%d, func_id=%d",
+			  task_tgid_nr(current),
+			  ((ENV_CONNECTION_DATA *)PVRSRVConnectionPrivateData(psConnection))->owner,
+			  psSrvkmCmd->bridge_id,
+			  psSrvkmCmd->bridge_func_id);
 
-	if (!OSAccessOK(PVR_VERIFY_WRITE,
-				   psBridgePackageUM,
-				   sizeof(PVRSRV_BRIDGE_PACKAGE)))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
-				 __FUNCTION__));
+	sBridgePackageKM.ui32BridgeID = psSrvkmCmd->bridge_id;
+	sBridgePackageKM.ui32FunctionID = psSrvkmCmd->bridge_func_id;
+	sBridgePackageKM.ui32Size = sizeof(sBridgePackageKM);
+	sBridgePackageKM.pvParamIn = CAST_BRIDGE_CMD_PTR_TO_PTR(psSrvkmCmd->in_data_ptr);
+	sBridgePackageKM.ui32InBufferSize = psSrvkmCmd->in_data_size;
+	sBridgePackageKM.pvParamOut = CAST_BRIDGE_CMD_PTR_TO_PTR(psSrvkmCmd->out_data_ptr);
+	sBridgePackageKM.ui32OutBufferSize = psSrvkmCmd->out_data_size;
 
-		return -EFAULT;
-	}
-	
-	if (OSCopyFromUser(NULL,
-					  psBridgePackageKM,
-					  psBridgePackageUM,
-					  sizeof(PVRSRV_BRIDGE_PACKAGE))
-	  != PVRSRV_OK)
-	{
-		return -EFAULT;
-	}
-
-	if (PVRSRV_GET_BRIDGE_ID(ioctlCmd) != psBridgePackageKM->ui32BridgeID ||
-	    psBridgePackageKM->ui32Size != sizeof(PVRSRV_BRIDGE_PACKAGE))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Inconsistent data passed from user space",
-				__FUNCTION__));
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-#endif
-
-#if defined(DEBUG_BRIDGE_CALLS)
-	{
-		IMG_UINT32 mangledID;
-		mangledID = psBridgePackageKM->ui32BridgeID;
-
-		psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
-
-		PVR_DPF((PVR_DBG_WARNING, "%s: Bridge ID (x%8x) %8u (mangled: x%8x) ", __FUNCTION__, psBridgePackageKM->ui32BridgeID, psBridgePackageKM->ui32BridgeID, mangledID));
-	}
-#else
-		psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
-#endif
-
-	return BridgedDispatchKM(psConnection, psBridgePackageKM);
+	error =  BridgedDispatchKM(psConnection, &sBridgePackageKM);
+	return OSPVRSRVToNativeError(error);
 }
 
-
-#if defined(CONFIG_COMPAT)
-#if defined(SUPPORT_DRM)
-int
-#else
-long
-#endif
-PVRSRV_BridgeCompatDispatchKM(struct file *pFile,
-                              unsigned int ioctlCmd,
-                              unsigned long arg)
-{
-	struct bridge_package_from_32
-	{
-		IMG_UINT32				bridge_id;			/*!< ioctl bridge group */
-		IMG_UINT32				function_id;        /*!< ioctl function index */
-		IMG_UINT32				size;				/*!< size of structure */
-		IMG_UINT32				addr_param_in;		/*!< input data buffer */ 
-		IMG_UINT32				in_buffer_size;		/*!< size of input data buffer */
-		IMG_UINT32				addr_param_out;		/*!< output data buffer */
-		IMG_UINT32				out_buffer_size;	/*!< size of output data buffer */
-	};
-
-	PVRSRV_BRIDGE_PACKAGE params_for_64;
-	struct bridge_package_from_32 params;
- 	struct bridge_package_from_32 * const params_addr = &params;
-	CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
-
-	if(psConnection == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
-		return -EFAULT;
-	}
-
-	if(OSGetDriverSuspended())
-	{
-		return -EINTR;
-	}
-
-	/* make sure there is no padding inserted by compiler */
-	BUILD_BUG_ON(sizeof(struct bridge_package_from_32) != 7 * sizeof(IMG_UINT32));
-
-	if(!OSAccessOK(PVR_VERIFY_READ, (void *) arg,
-				   sizeof(struct bridge_package_from_32)))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
-				 __FUNCTION__));
-
-		return -EFAULT;
-	}
-	
-	if(OSCopyFromUser(NULL, params_addr, (void*) arg,
-					  sizeof(struct bridge_package_from_32))
-	   != PVRSRV_OK)
-	{
-		return -EFAULT;
-	}
-
-#if defined(SUPPORT_DRM)
-	if (params_addr->size != sizeof(struct bridge_package_from_32))
-#else
-	if (PVRSRV_GET_BRIDGE_ID(ioctlCmd) != PVRSRV_GET_BRIDGE_ID(params_addr->bridge_id) ||
-	    params_addr->size != sizeof(struct bridge_package_from_32))
-#endif
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Inconsistent data passed from user space",
-		        __FUNCTION__));
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-	params_for_64.ui32BridgeID = PVRSRV_GET_BRIDGE_ID(params_addr->bridge_id);
-	params_for_64.ui32FunctionID = params_addr->function_id;
-	params_for_64.ui32Size = sizeof(params_for_64);
-	params_for_64.pvParamIn = (void*) ((size_t) params_addr->addr_param_in);
-	params_for_64.pvParamOut = (void*) ((size_t) params_addr->addr_param_out);
-	params_for_64.ui32InBufferSize = params_addr->in_buffer_size;
-	params_for_64.ui32OutBufferSize = params_addr->out_buffer_size;
-
-	return BridgedDispatchKM(psConnection, &params_for_64);
-}
-#endif /* defined(CONFIG_COMPAT) */
-
 int
 PVRSRV_MMap(struct file *pFile, struct vm_area_struct *ps_vma)
 {
@@ -922,25 +955,28 @@
 	 * related with the PVRSRV_MMap.
 	 */
 	mutex_lock(&g_sMMapMutex);
-	PMRLock();
 
 	eError = PVRSRVLookupHandle(psConnection->psHandleBase,
 								(void **)&psPMR,
 								hSecurePMRHandle,
-								PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+								PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+								IMG_TRUE);
 	if (eError != PVRSRV_OK)
 	{
 		goto e0;
 	}
 
-	/* Note: PMRMMapPMR will take a reference on the PMR */
+	/* Note: PMRMMapPMR will take a reference on the PMR.
+	 * Unref the handle immediately, because we have now done
+	 * the required operation on the PMR (whether it succeeded or not)
+	 */
 	eError = PMRMMapPMR(psPMR, ps_vma);
+	PVRSRVReleaseHandle(psConnection->psHandleBase, hSecurePMRHandle, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
 	if (eError != PVRSRV_OK)
 	{
 		goto e1;
 	}
 
-	PMRUnlock();
 	mutex_unlock(&g_sMMapMutex);
 
 	return 0;
@@ -950,7 +986,6 @@
 	goto em1;
 e0:
 	PVR_DPF((PVR_DBG_ERROR, "Error in mmap critical section"));
-	PMRUnlock();
 em1:
 	mutex_unlock(&g_sMMapMutex);
 
diff --git a/drivers/staging/imgtec/rogue/pvr_debug.c b/drivers/staging/imgtec/rogue/pvr_debug.c
index 003c37b..b2e64d6 100644
--- a/drivers/staging/imgtec/rogue/pvr_debug.c
+++ b/drivers/staging/imgtec/rogue/pvr_debug.c
@@ -42,7 +42,6 @@
 */ /**************************************************************************/
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/hardirq.h>
@@ -180,7 +179,7 @@
 
 static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
 						 const IMG_CHAR *pszFormat, va_list VArgs)
-						 IMG_FORMAT_PRINTF(3, 0);
+						 __printf(3, 0);
 
 
 #if defined(PVRSRV_NEED_PVR_DPF)
@@ -189,7 +188,7 @@
 
 static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
 						const IMG_CHAR *pszFormat, ...)
-						IMG_FORMAT_PRINTF(3, 4);
+						__printf(3, 4);
 
 /* NOTE: Must NOT be static! Used in module.c.. */
 IMG_UINT32 gPVRDebugLevel =
@@ -218,12 +217,8 @@
 /* The lock is used to control access to gszBufferNonIRQ */
 static DEFINE_MUTEX(gsDebugMutexNonIRQ);
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
 /* The lock is used to control access to gszBufferIRQ */
-static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED;
-#else
 static DEFINE_SPINLOCK(gsDebugLockIRQ);
-#endif
 
 #define	USE_SPIN_LOCK (in_interrupt() || !preemptible())
 
@@ -467,11 +462,11 @@
 
 		if (current->pid == task_tgid_nr(current))
 		{
-			(void) BAppend(pszBuf, ui32BufSiz, "%u: ", current->pid);
+			(void) BAppend(pszBuf, ui32BufSiz, "%5u: ", current->pid);
 		}
 		else
 		{
-			(void) BAppend(pszBuf, ui32BufSiz, "%u-%u: ", task_tgid_nr(current) /* pid id of group*/, current->pid /* task id */);
+			(void) BAppend(pszBuf, ui32BufSiz, "%5u-%5u: ", task_tgid_nr(current) /* pid id of group*/, current->pid /* task id */);
 		}
 
 		if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
@@ -595,32 +590,34 @@
 
 	if (pvData == SEQ_START_TOKEN)
 	{
-		const IMG_CHAR *pszSystemVersionString = PVRSRVGetSystemName();
-
 		if(psPVRSRVData->sDriverInfo.bIsNoMatch)
 		{
-			seq_printf(psSeqFile, "UM Version: %d (%s) %s\n",
+			seq_printf(psSeqFile, "Driver UM Version: %d (%s) %s\n",
 					psPVRSRVData->sDriverInfo.sUMBuildInfo.ui32BuildRevision,
 				    (psPVRSRVData->sDriverInfo.sUMBuildInfo.ui32BuildType)?"release":"debug",
 				    PVR_BUILD_DIR);
-			seq_printf(psSeqFile, "KM Version: %d (%s) %s\n",
+			seq_printf(psSeqFile, "Driver KM Version: %d (%s) %s\n",
 								psPVRSRVData->sDriverInfo.sKMBuildInfo.ui32BuildRevision,
 							    (BUILD_TYPE_RELEASE == psPVRSRVData->sDriverInfo.sKMBuildInfo.ui32BuildType)?"release":"debug",
 							    PVR_BUILD_DIR);
 		}else
 		{
-			seq_printf(psSeqFile, "Version: %s (%s) %s\n",
+			seq_printf(psSeqFile, "Driver Version: %s (%s) %s\n",
 						   PVRVERSION_STRING,
 						   PVR_BUILD_TYPE, PVR_BUILD_DIR);
 		}
-
-		seq_printf(psSeqFile, "System Version String: %s\n", pszSystemVersionString);
-
 	}
 	else if (pvData != NULL)
 	{
 		PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)pvData;
 
+		seq_printf(psSeqFile, "\nDevice Name: %s\n", psDevNode->psDevConfig->pszName);
+
+		if (psDevNode->psDevConfig->pszVersion)
+		{
+			seq_printf(psSeqFile, "Device Version: %s\n", psDevNode->psDevConfig->pszVersion);
+		}
+
 		if (psDevNode->pfnDeviceVersionString)
 		{
 			IMG_CHAR *pszDeviceVersionString;
@@ -696,7 +693,7 @@
 	(*puiPosition)++;
 
 	return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-										  _DebugVersionCompare_AnyVaCb,
+										  _DebugStatusCompare_AnyVaCb,
 										  &uiCurrentPosition,
 										  *puiPosition);
 }
@@ -728,14 +725,18 @@
 		PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
 		IMG_CHAR           *pszStatus = "";
 		IMG_CHAR           *pszReason = "";
+		PVRSRV_DEVICE_HEALTH_STATUS eHealthStatus;
+		PVRSRV_DEVICE_HEALTH_REASON eHealthReason;
 		
 		/* Update the health status now if possible... */
 		if (psDeviceNode->pfnUpdateHealthStatus)
 		{
 			psDeviceNode->pfnUpdateHealthStatus(psDeviceNode, IMG_FALSE);
 		}
+		eHealthStatus = OSAtomicRead(&psDeviceNode->eHealthStatus);
+		eHealthReason = OSAtomicRead(&psDeviceNode->eHealthReason);
 		
-		switch (psDeviceNode->eHealthStatus)
+		switch (eHealthStatus)
 		{
 			case PVRSRV_DEVICE_HEALTH_STATUS_OK:  pszStatus = "OK";  break;
 			case PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING:  pszStatus = "NOT RESPONDING";  break;
@@ -743,103 +744,84 @@
 			default:  pszStatus = "UNKNOWN";  break;
 		}
 
-		/* Write the device status to the sequence file... */
-		if (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
+		switch (eHealthReason)
 		{
-			switch (psDeviceNode->eHealthReason)
-			{
-				case PVRSRV_DEVICE_HEALTH_REASON_NONE:  pszReason = "";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_ASSERTED:  pszReason = " (FW Assert)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_POLL_FAILING:  pszReason = " (Poll failure)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS:  pszReason = " (Global Event Object timeouts rising)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_CORRUPT:  pszReason = " (KCCB offset invalid)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_STALLED:  pszReason = " (KCCB stalled)";  break;
-				default:  pszReason = " (Unknown reason)";  break;
-			}
+			case PVRSRV_DEVICE_HEALTH_REASON_NONE:  pszReason = "";  break;
+			case PVRSRV_DEVICE_HEALTH_REASON_ASSERTED:  pszReason = " (FW Assert)";  break;
+			case PVRSRV_DEVICE_HEALTH_REASON_POLL_FAILING:  pszReason = " (Poll failure)";  break;
+			case PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS:  pszReason = " (Global Event Object timeouts rising)";  break;
+			case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_CORRUPT:  pszReason = " (KCCB offset invalid)";  break;
+			case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_STALLED:  pszReason = " (KCCB stalled)";  break;
+			default:  pszReason = " (Unknown reason)";  break;
+		}
 
-			seq_printf(psSeqFile, "Firmware Status: %s%s\n", pszStatus, pszReason);
+		seq_printf(psSeqFile, "Firmware Status: %s%s\n", pszStatus, pszReason);
 
 #if defined(PVRSRV_GPUVIRT_GUESTDRV)
-			/*
-			 * Guest drivers do not support the following functionality:
-			 * 	- Perform actual on-chip fw tracing
-			 * 	- Collect actual on-chip GPU utilization stats
-			 * 	- Perform actual on-chip GPU power/dvfs management
-			 */
+		/*
+		 * Guest drivers do not support the following functionality:
+		 *	- Perform actual on-chip fw tracing
+		 *	- Collect actual on-chip GPU utilization stats
+		 *	- Perform actual on-chip GPU power/dvfs management
+		 */
+		PVR_UNREFERENCED_PARAMETER(ghGpuUtilUserDebugFS);
 #else
-			/* Write other useful stats to aid the test cycle... */
-			if (psDeviceNode->pvDevice != NULL)
-			{
-				PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-				RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
-
-				/* Calculate the number of HWR events in total across all the DMs... */
-				if (psRGXFWIfTraceBufCtl != NULL)
-				{
-					IMG_UINT32 ui32HWREventCount = 0;
-					IMG_UINT32 ui32CRREventCount = 0;
-					IMG_UINT32 ui32DMIndex;
-
-					for (ui32DMIndex = 0; ui32DMIndex < RGXFWIF_DM_MAX; ui32DMIndex++)
-					{
-						ui32HWREventCount += psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[ui32DMIndex];
-						ui32CRREventCount += psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[ui32DMIndex];
-					}
-
-					seq_printf(psSeqFile, "HWR Event Count: %d\n", ui32HWREventCount);
-					seq_printf(psSeqFile, "CRR Event Count: %d\n", ui32CRREventCount);
-				}
-
-				/* Write the number of APM events... */
-				seq_printf(psSeqFile, "APM Event Count: %d\n", psDevInfo->ui32ActivePMReqTotal);
-
-				/* Write the current GPU Utilisation values... */
-				if (psDevInfo->pfnGetGpuUtilStats &&
-				    psDeviceNode->eHealthStatus == PVRSRV_DEVICE_HEALTH_STATUS_OK)
-				{
-					RGXFWIF_GPU_UTIL_STATS sGpuUtilStats;
-					PVRSRV_ERROR eError = PVRSRV_OK;
-
-					eError = psDevInfo->pfnGetGpuUtilStats(psDeviceNode,
-					                                       ghGpuUtilUserDebugFS,
-					                                       &sGpuUtilStats);
-
-					if ((eError == PVRSRV_OK) &&
-					    ((IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative))
-					{
-						IMG_UINT64 util;
-						IMG_UINT32 rem;
-
-						util = 100 * (sGpuUtilStats.ui64GpuStatActiveHigh +
-						              sGpuUtilStats.ui64GpuStatActiveLow);
-						util = OSDivide64(util, (IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative, &rem);
-
-						seq_printf(psSeqFile, "GPU Utilisation: %u%%\n", (IMG_UINT32)util);
-					}
-					else
-					{
-						seq_printf(psSeqFile, "GPU Utilisation: -\n");
-					}
-				}
-			}
-#endif
-		}
-		else
+		/* Write other useful stats to aid the test cycle... */
+		if (psDeviceNode->pvDevice != NULL)
 		{
-			switch (psDeviceNode->eHealthReason)
+			PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+			RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+
+			/* Calculate the number of HWR events in total across all the DMs... */
+			if (psRGXFWIfTraceBufCtl != NULL)
 			{
-				case PVRSRV_DEVICE_HEALTH_REASON_NONE:  pszReason = "";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_ASSERTED:  pszReason = " (ASSERTED)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_POLL_FAILING:  pszReason = " (POLL FAILING)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS:  pszReason = " (TIMEOUTS)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_CORRUPT:  pszReason = " (QUEUE CORRUPT)";  break;
-				case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_STALLED:  pszReason = " (QUEUE STALLED)";  break;
-				default:  pszReason = " (UNKNOWN)";  break;
+				IMG_UINT32 ui32HWREventCount = 0;
+				IMG_UINT32 ui32CRREventCount = 0;
+				IMG_UINT32 ui32DMIndex;
+
+				for (ui32DMIndex = 0; ui32DMIndex < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; ui32DMIndex++)
+				{
+					ui32HWREventCount += psRGXFWIfTraceBufCtl->aui32HwrDmLockedUpCount[ui32DMIndex];
+					ui32CRREventCount += psRGXFWIfTraceBufCtl->aui32HwrDmOverranCount[ui32DMIndex];
+				}
+
+				seq_printf(psSeqFile, "HWR Event Count: %d\n", ui32HWREventCount);
+				seq_printf(psSeqFile, "CRR Event Count: %d\n", ui32CRREventCount);
 			}
 
-			seq_printf(psSeqFile, "Device %d Status: %s%s\n",
-					   psDeviceNode->sDevId.ui32DeviceIndex, pszStatus, pszReason);
+			/* Write the number of APM events... */
+			seq_printf(psSeqFile, "APM Event Count: %d\n", psDevInfo->ui32ActivePMReqTotal);
+
+			/* Write the current GPU Utilisation values... */
+			if (psDevInfo->pfnGetGpuUtilStats &&
+				eHealthStatus == PVRSRV_DEVICE_HEALTH_STATUS_OK)
+			{
+				RGXFWIF_GPU_UTIL_STATS sGpuUtilStats;
+				PVRSRV_ERROR eError = PVRSRV_OK;
+
+				eError = psDevInfo->pfnGetGpuUtilStats(psDeviceNode,
+													   ghGpuUtilUserDebugFS,
+													   &sGpuUtilStats);
+
+				if ((eError == PVRSRV_OK) &&
+					((IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative))
+				{
+					IMG_UINT64 util;
+					IMG_UINT32 rem;
+
+					util = 100 * (sGpuUtilStats.ui64GpuStatActiveHigh +
+								  sGpuUtilStats.ui64GpuStatActiveLow);
+					util = OSDivide64(util, (IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative, &rem);
+
+					seq_printf(psSeqFile, "GPU Utilisation: %u%%\n", (IMG_UINT32)util);
+				}
+				else
+				{
+					seq_printf(psSeqFile, "GPU Utilisation: -\n");
+				}
+			}
 		}
+#endif
 	}
 
 	return 0;
@@ -968,7 +950,7 @@
 
 		if (psDeviceNode->pvDevice != NULL)
 		{
-			PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX,
+			PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX,
 						_DumpDebugSeqPrintf, psSeqFile);
 		}
 	}
@@ -986,7 +968,7 @@
 /*************************************************************************/ /*!
  Firmware Trace DebugFS entry
 */ /**************************************************************************/
-
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 static void *_DebugFWTraceCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
 {
 	loff_t *puiCurrentPosition = va_arg(va, loff_t *);
@@ -1074,12 +1056,12 @@
 	.next  = _DebugFWTraceSeqNext,
 	.show  = _DebugFWTraceSeqShow,
 };
-
+#endif
 /*************************************************************************/ /*!
  Debug level DebugFS entry
 */ /**************************************************************************/
 
-#if defined(DEBUG)
+#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
 static void *DebugLevelSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
 {
 	if (*puiPosition == 0)
@@ -1177,7 +1159,7 @@
 
 static PVR_DEBUGFS_ENTRY_DATA *gpsFWTraceDebugFSEntry;
 
-#if defined(DEBUG)
+#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
 static PVR_DEBUGFS_ENTRY_DATA *gpsDebugLevelDebugFSEntry;
 #endif
 
@@ -1187,7 +1169,16 @@
 	int iResult;
 
 	PVR_ASSERT(psPVRSRVData != NULL);
-	PVR_ASSERT(gpsVersionDebugFSEntry == NULL);
+
+	/*
+	 * The DebugFS entries are designed to work in a single device system but
+	 * this function will be called multiple times in a multi-device system.
+	 * Return an error in this case.
+	 */
+	if (gpsVersionDebugFSEntry)
+	{
+		return -EEXIST;
+	}
 
 #if !defined(NO_HARDWARE)
 	if (RGXRegisterGpuUtilStats(&ghGpuUtilUserDebugFS) != PVRSRV_OK)
@@ -1234,7 +1225,7 @@
 	{
 		goto ErrorRemoveStatusEntry;
 	}
-
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	iResult = PVRDebugFSCreateEntry("firmware_trace",
 									NULL,
 									&gsFWTraceReadOps,
@@ -1247,8 +1238,8 @@
 	{
 		goto ErrorRemoveDumpDebugEntry;
 	}
-
-#if defined(DEBUG)
+#endif
+#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
 	iResult = PVRDebugFSCreateEntry("debug_level",
 									NULL,
 									&gsDebugLevelReadOps,
@@ -1269,10 +1260,10 @@
 ErrorRemoveFWTraceLogEntry:
 	PVRDebugFSRemoveEntry(&gpsFWTraceDebugFSEntry);
 #endif
-
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 ErrorRemoveDumpDebugEntry:
 	PVRDebugFSRemoveEntry(&gpsDumpDebugDebugFSEntry);
-
+#endif
 ErrorRemoveStatusEntry:
 	PVRDebugFSRemoveEntry(&gpsStatusDebugFSEntry);
 
@@ -1285,10 +1276,14 @@
 void PVRDebugRemoveDebugFSEntries(void)
 {
 #if !defined(NO_HARDWARE)
-	RGXUnregisterGpuUtilStats(ghGpuUtilUserDebugFS);
+	if (ghGpuUtilUserDebugFS != NULL)
+	{
+		RGXUnregisterGpuUtilStats(ghGpuUtilUserDebugFS);
+		ghGpuUtilUserDebugFS = NULL;
+	}
 #endif
 
-#if defined(DEBUG)
+#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
 	if (gpsDebugLevelDebugFSEntry != NULL)
 	{
 		PVRDebugFSRemoveEntry(&gpsDebugLevelDebugFSEntry);
diff --git a/drivers/staging/imgtec/rogue/pvr_debug.h b/drivers/staging/imgtec/rogue/pvr_debug.h
index 9fd7d46..bcb3346 100644
--- a/drivers/staging/imgtec/rogue/pvr_debug.h
+++ b/drivers/staging/imgtec/rogue/pvr_debug.h
@@ -44,6 +44,7 @@
 #ifndef __PVR_DEBUG_H__
 #define __PVR_DEBUG_H__
 
+#include "img_defs.h"
 #include "img_types.h"
 #include "pvrsrv_error.h"
 
@@ -86,23 +87,31 @@
 #define PVRSRV_NEED_PVR_TRACE
 #endif
 
+#if !defined(DOXYGEN)
 #if defined(__KERNEL__)
 	IMG_IMPORT const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
 #	define PVRSRVGETERRORSTRING PVRSRVGetErrorStringKM
 #else
+/*************************************************************************/ /*
+PVRSRVGetErrorString
+Returns a string describing the provided PVRSRV_ERROR code
+NB No doxygen comments provided as this function does not require porting
+   for other operating systems
+*/ /**************************************************************************/
 	IMG_IMPORT const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
 #	define PVRSRVGETERRORSTRING PVRSRVGetErrorString
 #endif
+#endif
 
 /* PVR_ASSERT() and PVR_DBG_BREAK handling */
 
-#if defined(PVRSRV_NEED_PVR_ASSERT)
+#if defined(PVRSRV_NEED_PVR_ASSERT) || defined(DOXYGEN)
 
 /* Unfortunately the klocworks static analysis checker doesn't understand our
  * ASSERT macros. Thus it reports lots of false positive. Defining our Assert
  * macros in a special way when the code is analysed by klocworks avoids
  * them. */
-#if defined(__KLOCWORK__) 
+#if defined(__KLOCWORK__)
   #define PVR_ASSERT(x) do { if (!(x)) abort(); } while (0)
 #else /* ! __KLOCWORKS__ */
 
@@ -110,7 +119,7 @@
 #define PVR_ASSERT(expr) do 									\
 	{															\
 		MSC_SUPPRESS_4127										\
-		if (!(expr))											\
+		if (unlikely(!(expr)))								\
 		{														\
 			PVRSRVDebugPrintf(DBGPRIV_FATAL, __FILE__, __LINE__,\
 					  "*** Debug assertion failed!");			\
@@ -129,7 +138,7 @@
    filename and line number in the panic message. */
 #define PVR_ASSERT(EXPR) do											\
 	{																\
-		if (!(EXPR))												\
+		if (unlikely(!(EXPR)))									\
 		{															\
 			PVRSRVDebugPrintf(DBGPRIV_FATAL, __FILE__, __LINE__,	\
 							  "Debug assertion failed!");			\
@@ -139,25 +148,26 @@
 
 #else /* defined(LINUX) && defined(__KERNEL__) */
 
-IMG_IMPORT void IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
-													   IMG_UINT32 ui32Line,
-													   const IMG_CHAR *pszAssertion)
-#if defined(__GNUC__)
-	__attribute__((noreturn))
-#endif
-	;
+/*************************************************************************/ /*!
+@Function       PVRSRVDebugAssertFail
+@Description    Indicate to the user that a debug assertion has failed and
+                prevent the program from continuing.
+                Invoked from the macro PVR_ASSERT().
+@Input          pszFile       The name of the source file where the assertion failed
+@Input          ui32Line      The line number of the failed assertion
+@Input          pszAssertion  String describing the assertion
+@Return         NEVER!
+*/ /**************************************************************************/
+IMG_IMPORT void IMG_CALLCONV __noreturn
+PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+                      IMG_UINT32 ui32Line,
+                      const IMG_CHAR *pszAssertion);
 
-#if defined(_MSC_VER)
-/* This alternate definition is for MSVC, which warns about do {} while (0) */
-#define PVR_ASSERT(EXPR)    MSC_SUPPRESS_4127										\
-							if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__)
-#else
 #define PVR_ASSERT(EXPR) do										\
 	{															\
-		if (!(EXPR))											\
+		if (unlikely(!(EXPR)))								\
 			PVRSRVDebugAssertFail(__FILE__, __LINE__, #EXPR);	\
 	} while (0)
-#endif
 
 #endif /* defined(LINUX) && defined(__KERNEL__) */
 #endif /* __KLOCWORKS__ */
@@ -193,8 +203,8 @@
      * ASSERT macros. Thus it reports lots of false positive. Defining our Assert
      * macros in a special way when the code is analysed by klocworks avoids
      * them. */
-    #if defined(__KLOCWORK__) 
-        #define PVR_ASSERT(EXPR) do { if (!(EXPR)) abort(); } while (0)
+    #if defined(__KLOCWORK__)
+        #define PVR_ASSERT(EXPR) do { if (unlikely(!(EXPR))) abort(); } while (0)
     #else
         #define PVR_ASSERT(EXPR) (void)(EXPR) /*!< Null Implementation of PVR_ASSERT (does nothing) */
     #endif
@@ -206,17 +216,17 @@
 
 /* PVR_DPF() handling */
 
-#if defined(PVRSRV_NEED_PVR_DPF)
+#if defined(PVRSRV_NEED_PVR_DPF) || defined(DOXYGEN)
 
 	/* New logging mechanism */
-	#define PVR_DBG_FATAL		DBGPRIV_FATAL
-	#define PVR_DBG_ERROR		DBGPRIV_ERROR
-	#define PVR_DBG_WARNING		DBGPRIV_WARNING
-	#define PVR_DBG_MESSAGE		DBGPRIV_MESSAGE
-	#define PVR_DBG_VERBOSE		DBGPRIV_VERBOSE
+	#define PVR_DBG_FATAL		DBGPRIV_FATAL		/*!< Debug level passed to PVRSRVDebugPrintf() for fatal errors. */
+	#define PVR_DBG_ERROR		DBGPRIV_ERROR		/*!< Debug level passed to PVRSRVDebugPrintf() for non-fatal errors. */
+	#define PVR_DBG_WARNING		DBGPRIV_WARNING		/*!< Debug level passed to PVRSRVDebugPrintf() for warnings. */
+	#define PVR_DBG_MESSAGE		DBGPRIV_MESSAGE		/*!< Debug level passed to PVRSRVDebugPrintf() for information only. */
+	#define PVR_DBG_VERBOSE		DBGPRIV_VERBOSE		/*!< Debug level passed to PVRSRVDebugPrintf() for very low-priority debug. */
 	#define PVR_DBG_CALLTRACE	DBGPRIV_CALLTRACE
 	#define PVR_DBG_ALLOC		DBGPRIV_ALLOC
-	#define PVR_DBG_BUFFERED	DBGPRIV_BUFFERED
+	#define PVR_DBG_BUFFERED	DBGPRIV_BUFFERED	/*!< Debug level passed to PVRSRVDebugPrintf() when debug should be written to the debug circular buffer. */
 	#define PVR_DBG_DEBUG		DBGPRIV_DEBUG
 	#define PVR_DBGDRIV_MESSAGE	DBGPRIV_DBGDRV_MESSAGE
 
@@ -238,7 +248,7 @@
 #endif
 
 	/* Some are compiled out completely in release builds */
-#if defined(DEBUG)
+#if defined(DEBUG) || defined(DOXYGEN)
 	#define __PVR_DPF_0x004UL(...) PVRSRVDebugPrintf(DBGPRIV_WARNING, __VA_ARGS__)
 	#define __PVR_DPF_0x008UL(...) PVRSRVDebugPrintf(DBGPRIV_MESSAGE, __VA_ARGS__)
 	#define __PVR_DPF_0x010UL(...) PVRSRVDebugPrintf(DBGPRIV_VERBOSE, __VA_ARGS__)
@@ -270,65 +280,109 @@
 		PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__));
 
 	#define PVR_LOG_IF_ERROR(_rc, _call) do \
-		{ if (_rc != PVRSRV_OK) \
+		{ if (unlikely(_rc != PVRSRV_OK)) \
 			PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
 		MSC_SUPPRESS_4127\
 		} while (0)
 
 	#define PVR_LOGR_IF_NOMEM(_expr, _call) do \
-		{ if (_expr == NULL) { \
+		{ if (unlikely(_expr == NULL)) { \
 			PVR_DPF((PVR_DBG_ERROR, "%s() failed (PVRSRV_ERROR_OUT_OF_MEMORY) in %s()", _call, __func__)); \
 			return (PVRSRV_ERROR_OUT_OF_MEMORY); }\
 		MSC_SUPPRESS_4127\
 		} while (0)
 
+	#define PVR_LOGG_IF_NOMEM(_expr, _call, _err, _go) do \
+		{ if (unlikely(_expr == NULL)) { \
+			PVR_DPF((PVR_DBG_ERROR, "%s() failed (PVRSRV_ERROR_OUT_OF_MEMORY) in %s()", _call, __func__)); \
+			_err = PVRSRV_ERROR_OUT_OF_MEMORY; \
+			goto _go; } \
+		MSC_SUPPRESS_4127\
+		} while (0)
+
 	#define PVR_LOGR_IF_ERROR(_rc, _call) do \
-		{ if (_rc != PVRSRV_OK) { \
+		{ if (unlikely(_rc != PVRSRV_OK)) { \
 			PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
 			return (_rc); }\
 		MSC_SUPPRESS_4127\
 		} while (0)
 
 	#define PVR_LOGRN_IF_ERROR(_rc, _call) do \
-		{ if (_rc != PVRSRV_OK) { \
+		{ if (unlikely(_rc != PVRSRV_OK)) { \
 			PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
 			return; }\
 		MSC_SUPPRESS_4127\
 		} while (0)
 
 	#define PVR_LOGG_IF_ERROR(_rc, _call, _go) do \
-		{ if (_rc != PVRSRV_OK) { \
+		{ if (unlikely(_rc != PVRSRV_OK)) { \
 			PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
 			goto _go; }\
 		MSC_SUPPRESS_4127\
 		} while (0)
 
 	#define PVR_LOG_IF_FALSE(_expr, _msg) do \
-		{ if (!(_expr)) \
+		{ if (unlikely(!(_expr))) \
 			PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
 		MSC_SUPPRESS_4127\
 		} while (0)
 
 	#define PVR_LOGR_IF_FALSE(_expr, _msg, _rc) do \
-		{ if (!(_expr)) { \
+		{ if (unlikely(!(_expr))) { \
 			PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
 			return (_rc); }\
 		MSC_SUPPRESS_4127\
 		} while (0)
 
 	#define PVR_LOGG_IF_FALSE(_expr, _msg, _go) do \
-		{ if (!(_expr)) { \
+		{ if (unlikely(!(_expr))) { \
 			PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
 			goto _go; }\
 		MSC_SUPPRESS_4127\
 		} while (0)
 
+/*************************************************************************/ /*!
+@Function       PVRSRVDebugPrintf
+@Description    Output a debug message to the user, using an OS-specific
+                method, to a log or console which can be read by developers
+                Invoked from the macro PVR_DPF().
+@Input          ui32DebugLevel   The debug level of the message. This can
+                                 be used to restrict the output of debug
+                                 messages based on their severity.
+                                 If this is PVR_DBG_BUFFERED, the message
+                                 should be written into a debug circular
+                                 buffer instead of being output immediately
+                                 (useful when performance would otherwise
+                                 be adversely affected).
+                                 The debug circular buffer shall only be
+                                 output when PVRSRVDebugPrintfDumpCCB() is
+                                 called.
+@Input          pszFileName      The source file containing the code that is
+                                 generating the message
+@Input          ui32Line         The line number in the source file
+@Input          pszFormat        The formatted message string
+@Input          ...              Zero or more arguments for use by the
+                                 formatted string
+@Return         None
+*/ /**************************************************************************/
 IMG_IMPORT void IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
-												   const IMG_CHAR *pszFileName,
-												   IMG_UINT32 ui32Line,
-												   const IMG_CHAR *pszFormat,
-												   ...) IMG_FORMAT_PRINTF(4, 5);
+                                               const IMG_CHAR *pszFileName,
+                                               IMG_UINT32 ui32Line,
+                                               const IMG_CHAR *pszFormat,
+                                               ...) __printf(4, 5);
 
+/*************************************************************************/ /*!
+@Function       PVRSRVDebugPrintfDumpCCB
+@Description    When PVRSRVDebugPrintf() is called with the ui32DebugLevel
+                specified as DBGPRIV_BUFFERED, the debug shall be written to
+                the debug circular buffer instead of being output immediately.
+                (This could be used to obtain debug without incurring a
+                performance hit by printing it at that moment).
+                This function shall dump the contents of that debug circular
+                buffer to be output in an OS-specific method to a log or
+                console which can be read by developers.
+@Return         None
+*/ /**************************************************************************/
 IMG_IMPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
 
 #else  /* defined(PVRSRV_NEED_PVR_DPF) */
@@ -338,20 +392,36 @@
 	#define PVR_LOG_ERROR(_rc, _call) (void)(_rc)
 	#define PVR_LOG_IF_ERROR(_rc, _call) (void)(_rc)
 
-	#define PVR_LOGR_IF_NOMEM(_expr, _call) do { if (_expr == NULL) { return (PVRSRV_ERROR_OUT_OF_MEMORY); } MSC_SUPPRESS_4127 } while (0)
-	#define PVR_LOGR_IF_ERROR(_rc, _call) do { if (_rc != PVRSRV_OK) { return (_rc); } MSC_SUPPRESS_4127 } while(0)
-	#define PVR_LOGRN_IF_ERROR(_rc, _call) do { if (_rc != PVRSRV_OK) { return; } MSC_SUPPRESS_4127 } while(0)
-	#define PVR_LOGG_IF_ERROR(_rc, _call, _go) do { if (_rc != PVRSRV_OK) { goto _go; } MSC_SUPPRESS_4127 } while(0)
+	#define PVR_LOGR_IF_NOMEM(_expr, _call) do { if (unlikely(_expr == NULL)) { return (PVRSRV_ERROR_OUT_OF_MEMORY); } MSC_SUPPRESS_4127 } while (0)
+	#define PVR_LOGG_IF_NOMEM(_expr, _call, _err, _go) do { if (unlikely(_expr == NULL)) { _err = PVRSRV_ERROR_OUT_OF_MEMORY; goto _go; } MSC_SUPPRESS_4127	} while (0)
+	#define PVR_LOGR_IF_ERROR(_rc, _call) do { if (unlikely(_rc != PVRSRV_OK)) { return (_rc); } MSC_SUPPRESS_4127 } while(0)
+	#define PVR_LOGRN_IF_ERROR(_rc, _call) do { if (unlikely(_rc != PVRSRV_OK)) { return; } MSC_SUPPRESS_4127 } while(0)
+	#define PVR_LOGG_IF_ERROR(_rc, _call, _go) do { if (unlikely(_rc != PVRSRV_OK)) { goto _go; } MSC_SUPPRESS_4127 } while(0)
 	
 	#define PVR_LOG_IF_FALSE(_expr, _msg) (void)(_expr)
-	#define PVR_LOGR_IF_FALSE(_expr, _msg, _rc) do { if (!(_expr)) { return (_rc); } MSC_SUPPRESS_4127 } while(0)
-	#define PVR_LOGG_IF_FALSE(_expr, _msg, _go) do { if (!(_expr)) { goto _go; } MSC_SUPPRESS_4127 } while(0)
+	#define PVR_LOGR_IF_FALSE(_expr, _msg, _rc) do { if (unlikely(!(_expr))) { return (_rc); } MSC_SUPPRESS_4127 } while(0)
+	#define PVR_LOGG_IF_FALSE(_expr, _msg, _go) do { if (unlikely(!(_expr))) { goto _go; } MSC_SUPPRESS_4127 } while(0)
 
 	#undef PVR_DPF_FUNCTION_TRACE_ON
 
 #endif /* defined(PVRSRV_NEED_PVR_DPF) */
 
 
+#if defined(DEBUG)
+	#define PVR_LOG_WARN(_rc, _call) \
+		PVR_DPF((PVR_DBG_WARNING, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__));
+
+	#define PVR_LOG_WARN_IF_ERROR(_rc, _call) do \
+		{ if (unlikely(_rc != PVRSRV_OK)) \
+			PVR_DPF((PVR_DBG_WARNING, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
+		MSC_SUPPRESS_4127\
+		} while (0)
+#else
+	#define PVR_LOG_WARN(_rc, _call) (void)(_rc)
+	#define PVR_LOG_WARN_IF_ERROR(_rc, _call) (void)(_rc)
+#endif
+
+
 #if defined(PVR_DPF_FUNCTION_TRACE_ON)
 
 	#define PVR_DPF_ENTERED \
@@ -391,21 +461,48 @@
 
 #endif /* defined(PVR_DPF_FUNCTION_TRACE_ON) */
 
+#if defined(__KERNEL__) || defined(DOXYGEN)
+/*Use PVR_DPF() unless message is necessary in release build */
+#ifdef PVR_DISABLE_LOGGING
+#define PVR_LOG(X)
+#else
+#define PVR_LOG(X) PVRSRVReleasePrintf X;
+#endif
+
+/*************************************************************************/ /*!
+@Function       PVRSRVReleasePrintf
+@Description    Output an important message, using an OS-specific method,
+                to a log or console which can be read by developers in
+                release builds.
+                Invoked from the macro PVR_LOG().
+@Input          pszFormat   The message format string
+@Input          ...         Zero or more arguments for use by the format string
+@Return         None
+*/ /**************************************************************************/
+IMG_IMPORT void IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) __printf(1, 2);
+#endif
 
 /* PVR_TRACE() handling */
 
-#if defined(PVRSRV_NEED_PVR_TRACE)
+#if defined(PVRSRV_NEED_PVR_TRACE) || defined(DOXYGEN)
 
 	#define PVR_TRACE(X)	PVRSRVTrace X    /*!< PowerVR Debug Trace Macro */
 	/* Empty string implementation that is -O0 build friendly */
 	#define PVR_TRACE_EMPTY_LINE()	PVR_TRACE(("%s", ""))
 
+/*************************************************************************/ /*!
+@Function       PVRTrace
+@Description    Output a debug message to the user
+                Invoked from the macro PVR_TRACE().
+@Input          pszFormat   The message format string
+@Input          ...         Zero or more arguments for use by the format string
+*/ /**************************************************************************/
 IMG_IMPORT void IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
-	IMG_FORMAT_PRINTF(1, 2);
+	__printf(1, 2);
 
 #else /* defined(PVRSRV_NEED_PVR_TRACE) */
     /*! Null Implementation of PowerVR Debug Trace Macro (does nothing) */
-	#define PVR_TRACE(X)    
+	#define PVR_TRACE(X)
 
 #endif /* defined(PVRSRV_NEED_PVR_TRACE) */
 
diff --git a/drivers/staging/imgtec/rogue/pvr_debugfs.c b/drivers/staging/imgtec/rogue/pvr_debugfs.c
index cba6d6c..b1557d4 100644
--- a/drivers/staging/imgtec/rogue/pvr_debugfs.c
+++ b/drivers/staging/imgtec/rogue/pvr_debugfs.c
@@ -47,7 +47,7 @@
 #include "pvr_debugfs.h"
 #include "allocmem.h"
 
-#define PVR_DEBUGFS_DIR_NAME "pvr" PVRSRV_GPUVIRT_OSID_STR
+#define PVR_DEBUGFS_DIR_NAME PVR_DRM_NAME
 
 /* Define to set the PVR_DPF debug output level for pvr_debugfs.
  * Normally, leave this set to PVR_DBGDRIV_MESSAGE, but when debugging
@@ -68,6 +68,14 @@
  Statistic entry read functions
 */ /**************************************************************************/
 
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+typedef struct _PVR_DEBUGFS_RAW_DRIVER_STAT_
+{
+	OS_STATS_PRINT_FUNC *pfStatsPrint;
+	PVR_DEBUGFS_ENTRY_DATA *pvDebugFsEntry;
+} PVR_DEBUGFS_RAW_DRIVER_STAT;
+#endif
+
 typedef struct _PVR_DEBUGFS_DRIVER_STAT_
 {
 	void				 *pvData;
@@ -95,7 +103,7 @@
 
 typedef struct _PVR_DEBUGFS_PRIV_DATA_
 {
-	struct seq_operations	*psReadOps;
+	const struct seq_operations *psReadOps;
 	PVRSRV_ENTRY_WRITE_FUNC	*pfnWrite;
 	void			*pvData;
 	PVRSRV_INC_FSENTRY_PVDATA_REFCNT_FN *pfIncPvDataRefCnt;
@@ -394,9 +402,12 @@
 */ /**************************************************************************/
 void PVRDebugFSDeInit(void)
 {
-	debugfs_remove(gpsPVRDebugFSEntryDir);
-	gpsPVRDebugFSEntryDir = NULL;
-	mutex_destroy(&gDebugFSLock);
+	if (gpsPVRDebugFSEntryDir != NULL)
+	{
+		debugfs_remove(gpsPVRDebugFSEntryDir);
+		gpsPVRDebugFSEntryDir = NULL;
+		mutex_destroy(&gDebugFSLock);
+	}
 }
 
 /*************************************************************************/ /*!
@@ -504,7 +515,7 @@
 */ /**************************************************************************/
 int PVRDebugFSCreateEntry(const char *pszName,
 			  PVR_DEBUGFS_DIR_DATA *psParentDir,
-			  struct seq_operations *psReadOps,
+			  const struct seq_operations *psReadOps,
 			  PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
 			  PVRSRV_INC_FSENTRY_PVDATA_REFCNT_FN *pfnIncPvDataRefCnt,
 			  PVRSRV_DEC_FSENTRY_PVDATA_REFCNT_FN *pfnDecPvDataRefCnt,
@@ -699,13 +710,150 @@
 	_UnrefAndMaybeDestroyStatEntry(psStatEntry);
 }
 
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+static void *_DebugFSRawStatisticSeqStart(struct seq_file *psSeqFile,
+                                          loff_t *puiPosition)
+{
+	PVR_DEBUGFS_RAW_DRIVER_STAT *psStatData =
+	        (PVR_DEBUGFS_RAW_DRIVER_STAT *) psSeqFile->private;
+
+	if (psStatData)
+	{
+		if (*puiPosition == 0)
+		{
+			return psStatData;
+		}
+	}
+	else
+	{
+		PVR_DPF((PVR_DEBUGFS_PVR_DPF_LEVEL, "%s: Called when psStatData is"
+		        " NULL", __func__));
+	}
+
+	return NULL;
+}
+
+static void _DebugFSRawStatisticSeqStop(struct seq_file *psSeqFile,
+                                        void *pvData)
+{
+	PVR_DEBUGFS_RAW_DRIVER_STAT *psStatData =
+	        (PVR_DEBUGFS_RAW_DRIVER_STAT *) psSeqFile->private;
+
+	if (!psStatData)
+	{
+		PVR_DPF((PVR_DEBUGFS_PVR_DPF_LEVEL, "%s: Called when psStatData is"
+		        " NULL", __func__));
+	}
+}
+
+static void *_DebugFSRawStatisticSeqNext(struct seq_file *psSeqFile,
+                                         void *pvData,
+                                         loff_t *puiPosition)
+{
+	PVR_DEBUGFS_RAW_DRIVER_STAT *psStatData =
+	        (PVR_DEBUGFS_RAW_DRIVER_STAT *) psSeqFile->private;
+	PVR_UNREFERENCED_PARAMETER(pvData);
+
+	if (!psStatData)
+	{
+		PVR_DPF((PVR_DEBUGFS_PVR_DPF_LEVEL, "%s: Called when psStatData is"
+		        " NULL", __func__));
+	}
+
+	return NULL;
+}
+
+static int _DebugFSRawStatisticSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+	PVR_DEBUGFS_RAW_DRIVER_STAT *psStatData =
+	        (PVR_DEBUGFS_RAW_DRIVER_STAT *) pvData;
+
+	if (psStatData != NULL)
+	{
+		psStatData->pfStatsPrint((void *) psSeqFile, NULL,
+		                         _StatsSeqPrintf);
+		return 0;
+	}
+	else
+	{
+		PVR_DPF((PVR_DEBUGFS_PVR_DPF_LEVEL, "%s: Called when psStatData is"
+		        " NULL, returning -ENODATA(%d)", __FUNCTION__, -ENODATA));
+	}
+
+	return -ENODATA;
+}
+
+static struct seq_operations gsDebugFSRawStatisticReadOps =
+{
+	.start = _DebugFSRawStatisticSeqStart,
+	.stop  = _DebugFSRawStatisticSeqStop,
+	.next  = _DebugFSRawStatisticSeqNext,
+	.show  = _DebugFSRawStatisticSeqShow,
+};
+
+PVR_DEBUGFS_RAW_DRIVER_STAT *PVRDebugFSCreateRawStatisticEntry(
+                                             const IMG_CHAR *pszFileName,
+                                             void *pvParentDir,
+                                             OS_STATS_PRINT_FUNC *pfStatsPrint)
+{
+	PVR_DEBUGFS_RAW_DRIVER_STAT *psStatData;
+	PVR_DEBUGFS_ENTRY_DATA *psDebugFsEntry;
+
+	int iResult;
+
+	if (pszFileName == NULL || pfStatsPrint == NULL)
+	{
+		return NULL;
+	}
+
+	psStatData = OSAllocZMemNoStats(sizeof(*psStatData));
+	if (psStatData == NULL)
+	{
+		return NULL;
+	}
+
+	psStatData->pfStatsPrint = pfStatsPrint;
+
+	PVR_ASSERT((pvParentDir == NULL));
+
+	iResult = PVRDebugFSCreateEntry(pszFileName,
+	                                pvParentDir,
+	                                &gsDebugFSRawStatisticReadOps,
+	                                NULL,
+	                                NULL,
+	                                NULL,
+	                                psStatData,
+	                                &psDebugFsEntry);
+	if (iResult != 0)
+	{
+		OSFreeMemNoStats(psStatData);
+		return NULL;
+	}
+	psStatData->pvDebugFsEntry = (void *) psDebugFsEntry;
+
+	psDebugFsEntry->ui32RefCount = 1;
+
+	return psStatData;
+}
+
+void PVRDebugFSRemoveRawStatisticEntry(PVR_DEBUGFS_RAW_DRIVER_STAT *psStatEntry)
+{
+	PVR_ASSERT(psStatEntry != NULL);
+
+	PVRDebugFSRemoveEntry(&psStatEntry->pvDebugFsEntry);
+	OSFreeMemNoStats(psStatEntry);
+}
+#endif
+
 static IMG_BOOL _RefDirEntry(PVR_DEBUGFS_DIR_DATA *psDirEntry)
 {
 	IMG_BOOL bStatus = IMG_FALSE;
 
+	PVR_ASSERT(psDirEntry != NULL && psDirEntry->psDir != NULL);
+
 	mutex_lock(&gDebugFSLock);
 
-	if (psDirEntry != NULL && psDirEntry->ui32RefCount > 0)
+	if (psDirEntry->ui32RefCount > 0)
 	{
 		/* Increment refCount */
 		psDirEntry->ui32RefCount++;
@@ -727,7 +875,9 @@
 {
 	PVR_DEBUGFS_DIR_DATA *psDirEntry = *ppsDirEntry;
 
-	if (psDirEntry != NULL && psDirEntry->ui32RefCount > 0)
+	PVR_ASSERT(psDirEntry != NULL && psDirEntry->psDir != NULL);
+
+	if (psDirEntry->ui32RefCount > 0)
 	{
 		/* Decrement refCount and free if now zero */
 		if (--psDirEntry->ui32RefCount == 0)
diff --git a/drivers/staging/imgtec/rogue/pvr_debugfs.h b/drivers/staging/imgtec/rogue/pvr_debugfs.h
index 90cf9e2..17fb737 100644
--- a/drivers/staging/imgtec/rogue/pvr_debugfs.h
+++ b/drivers/staging/imgtec/rogue/pvr_debugfs.h
@@ -64,33 +64,46 @@
 typedef struct _PVR_DEBUGFS_DIR_DATA_ PVR_DEBUGFS_DIR_DATA;
 typedef struct _PVR_DEBUGFS_ENTRY_DATA_ PVR_DEBUGFS_ENTRY_DATA;
 typedef struct _PVR_DEBUGFS_DRIVER_STAT_ PVR_DEBUGFS_DRIVER_STAT;
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+typedef struct _PVR_DEBUGFS_RAW_DRIVER_STAT_ PVR_DEBUGFS_RAW_DRIVER_STAT;
+#endif
 
 int PVRDebugFSInit(void);
 void PVRDebugFSDeInit(void);
 
 int PVRDebugFSCreateEntryDir(IMG_CHAR *pszName,
-				 	 	 	 PVR_DEBUGFS_DIR_DATA *psParentDir,
-							 PVR_DEBUGFS_DIR_DATA **ppsNewDir);
+ 	 	 	     PVR_DEBUGFS_DIR_DATA *psParentDir,
+			     PVR_DEBUGFS_DIR_DATA **ppsNewDir);
 
 void PVRDebugFSRemoveEntryDir(PVR_DEBUGFS_DIR_DATA **ppsDir);
 
 int PVRDebugFSCreateEntry(const char *pszName,
-			  	  	  	  PVR_DEBUGFS_DIR_DATA *psParentDir,
-						  struct seq_operations *psReadOps,
-						  PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
-						  PVRSRV_INC_FSENTRY_PVDATA_REFCNT_FN *pfnIncPvDataRefCnt,
-						  PVRSRV_DEC_FSENTRY_PVDATA_REFCNT_FN *pfnDecPvDataRefCnt,
-						  void *pvData,
-						  PVR_DEBUGFS_ENTRY_DATA **ppsNewEntry);
+			  PVR_DEBUGFS_DIR_DATA *psParentDir,
+			  const struct seq_operations *psReadOps,
+			  PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
+			  PVRSRV_INC_FSENTRY_PVDATA_REFCNT_FN *pfnIncPvDataRefCnt,
+			  PVRSRV_DEC_FSENTRY_PVDATA_REFCNT_FN *pfnDecPvDataRefCnt,
+			  void *pvData,
+			  PVR_DEBUGFS_ENTRY_DATA **ppsNewEntry);
 
 void PVRDebugFSRemoveEntry(PVR_DEBUGFS_ENTRY_DATA **ppsDebugFSEntry);
 
 PVR_DEBUGFS_DRIVER_STAT *PVRDebugFSCreateStatisticEntry(const char *pszName,
-					 	 	 	 	 	 	 	 	 	PVR_DEBUGFS_DIR_DATA *psDir,
-														OS_STATS_PRINT_FUNC *pfnStatsPrint,
-														PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnIncStatMemRefCount,
-														PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnDecStatMemRefCount,
-														void *pvData);
+		       PVR_DEBUGFS_DIR_DATA *psDir,
+		       OS_STATS_PRINT_FUNC *pfnStatsPrint,
+		       PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnIncStatMemRefCount,
+		       PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnDecStatMemRefCount,
+		       void *pvData);
+
 void PVRDebugFSRemoveStatisticEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry);
 
+#if defined(PVRSRV_ENABLE_MEMTRACK_STATS_FILE)
+PVR_DEBUGFS_RAW_DRIVER_STAT *PVRDebugFSCreateRawStatisticEntry(
+                                             const IMG_CHAR *pszFileName,
+                                             void *pvParentDir,
+                                             OS_STATS_PRINT_FUNC* pfnStatsPrint);
+
+void PVRDebugFSRemoveRawStatisticEntry(PVR_DEBUGFS_RAW_DRIVER_STAT *psStatEntry);
+#endif
+
 #endif /* !defined(__PVR_DEBUGFS_H__) */
diff --git a/drivers/staging/imgtec/rogue/pvr_drm.c b/drivers/staging/imgtec/rogue/pvr_drm.c
deleted file mode 100644
index b08f01d..0000000
--- a/drivers/staging/imgtec/rogue/pvr_drm.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* vi: set ts=8 sw=8 sts=8: */
-/*************************************************************************/ /*!
-@File
-@Title          PowerVR drm driver
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Linux module setup
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#if defined(SUPPORT_DRM)
-
-#include <linux/version.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/proc_fs.h>
-#include <linux/sched.h>
-#include <asm/ioctl.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-
-#include "allocmem.h"
-#include "img_defs.h"
-#include "services_km.h"
-#include "sysinfo.h"
-#include "mm.h"
-#include "pvr_debug.h"
-#include "srvkm.h"
-#include "handle.h"
-#include "pvr_bridge.h"
-#include "pvrmodule.h"
-#include "pvrversion.h"
-#include "linkage.h"
-#include "pvr_drm.h"
-#include "pvr_drm_shared.h"
-#if !defined(SUPPORT_KERNEL_SRVINIT)
-#include "power.h"
-#include "driverlock.h"
-#endif	/* #if !defined(SUPPORT_KERNEL_SRVINIT) */
-#include "private_data.h"
-#include "syscommon.h"
-#include "pvrsrv.h"
-#include "lists.h"
-#include "device.h"
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
-#define DRIVER_RENDER 0
-#define DRM_RENDER_ALLOW 0
-#endif
-
-#define PVR_DRM_NAME	"pvr"
-#define PVR_DRM_DESC	"Imagination Technologies PVR DRM"
-#define	PVR_DRM_DATE	"20110701"
-
-/* These defines must be prefixed with "DRM_IOCTL_". */
-#define	DRM_IOCTL_PVR_SRVKM_CMD		DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_SRVKM_CMD, PVRSRV_BRIDGE_PACKAGE)
-
-#if defined(PDUMP)
-#define	DRM_IOCTL_PVR_DBGDRV_CMD	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_DBGDRV_CMD, IOCTL_PACKAGE)
-#endif
-
-DECLARE_WAIT_QUEUE_HEAD(sWaitForInit);
-
-/* Once bInitComplete and bInitFailed are set, they stay set */
-IMG_BOOL bInitComplete;
-IMG_BOOL bInitFailed;
-
-static int PVRSRVDRMLoad(struct drm_device *dev, unsigned long flags)
-{
-	int iRes;
-
-	PVR_TRACE(("PVRSRVDRMLoad"));
-
-#if defined(LDM_PLATFORM)
-	/* The equivalent is done for PCI modesetting drivers by drm_get_pci_dev() */
-	platform_set_drvdata(dev->platformdev, dev);
-#endif
-
-	/* Module initialisation */
-	iRes = PVRSRVSystemInit(dev);
-	if (iRes != 0)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: System initialisation failed (error = %d)", __FUNCTION__, iRes));
-		goto error_exit;
-	}
-
-	drm_mode_config_init(dev);
-
-	goto exit;
-
-error_exit:
-	wake_up_interruptible(&sWaitForInit);
-
-	bInitFailed = IMG_TRUE;
-
-exit:
-	bInitComplete = IMG_TRUE;
-
-	return iRes;
-}
-
-static int PVRSRVDRMUnload(struct drm_device *dev)
-{
-#if defined(LDM_PLATFORM)
-	LDM_DEV *pDevice = dev->platformdev;
-#elif defined(LDM_PCI)
-	LDM_DEV *pDevice = dev->pdev;
-#endif
-
-	PVR_TRACE(("PVRSRVDRMUnload"));
-
-	PVRSRVSystemDeInit(pDevice);
-
-	return 0;
-}
-
-static int PVRSRVDRMOpen(struct drm_device *dev, struct drm_file *file)
-{
-	while (!bInitComplete)
-	{
-		DEFINE_WAIT(sWait);
-
-		prepare_to_wait(&sWaitForInit, &sWait, TASK_INTERRUPTIBLE);
-
-		if (!bInitComplete)
-		{
-			PVR_TRACE(("%s: Waiting for module initialisation to complete", __FUNCTION__));
-
-			schedule();
-		}
-
-		finish_wait(&sWaitForInit, &sWait);
-
-		if (signal_pending(current))
-		{
-			return -ERESTARTSYS;
-		}
-	}
-
-	if (bInitFailed)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Module initialisation failed", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	return PVRSRVOpen(dev, file);
-}
-
-#if !defined(SUPPORT_KERNEL_SRVINIT)
-static int PVRDRMUnprivCmd(struct drm_device *dev, void *arg, struct drm_file *file)
-{
-	int ret = 0;
-
-	OSAcquireBridgeLock();
-
-	if (arg == NULL)
-	{
-		ret = -EFAULT;
-	}
-	else
-	{
-		struct drm_pvr_unpriv_cmd *psCommand = (struct drm_pvr_unpriv_cmd *)arg;
-
-		switch (psCommand->cmd)
-		{
-			case DRM_PVR_UNPRIV_CMD_INIT_SUCCESFUL:
-				psCommand->result = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
-				break;
-			default:
-				ret = -EFAULT;
-		}
-	}
-
-	OSReleaseBridgeLock();
-
-	return ret;
-}
-#endif /* #if !defined(SUPPORT_KERNEL_SRVINIT) */
-
-#if defined(PDUMP)
-static int PVRSRVDRMDbgDrvIoctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
-{
-#if defined(CONFIG_COMPAT)
-	IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
-	/* check whether the compatibility mode is required for this call */
-	if(pIP->ui32PtrSize != __SIZEOF_POINTER__)
-	{
-		return dbgdrv_ioctl_compat(dev, arg, pFile);
-	}
-#endif
-	return dbgdrv_ioctl(dev, arg, pFile);
-}
-#endif /* defined(PDUMP) */
-
-/*
- * The big kernel lock is taken for ioctls unless the DRM_UNLOCKED flag is set.
- * If you revise one of the driver specific ioctls, or add a new one, that has
- * DRM_UNLOCKED set then consider whether the gPVRSRVLock mutex needs to be taken.
- */
-struct drm_ioctl_desc sPVRDRMIoctls[] =
-{
-	DRM_IOCTL_DEF_DRV(PVR_SRVKM_CMD, PVRSRV_BridgeDispatchKM, DRM_RENDER_ALLOW | DRM_UNLOCKED),
-#if defined(PDUMP)
-	DRM_IOCTL_DEF_DRV(PVR_DBGDRV_CMD, PVRSRVDRMDbgDrvIoctl, DRM_RENDER_ALLOW | DRM_AUTH | DRM_UNLOCKED),
-#endif
-#if !defined(SUPPORT_KERNEL_SRVINIT)
-	DRM_IOCTL_DEF_DRV(PVR_UNPRIV_CMD, PVRDRMUnprivCmd, DRM_RENDER_ALLOW | DRM_UNLOCKED),
-#endif
-};
-
-#if defined(CONFIG_COMPAT)
-static drm_ioctl_compat_t *apfnPVRDRMCompatIoctls[] =
-{
-	[DRM_PVR_SRVKM_CMD] = PVRSRV_BridgeCompatDispatchKM,
-};
-
-static long PVRSRVDRMCompatIoctl(struct file *file,
-				 unsigned int cmd,
-				 unsigned long arg)
-{
-	unsigned int nr = DRM_IOCTL_NR(cmd);
-	drm_ioctl_compat_t *pfnBridge = NULL;
-
-	if (nr < DRM_COMMAND_BASE)
-	{
-		return drm_compat_ioctl(file, cmd, arg);
-	}
-
-	if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(apfnPVRDRMCompatIoctls))
-	{
-		pfnBridge = apfnPVRDRMCompatIoctls[nr - DRM_COMMAND_BASE];
-	}
-
-	if (pfnBridge)
-	{
-		return pfnBridge(file, cmd, arg);
-	}
-
-	return drm_ioctl(file, cmd, arg);
-}
-#endif /* defined(CONFIG_COMPAT) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
-static const struct file_operations sPVRFileOps =
-{
-	.owner			= THIS_MODULE,
-	.open			= drm_open,
-	.release		= drm_release,
-	.unlocked_ioctl		= drm_ioctl,
-#if defined(CONFIG_COMPAT)
-	.compat_ioctl		= PVRSRVDRMCompatIoctl,
-#endif
-	.mmap			= PVRSRV_MMap,
-	.poll			= drm_poll,
-	.read			= drm_read,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
-	.fasync			= drm_fasync,
-#endif
-};
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
-
-struct drm_driver sPVRDRMDriver =
-{
-	.driver_features	= DRIVER_MODESET | DRIVER_RENDER,
-
-	.dev_priv_size		= 0,
-	.load			= PVRSRVDRMLoad,
-	.unload			= PVRSRVDRMUnload,
-	.open			= PVRSRVDRMOpen,
-	.postclose		= PVRSRVRelease,
-
-	.ioctls			= sPVRDRMIoctls,
-	.num_ioctls		= ARRAY_SIZE(sPVRDRMIoctls),
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
-	.fops			= &sPVRFileOps,
-#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
-	.fops =
-	{
-		.owner		= THIS_MODULE,
-		.open		= drm_open,
-		.release	= drm_release,
-		.unlocked_ioctl	= drm_ioctl,
-#if defined(CONFIG_COMPAT)
-		.compat_ioctl	= PVRSRVDRMCompatIoctl,
-#endif
-		.mmap		= PVRSRV_MMap,
-		.poll		= drm_poll,
-		.fasync		= drm_fasync,
-		.read		= drm_read,
-	},
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
-#if defined(LDM_PCI)
-	.set_busid      	= drm_pci_set_busid,
-#elif defined(LDM_PLATFORM)
-	.set_busid      	= drm_platform_set_busid,
-#else
-#error "LDM_PLATFORM or LDM_PCI must be defined"
-#endif
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) */
-
-	.name			= PVR_DRM_NAME,
-	.desc			= PVR_DRM_DESC,
-	.date			= PVR_DRM_DATE,
-	.major			= PVRVERSION_MAJ,
-	.minor			= PVRVERSION_MIN,
-	.patchlevel		= PVRVERSION_BUILD,
-
-};
-#endif	/* defined(SUPPORT_DRM) */
diff --git a/drivers/staging/imgtec/rogue/pvr_drm.h b/drivers/staging/imgtec/rogue/pvr_drm.h
deleted file mode 100644
index e7f30a6..0000000
--- a/drivers/staging/imgtec/rogue/pvr_drm.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* vi: set ts=8 sw=8 sts=8: */
-/*************************************************************************/ /*!
-@File
-@Title          PowerVR drm driver
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    drm module
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#if !defined(__PVR_DRM_H__)
-#define __PVR_DRM_H__
-
-#include <linux/version.h>
-#include <drm/drmP.h>
-
-#include "module_common.h"
-#include "connection_server.h"
-#include "sync_server.h"
-#include "pmr.h"
-
-#if defined(SUPPORT_BUFFER_SYNC)
-#include "pvr_fence.h"
-#endif
-
-#if defined(PDUMP)
-#include "linuxsrv.h"
-#endif
-
-#if defined(SUPPORT_DRM)
-#if (!defined(LDM_PLATFORM) && !defined(LDM_PCI)) || \
-	(defined(LDM_PLATFORM) && defined(LDM_PCI))
-	#error "LDM_PLATFORM or LDM_PCI must be defined"
-#endif
-
-#define	PVR_DRM_FILE_FROM_FILE(pFile)		((struct drm_file *)((pFile)->private_data))
-#define	PVR_FILE_FROM_DRM_FILE(pDRMFile)	((pDRMFile)->filp)
-
-extern struct drm_driver sPVRDRMDriver;
-
-int PVRSRVSystemInit(struct drm_device *pDrmDevice);
-void PVRSRVSystemDeInit(LDM_DEV *pDevice);
-
-int PVRSRVOpen(struct drm_device *dev, struct drm_file *file);
-void PVRSRVRelease(struct drm_device *dev, struct drm_file *file);
-
-#if defined(PDUMP)
-int dbgdrv_init(void);
-void dbgdrv_cleanup(void);
-int dbgdrv_ioctl(struct drm_device *dev, void *arg, struct drm_file *file);
-int dbgdrv_ioctl_compat(struct drm_device *dev, void *arg, struct drm_file *file);
-#endif
-
-int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *file);
-
-#if defined(CONFIG_COMPAT)
-int PVRSRV_BridgeCompatDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
-#endif
-
-#endif	/* defined(SUPPORT_DRM) */
-#endif /* !defined(__PVR_DRM_H__) */
diff --git a/drivers/staging/imgtec/rogue/pvr_dvfs.h b/drivers/staging/imgtec/rogue/pvr_dvfs.h
new file mode 100644
index 0000000..156aa33
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/pvr_dvfs.h
@@ -0,0 +1,133 @@
+/*************************************************************************/ /*!
+@File           pvr_dvfs.h
+@Title          System level interface for DVFS
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _PVR_DVFS_H_
+#define _PVR_DVFS_H_
+
+#if defined(PVR_DVFS)
+#include <linux/devfreq.h>
+#endif
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "lock.h"
+
+typedef void (*PFN_SYS_DEV_DVFS_SET_FREQUENCY)(IMG_UINT32 ui32Freq);
+typedef void (*PFN_SYS_DEV_DVFS_SET_VOLTAGE)(IMG_UINT32 ui32Volt);
+
+typedef struct _IMG_OPP_
+{
+	IMG_UINT32			ui32Volt;
+	/*
+	 * Unit of frequency in Hz.
+	 */
+	IMG_UINT32			ui32Freq;
+} IMG_OPP;
+
+typedef struct _IMG_DVFS_DEVICE_CFG_
+{
+	const IMG_OPP  *pasOPPTable;
+	IMG_UINT32      ui32OPPTableSize;
+#if defined(PVR_DVFS)
+	IMG_UINT32      ui32PollMs;
+#endif
+	IMG_BOOL        bIdleReq;
+	PFN_SYS_DEV_DVFS_SET_FREQUENCY  pfnSetFrequency;
+	PFN_SYS_DEV_DVFS_SET_VOLTAGE    pfnSetVoltage;
+
+#if defined(CONFIG_DEVFREQ_THERMAL) && defined(PVR_DVFS)
+	struct devfreq_cooling_power *psPowerOps;
+#endif
+
+} IMG_DVFS_DEVICE_CFG;
+
+#if defined(PVR_DVFS)
+typedef struct _IMG_DVFS_GOVERNOR_
+{
+	IMG_BOOL			bEnabled;
+} IMG_DVFS_GOVERNOR;
+
+typedef struct _IMG_DVFS_GOVERNOR_CFG_
+{
+	IMG_UINT32			ui32UpThreshold;
+	IMG_UINT32			ui32DownDifferential;
+} IMG_DVFS_GOVERNOR_CFG;
+#endif
+
+#if defined(__linux__)
+#if defined(PVR_DVFS)
+typedef struct _IMG_DVFS_DEVICE_
+{
+	struct dev_pm_opp		*psOPP;
+	struct devfreq			*psDevFreq;
+	IMG_BOOL			bEnabled;
+	IMG_HANDLE			hGpuUtilUserDVFS;
+	struct devfreq_simple_ondemand_data data;
+#if defined(CONFIG_DEVFREQ_THERMAL)
+	struct thermal_cooling_device	*psDevfreqCoolingDevice;
+#endif
+} IMG_DVFS_DEVICE;
+#endif
+
+#if defined(SUPPORT_PDVFS)
+typedef struct _PDVFS_DATA_
+{
+	IMG_HANDLE hReactiveTimer;
+	IMG_BOOL bWorkInFrame;
+} PDVFS_DATA;
+#endif
+
+typedef struct _IMG_DVFS_
+{
+#if defined(PVR_DVFS)
+	IMG_DVFS_DEVICE			sDVFSDevice;
+	IMG_DVFS_GOVERNOR		sDVFSGovernor;
+	IMG_DVFS_GOVERNOR_CFG	sDVFSGovernorCfg;
+#endif
+#if defined(SUPPORT_PDVFS)
+	PDVFS_DATA				sPDVFSData;
+#endif
+	IMG_DVFS_DEVICE_CFG		sDVFSDeviceCfg;
+} PVRSRV_DVFS;
+#endif/* (__linux__) */
+
+#endif /* _PVR_DVFS_H_ */
diff --git a/drivers/staging/imgtec/rogue/pvr_gputrace.c b/drivers/staging/imgtec/rogue/pvr_gputrace.c
index 01bd835..f375041 100644
--- a/drivers/staging/imgtec/rogue/pvr_gputrace.c
+++ b/drivers/staging/imgtec/rogue/pvr_gputrace.c
@@ -54,7 +54,6 @@
 #include <trace/events/gpu.h>
 #include "rogue_trace_events.h"
 
-#define KM_FTRACE_NO_PRIORITY (0)
 
 
 /******************************************************************************
@@ -213,15 +212,18 @@
 void PVRGpuTraceWorkSwitch(
 		IMG_UINT64 ui64HWTimestampInOSTime,
 		const IMG_UINT32 ui32CtxId,
+		const IMG_UINT32 ui32CtxPriority,
 		const IMG_UINT32 ui32JobId,
 		const IMG_CHAR* pszWorkType,
 		PVR_GPUTRACE_SWITCH_TYPE eSwType)
 {
 	PVR_ASSERT(pszWorkType);
 
+	/* Invert the priority cause this is what systrace expects. Lower values
+	 * convey a higher priority to systrace. */
 	trace_gpu_sched_switch(pszWorkType, ui64HWTimestampInOSTime,
 			eSwType == PVR_GPUTRACE_SWITCH_TYPE_END ? 0 : ui32CtxId,
-			KM_FTRACE_NO_PRIORITY, ui32JobId);
+			2-ui32CtxPriority, ui32JobId);
 }
 
 void PVRGpuTraceUfo(
@@ -259,6 +261,14 @@
 	}
 }
 
+void PVRGpuTraceFirmware(
+		IMG_UINT64 ui64HWTimestampInOSTime,
+		const IMG_CHAR* pszWorkType,
+		PVR_GPUTRACE_SWITCH_TYPE eSwType)
+{
+	trace_rogue_firmware_activity(ui64HWTimestampInOSTime, pszWorkType, eSwType);
+}
+
 void PVRGpuTraceEventsLost(
 		const RGX_HWPERF_STREAM_ID eStreamId,
 		const IMG_UINT32 ui32LastOrdinal,
@@ -271,7 +281,7 @@
 {
 	PVRSRV_ERROR eError;
 
-	eError = RGXHWPerfFTraceGPUInit(psDeviceNode->pvDevice);
+	eError = RGXHWPerfFTraceGPUInit(psDeviceNode);
 	if (eError != PVRSRV_OK)
 		return eError;
 
@@ -281,16 +291,20 @@
 	                               &gpsPVRDebugFSGpuTracingOnEntry);
 	if (eError != PVRSRV_OK)
 	{
-		RGXHWPerfFTraceGPUDeInit();
+		RGXHWPerfFTraceGPUDeInit(psDeviceNode);
 		return eError;
 	}
 
 	return PVRSRV_OK;
 }
 
-void PVRGpuTraceDeInit(void)
+void PVRGpuTraceDeInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	RGXHWPerfFTraceGPUDeInit();
+	/* gbFTraceGPUEventsEnabled and gbFTraceGPUEventsPreEnabled are cleared
+	 * in this function. */
+	PVRGpuTraceEnabledSet(IMG_FALSE);
+
+	RGXHWPerfFTraceGPUDeInit(psDeviceNode);
 
 	/* Can be NULL if driver startup failed */
 	if (gpsPVRDebugFSGpuTracingOnEntry)
diff --git a/drivers/staging/imgtec/rogue/pvr_gputrace.h b/drivers/staging/imgtec/rogue/pvr_gputrace.h
index 44c52db..d47116d 100644
--- a/drivers/staging/imgtec/rogue/pvr_gputrace.h
+++ b/drivers/staging/imgtec/rogue/pvr_gputrace.h
@@ -78,6 +78,7 @@
 void PVRGpuTraceWorkSwitch(
 		IMG_UINT64 ui64OSTimestamp,
 		const IMG_UINT32 ui32ContextId,
+		const IMG_UINT32 ui32CtxPriority,
 		const IMG_UINT32 ui32JobId,
 		const IMG_CHAR* pszWorkType,
 		PVR_GPUTRACE_SWITCH_TYPE eSwType);
@@ -91,6 +92,11 @@
 		const IMG_UINT32 ui32UFOCount,
 		const RGX_HWPERF_UFO_DATA_ELEMENT *puData);
 
+void PVRGpuTraceFirmware(
+		IMG_UINT64 ui64HWTimestampInOSTime,
+		const IMG_CHAR* pszWorkType,
+		PVR_GPUTRACE_SWITCH_TYPE eSwType);
+
 void PVRGpuTraceEventsLost(
 		const RGX_HWPERF_STREAM_ID eStreamId,
 		const IMG_UINT32 ui32LastOrdinal,
@@ -100,7 +106,8 @@
  * This function creates debugfs entry and initialises some necessary
  * structures. */
 PVRSRV_ERROR PVRGpuTraceInit(PVRSRV_DEVICE_NODE *psDeviceNode);
-void PVRGpuTraceDeInit(void);
+
+void PVRGpuTraceDeInit(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 IMG_BOOL PVRGpuTraceEnabled(void);
 void PVRGpuTraceSetEnabled(IMG_BOOL bEnabled);
@@ -112,4 +119,7 @@
 void PVRGpuTraceEnableUfoCallback(void);
 void PVRGpuTraceDisableUfoCallback(void);
 
+void PVRGpuTraceEnableFirmwareActivityCallback(void);
+void PVRGpuTraceDisableFirmwareActivityCallback(void);
+
 #endif /* PVR_GPUTRACE_H_ */
diff --git a/drivers/staging/imgtec/rogue/pvr_hwperf.c b/drivers/staging/imgtec/rogue/pvr_hwperf.c
deleted file mode 100644
index 7df2caf..0000000
--- a/drivers/staging/imgtec/rogue/pvr_hwperf.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX HW Performance implementation
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX HW Performance implementation
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include "pvr_hwperf.h"
-#include "pvr_debugfs.h"
-#include "pvr_uaccess.h"
-
-#include "rgxhwperf.h"
-#include "rgx_hwperf_km.h"
-#include "rgxapi_km.h"
-
-struct
-{
-	PVR_DEBUGFS_DIR_DATA *psRootDir;
-	PVR_DEBUGFS_ENTRY_DATA *psGpuFilterEntry;
-	PVR_DEBUGFS_ENTRY_DATA *psHostFilterEntry;
-} g_sHWPerfDebugFs = {0};
-
-static void *HWPerfFilterSeqStart(struct seq_file *psSeqFile,
-                                  loff_t *puiPosition)
-{
-	if (*puiPosition == 0)
-	{
-		/* We want only one entry in the sequence, one call to show() */
-		return (void *) 1;
-	}
-
-	PVR_UNREFERENCED_PARAMETER(psSeqFile);
-
-	return NULL;
-}
-
-static void HWPerfFilterSeqStop(struct seq_file *psSeqFile, void *pvData)
-{
-	PVR_UNREFERENCED_PARAMETER(psSeqFile);
-	PVR_UNREFERENCED_PARAMETER(pvData);
-}
-
-static void *HWPerfFilterSeqNext(struct seq_file *psSeqFile, void *pvData,
-                                 loff_t *puiPosition)
-{
-	PVR_UNREFERENCED_PARAMETER(psSeqFile);
-	PVR_UNREFERENCED_PARAMETER(pvData);
-	PVR_UNREFERENCED_PARAMETER(puiPosition);
-	return NULL;
-}
-
-static int HWPerfFilterSeqShow(struct seq_file *psSeqFile, void *pvData)
-{
-	IMG_CHAR buff[sizeof("0x0123456789abcdef") + 1] = {'\0'};
-	RGX_HWPERF_STREAM_ID eStreamId = (RGX_HWPERF_STREAM_ID) psSeqFile->private;
-	IMG_UINT64 ui64Filter = 0;
-	IMG_HANDLE hHWPerf = NULL;
-	PVRSRV_ERROR eError;
-
-	eError = RGXHWPerfLazyConnect(&hHWPerf);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "Could not connect to HWPerf. Most likely"
-				" not initialised yet."));
-		return -EFAULT;
-	}
-
-	eError = RGXHWPerfGetFilter(hHWPerf, eStreamId, &ui64Filter);
-
-	(void) RGXHWPerfFreeConnection(hHWPerf); /* ignore return status */
-
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get HWPerf filter value of"
-		        " stream %d.", __func__, eStreamId));
-		return -EFAULT;
-	}
-
-	switch (eStreamId)
-	{
-		case RGX_HWPERF_STREAM_ID0_FW:
-			if (OSSNPrintf(buff, sizeof(buff), "0x%016llx\n", ui64Filter) < 0)
-			{
-				PVR_DPF((PVR_DBG_ERROR, "%s: OSSNPrintf failed to write"
-						" filter value of stream %d", __func__, eStreamId));
-				return -EFAULT;
-			}
-			break;
-		case RGX_HWPERF_STREAM_ID1_HOST:
-			if (OSSNPrintf(buff, sizeof(buff), "0x%08x\n",
-			        (IMG_UINT32) ui64Filter) < 0)
-			{
-				PVR_DPF((PVR_DBG_ERROR, "%s: OSSNPrintf failed to write"
-						" filter value of stream %d", __func__, eStreamId));
-				return -EFAULT;
-			}
-			break;
-		default:
-			break;
-	}
-
-	seq_puts(psSeqFile, buff);
-
-	PVR_UNREFERENCED_PARAMETER(pvData);
-	return 0;
-}
-
-static struct seq_operations g_sSeqOps = {
-	.start = HWPerfFilterSeqStart,
-	.stop  = HWPerfFilterSeqStop,
-	.next  = HWPerfFilterSeqNext,
-	.show  = HWPerfFilterSeqShow
-};
-
-static ssize_t HWPerfFilterSet(const char __user *buffer, size_t count,
-                               loff_t uiPosition, void *data)
-{
-	IMG_CHAR buff[sizeof("0x0123456789abcdef") + 1];
-	RGX_HWPERF_STREAM_ID eStreamId = (RGX_HWPERF_STREAM_ID) data;
-	IMG_UINT64 ui64Filter = 0;
-	IMG_UINT uiBuffLen = 0;
-	PVRSRV_ERROR eError;
-	IMG_HANDLE hHWPerf;
-
-	switch (eStreamId)
-	{
-		case RGX_HWPERF_STREAM_ID0_FW:
-			uiBuffLen = sizeof("0x") + sizeof(IMG_UINT64) * 2;
-			break;
-		case RGX_HWPERF_STREAM_ID1_HOST:
-			uiBuffLen = sizeof("0x") + sizeof(IMG_UINT32) * 2;
-			break;
-		default:
-			return count;
-	}
-
-	if (count > uiBuffLen)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfFilterSet: String too long (%zd)",
-		         count));
-		return -EINVAL;
-	}
-
-	if (pvr_copy_from_user(buff, buffer, count))
-	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfFilterSet: Copy of user data failed"));
-		return -EFAULT;
-	}
-	buff[count] = '\0';
-
-	if (count > uiBuffLen - 2 && !(buff[0] == '0' && buff[1] == 'x'))
-	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfFilterSet: String too long (%zd)",
-		         count));
-		return -EINVAL;
-	}
-
-	if (sscanf(buff, "%llx", &ui64Filter) != 1)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfFilterSet: Invalid input data"));
-		return -EINVAL;
-	}
-
-	if (RGXHWPerfLazyConnect(&hHWPerf) != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "Could not connect to HWPerf. Most likely"
-				" not initialised yet."));
-		return -EFAULT;
-	}
-
-	eError = RGXHWPerfControl(hHWPerf, eStreamId, IMG_FALSE, ui64Filter);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfFilterSet: Failed to set filter in"
-		         "for the GPU"));
-		return -EFAULT;
-	}
-
-	(void) RGXHWPerfFreeConnection(hHWPerf); /* ignore return status */
-
-	PVR_UNREFERENCED_PARAMETER(uiPosition);
-	return count;
-}
-
-PVRSRV_ERROR PVRSRVHWperfCreateDebugFs(void)
-{
-	int iError;
-
-	iError = PVRDebugFSCreateEntryDir("hwperf", NULL,
-	                                  &g_sHWPerfDebugFs.psRootDir);
-	if (iError)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "Failed to create \"hwperf\" DebugFS"
-				 "directory."));
-		return iError;
-	}
-
-	iError = PVRDebugFSCreateEntry("gpu_filter", g_sHWPerfDebugFs.psRootDir,
-	                               &g_sSeqOps, HWPerfFilterSet, NULL, NULL,
-	                               (void *) RGX_HWPERF_STREAM_ID0_FW,
-	                               &g_sHWPerfDebugFs.psGpuFilterEntry);
-	if (iError)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "Failed to create \"gpu_filter\" DebugFS"
-				 " entry."));
-	}
-
-	iError = PVRDebugFSCreateEntry("host_filter", g_sHWPerfDebugFs.psRootDir,
-	                               &g_sSeqOps, HWPerfFilterSet, NULL, NULL,
-	                               (void *) RGX_HWPERF_STREAM_ID1_HOST,
-	                               &g_sHWPerfDebugFs.psHostFilterEntry);
-	if (iError)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "Failed to create \"host_filter\""
-				" DebugFS entry."));
-	}
-
-	return iError == 0 ? PVRSRV_OK : iError; /* return ok or last error */
-}
-
-void PVRSRVHWperfDestroyDebugFs(void)
-{
-	if (g_sHWPerfDebugFs.psGpuFilterEntry)
-	{
-		PVRDebugFSRemoveEntry(&g_sHWPerfDebugFs.psGpuFilterEntry);
-	}
-
-	if (g_sHWPerfDebugFs.psHostFilterEntry)
-	{
-		PVRDebugFSRemoveEntry(&g_sHWPerfDebugFs.psHostFilterEntry);
-	}
-
-	if (g_sHWPerfDebugFs.psRootDir)
-	{
-		PVRDebugFSRemoveEntryDir(&g_sHWPerfDebugFs.psRootDir);
-	}
-}
diff --git a/drivers/staging/imgtec/rogue/pvr_notifier.c b/drivers/staging/imgtec/rogue/pvr_notifier.c
new file mode 100644
index 0000000..dd7d136
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/pvr_notifier.c
@@ -0,0 +1,481 @@
+/*************************************************************************/ /*!
+@File
+@Title          PowerVR notifier interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "allocmem.h"
+#include "device.h"
+#include "dllist.h"
+#include "img_defs.h"
+#include "osfunc.h"
+#include "pvr_notifier.h"
+#include "pvrsrv.h"
+#include "pvrversion.h"
+
+
+/*************************************************************************/ /*!
+Command Complete Notifier Interface
+*/ /**************************************************************************/
+
+typedef struct PVRSRV_CMDCOMP_NOTIFY_TAG
+{
+	PVRSRV_CMDCOMP_HANDLE	hCmdCompHandle;
+	PFN_CMDCOMP_NOTIFY		pfnCmdCompleteNotify;
+	DLLIST_NODE				sListNode;
+} PVRSRV_CMDCOMP_NOTIFY;
+
+/* Head of the list of callbacks called when command complete happens */
+static DLLIST_NODE g_sCmdCompNotifyHead;
+static POSWR_LOCK g_hCmdCompNotifyLock;
+
+PVRSRV_ERROR
+PVRSRVCmdCompleteInit(void)
+{
+	PVRSRV_ERROR eError;
+
+	eError = OSWRLockCreate(&g_hCmdCompNotifyLock);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	dllist_init(&g_sCmdCompNotifyHead);
+
+	return PVRSRV_OK;
+}
+
+void
+PVRSRVCmdCompleteDeinit(void)
+{
+	/* Check that all notify function have been unregistered */
+	if (!dllist_is_empty(&g_sCmdCompNotifyHead))
+	{
+		PDLLIST_NODE psNode;
+
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Command complete notify list is not empty!", __func__));
+
+		/* Clean up any stragglers */
+		psNode = dllist_get_next_node(&g_sCmdCompNotifyHead);
+		while (psNode)
+		{
+			PVRSRV_CMDCOMP_NOTIFY *psNotify;
+
+			dllist_remove_node(psNode);
+			
+			psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
+			OSFreeMem(psNotify);
+
+			psNode = dllist_get_next_node(&g_sCmdCompNotifyHead);
+		}
+	}
+
+	if (g_hCmdCompNotifyLock)
+	{
+		OSWRLockDestroy(g_hCmdCompNotifyLock);
+	}
+}
+
+PVRSRV_ERROR
+PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify,
+								PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify,
+								PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+{
+	PVRSRV_CMDCOMP_NOTIFY *psNotify;
+
+	if (!phNotify || !pfnCmdCompleteNotify || !hCmdCompHandle)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Bad arguments (%p, %p, %p)",
+				 __func__, phNotify, pfnCmdCompleteNotify, hCmdCompHandle));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psNotify = OSAllocMem(sizeof(*psNotify));
+	if (!psNotify)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Not enough memory to allocate CmdCompleteNotify function",
+				 __func__));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;		
+	}
+
+	/* Set-up the notify data */
+	psNotify->hCmdCompHandle = hCmdCompHandle;
+	psNotify->pfnCmdCompleteNotify = pfnCmdCompleteNotify;
+
+	/* Add it to the list of Notify functions */
+	OSWRLockAcquireWrite(g_hCmdCompNotifyLock);
+	dllist_add_to_tail(&g_sCmdCompNotifyHead, &psNotify->sListNode);
+	OSWRLockReleaseWrite(g_hCmdCompNotifyLock);
+
+	*phNotify = psNotify;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify)
+{
+	PVRSRV_CMDCOMP_NOTIFY *psNotify;
+
+	psNotify = (PVRSRV_CMDCOMP_NOTIFY *) hNotify;
+	if (!psNotify)
+	{
+		PVR_DPF((PVR_DBG_ERROR," %s: Bad arguments (%p)", __func__, hNotify));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	OSWRLockAcquireWrite(g_hCmdCompNotifyLock);
+	dllist_remove_node(&psNotify->sListNode);
+	OSWRLockReleaseWrite(g_hCmdCompNotifyLock);
+
+	OSFreeMem(psNotify);
+
+	return PVRSRV_OK;
+}
+
+void
+PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle)
+{
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+#if !defined(NO_HARDWARE)
+	DLLIST_NODE *psNode, *psNext;
+#endif
+
+	/* Call notify callbacks to check if blocked work items can now proceed */
+#if !defined(NO_HARDWARE)
+	OSWRLockAcquireRead(g_hCmdCompNotifyLock);
+	dllist_foreach_node(&g_sCmdCompNotifyHead, psNode, psNext)
+	{
+		PVRSRV_CMDCOMP_NOTIFY *psNotify =
+			IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
+
+		if (hCmdCompCallerHandle != psNotify->hCmdCompHandle)
+		{
+			psNotify->pfnCmdCompleteNotify(psNotify->hCmdCompHandle);
+		}
+	}
+	OSWRLockReleaseRead(g_hCmdCompNotifyLock);
+#endif
+
+	if (psPVRSRVData->hGlobalEventObject)
+	{
+		OSEventObjectSignal(psPVRSRVData->hGlobalEventObject);
+	}
+}
+
+/*************************************************************************/ /*!
+Debug Notifier Interface
+*/ /**************************************************************************/
+
+typedef struct DEBUG_REQUEST_ENTRY_TAG
+{
+	IMG_UINT32		ui32RequesterID;
+	DLLIST_NODE		sListHead;
+} DEBUG_REQUEST_ENTRY;
+
+typedef struct DEBUG_REQUEST_TABLE_TAG
+{
+	POSWR_LOCK				hLock;
+	IMG_UINT32				ui32RequestCount;
+	DEBUG_REQUEST_ENTRY		asEntry[1];
+} DEBUG_REQUEST_TABLE;
+
+typedef struct DEBUG_REQUEST_NOTIFY_TAG
+{
+	PVRSRV_DEVICE_NODE		*psDevNode;
+	PVRSRV_DBGREQ_HANDLE	hDbgRequestHandle;
+	PFN_DBGREQ_NOTIFY		pfnDbgRequestNotify;
+	IMG_UINT32				ui32RequesterID;
+	DLLIST_NODE				sListNode;
+} DEBUG_REQUEST_NOTIFY;
+
+
+PVRSRV_ERROR
+PVRSRVRegisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT32 *paui32Table,
+					   IMG_UINT32 ui32Length)
+{
+	DEBUG_REQUEST_TABLE *psDebugTable;
+	IMG_UINT32 i;
+	PVRSRV_ERROR eError;
+
+	if (psDevNode->hDebugTable)
+	{
+		return PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED;
+	}
+
+	psDebugTable = OSAllocMem(sizeof(DEBUG_REQUEST_TABLE) +
+							  (sizeof(DEBUG_REQUEST_ENTRY) * (ui32Length-1)));
+	if (!psDebugTable)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	eError = OSWRLockCreate(&psDebugTable->hLock);
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorFreeDebugTable;
+	}
+
+	psDebugTable->ui32RequestCount = ui32Length;
+
+	/* Init the list heads */
+	for (i = 0; i < ui32Length; i++)
+	{
+		psDebugTable->asEntry[i].ui32RequesterID = paui32Table[i];
+		dllist_init(&psDebugTable->asEntry[i].sListHead);
+	}
+
+	psDevNode->hDebugTable = (IMG_HANDLE *) psDebugTable;
+
+	return PVRSRV_OK;
+
+ErrorFreeDebugTable:
+	OSFreeMem(psDebugTable);
+	psDebugTable = NULL;
+
+	return eError;
+}
+
+void
+PVRSRVUnregisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode)
+{
+	DEBUG_REQUEST_TABLE *psDebugTable;
+	IMG_UINT32 i;
+
+	PVR_ASSERT(psDevNode->hDebugTable);
+	psDebugTable = (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
+	psDevNode->hDebugTable = NULL;
+
+	for (i = 0; i < psDebugTable->ui32RequestCount; i++)
+	{
+		if (!dllist_is_empty(&psDebugTable->asEntry[i].sListHead))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Found registered callback(s) on %d",
+					 __func__, i));
+		}
+	}
+
+	OSWRLockDestroy(psDebugTable->hLock);
+	psDebugTable->hLock = NULL;
+
+	OSFreeMem(psDebugTable);
+}
+
+PVRSRV_ERROR
+PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify,
+							   PVRSRV_DEVICE_NODE *psDevNode,
+							   PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+							   IMG_UINT32 ui32RequesterID,
+							   PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
+{
+	DEBUG_REQUEST_TABLE *psDebugTable;
+	DEBUG_REQUEST_NOTIFY *psNotify;
+	PDLLIST_NODE psHead = NULL;
+	IMG_UINT32 i;
+	PVRSRV_ERROR eError;
+
+	if (!phNotify || !psDevNode || !pfnDbgRequestNotify)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Bad arguments (%p, %p, %p)",
+				 __func__, phNotify, psDevNode, pfnDbgRequestNotify));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDebugTable = (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
+
+	PVR_ASSERT(psDebugTable);
+
+	psNotify = OSAllocMem(sizeof(*psNotify));
+	if (!psNotify)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Not enough memory to allocate DbgRequestNotify structure",
+				 __func__));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Set-up the notify data */
+	psNotify->psDevNode = psDevNode;
+	psNotify->hDbgRequestHandle = hDbgRequestHandle;
+	psNotify->pfnDbgRequestNotify = pfnDbgRequestNotify;
+	psNotify->ui32RequesterID = ui32RequesterID;
+
+	/* Lock down all the lists */
+	OSWRLockAcquireWrite(psDebugTable->hLock);
+
+	/* Find which list to add it to */
+	for (i = 0; i < psDebugTable->ui32RequestCount; i++)
+	{
+		if (psDebugTable->asEntry[i].ui32RequesterID == ui32RequesterID)
+		{
+			psHead = &psDebugTable->asEntry[i].sListHead;
+		}
+	}
+
+	if (!psHead)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to find debug requester", __func__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto ErrorReleaseLock;
+	}
+
+	/* Add it to the list of Notify functions */
+	dllist_add_to_tail(psHead, &psNotify->sListNode);
+
+	/* Unlock the lists */
+	OSWRLockReleaseWrite(psDebugTable->hLock);
+
+	*phNotify = psNotify;
+
+	return PVRSRV_OK;
+
+ErrorReleaseLock:
+	OSWRLockReleaseWrite(psDebugTable->hLock);
+	OSFreeMem(psNotify);
+
+	return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
+{
+	DEBUG_REQUEST_NOTIFY *psNotify = (DEBUG_REQUEST_NOTIFY *) hNotify;
+	DEBUG_REQUEST_TABLE *psDebugTable;
+
+	if (!psNotify)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Bad arguments (%p)", __func__, hNotify));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDebugTable = (DEBUG_REQUEST_TABLE *) psNotify->psDevNode->hDebugTable;
+
+	OSWRLockAcquireWrite(psDebugTable->hLock);
+	dllist_remove_node(&psNotify->sListNode);
+	OSWRLockReleaseWrite(psDebugTable->hLock);
+
+	OSFreeMem(psNotify);
+
+	return PVRSRV_OK;
+}
+
+void
+PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
+				   IMG_UINT32 ui32VerbLevel,
+				   DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				   void *pvDumpDebugFile)
+{
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	DEBUG_REQUEST_TABLE *psDebugTable =
+		(DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
+	static const IMG_CHAR *apszVerbosityTable[] = { "Low", "Medium", "High" };
+	const IMG_CHAR *szVerbosityLevel;
+	IMG_UINT32 i;
+	IMG_UINT32 j;
+
+	static_assert(IMG_ARR_NUM_ELEMS(apszVerbosityTable) == DEBUG_REQUEST_VERBOSITY_MAX+1,
+	              "Incorrect number of verbosity levels");
+
+	PVR_ASSERT(psDebugTable);
+
+	OSWRLockAcquireRead(psDebugTable->hLock);
+
+	if (ui32VerbLevel < IMG_ARR_NUM_ELEMS(apszVerbosityTable))
+	{
+		szVerbosityLevel = apszVerbosityTable[ui32VerbLevel];
+	}
+	else
+	{
+		szVerbosityLevel = "unknown";
+		PVR_ASSERT(!"Invalid verbosity level received");
+	}
+
+	PVR_DUMPDEBUG_LOG("------------[ PVR DBG: START (%s) ]------------",
+			szVerbosityLevel);
+
+	PVR_DUMPDEBUG_LOG("DDK info: %s (%s) %s",
+					   PVRVERSION_STRING, PVR_BUILD_TYPE, PVR_BUILD_DIR);
+	PVR_DUMPDEBUG_LOG("Time now: %015llu", OSClockus64());
+
+	switch (psPVRSRVData->eServicesState)
+	{
+		case PVRSRV_SERVICES_STATE_OK:
+			PVR_DUMPDEBUG_LOG("Services State: OK");
+			break;
+		case PVRSRV_SERVICES_STATE_BAD:
+			PVR_DUMPDEBUG_LOG("Services State: BAD");
+			break;
+		default:
+			PVR_DUMPDEBUG_LOG("Services State: UNKNOWN (%d)",
+							   psPVRSRVData->eServicesState);
+			break;
+	}
+
+	/* For each verbosity level */
+	for (j = 0; j <= ui32VerbLevel; j++)
+	{
+		/* For each requester */
+		for (i = 0; i < psDebugTable->ui32RequestCount; i++)
+		{
+			DLLIST_NODE *psNode;
+			DLLIST_NODE *psNext;
+
+			dllist_foreach_node(&psDebugTable->asEntry[i].sListHead, psNode, psNext)
+			{
+				DEBUG_REQUEST_NOTIFY *psNotify =
+					IMG_CONTAINER_OF(psNode, DEBUG_REQUEST_NOTIFY, sListNode);
+				psNotify->pfnDbgRequestNotify(psNotify->hDbgRequestHandle, j,
+								pfnDumpDebugPrintf, pvDumpDebugFile);
+			}
+		}
+	}
+
+	PVR_DUMPDEBUG_LOG("------------[ PVR DBG: END ]------------");
+	OSWRLockReleaseRead(psDebugTable->hLock);
+
+	if (!pfnDumpDebugPrintf)
+	{
+		/* Only dump the call stack to the kernel log if the debug
+		 * dump has gone there
+		 */
+		OSWarnOn(IMG_TRUE);
+	}
+}
diff --git a/drivers/staging/imgtec/rogue/pvr_notifier.h b/drivers/staging/imgtec/rogue/pvr_notifier.h
index 132bd6c..6fa968b 100644
--- a/drivers/staging/imgtec/rogue/pvr_notifier.h
+++ b/drivers/staging/imgtec/rogue/pvr_notifier.h
@@ -46,6 +46,88 @@
 #include "img_types.h"
 #include "pvr_debug.h"
 
+
+/**************************************************************************/ /*!
+Command Complete Notifier Interface
+*/ /***************************************************************************/
+
+typedef IMG_HANDLE PVRSRV_CMDCOMP_HANDLE;
+typedef void (*PFN_CMDCOMP_NOTIFY)(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVCmdCompleteInit
+@Description    Performs initialisation of the command complete notifier
+                interface.
+@Return         PVRSRV_ERROR         PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVCmdCompleteInit(void);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVCmdCompleteDeinit
+@Description    Performs cleanup for the command complete notifier interface.
+@Return         PVRSRV_ERROR         PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+void
+PVRSRVCmdCompleteDeinit(void);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVRegisterCmdCompleteNotify
+@Description    Register a callback function that is called when some device
+                finishes some work, which is signalled via a call to
+                PVRSRVCheckStatus.
+@Output         phNotify             On success, points to command complete
+                                     notifier handle
+@Input          pfnCmdCompleteNotify Function callback
+@Input          hPrivData            Data to be passed back to the caller via
+                                     the callback function
+@Return         PVRSRV_ERROR         PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify,
+								PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify,
+								PVRSRV_CMDCOMP_HANDLE hPrivData);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVUnregisterCmdCompleteNotify
+@Description    Unregister a previously registered callback function.
+@Input          hNotify              Command complete notifier handle
+@Return         PVRSRV_ERROR         PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVCheckStatus
+@Description    Notify any registered command complete handlers that some work
+                has been finished (unless hCmdCompCallerHandle matches a
+                handler's hPrivData). Also signal the global event object.
+@Input          hCmdCompCallerHandle Used to prevent a handler from being
+                                     notified. A NULL value results in all
+									 handlers being notified.
+*/ /***************************************************************************/
+void
+PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle);
+
+
+/**************************************************************************/ /*!
+Debug Notifier Interface
+*/ /***************************************************************************/
+
+#define DEBUG_REQUEST_DC                0
+#define DEBUG_REQUEST_SERVERSYNC        1
+#define DEBUG_REQUEST_SYS               2
+#define DEBUG_REQUEST_ANDROIDSYNC       3
+#define DEBUG_REQUEST_LINUXFENCE        4
+#define DEBUG_REQUEST_SYNCCHECKPOINT    5
+#define DEBUG_REQUEST_HTB               6
+#define DEBUG_REQUEST_APPHINT           7
+
+#define DEBUG_REQUEST_VERBOSITY_LOW		0
+#define DEBUG_REQUEST_VERBOSITY_MEDIUM	1
+#define DEBUG_REQUEST_VERBOSITY_HIGH	2
+#define DEBUG_REQUEST_VERBOSITY_MAX		DEBUG_REQUEST_VERBOSITY_HIGH
+
 /*
  * Macro used within debug dump functions to send output either to PVR_LOG or
  * a custom function. The custom function should be stored as a function pointer
@@ -62,6 +144,8 @@
 			PVR_LOG((__VA_ARGS__));                           \
 	} while(0)
 
+struct _PVRSRV_DEVICE_NODE_;
+
 typedef IMG_HANDLE PVRSRV_DBGREQ_HANDLE;
 typedef void (DUMPDEBUG_PRINTF_FUNC)(void *pvDumpDebugFile,
 					const IMG_CHAR *pszFormat, ...);
@@ -70,4 +154,89 @@
 					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 					void *pvDumpDebugFile);
 
+
+/**************************************************************************/ /*!
+@Function       PVRSRVRegisterDbgTable
+@Description    Registers a debug requester table for the given device. The
+                order in which the debug requester IDs appear in the given
+                table determine the order in which a set of notifier callbacks
+                will be called. In other words, the requester ID that appears
+                first will have all of its associated debug notifier callbacks
+                called first. This will then be followed by all the callbacks
+                associated with the next requester ID in the table and so on.
+@Input          psDevNode     Device node with which to register requester table
+@Input          paui32Table   Array of requester IDs
+@Input          ui32Length    Number of elements in paui32Table
+@Return         PVRSRV_ERROR  PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRegisterDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+					   IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVUnregisterDbgTable
+@Description    Unregisters a debug requester table.
+@Input          psDevNode     Device node for which the requester table should
+                              be unregistered
+@Return         void
+*/ /***************************************************************************/
+void
+PVRSRVUnregisterDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVRegisterDbgRequestNotify
+@Description    Register a callback function that is called when a debug request
+                is made via a call PVRSRVDebugRequest. There are a number of
+				verbosity levels ranging from DEBUG_REQUEST_VERBOSITY_LOW up to
+                DEBUG_REQUEST_VERBOSITY_MAX. The callback will be called once
+                for each level up to the highest level specified to
+                PVRSRVDebugRequest.
+@Output         phNotify             On success, points to debug notifier handle
+@Input          psDevNode            Device node for which the debug callback
+                                     should be registered
+@Input          pfnDbgRequestNotify  Function callback
+@Input          ui32RequesterID      Requester ID. This is used to determine
+                                     the order in which callbacks are called
+@Input          hDbgReqeustHandle    Data to be passed back to the caller via
+                                     the callback function
+@Return         PVRSRV_ERROR         PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify,
+							   struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+							   PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+							   IMG_UINT32 ui32RequesterID,
+							   PVRSRV_DBGREQ_HANDLE hDbgReqeustHandle);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVUnregisterDbgRequestNotify
+@Description    Unregister a previously registered callback function.
+@Input          hNotify              Debug notifier handle.
+@Return         PVRSRV_ERROR         PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVDebugRequest
+@Description    Notify any registered debug request handlers that a debug
+                request has been made and at what level.
+@Input          psDevNode           Device node for which the debug request has
+                                    been made
+@Input          ui32VerbLevel       The maximum verbosity level to dump
+@Input          pfnDumpDebugPrintf  Used to specify the print function that
+                                    should be used to dump any debug
+                                    information. If this argument is NULL then
+                                    PVR_LOG() will be used as the default print
+                                    function.
+@Input          pvDumpDebugFile     Optional file identifier to be passed to
+                                    the print function if required.
+@Return         void
+*/ /***************************************************************************/
+void
+PVRSRVDebugRequest(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+				   IMG_UINT32 ui32VerbLevel,
+				   DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				   void *pvDumpDebugFile);
+
 #endif /* !defined(__PVR_NOTIFIER_H__) */
diff --git a/drivers/staging/imgtec/rogue/pvr_tl.h b/drivers/staging/imgtec/rogue/pvr_tl.h
deleted file mode 100644
index 9724a4f..0000000
--- a/drivers/staging/imgtec/rogue/pvr_tl.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Services Transport Layer UM Client API
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    User mode Transport layer API for clients.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
- 
-#ifndef __PVR_TL_H__
-#define __PVR_TL_H__
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-
-#include "img_defs.h"
-#include "pvrsrv_error.h"
-#include "services_km.h"
-
-#include "pvr_tlcommon.h"
-
-
-/**************************************************************************/ /*!
- @Function		PVRSRVTLConnect
- @Description	Initialise connection to Services kernel server transport layer
- @Output		ppsConnection	Address of a pointer to a connection object
- @Return        PVRSRV_ERROR:	for system error codes
-*/ /***************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVTLConnect(PVRSRV_DEV_CONNECTION **ppsConnection);
-
-
-/**************************************************************************/ /*!
- @Function		PVRSRVTLDisconnect
- @Description	Disconnect from the Services kernel server transport layer
- @Input			psConnection	Pointer to connection object as returned from
- 	 	 	 	 	 	 	 	PVRSRVTLConnect()
- @Return        PVRSRV_ERROR:	for system error codes
-*/ /***************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVTLDisconnect(PVRSRV_DEV_CONNECTION* psConnection);
-
-
-/**************************************************************************/ /*!
- @Function		PVRSRVTLOpenStream
- @Description	Open a descriptor onto an existing PVR transport stream. If
-				the stream does not exist it returns a NOT_FOUND error unless
-				the OPEN_WAIT flag is supplied. In this case it will wait for
-				the stream to be created. If it is not created in the wait
-				period a TIMEOUT error is returned.
- @Input			psConnection	Address of a pointer to a connection object
- @Input			pszName			Address of the stream name string, no longer
- 	 	 	 	 	 	 	 	than PRVSRVTL_MAX_STREAM_NAME_SIZE.
- @Input			ui32Mode    Flags defined in pvr_tlcommon.h
-							ACQUIRE_NONBLOCKING: Results in non-blocking reads
-							    on stream. Reads are blocking by default
-                            OPEN_WAIT: Causes open to wait for a brief moment
-                                if the stream does not exist
- @Output		phSD		Address of a pointer to an stream object
- @Return 		PVRSRV_ERROR_NOT_FOUND:        when named stream not found
- @Return		PVRSRV_ERROR_ALREADY_OPEN:     stream already open by another
- @Return		PVRSRV_ERROR_STREAM_ERROR:     internal driver state error
- @Return        PVRSRV_ERROR_TIMEOUT:          block timed out, stream not found
- @Return		PVRSRV_ERROR:			       for other system codes
-*/ /***************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVTLOpenStream(PVRSRV_DEV_CONNECTION* psConnection,
-		IMG_PCHAR    pszName,
-		IMG_UINT32   ui32Mode,
-		PVRSRVTL_SD* phSD);
-
-
-/**************************************************************************/ /*!
- @Function		PVRSRVTLCloseStream
- @Description	Close and release the stream connection to Services kernel
-				server transport layer. Any outstanding Acquire will be
-				released.
- @Input			psConnection	Address of a pointer to a connection object
- @Input			hSD				Handle of the stream object to close
- @Return		PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle is not known
- @Return		PVRSRV_ERROR_STREAM_ERROR: 	  internal driver state error
- @Return		PVRSRV_ERROR:				  for system codes
-*/ /***************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVTLCloseStream(PVRSRV_DEV_CONNECTION* psConnection,
-		PVRSRVTL_SD hSD);
-
-
-
-/****************************************************************************
- * Stream Buffer Data retrieval API(s)
- * 
- * The client must ensure their use of this acquire/release API for a single 
- * connection/stream must not be shared with multiple execution contexts e.g.
- * between a kernel thread and an ISR handler. It is the client’s
- * responsibility to ensure this API is not interrupted by a high priority
- * thread/ISR
- ****************************************************************************/
-
-/**************************************************************************/ /*!
- @Function		PVRSRVTLAcquireData
- @Description	When there is data available in the stream buffer this call
- 	 	 	 	returns with the address and length of the data buffer the
- 	 	 	 	client can safely read. This buffer may contain one or more
- 	 	 	 	packets of data.
- 	 	 	 	If no data is available then this call blocks until it becomes
- 	 	 	 	available. However if the stream has been destroyed while
- 	 	 	 	waiting then a resource unavailable error will be returned
- 	 	 	 	to the caller. Clients must pair this call with a
- 	 	 	 	ReleaseData call.
- @Input			psConnection	Address of a pointer to a connection object
- @Input			hSD				Handle of the stream object to read
- @Output		ppPacketBuf		Address of a pointer to an byte buffer. On exit
-								pointer contains address of buffer to read from
- @Output		puiBufLen		Pointer to an integer. On exit it is the size
-								of the data to read from the packet buffer
- @Return		PVRSRV_ERROR_RESOURCE_UNAVAILABLE: when stream no longer exists
- @Return		PVRSRV_ERROR_HANDLE_NOT_FOUND:     when SD handle not known
- @Return		PVRSRV_ERROR_STREAM_ERROR: 	       internal driver state error
- @Return		PVRSRV_ERROR_RETRY:				   release not called beforehand
- @Return        PVRSRV_ERROR_TIMEOUT:              block timed out, no data
- @Return		PVRSRV_ERROR:					   for other system codes
-*/ /***************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVTLAcquireData(PVRSRV_DEV_CONNECTION* psConnection,
-		PVRSRVTL_SD hSD,
-		IMG_PBYTE*  ppPacketBuf,
-		IMG_UINT32* puiBufLen);
-
-
-/**************************************************************************/ /*!
- @Function		PVRSRVTLReleaseData
- @Description	Called after client has read the stream data out of the buffer
- 	 	 	 	The data is subsequently flushed from the stream buffer to make
- 	 	 	 	room for more data packets from the stream source.
- @Input			psConnection	Address of a pointer to a connection object
- @Input			hSD				Handle of the stream object to read
- @Return		PVRSRV_ERROR_RESOURCE_UNAVAILABLE: when stream no longer exists
- @Return		PVRSRV_ERROR_HANDLE_NOT_FOUND:   when SD handle not known to TL
- @Return		PVRSRV_ERROR_STREAM_ERROR: 	     internal driver state error
- @Return		PVRSRV_ERROR_RETRY:				 acquire not called beforehand
- @Return		PVRSRV_ERROR:	                 for system codes
-*/ /***************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVTLReleaseData(PVRSRV_DEV_CONNECTION* psConnection,
-		PVRSRVTL_SD hSD);
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* __PVR_TL_H__ */
-
-/******************************************************************************
- End of file (pvr_tl.h)
-******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/pvr_tlcommon.h b/drivers/staging/imgtec/rogue/pvr_tlcommon.h
index 91e8d33..919f7c7 100644
--- a/drivers/staging/imgtec/rogue/pvr_tlcommon.h
+++ b/drivers/staging/imgtec/rogue/pvr_tlcommon.h
@@ -1,6 +1,6 @@
 /*************************************************************************/ /*!
 @File
-@Title          Services Transport Layer common types and definitions
+@Title          Services Transport Layer compatibility header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @Description    Transport layer common types and definitions included into
                 both user mode and kernel mode source.
@@ -41,154 +41,15 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-#ifndef __PVR_TLCOMMON_H__
-#define __PVR_TLCOMMON_H__
 
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-#include "img_defs.h"
-
-
-/*! Handle type for stream descriptor objects as created by this API */
-typedef IMG_HANDLE PVRSRVTL_SD;
-
-
-/*! Maximum stream name length including the null byte */
-#define PRVSRVTL_MAX_STREAM_NAME_SIZE	20U
-
-/*! Packet lengths are always rounded up to a multiple of 4 bytes */
-#define PVRSRVTL_PACKET_ALIGNMENT		4U
-#define PVRSRVTL_ALIGN(x) 				((x+PVRSRVTL_PACKET_ALIGNMENT-1) & ~(PVRSRVTL_PACKET_ALIGNMENT-1))
-
-
-/*! A packet is made up of a header structure followed by the data bytes.
- * There are 3 types of packet: normal (has data), data lost and padding,
- * see packet flags. Header kept small to reduce data overhead.
- *
- * if the ORDER of the structure members is changed, please UPDATE the 
- *   PVRSRVTL_PACKET_FLAG_OFFSET macro.
+/*
+   This header is provided to maintain compatibility with source files
+   outside the DDK that include this header that has been moved/renamed to:
+   DDK/include/pvrsrv_tlcommon.h.
  */
-typedef struct _PVRSRVTL_PACKETHDR_
-{
-	IMG_UINT16 uiDataLen;	/*!< Number of bytes following header */
-	IMG_UINT16 uiFlags;		/*!< Packet flag word */
 
-	/* First bytes of data ... */
-	//IMG_UINT32 ui32Data;	// ... variable length data array
+#include "pvrsrv_tlcommon.h"
 
-} PVRSRVTL_PACKETHDR, *PVRSRVTL_PPACKETHDR;
-
-/* Structure must always be a size multiple of 4 as stream buffer
- * still an array of IMG_UINT32s.
- */
-static_assert((sizeof(PVRSRVTL_PACKETHDR) & 3) == 0,
-			  "sizeof(PVRSRVTL_PACKETHDR) must be a multiple of 4");
-
-/*! Packet header mask used to extract the type from the uiFlags member.
- * Do not use directly, \see TEST_PACKET_FLAG
- */
-#define PVRSRVTL_PACKETHDR_TYPE_MASK			0x000f
-
-/*! Packet header mask used to extract the flags from the uiFlags member.
- * Do not use directly, \see GET_PACKET_TYPE
- */
-#define PVRSRVTL_PACKETHDR_FLAG_MASK			0xfff0
-
-/*! Packet type enumeration.
- */
-typedef enum _PVRSRVTL_PACKETTYPE_
-{
-	/*! Undefined packet */
-	PVRSRVTL_PACKETTYPE_UNDEF = 0,
-
-	/*! Normal packet type. Indicates data follows the header.
-	 */
-	PVRSRVTL_PACKETTYPE_DATA = 1,
-
-	/*! When seen this packet type indicates that at this moment in the stream
-	 * packet(s) were not able to be accepted due to space constraints and that
-	 * recent data may be lost - depends on how the producer handles the
-	 * error. Such packets have no data, data length is 0.
-	 */
-	PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED = 2,
-
-	/*! Packets with this type set are padding packets that contain undefined
-	 * data and must be ignored/skipped by the client. They are used when the
-	 * circular stream buffer wraps around and there is not enough space for
-	 * the data at the end of the buffer. Such packets have a length of 0 or
-	 * more.
-	 */
-	PVRSRVTL_PACKETTYPE_PADDING = 3,
-
-	/*! This packet type conveys to the stream consumer that the stream producer
-	 * has reached the end of data for that data sequence. The TLDaemon
-	 * has several options for processing these packets that can be selected
-	 * on a per stream basis.
-	 */
-	PVRSRVTL_PACKETTYPE_MARKER_EOS = 4,
-
-	PVRSRVTL_PACKETTYPE_LAST = PVRSRVTL_PACKETTYPE_MARKER_EOS
-} PVRSRVTL_PACKETTYPE;
-
-/* The SET_PACKET_* macros rely on the order the PVRSRVTL_PACKETHDR members are declared:
- * uiFlags is the upper half of a structure consisting of 2 uint16 quantities.
- */
-#define PVRSRVTL_PACKET_FLAG_OFFSET		(8 * sizeof( ((PVRSRVTL_PACKETHDR *)NULL)->uiDataLen ))
-#define PVRSRVTL_SET_PACKET_DATA(len)   	(len) | (PVRSRVTL_PACKETTYPE_DATA                  <<PVRSRVTL_PACKET_FLAG_OFFSET)
-#define PVRSRVTL_SET_PACKET_PADDING(len)	(len) | (PVRSRVTL_PACKETTYPE_PADDING               <<PVRSRVTL_PACKET_FLAG_OFFSET)
-#define PVRSRVTL_SET_PACKET_HDR(len,type)	(len) | ((type)						               <<PVRSRVTL_PACKET_FLAG_OFFSET)
-#define PVRSRVTL_SET_PACKET_WRITE_FAILED           (PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED <<PVRSRVTL_PACKET_FLAG_OFFSET)
-
-/*! Returns the number of bytes of data in the packet. p may be any address type
- * */
-#define GET_PACKET_DATA_LEN(p)	\
-	((IMG_UINT32) ((PVRSRVTL_PPACKETHDR)(p))->uiDataLen )
-
-/*! Returns a IMG_BYTE* pointer to the first byte of data in the packet */
-#define GET_PACKET_DATA_PTR(p)	\
-	((IMG_PBYTE) ( ((size_t)p) + sizeof(PVRSRVTL_PACKETHDR)) )
-
-/*! Given a PVRSRVTL_PPACKETHDR address, return the address of the next pack
- *  It is up to the caller to determine if the new address is within the packet
- *  buffer.
- */
-#define GET_NEXT_PACKET_ADDR(p) \
-	((PVRSRVTL_PPACKETHDR) ( ((IMG_UINT8 *)p) + sizeof(PVRSRVTL_PACKETHDR) + \
-	(((((PVRSRVTL_PPACKETHDR)p)->uiDataLen) + \
-	(PVRSRVTL_PACKET_ALIGNMENT-1)) & (~(PVRSRVTL_PACKET_ALIGNMENT-1)) ) ))
-
-/*! Turns the packet address p into a PVRSRVTL_PPACKETHDR pointer type
- */
-#define GET_PACKET_HDR(p)		((PVRSRVTL_PPACKETHDR)(p))
-
-/*! Get the type of the packet. p is of type PVRSRVTL_PPACKETHDR
- */
-#define GET_PACKET_TYPE(p)		(((p)->uiFlags & PVRSRVTL_PACKETHDR_TYPE_MASK))
-
-/*! Tests if a packet flag is set or not. p is of type PVRSRVTL_PPACKETHDR and
- *  f is one of the flags
- */
-#define TEST_PACKET_FLAG(p, f)	((p->uiFlags & (f)) ? IMG_TRUE : IMG_FALSE)
-
-
-/*! Flags for use with PVRSRVTLOpenStream
- * 0x01 - Do not block in PVRSRVTLAcquireData() when no bytes are available
- * 0x02 - When the stream does not exist wait for a bit (2s) in
- *        PVRSRVTLOpenStream() and then exit with a timeout error if it still
- *        does not exist.
- */
-#define PVRSRV_STREAM_FLAG_NONE                 (1U<<0)
-#define PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING  (1U<<1)
-#define PVRSRV_STREAM_FLAG_OPEN_WAIT            (1U<<2)
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* __PVR_TLCOMMON_H__ */
 /******************************************************************************
  End of file (pvr_tlcommon.h)
 ******************************************************************************/
-
diff --git a/drivers/staging/imgtec/rogue/pvr_uaccess.h b/drivers/staging/imgtec/rogue/pvr_uaccess.h
index 53c8f0a..382cca4 100644
--- a/drivers/staging/imgtec/rogue/pvr_uaccess.h
+++ b/drivers/staging/imgtec/rogue/pvr_uaccess.h
@@ -42,27 +42,16 @@
 #ifndef __PVR_UACCESS_H__
 #define __PVR_UACCESS_H__
 
-#include <linux/version.h>
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-#endif
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static inline unsigned long pvr_copy_to_user(void __user *pvTo, const void *pvFrom, unsigned long ulBytes)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
     if (access_ok(VERIFY_WRITE, pvTo, ulBytes))
     {
-	return __copy_to_user(pvTo, pvFrom, ulBytes);
+		return __copy_to_user(pvTo, pvFrom, ulBytes);
     }
+
     return ulBytes;
-#else
-    return copy_to_user(pvTo, pvFrom, ulBytes);
-#endif
 }
 
 
@@ -85,20 +74,16 @@
 
 static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
 {
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
     /*
      * The compile time correctness checking introduced for copy_from_user in
      * Linux 2.6.33 isn't fully compatible with our usage of the function.
      */
     if (access_ok(VERIFY_READ, pvFrom, ulBytes))
     {
-	return __copy_from_user(pvTo, pvFrom, ulBytes);
+		return __copy_from_user(pvTo, pvFrom, ulBytes);
     }
+
     return ulBytes;
-#else
-    return copy_from_user(pvTo, pvFrom, ulBytes);
-#endif
 }
 #endif /* klocworks */ 
 
diff --git a/drivers/staging/imgtec/rogue/pvrsrv.c b/drivers/staging/imgtec/rogue/pvrsrv.c
index f8f67b9..9674155 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv.c
+++ b/drivers/staging/imgtec/rogue/pvrsrv.c
@@ -51,22 +51,23 @@
 #include "pvrsrv.h"
 #include "srvcore.h"
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
-#include "pvrsrv_virt.h"
+#include "pvrsrv_vz.h"
 #endif
 #include "services_km.h"
 #include "pvrsrv_device.h"
 #include "pvr_debug.h"
+#include "pvr_notifier.h"
 #include "sync.h"
 #include "sync_server.h"
 #include "devicemem.h"
+#include "cache_km.h"
 
 #include "log2.h"
 
-#include "pvrversion.h"
-
 #include "lists.h"
 #include "dllist.h"
 #include "syscommon.h"
+#include "sysvalidation.h"
 
 #include "physmem_lma.h"
 #include "physmem_osmem.h"
@@ -79,8 +80,6 @@
 #include "rgxfwutils.h"
 #endif
 
-#include "debug_request_ids.h"
-
 #if defined(PVR_RI_DEBUG)
 #include "ri_server.h"
 #endif
@@ -107,288 +106,46 @@
 #include "dc_server.h"
 #endif
 
+#if defined(SUPPORT_KERNEL_SRVINIT)
+#include "rgx_options.h"
+#include "srvinit.h"
+#include "rgxutils.h"
+#endif
+
+#include "oskm_apphint.h"
+#include "pvrsrv_apphint.h"
+
+#include "rgx_bvnc_defs_km.h"
+
 /*! Wait 100ms before retrying deferred clean-up again */
-#define CLEANUP_THREAD_WAIT_RETRY_TIMEOUT 0x00000064
+#define CLEANUP_THREAD_WAIT_RETRY_TIMEOUT 100000ULL
 
 /*! Wait 8hrs when no deferred clean-up required. Allows a poll several times
  * a day to check for any missed clean-up. */
-#define CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT 0x01B77400
+#define CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT 28800000000ULL
 
 /*! When unloading try a few times to free everything remaining on the list */
 #define CLEANUP_THREAD_UNLOAD_RETRY 4
 
-typedef struct DEBUG_REQUEST_ENTRY_TAG
-{
-	IMG_UINT32		ui32RequesterID;
-	DLLIST_NODE		sListHead;
-} DEBUG_REQUEST_ENTRY;
-
-typedef struct DEBUG_REQUEST_TABLE_TAG
-{
-	IMG_UINT32				ui32RequestCount;
-	DEBUG_REQUEST_ENTRY		asEntry[1];
-}DEBUG_REQUEST_TABLE;
+#define PVRSRV_PROC_HANDLE_BASE_INIT 10
 
 static PVRSRV_DATA	*gpsPVRSRVData = NULL;
-static IMG_HANDLE   g_hDbgSysNotify;
-
-static PVRSRV_SYSTEM_CONFIG *gpsSysConfig = NULL;
-
-typedef PVRSRV_ERROR (*PFN_REGISTER_DEVICE)(PVRSRV_DEVICE_NODE *psDeviceNode);
-typedef PVRSRV_ERROR (*PFN_UNREGISTER_DEVICE)(PVRSRV_DEVICE_NODE *psDeviceNode);
-
-static PFN_REGISTER_DEVICE sRegisterDevice[PVRSRV_DEVICE_TYPE_LAST + 1];
-static PFN_UNREGISTER_DEVICE sUnregisterDevice[PVRSRV_DEVICE_TYPE_LAST + 1];
-
-static PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PVRSRV_DEVICE_CONFIG *psDevConfig);
-static PVRSRV_ERROR IMG_CALLCONV PVRSRVUnregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
-
-static PVRSRV_ERROR PVRSRVRegisterDbgTable(IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length, void **phTable);
-static void PVRSRVUnregisterDbgTable(void *hTable);
-
-static void _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel,
-	DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile);
-
-IMG_UINT32	g_ui32InitFlags;
+static IMG_UINT32 g_ui32InitFlags;
 
 /* mark which parts of Services were initialised */
 #define		INIT_DATA_ENABLE_PDUMPINIT	0x1U
 
-/* Head of the list of callbacks called when Cmd complete happens */
-static DLLIST_NODE sCmdCompNotifyHead;
-static POSWR_LOCK hNotifyLock = NULL;
-
-/* Debug request table and lock */
-static POSWR_LOCK g_hDbgNotifyLock = NULL;
-static DEBUG_REQUEST_TABLE *g_psDebugTable;
-
-static void *g_hDebugTable = NULL;
-
 static IMG_UINT32 g_aui32DebugOrderTable[] = {
 	DEBUG_REQUEST_SYS,
-	DEBUG_REQUEST_RGX,
+	DEBUG_REQUEST_APPHINT,
+	DEBUG_REQUEST_HTB,
 	DEBUG_REQUEST_DC,
+	DEBUG_REQUEST_SYNCCHECKPOINT,
 	DEBUG_REQUEST_SERVERSYNC,
 	DEBUG_REQUEST_ANDROIDSYNC,
-	DEBUG_REQUEST_DRMDISPLAY,
 	DEBUG_REQUEST_LINUXFENCE
 };
 
-/*!
-******************************************************************************
-
- @Function	AllocateDeviceID
-
- @Description
-
- allocates a device id from the pool of valid ids
-
- @input psPVRSRVData :	Services private data
-
- @input pui32DevID : device id to return
-
- @Return device id
-
-******************************************************************************/
-static PVRSRV_ERROR AllocateDeviceID(PVRSRV_DATA *psPVRSRVData, IMG_UINT32 *pui32DevID)
-{
-	SYS_DEVICE_ID* psDeviceWalker;
-	SYS_DEVICE_ID* psDeviceEnd;
-
-	psDeviceWalker = &psPVRSRVData->sDeviceID[0];
-	psDeviceEnd = psDeviceWalker + SYS_DEVICE_COUNT;
-
-	/* find a free ID */
-	while (psDeviceWalker < psDeviceEnd)
-	{
-		if (!psDeviceWalker->bInUse)
-		{
-			psDeviceWalker->bInUse = IMG_TRUE;
-			*pui32DevID = psDeviceWalker->uiID;
-
-			return PVRSRV_OK;
-		}
-		psDeviceWalker++;
-	}
-
-	PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
-
-	/* Should never get here: sDeviceID[] may have been setup too small */
-	PVR_ASSERT(psDeviceWalker < psDeviceEnd);
-
-	return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVAILABLE;
-}
-
-
-/*!
-******************************************************************************
-
- @Function	FreeDeviceID
-
- @Description
-
- frees a device id from the pool of valid ids
-
- @input psPVRSRVData :	Services private data
-
- @input ui32DevID : device id to free
-
- @Return device id
-
-******************************************************************************/
-static PVRSRV_ERROR FreeDeviceID(PVRSRV_DATA *psPVRSRVData, IMG_UINT32 ui32DevID)
-{
-	SYS_DEVICE_ID* psDeviceWalker;
-	SYS_DEVICE_ID* psDeviceEnd;
-
-	psDeviceWalker = &psPVRSRVData->sDeviceID[0];
-	psDeviceEnd = psDeviceWalker + SYS_DEVICE_COUNT;
-
-	/* find the ID to free */
-	while (psDeviceWalker < psDeviceEnd)
-	{
-		/* if matching id and in use, free */
-		if	(
-				(psDeviceWalker->uiID == ui32DevID) &&
-				(psDeviceWalker->bInUse)
-			)
-		{
-			psDeviceWalker->bInUse = IMG_FALSE;
-			return PVRSRV_OK;
-		}
-		psDeviceWalker++;
-	}
-
-	PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
-
-	/* should never get here */
-	PVR_ASSERT(psDeviceWalker < psDeviceEnd);
-
-	return PVRSRV_ERROR_INVALID_DEVICEID;
-}
-
-
-/*!
-******************************************************************************
- @Function	PVRSRVEnumerateDevicesKM_ForEachVaCb
-
- @Description
-
- Enumerates the device node (if is of the same class as given).
-
- @Input psDeviceNode	- The device node to be enumerated
- 		va				- variable arguments list, with:
-							pui32DevCount	- The device count pointer (to be increased)
-							ppeDeviceType     - The pointer to the device type pointer (to be updated and increased)
-							ppeDeviceClass    - The pointer to the device classes pointer (to be updated and increased)
-							ppui32DeviceIndex - The pointer to the device indexes pointer (to be updated and increased)
-******************************************************************************/
-static void PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
-{
-	IMG_UINT *pui32DevCount;
-	PVRSRV_DEVICE_TYPE **ppeDeviceType;
-	PVRSRV_DEVICE_CLASS **ppeDeviceClass;
-	IMG_UINT32 **ppui32DeviceIndex;
-
-	pui32DevCount = va_arg(va, IMG_UINT*);
-	ppeDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE**);
-	ppeDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS**);
-	ppui32DeviceIndex = va_arg(va, IMG_UINT32**);
-
-	if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
-	{
-		**ppeDeviceType = psDeviceNode->sDevId.eDeviceType;
-		**ppeDeviceClass = psDeviceNode->sDevId.eDeviceClass;
-		**ppui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
-
-		(*ppeDeviceType)++;
-		(*ppeDeviceClass)++;
-		(*ppui32DeviceIndex)++;
-
-		(*pui32DevCount)++;
-	}
-}
-
-
-
-/*!
-******************************************************************************
-
- @Function PVRSRVEnumerateDevicesKM
-
- @Description
- This function will enumerate all the devices supported by the
- PowerVR services within the target system.
- The function returns a list of the device ID structures stored either in
- the services or constructed in the user mode glue component in certain
- environments. The number of devices in the list is also returned.
-
- In a binary layered component which does not support dynamic runtime selection,
- the glue code should compile to return the supported devices statically,
- e.g. multiple instances of the same device if multiple devices are supported,
- or the target combination of Rogue and display device.
-
- In the case of an environment (for instance) where one Rogue may connect to two
- display devices this code would enumerate all three devices and even
- non-dynamic Rogue selection code should retain the facility to parse the list
- to find the index of the Rogue device
-
- @output pui32NumDevices :	On success, contains the number of devices present
- 							in the system
-
- @output peDeviceType	 :	Pointer to called supplied buffer to receive the
- 							list of PVRSRV_DEVICE_TYPE
-
- @output peDeviceClass	 :	Pointer to called supplied buffer to receive the
- 							list of PVRSRV_DEVICE_CLASS
-
- @output pui32DeviceIndex:	Pointer to called supplied buffer to receive the
- 							list of device indexes
-
- @return PVRSRV_ERROR  :	
-
-******************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
-                                                   PVRSRV_DEVICE_TYPE *peDeviceType,
-                                                   PVRSRV_DEVICE_CLASS *peDeviceClass,
-                                                   IMG_UINT32 *pui32DeviceIndex)
-{
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-	IMG_UINT32 			i;
-
-	if (!pui32NumDevices || !peDeviceType || !peDeviceClass || !pui32DeviceIndex)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-	/*
-		setup input buffer to be `empty'
-	*/
-	for (i=0; i<PVRSRV_MAX_DEVICES; i++)
-	{
-		peDeviceType[i] = PVRSRV_DEVICE_TYPE_UNKNOWN;
-	}
-
-	/* and zero device count */
-	*pui32NumDevices = 0;
-
-	/*
-		Search through the device list for services managed devices
-		return id info for each device and the number of devices
-		available
-	*/
-	List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
-									   &PVRSRVEnumerateDevicesKM_ForEachVaCb,
-									   pui32NumDevices,
-									   &peDeviceType,
-									   &peDeviceClass,
-									   &pui32DeviceIndex);
-
-	return PVRSRV_OK;
-}
-
 /* Add work to the cleanup thread work list.
  * The work item will be executed by the cleanup thread
  */
@@ -400,8 +157,11 @@
 	psPVRSRVData = PVRSRVGetPVRSRVData();
 
 	PVR_ASSERT(psData != NULL);
-
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	if(psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK || psPVRSRVData->bUnload)
+#else
 	if(psPVRSRVData->bUnload)
+#endif
 	{
 		CLEANUP_THREAD_FN pfnFree = psData->pfnFree;
 
@@ -447,7 +207,8 @@
 }
 
 /* Process the cleanup thread work list */
-static IMG_BOOL _CleanupThreadProcessWorkList(PVRSRV_DATA *psPVRSRVData)
+static IMG_BOOL _CleanupThreadProcessWorkList(PVRSRV_DATA *psPVRSRVData,
+                                              IMG_BOOL *pbUseGlobalEO)
 {
 	DLLIST_NODE *psNodeIter, *psNodeLast;
 	PVRSRV_ERROR eError;
@@ -482,6 +243,7 @@
 			 */
 			pfnFree = psData->pfnFree;
 
+			*pbUseGlobalEO = psData->bDependsOnHW;
 			eError = pfnFree(psData->pvData);
 
 			if(eError != PVRSRV_OK)
@@ -540,8 +302,10 @@
 {
 	PVRSRV_DATA *psPVRSRVData = pvData;
 	IMG_BOOL     bRetryWorkList = IMG_FALSE;
+	IMG_HANDLE	 hGlobalEvent;
 	IMG_HANDLE	 hOSEvent;
 	PVRSRV_ERROR eRc;
+	IMG_BOOL bUseGlobalEO = IMG_FALSE;
 	IMG_UINT32 uiUnloadRetry = 0;
 
 	/* Store the process id (pid) of the clean-up thread */
@@ -555,11 +319,16 @@
 	eRc = OSEventObjectOpen(psPVRSRVData->hCleanupEventObject, &hOSEvent);
 	PVR_ASSERT(eRc == PVRSRV_OK);
 
+	eRc = OSEventObjectOpen(psPVRSRVData->hGlobalEventObject, &hGlobalEvent);
+	PVR_ASSERT(eRc == PVRSRV_OK);
+
 	/* While the driver is in a good state and is not being unloaded
 	 * try to free any deferred items when signalled
 	 */
 	while ((psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK))
 	{
+		IMG_HANDLE hEvent;
+
 		if (psPVRSRVData->bUnload)
 		{
 			if (dllist_is_empty(&psPVRSRVData->sCleanupThreadWorkList) ||
@@ -569,12 +338,23 @@
 			}
 			uiUnloadRetry++;
 		}
+
 		/* Wait until signalled for deferred clean up OR wait for a
 		 * short period if the previous deferred clean up was not able
 		 * to release all the resources before trying again.
 		 * Bridge lock re-acquired on our behalf before the wait call returns.
 		 */
-		eRc = OSEventObjectWaitTimeout(hOSEvent,
+
+		if(bRetryWorkList && bUseGlobalEO)
+		{
+			hEvent = hGlobalEvent;
+		}
+		else
+		{
+			hEvent = hOSEvent;
+		}
+
+		eRc = OSEventObjectWaitTimeout(hEvent,
 				bRetryWorkList ?
 				CLEANUP_THREAD_WAIT_RETRY_TIMEOUT :
 				CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT);
@@ -591,7 +371,7 @@
 			PVR_DPF((PVR_DBG_ERROR, "CleanupThread: wait error %d", eRc));
 		}
 
-		bRetryWorkList = _CleanupThreadProcessWorkList(psPVRSRVData);
+		bRetryWorkList = _CleanupThreadProcessWorkList(psPVRSRVData, &bUseGlobalEO);
 	}
 
 	OSLockDestroy(psPVRSRVData->hCleanupThreadWorkListLock);
@@ -599,9 +379,79 @@
 	eRc = OSEventObjectClose(hOSEvent);
 	PVR_LOG_IF_ERROR(eRc, "OSEventObjectClose");
 
+	eRc = OSEventObjectClose(hGlobalEvent);
+	PVR_LOG_IF_ERROR(eRc, "OSEventObjectClose");
+
 	PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread ending... "));
 }
 
+static IMG_BOOL DevicesWatchdogThread_Powered_Any(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_DEV_POWER_STATE ePowerState = PVRSRV_DEV_POWER_STATE_ON;
+	PVRSRV_ERROR eError;
+
+	eError = PVRSRVPowerLock(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		if (eError == PVRSRV_ERROR_RETRY)
+		{
+			/* Power lock cannot be acquired at this time (sys power is off) */
+			return IMG_FALSE;
+		}
+
+		/* Any other error is unexpected so we assume the device is on */
+		PVR_DPF((PVR_DBG_ERROR,
+				 "DevicesWatchdogThread: Failed to acquire power lock for device %p (%s)",
+				 psDeviceNode, PVRSRVGetErrorStringKM(eError)));
+		return IMG_TRUE;
+	}
+
+	(void) PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+
+	PVRSRVPowerUnlock(psDeviceNode);
+
+	return (ePowerState == PVRSRV_DEV_POWER_STATE_ON) ? IMG_TRUE : IMG_FALSE;
+}
+
+static void DevicesWatchdogThread_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode,
+											  va_list va)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+	PVRSRV_DEVICE_HEALTH_STATUS *pePreviousHealthStatus, eHealthStatus;
+	PVRSRV_ERROR eError;
+
+	pePreviousHealthStatus = va_arg(va, PVRSRV_DEVICE_HEALTH_STATUS *);
+
+	if (psDeviceNode->pfnUpdateHealthStatus != NULL)
+	{
+		eError = psDeviceNode->pfnUpdateHealthStatus(psDeviceNode, IMG_TRUE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
+					 "Could not check for fatal error (%d)!",
+					 eError));
+		}
+	}
+	eHealthStatus = OSAtomicRead(&psDeviceNode->eHealthStatus);
+
+	if (eHealthStatus != PVRSRV_DEVICE_HEALTH_STATUS_OK)
+	{
+		if (eHealthStatus != *pePreviousHealthStatus)
+		{
+			if (!(psDevInfo->ui32DeviceFlags &
+				  RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "DevicesWatchdogThread: "
+						 "Device not responding!!!"));
+				PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX,
+								   NULL, NULL);
+			}
+		}
+	}
+
+	*pePreviousHealthStatus = eHealthStatus;
+}
+
 static void DevicesWatchdogThread(void *pvData)
 {
 	PVRSRV_DATA *psPVRSRVData = pvData;
@@ -609,7 +459,6 @@
 	IMG_HANDLE hOSEvent;
 	PVRSRV_ERROR  eError;
 	IMG_UINT32 ui32Timeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
-	PVRSRV_DEV_POWER_STATE ePowerState;
 
 	PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Power off sleep time: %d.",
 			DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT));
@@ -620,14 +469,18 @@
 	PVR_LOGRN_IF_ERROR(eError, "OSEventObjectOpen");
 
 	/* Loop continuously checking the device status every few seconds. */
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	while ((psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK) &&
+			!psPVRSRVData->bUnload)
+#else
 	while (!psPVRSRVData->bUnload)
+#endif
 	{
-		IMG_UINT32 i;
 		IMG_BOOL bPwrIsOn = IMG_FALSE;
 
 		/* Wait time between polls (done at the start of the loop to allow devices
 		   to initialise) or for the event signal (shutdown or power on). */
-		eError = OSEventObjectWaitTimeout(hOSEvent, ui32Timeout);
+		eError = OSEventObjectWaitTimeout(hOSEvent, (IMG_UINT64)ui32Timeout * 1000);
 
 #ifdef PVR_TESTING_UTILS
 		psPVRSRVData->ui32DevicesWdWakeupCounter++;
@@ -651,92 +504,24 @@
 					"Error (%d) when waiting for event!", eError));
 		}
 
-		eError = PVRSRVPowerLock();
-		if (eError == PVRSRV_ERROR_RETRY)
+		bPwrIsOn = List_PVRSRV_DEVICE_NODE_IMG_BOOL_Any(psPVRSRVData->psDeviceNodeList,
+														DevicesWatchdogThread_Powered_Any);
+		if (bPwrIsOn || psPVRSRVData->ui32DevicesWatchdogPwrTrans)
 		{
-			/* power lock cannot be acquired at this time (sys power is off) */
-			ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
-		}
-		else if (eError != PVRSRV_OK)
-		{
-			/* any other error is unexpected */
-			PVR_DPF((PVR_DBG_ERROR,"DevicesWatchdogThread: Failed to acquire power lock (%s)", PVRSRVGetErrorStringKM(eError)));
+			psPVRSRVData->ui32DevicesWatchdogPwrTrans = 0;
+			ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
 		}
 		else
 		{
-			/* Check if at least one of the devices is on. */
-			for (i = 0; i < psPVRSRVData->ui32RegisteredDevices && !bPwrIsOn; i++)
-			{
-				if (PVRSRVGetDevicePowerState(i, &ePowerState) == PVRSRV_OK)
-				{
-					bPwrIsOn = ePowerState == PVRSRV_DEV_POWER_STATE_ON;
-					break;
-				}
-			}
-
-			if (bPwrIsOn || psPVRSRVData->ui32DevicesWatchdogPwrTrans)
-			{
-				psPVRSRVData->ui32DevicesWatchdogPwrTrans = 0;
-				ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
-			}
-			else
-			{
-				ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
-			}
-
-			PVRSRVPowerUnlock();
+			ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
 		}
 
-		for (i = 0;  i < psPVRSRVData->ui32RegisteredDevices; i++)
-		{
-			PVRSRV_DEVICE_NODE* psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
-			PVRSRV_RGXDEV_INFO* psDevInfo = (PVRSRV_RGXDEV_INFO*) psDeviceNode->pvDevice;
-			
-			if (psDeviceNode->pfnUpdateHealthStatus != NULL)
-			{
-				eError = psDeviceNode->pfnUpdateHealthStatus(psDeviceNode, IMG_TRUE);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
-							"Could not check for fatal error (%d)!",
-							eError));
-				}
-			}
+		List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
+										   DevicesWatchdogThread_ForEachVaCb,
+										   &ePreviousHealthStatus);
 
-			if (psDeviceNode->eHealthStatus != PVRSRV_DEVICE_HEALTH_STATUS_OK)
-			{
-				if (psDeviceNode->eHealthStatus != ePreviousHealthStatus)
-				{
-					if (!(psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN))
-					{
-						PVR_DPF((PVR_DBG_ERROR, "DevicesWatchdogThread: Device not responding!!!"));
-						PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
-					}
-				}
-			}
-			ePreviousHealthStatus = psDeviceNode->eHealthStatus;
-			
-			/* Attempt to service the HWPerf buffer to regularly transport 
-			 * idle / periodic packets to host buffer. */
-			if (psDeviceNode->pfnServiceHWPerf != NULL)
-			{
-				eError = psDeviceNode->pfnServiceHWPerf(psDeviceNode);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
-							"Error occurred when servicing HWPerf buffer (%d)",
-							eError));
-				}
-			}
-		}
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-		{
-			#if defined(EMULATOR)
-			{
-				SysPrintAndResetFaultStatusRegister();
-			}
-			#endif
-		}
+#if defined(SUPPORT_GPUVIRT_VALIDATION) && defined(EMULATOR)
+		SysPrintAndResetFaultStatusRegister();
 #endif
 	}
 
@@ -750,19 +535,30 @@
 	return gpsPVRSRVData;
 }
 
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(void *hDevice)
+PVRSRV_ERROR IMG_CALLCONV
+PVRSRVDriverInit(void)
 {
-	PVRSRV_ERROR	eError;
-	PVRSRV_SYSTEM_CONFIG *psSysConfig;
-	IMG_UINT32 i;
+	PVRSRV_ERROR eError;
 	PVRSRV_DATA	*psPVRSRVData = NULL;
 
-#if defined (SUPPORT_RGX)
-	sRegisterDevice[PVRSRV_DEVICE_TYPE_RGX] = RGXRegisterDevice;
-#endif
+	IMG_UINT32 ui32AppHintCleanupThreadPriority;
+	IMG_UINT32 ui32AppHintCleanupThreadWeight;
+	IMG_UINT32 ui32AppHintWatchdogThreadPriority;
+	IMG_UINT32 ui32AppHintWatchdogThreadWeight;
 
-	SET_LOG2_PAGESIZE(OSGetPageShift());
+	void *pvAppHintState = NULL;
+	IMG_UINT32 ui32AppHintDefault;
+
+	/*
+	 * As this function performs one time driver initialisation, use the
+	 * Services global device-independent data to determine whether or not
+	 * this function has already been called.
+	 */
+	if (gpsPVRSRVData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Driver already initialised", __func__));
+		return PVRSRV_ERROR_ALREADY_EXISTS;
+	}
 
 	eError = PhysHeapInit();
 	if (eError != PVRSRV_OK)
@@ -770,28 +566,6 @@
 		goto Error;
 	}
 
-	/* Get the system config */
-	eError = SysCreateConfigData(&psSysConfig, hDevice);
-	if (eError != PVRSRV_OK)
-	{
-		goto Error;
-	}
-
-	if (psSysConfig->uiDeviceCount > 1)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVInit: System config contains too many devices"));
-		eError = PVRSRV_ERROR_INVALID_DEVICE;
-		goto Error;
-	}
-
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	/* Perform virtualization initliazation if any */
-	PVRSRVVirtInit(psSysConfig);
-#endif
-
-	/* Save to global pointer for later */
-	gpsSysConfig = psSysConfig;
-
 	/*
 	 * Allocate the device-independent data
 	 */
@@ -802,30 +576,6 @@
 		goto Error;
 	}
 
-	psPVRSRVData->ui32NumDevices = psSysConfig->uiDeviceCount;
-
-	for (i=0;i<SYS_DEVICE_COUNT;i++)
-	{
-		psPVRSRVData->sDeviceID[i].uiID = i;
-		psPVRSRVData->sDeviceID[i].bInUse = IMG_FALSE;
-	}
-
-	/*
-	 * Register the physical memory heaps
-	 */
-	PVR_ASSERT(psSysConfig->ui32PhysHeapCount <= SYS_PHYS_HEAP_COUNT);
-	for (i=0;i<psSysConfig->ui32PhysHeapCount;i++)
-	{
-		eError = PhysHeapRegister(&psSysConfig->pasPhysHeaps[i],
-								  &psPVRSRVData->apsRegisteredPhysHeaps[i]);
-		if (eError != PVRSRV_OK)
-		{
-			/* point gpsPVRSRVData to the actual data, so it will be freed */
-			gpsPVRSRVData = psPVRSRVData;
-			goto Error;
-		}
-		psPVRSRVData->ui32RegisteredPhysHeaps++;
-	}
 	/* Now it is set up, point gpsPVRSRVData to the actual data */
 	gpsPVRSRVData = psPVRSRVData;
 
@@ -845,15 +595,17 @@
 
 	if(eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Failed to initialise DevicememHistory"));
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to initialise DevicememHistoryInitKM", __func__));
 		goto Error;
 	}
 #endif
 
-	eError = BridgeBufferPoolCreate();
+	eError = BridgeInit();
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Failed to initialise bridge buffer pool."));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise bridge",
+				 __func__));
 		goto Error;
 	}
 
@@ -863,6 +615,12 @@
 		goto Error;
 	}
 
+	eError = CacheOpInit();
+	if (eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
 #if defined(SUPPORT_DISPLAY_CLASS)
 	eError = DCInit();
 	if (eError != PVRSRV_OK)
@@ -871,17 +629,6 @@
 	}
 #endif
 
-	/* Initialise Power Manager Lock */
-	eError = OSLockCreate(&gpsPVRSRVData->hPowerLock, LOCK_TYPE_PASSIVE);
-	if (eError != PVRSRV_OK)
-	{
-		goto Error;
-	}
-
-	/* Initialise system power state */
-	gpsPVRSRVData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_ON;
-	gpsPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
-
 	/* Initialise overall system state */
 	gpsPVRSRVData->eServicesState = PVRSRV_SERVICES_STATE_OK;
 
@@ -893,34 +640,7 @@
 	}
 	gpsPVRSRVData->ui32GEOConsecutiveTimeouts = 0;
 
-	/* initialise list of command complete notifiers */
-	dllist_init(&sCmdCompNotifyHead);
-
-	/* Create a lock of the list notifiers */
-	eError = OSWRLockCreate(&hNotifyLock);
-	if (eError != PVRSRV_OK)
-	{
-		goto Error;
-	}
-
-	/* Create a lock of the debug notifiers */
-	eError = OSWRLockCreate(&g_hDbgNotifyLock);
-	if (eError != PVRSRV_OK)
-	{
-		goto Error;
-	}
-
-	eError = PVRSRVRegisterDbgTable(g_aui32DebugOrderTable,
-									sizeof(g_aui32DebugOrderTable)/sizeof(g_aui32DebugOrderTable[0]),
-									&g_hDebugTable);
-	if (eError != PVRSRV_OK)
-	{
-		goto Error;
-	}
-
-	PVRSRVRegisterDbgRequestNotify(&g_hDbgSysNotify, &_SysDebugRequestNotify, DEBUG_REQUEST_SYS, gpsPVRSRVData);
-
-	eError = ServerSyncInit();
+	eError = PVRSRVCmdCompleteInit();
 	if (eError != PVRSRV_OK)
 	{
 		goto Error;
@@ -935,52 +655,51 @@
 
 	g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
 
-	/* Register all the system devices */
-	for (i=0;i<psSysConfig->uiDeviceCount;i++)
-	{
-		eError = PVRSRVRegisterDevice(&psSysConfig->pasDevices[i]);
-		if (eError != PVRSRV_OK)
-		{
-			goto Error;
-		}
-
-		/* Initialise the Transport Layer.
-		 * Need to remember the RGX device node for use in the Transport Layer
-		 * when allocating stream buffers that are shared with clients.
-		 * Note however when the device is an LMA device our buffers will not
-		 * be in host memory but card memory.
-		 */
-		if (gpsPVRSRVData->apsRegisteredDevNodes[gpsPVRSRVData->ui32RegisteredDevices-1]->psDevConfig->eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
-		{
-			eError = TLInit(gpsPVRSRVData->apsRegisteredDevNodes[gpsPVRSRVData->ui32RegisteredDevices-1]);
-			PVR_LOGG_IF_ERROR(eError, "TLInit", Error);
-		}
-	}
-
 	eError = PVRSRVHandleInit();
 	if(eError != PVRSRV_OK)
 	{
 		goto Error;
 	}
 
-	eError = PVRSRVConnectionInit();
-	if(eError != PVRSRV_OK)
-	{
-		goto Error;
-	}
-
 	eError = _CleanupThreadPrepare(gpsPVRSRVData);
 	PVR_LOGG_IF_ERROR(eError, "_CleanupThreadPrepare", Error);
 
 	/* Create a thread which is used to do the deferred cleanup */
 	eError = OSThreadCreatePriority(&gpsPVRSRVData->hCleanupThread,
-							"pvr_defer_free" PVRSRV_GPUVIRT_OSID_STR,
+							"pvr_defer_free",
 							CleanupThread,
 							gpsPVRSRVData,
 							OS_THREAD_LOWEST_PRIORITY);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to create deferred cleanup thread"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create deferred cleanup thread",
+				 __func__));
+		goto Error;
+	}
+
+	OSCreateKMAppHintState(&pvAppHintState);
+	ui32AppHintDefault = PVRSRV_APPHINT_CLEANUPTHREADPRIORITY;
+	OSGetKMAppHintUINT32(pvAppHintState, CleanupThreadPriority,
+	                     &ui32AppHintDefault, &ui32AppHintCleanupThreadPriority);
+	ui32AppHintDefault = PVRSRV_APPHINT_CLEANUPTHREADWEIGHT;
+	OSGetKMAppHintUINT32(pvAppHintState, CleanupThreadWeight,
+	                     &ui32AppHintDefault, &ui32AppHintCleanupThreadWeight);
+	ui32AppHintDefault = PVRSRV_APPHINT_WATCHDOGTHREADPRIORITY;
+	OSGetKMAppHintUINT32(pvAppHintState, WatchdogThreadPriority,
+	                     &ui32AppHintDefault, &ui32AppHintWatchdogThreadPriority);
+	ui32AppHintDefault = PVRSRV_APPHINT_WATCHDOGTHREADWEIGHT;
+	OSGetKMAppHintUINT32(pvAppHintState, WatchdogThreadWeight,
+	                     &ui32AppHintDefault, &ui32AppHintWatchdogThreadWeight);
+	OSFreeKMAppHintState(pvAppHintState);
+	pvAppHintState = NULL;
+
+	eError = OSSetThreadPriority(gpsPVRSRVData->hCleanupThread,
+								 ui32AppHintCleanupThreadPriority,
+								 ui32AppHintCleanupThreadWeight);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set thread priority of deferred cleanup thread.",
+				 __func__));	
 		goto Error;
 	}
 
@@ -990,68 +709,90 @@
 
 	/* Create a thread which is used to detect fatal errors */
 	eError = OSThreadCreate(&gpsPVRSRVData->hDevicesWatchdogThread,
-							"pvr_device_wdg" PVRSRV_GPUVIRT_OSID_STR,
+							"pvr_device_wdg",
 							DevicesWatchdogThread,
 							gpsPVRSRVData);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to create devices watchdog thread"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create devices watchdog thread",
+				 __func__));
 		goto Error;
 	}
 
-#if defined(PVR_TESTING_UTILS)
-	TUtilsInit();
-#endif
-
-#if defined(PVR_DVFS)
-	eError = InitDVFS(gpsPVRSRVData, hDevice);
+	eError = OSSetThreadPriority(gpsPVRSRVData->hDevicesWatchdogThread,
+								 ui32AppHintWatchdogThreadPriority,
+								 ui32AppHintWatchdogThreadWeight);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to start DVFS"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set thread priority of the watchdog thread.",
+				 __func__));	
 		goto Error;
 	}
-#endif
+
+	gpsPVRSRVData->psProcessHandleBase_Table = HASH_Create(PVRSRV_PROC_HANDLE_BASE_INIT);
+
+	if (gpsPVRSRVData->psProcessHandleBase_Table == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Failed to create hash table for process handle base.",
+				__func__));
+		eError = PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+		goto Error;
+	}
+
+	eError = OSLockCreate(&gpsPVRSRVData->hProcessHandleBase_Lock, LOCK_TYPE_PASSIVE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Failed to create lock for process handle base.",
+				__func__));
+		goto Error;
+	}
 
 	return 0;
 
 Error:
-	PVRSRVDeInit(hDevice);
+	PVRSRVDriverDeInit();
 	return eError;
 }
 
-
-void IMG_CALLCONV PVRSRVDeInit(void *hDevice)
+void IMG_CALLCONV
+PVRSRVDriverDeInit(void)
 {
-	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_ERROR	eError = PVRSRV_OK;
-	IMG_UINT32		i;
+	PVRSRV_ERROR eError = PVRSRV_OK;
 
 	if (gpsPVRSRVData == NULL)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit failed - invalid gpsPVRSRVData"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: missing device-independent data",
+				 __func__));
 		return;
 	}
 
-#if defined(PVR_TESTING_UTILS)
-	TUtilsDeinit();
-#endif
+	gpsPVRSRVData->bUnload = IMG_TRUE;
 
-#if defined (SUPPORT_RGX)
-	sUnregisterDevice[PVRSRV_DEVICE_TYPE_RGX] = DevDeInitRGX;
-#endif
-
-	psPVRSRVData->bUnload = IMG_TRUE;
-	if (psPVRSRVData->hGlobalEventObject)
+	if (gpsPVRSRVData->hProcessHandleBase_Lock)
 	{
-		OSEventObjectSignal(psPVRSRVData->hGlobalEventObject);
+		OSLockDestroy(gpsPVRSRVData->hProcessHandleBase_Lock);
+		gpsPVRSRVData->hProcessHandleBase_Lock = NULL;
+	}
+
+	if (gpsPVRSRVData->psProcessHandleBase_Table)
+	{
+		HASH_Delete(gpsPVRSRVData->psProcessHandleBase_Table);
+		gpsPVRSRVData->psProcessHandleBase_Table = NULL;
+	}
+
+	if (gpsPVRSRVData->hGlobalEventObject)
+	{
+		OSEventObjectSignal(gpsPVRSRVData->hGlobalEventObject);
 	}
 
 	/* Stop and cleanup the devices watchdog thread */
-	if (psPVRSRVData->hDevicesWatchdogThread)
+	if (gpsPVRSRVData->hDevicesWatchdogThread)
 	{
-		if (psPVRSRVData->hDevicesWatchdogEvObj)
+		if (gpsPVRSRVData->hDevicesWatchdogEvObj)
 		{
-			eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
+			eError = OSEventObjectSignal(gpsPVRSRVData->hDevicesWatchdogEvObj);
 			PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
 		}
 		LOOP_UNTIL_TIMEOUT(OS_THREAD_DESTROY_TIMEOUT_US)
@@ -1077,11 +818,11 @@
 	/* Stop and cleanup the deferred clean up thread, event object and
 	 * deferred context list.
 	 */
-	if (psPVRSRVData->hCleanupThread)
+	if (gpsPVRSRVData->hCleanupThread)
 	{
-		if (psPVRSRVData->hCleanupEventObject)
+		if (gpsPVRSRVData->hCleanupEventObject)
 		{
-			eError = OSEventObjectSignal(psPVRSRVData->hCleanupEventObject);
+			eError = OSEventObjectSignal(gpsPVRSRVData->hCleanupEventObject);
 			PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
 		}
 		LOOP_UNTIL_TIMEOUT(OS_THREAD_DESTROY_TIMEOUT_US)
@@ -1105,83 +846,14 @@
 	}
 
 	/* Tear down the HTB before PVRSRVHandleDeInit() removes its TL handle */
-	HTBDeInit();
-
-	eError = PVRSRVConnectionDeInit();
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVConnectionDataDeInit failed"));
-	}
+	/* HTB De-init happens in device de-registration currently */
+	eError = HTBDeInit();
+	PVR_LOG_IF_ERROR(eError, "HTBDeInit");
 
 	eError = PVRSRVHandleDeInit();
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
-	}
-
-	/* Unregister all the system devices */
-	for (i=0;i<psPVRSRVData->ui32RegisteredDevices;i++)
-	{
-		PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
-
-		/* set device state */
-		psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_DEINIT;
-
-		/* Counter part to what gets done in PVRSRVFinaliseSystem */
-		if (psDeviceNode->hSyncPrimContext != NULL)
-		{
-			if (psDeviceNode->psSyncPrim != NULL)
-			{
-				/* Free general pupose sync primitive */
-				SyncPrimFree(psDeviceNode->psSyncPrim);
-				psDeviceNode->psSyncPrim = NULL;
-			}
-
-			SyncPrimContextDestroy(psDeviceNode->hSyncPrimContext);
-			psDeviceNode->hSyncPrimContext = NULL;
-		}
-
-		PVRSRVUnregisterDevice(psDeviceNode);
-		psPVRSRVData->apsRegisteredDevNodes[i] = NULL;
-	}
-
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	/* Perform virtualization deinitliazation if any */
-	PVRSRVVirtDeInit(gpsSysConfig);
-#endif
-
-	SysDestroyConfigData(gpsSysConfig);
-
-#if defined(PVR_DVFS)
-	DeinitDVFS(gpsPVRSRVData, hDevice);
-#endif
-
-	/* Clean up Transport Layer resources that remain. 
-	 * Done after RGX node clean up as HWPerf stream is destroyed during 
-	 * this
-	 */
-	TLDeInit();
-
-	ServerSyncDeinit();
-
-	if (g_hDbgSysNotify)
-	{
-		PVRSRVUnregisterDbgRequestNotify(g_hDbgSysNotify);
-	}
-
-	if (g_hDebugTable)
-	{
-		PVRSRVUnregisterDbgTable(g_hDebugTable);
-	}
-
-	if (g_hDbgNotifyLock)
-	{
-		OSWRLockDestroy(g_hDbgNotifyLock);
-	}
-
-	if (hNotifyLock)
-	{
-		OSWRLockDestroy(hNotifyLock);
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVHandleDeInit failed", __func__));
 	}
 
 	/* deinitialise pdump */
@@ -1197,46 +869,29 @@
 		gpsPVRSRVData->hGlobalEventObject = NULL;
 	}
 
-	/* Check there is no notify function */
-	if (!dllist_is_empty(&sCmdCompNotifyHead))
-	{
-		PDLLIST_NODE psNode = dllist_get_next_node(&sCmdCompNotifyHead);
-
-		/* some device did not unregistered properly */
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: Notify list for cmd complete is not empty!!"));
-
-		/* clean the nodes anyway */
-		while (psNode != NULL)
-		{
-			PVRSRV_CMDCOMP_NOTIFY	*psNotify;
-
-			dllist_remove_node(psNode);
-			
-			psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
-			OSFreeMem(psNotify);
-
-			psNode = dllist_get_next_node(&sCmdCompNotifyHead);
-		}
-	}
-
-	OSLockDestroy(gpsPVRSRVData->hPowerLock);
+	PVRSRVCmdCompleteDeinit();
 
 #if defined(SUPPORT_DISPLAY_CLASS)
 	eError = DCDeInit();
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: DCInit() failed"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: DCDeInit failed", __func__));
 	}
 #endif
 
+    eError = CacheOpDeInit();
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: CacheOpDeInit failed", __func__));
+	}
 
     eError = PMRDeInit();
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PMRDeInit() failed"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: PMRDeInit failed", __func__));
 	}
 
-	BridgeBufferPoolDestroy();
+	BridgeDeinit();
 
 #if defined(PVR_RI_DEBUG)
 	RIDeInitKM();
@@ -1248,173 +903,16 @@
 	
 	OSDeInitEnvData();
 
-	for (i=0;i<gpsPVRSRVData->ui32RegisteredPhysHeaps;i++)
-	{
-		PhysHeapUnregister(gpsPVRSRVData->apsRegisteredPhysHeaps[i]);
-	}
 	eError = PhysHeapDeinit();
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PhysHeapDeinit() failed"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: PhysHeapDeinit failed", __func__));
 	}
 
 	OSFreeMem(gpsPVRSRVData);
 	gpsPVRSRVData = NULL;
 }
 
-PVRSRV_ERROR LMA_PhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
-							PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr)
-{
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-	IMG_UINT32  ui32OSid = 0;
-#endif
-	IMG_BOOL bSuccess;
-	RA_BASE_T uiCardAddr;
-	RA_LENGTH_T uiActualSize;
-	RA_ARENA *pArena=psDevNode->psLocalDevMemArena;
-	IMG_UINT32 ui32Log2NumPages = 0;
-	
-	PVR_ASSERT(uiSize != 0);
-	ui32Log2NumPages = OSGetOrder(uiSize);
-	uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-{
-	IMG_UINT32	ui32OSidReg = 0;
-
-	IMG_PID		pId = OSGetCurrentClientProcessIDKM();
-
-	RetrieveOSidsfromPidList(pId, &ui32OSid, &ui32OSidReg);
-
-	pArena = psDevNode->psOSidSubArena[ui32OSid];
-}
-#endif
-
-	bSuccess = RA_Alloc(pArena,
-						uiSize,
-						RA_NO_IMPORT_MULTIPLIER,
-						0,							/* No flags */
-						OSGetPageSize(),
-						&uiCardAddr,
-						&uiActualSize,
-						NULL);					/* No private handle */
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-{
-	PVR_DPF((PVR_DBG_MESSAGE,"(GPU Virtualization Validation): LMA_PhyContigPagesAlloc: Address:%llu, size:%llu", uiCardAddr,uiActualSize));
-}
-#endif
-
-	PVR_ASSERT(uiSize == uiActualSize);
-
-	psMemHandle->u.ui64Handle = uiCardAddr;
-	psDevPAddr->uiAddr = (IMG_UINT64) uiCardAddr;
-
-	if (bSuccess)
-	{
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-	PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, uiSize);
-#else
-		IMG_CPU_PHYADDR	sCpuPAddr;
-		sCpuPAddr.uiAddr = psDevPAddr->uiAddr;
-
-		PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
-															 NULL,
-															 sCpuPAddr,
-															 uiSize,
-															 NULL);
-#endif
-#endif
-		psMemHandle->ui32Order = ui32Log2NumPages;
-		return PVRSRV_OK;
-	}
-	else
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
-}
-
-void LMA_PhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
-{
-	RA_BASE_T uiCardAddr = (RA_BASE_T) psMemHandle->u.ui64Handle;
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-	IMG_UINT32 ui32NumPages = (1 << psMemHandle->ui32Order);
-	PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, ui32NumPages * OSGetPageSize());
-#else
-		PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT64)uiCardAddr);
-#endif
-#endif
-	RA_Free(psDevNode->psLocalDevMemArena, uiCardAddr);
-	psMemHandle->ui32Order = 0;
-}
-
-PVRSRV_ERROR LMA_PhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
-							size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
-							void **pvPtr)
-{
-	IMG_CPU_PHYADDR sCpuPAddr;
-	IMG_UINT32 ui32NumPages = (1 << psMemHandle->ui32Order);
-	PVR_UNREFERENCED_PARAMETER(psMemHandle);
-	PVR_UNREFERENCED_PARAMETER(uiSize);
-
-	PhysHeapDevPAddrToCpuPAddr(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], 1, &sCpuPAddr, psDevPAddr);
-	*pvPtr = OSMapPhysToLin(sCpuPAddr,
-							ui32NumPages * OSGetPageSize(),
-							0);
-	if (*pvPtr == NULL)
-	{
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
-	}
-	else
-	{
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-		PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, ui32NumPages * OSGetPageSize());
-#else
-		{
-			PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
-										 *pvPtr,
-										 sCpuPAddr,
-										 ui32NumPages * OSGetPageSize(),
-										 NULL);
-		}
-#endif
-#endif
-		return PVRSRV_OK;
-	}
-}
-
-void LMA_PhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
-						void *pvPtr)
-{
-	IMG_UINT32 ui32NumPages = (1 << psMemHandle->ui32Order);
-	PVR_UNREFERENCED_PARAMETER(psMemHandle);
-	PVR_UNREFERENCED_PARAMETER(psDevNode);
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-		PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, ui32NumPages * OSGetPageSize());
-#else
-	PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, (IMG_UINT64)(uintptr_t)pvPtr);
-#endif
-#endif
-
-	OSUnMapPhysToLin(pvPtr, ui32NumPages * OSGetPageSize(), 0);
-}
-
-PVRSRV_ERROR LMA_PhyContigPagesClean(PG_HANDLE *psMemHandle,
-                                     IMG_UINT32 uiOffset,
-                                     IMG_UINT32 uiLength)
-{
-	/* No need to flush because we map as uncached */
-	PVR_UNREFERENCED_PARAMETER(psMemHandle);
-	PVR_UNREFERENCED_PARAMETER(uiOffset);
-	PVR_UNREFERENCED_PARAMETER(uiLength);
-
-	return PVRSRV_OK;
-}
-
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 static PVRSRV_ERROR CreateLMASubArenas(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
@@ -1423,7 +921,7 @@
 	for (uiCounter = 0; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
 	{
 		psDeviceNode->psOSidSubArena[uiCounter] =
-			RA_Create(psDeviceNode->szRAName,
+			RA_Create(psDeviceNode->apszRANames[0],
 					  OSGetPageShift(),			/* Use host page size, keeps things simple */
 					  RA_LOCKCLASS_0,			/* This arena doesn't use any other arenas. */
 					  NULL,					/* No Import */
@@ -1451,7 +949,7 @@
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	psDeviceNode->psLocalDevMemArena = psDeviceNode->psOSidSubArena[0];
+	psDeviceNode->apsLocalDevMemArenas[0] = psDeviceNode->psOSidSubArena[0];
 
 	return PVRSRV_OK;
 }
@@ -1491,153 +989,265 @@
 
 #endif
 
-/*!
-******************************************************************************
+static void _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
+					IMG_UINT32 ui32VerbLevel,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	/* Only dump info once */
+	if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_LOW)
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode =
+			(PVRSRV_DEVICE_NODE *) hDebugRequestHandle;
 
- @Function	PVRSRVRegisterDevice
+		switch (psDeviceNode->eCurrentSysPowerState)
+		{
+			case PVRSRV_SYS_POWER_STATE_OFF:
+				PVR_DUMPDEBUG_LOG("Device System Power State: OFF");
+				break;
+			case PVRSRV_SYS_POWER_STATE_ON:
+				PVR_DUMPDEBUG_LOG("Device System Power State: ON");
+				break;
+			default:
+				PVR_DUMPDEBUG_LOG("Device System Power State: UNKNOWN (%d)",
+								   psDeviceNode->eCurrentSysPowerState);
+				break;
+		}
 
- @Description
+		SysDebugInfo(psDeviceNode->psDevConfig, pfnDumpDebugPrintf, pvDumpDebugFile);
+	}
+}
 
- registers a device with the system
-
- @Input	   psDevConfig			: Device configuration structure
-
- @Return   PVRSRV_ERROR  :
-
-******************************************************************************/
-static PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PVRSRV_DEVICE_CONFIG *psDevConfig)
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeviceCreate(void *pvOSDevice,
+											 PVRSRV_DEVICE_NODE **ppsDeviceNode)
 {
 	PVRSRV_DATA				*psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_ERROR			eError;
+	PVRSRV_DEVICE_CONFIG	*psDevConfig;
 	PVRSRV_DEVICE_NODE		*psDeviceNode;
 	PVRSRV_DEVICE_PHYS_HEAP	physHeapIndex;
+	IMG_UINT32				i;
 
-	if (psDevConfig->eDeviceType != PVRSRV_DEVICE_TYPE_RGX)
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	if (0 != psPVRSRVData->ui32RegisteredDevices)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRegisterDevice : Unsupported device type %d",
-			 psDevConfig->eDeviceType));
-		return PVRSRV_ERROR_INVALID_DEVICE;
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+#endif
+	psDeviceNode = OSAllocZMem(sizeof(*psDeviceNode));
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate device node",
+				 __func__));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	/* Allocate device node */
-	psDeviceNode = OSAllocMem(sizeof(PVRSRV_DEVICE_NODE));
-	if (psDeviceNode == NULL)
+	eError = SysDevInit(pvOSDevice, &psDevConfig);
+	if (eError)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get device config (%s)",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
 		goto e0;
 	}
-	OSMemSet(psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
 
-	/* set device state */
+	PVR_ASSERT(psDevConfig);
+	PVR_ASSERT(psDevConfig->pvOSDevice == pvOSDevice);
+	PVR_ASSERT(!psDevConfig->psDevNode);
+
+	/* Store the device node in the device config for the system layer to use */
+	psDevConfig->psDevNode = psDeviceNode;
+
 	psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_INIT;
+	psDeviceNode->psDevConfig = psDevConfig;
+	psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_ON;
 
-	/* The physical backing storage for the following physical heaps [CPU,GPU,FW]  may or may not come from the same underlying source */
-	eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+	eError = PVRSRVRegisterDbgTable(psDeviceNode,
+									g_aui32DebugOrderTable,
+									IMG_ARR_NUM_ELEMS(g_aui32DebugOrderTable));
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL physical memory heap"));
-		goto e1;
-	}
-	eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL physical memory heap"));
-		goto e1;
-	}
-	eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL]);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL physical memory heap"));
 		goto e1;
 	}
 
-	/* Do we have card memory? If so create an RA to manage it */
+	eError = OSLockCreate(&psDeviceNode->hPowerLock, LOCK_TYPE_PASSIVE);
+	if (eError != PVRSRV_OK)
+	{
+		goto e2;
+	}
+
+	/* Register the physical memory heaps */
+	psDeviceNode->papsRegisteredPhysHeaps =
+		OSAllocZMem(sizeof(*psDeviceNode->papsRegisteredPhysHeaps) *
+					psDevConfig->ui32PhysHeapCount);
+	if (!psDeviceNode->papsRegisteredPhysHeaps)
+	{
+		goto e3;
+	}
+
+	for (i = 0; i < psDevConfig->ui32PhysHeapCount; i++)
+	{
+		eError = PhysHeapRegister(&psDevConfig->pasPhysHeaps[i],
+								  &psDeviceNode->papsRegisteredPhysHeaps[i]);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to register physical heap %d (%s)",
+					 __func__, psDevConfig->pasPhysHeaps[i].ui32PhysHeapID,
+					 PVRSRVGetErrorStringKM(eError)));
+			goto e4;
+		}
+
+		psDeviceNode->ui32RegisteredPhysHeaps++;
+	}
+
+	/*
+	 * The physical backing storage for the following physical heaps
+	 * [CPU,GPU,FW] may or may not come from the same underlying source
+	 */
+	eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL],
+							 &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL physical memory heap",
+				 __func__));
+		goto e4;
+	}
+
+	eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL],
+							 &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL physical memory heap",
+				 __func__));
+		goto e5;
+	}
+
+	eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL],
+							 &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL physical memory heap",
+				 __func__));
+		goto e5;
+	}
+
+	/* Do we have card memory? If so create RAs to manage it */
 	if (PhysHeapGetType(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]) == PHYS_HEAP_TYPE_LMA)
 	{
 		RA_BASE_T uBase;
 		RA_LENGTH_T uSize;
 		IMG_UINT64 ui64Size;
 		IMG_CPU_PHYADDR sCpuPAddr;
+		IMG_DEV_PHYADDR sDevPAddr;
 
-		eError = PhysHeapGetAddress(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &sCpuPAddr);
-		if (eError != PVRSRV_OK)
+		IMG_UINT32 ui32NumOfLMARegions;
+		IMG_UINT32 ui32RegionId;
+		PHYS_HEAP* psLMAHeap;
+
+		psLMAHeap = psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL];
+		ui32NumOfLMARegions = PhysHeapNumberOfRegions(psLMAHeap);
+
+		if (ui32NumOfLMARegions == 0)
 		{
-			/* We can only get here if there is a bug in this module */
-			PVR_ASSERT(IMG_FALSE);
-			return eError;
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: LMA heap has no memory regions defined.", __func__));
+			eError = PVRSRV_ERROR_DEVICEMEM_INVALID_LMA_HEAP;
+			goto e5;
 		}
 
-		eError = PhysHeapGetSize(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &ui64Size);
-		if (eError != PVRSRV_OK)
+		/* Allocate memory for RA pointers and name strings */
+		psDeviceNode->apsLocalDevMemArenas = OSAllocMem(sizeof(RA_ARENA*) * ui32NumOfLMARegions);
+		psDeviceNode->ui32NumOfLocalMemArenas = ui32NumOfLMARegions;
+		psDeviceNode->apszRANames = OSAllocMem(ui32NumOfLMARegions * sizeof(IMG_PCHAR));
+
+		for (ui32RegionId = 0; ui32RegionId < ui32NumOfLMARegions; ui32RegionId++)
 		{
-			/* We can only get here if there is a bug in this module */
-			PVR_ASSERT(IMG_FALSE);
-			return eError;
+			eError = PhysHeapRegionGetSize(psLMAHeap, ui32RegionId, &ui64Size);
+			if (eError != PVRSRV_OK)
+			{
+				/* We can only get here if there is a bug in this module */
+				PVR_ASSERT(IMG_FALSE);
+				return eError;
+			}
+
+			eError = PhysHeapRegionGetCpuPAddr(psLMAHeap, ui32RegionId, &sCpuPAddr);
+			if (eError != PVRSRV_OK)
+			{
+				/* We can only get here if there is a bug in this module */
+				PVR_ASSERT(IMG_FALSE);
+				return eError;
+			}
+
+			eError = PhysHeapRegionGetDevPAddr(psLMAHeap, ui32RegionId, &sDevPAddr);
+			if (eError != PVRSRV_OK)
+			{
+				/* We can only get here if there is a bug in this module */
+				PVR_ASSERT(IMG_FALSE);
+				return eError;
+			}
+
+			PVR_DPF((PVR_DBG_MESSAGE,
+					 "Creating RA for card memory - region %d - 0x%016llx-0x%016llx",
+					 ui32RegionId, (IMG_UINT64) sCpuPAddr.uiAddr,
+					 sCpuPAddr.uiAddr + ui64Size));
+
+			psDeviceNode->apszRANames[ui32RegionId] =
+				OSAllocMem(PVRSRV_MAX_RA_NAME_LENGTH);
+			OSSNPrintf(psDeviceNode->apszRANames[ui32RegionId],
+					   PVRSRV_MAX_RA_NAME_LENGTH,
+					   "%s card mem",
+					   psDevConfig->pszName);
+
+			uBase = sDevPAddr.uiAddr;
+			uSize = (RA_LENGTH_T) ui64Size;
+			PVR_ASSERT(uSize == ui64Size);
+
+			/* Use host page size, keeps things simple */
+			psDeviceNode->apsLocalDevMemArenas[ui32RegionId] =
+				RA_Create(psDeviceNode->apszRANames[ui32RegionId],
+						  OSGetPageShift(), RA_LOCKCLASS_0, NULL, NULL, NULL,
+						  IMG_FALSE);
+
+			if (psDeviceNode->apsLocalDevMemArenas[ui32RegionId] == NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create LMA memory arena",
+						 __func__));
+				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto e6;
+			}
+
+			if (!RA_Add(psDeviceNode->apsLocalDevMemArenas[ui32RegionId],
+						uBase, uSize, 0, NULL))
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: Failed to add memory to LMA memory arena",
+						 __func__));
+				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+				goto e6;
+			}
 		}
 
-		eError = PhysHeapGetBase(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], (IMG_UINT64*)&uBase);
-		if (eError != PVRSRV_OK)
-		{
-			/* We can only get here if there is a bug in this module */
-			PVR_ASSERT(IMG_FALSE);
-			return eError;
-		}
-
-		PVR_DPF((PVR_DBG_MESSAGE, "Creating RA for card memory 0x%016llx-0x%016llx",
-				 (IMG_UINT64) sCpuPAddr.uiAddr, sCpuPAddr.uiAddr + ui64Size));
-
-		OSSNPrintf(psDeviceNode->szRAName, sizeof(psDeviceNode->szRAName),
-											"%s card mem",
-											psDevConfig->pszName);
-
-		if (gpsSysConfig->uiSysFlags & PVRSRV_SYSTEM_CONFIG_APPLY_OFFSET)
-		{
-			uBase = gpsSysConfig->ui64DevMemPhysOffset;
-		}
-
-		uSize = (RA_LENGTH_T) ui64Size;
-		PVR_ASSERT(uSize == ui64Size);
-
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
-{
 		eError = CreateLMASubArenas(psDeviceNode);
 		if (eError != PVRSRV_OK)
 		{
-			goto e2;
-		}
-}
-#else
-		psDeviceNode->psLocalDevMemArena =
-			RA_Create(psDeviceNode->szRAName,
-						OSGetPageShift(),	/* Use host page size, keeps things simple */
-						RA_LOCKCLASS_0,     /* This arena doesn't use any other arenas. */
-						NULL,			/* No Import */
-						NULL,			/* No free import */
-						NULL,			/* No import handle */
-						IMG_FALSE);
-
-		if (psDeviceNode->psLocalDevMemArena == NULL)
-		{
-			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-			goto e2;
-		}
-
-		if (!RA_Add(psDeviceNode->psLocalDevMemArena, uBase, uSize, 0 /* No flags */, NULL /* No private data */))
-		{
-			RA_Delete(psDeviceNode->psLocalDevMemArena);
-			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-			goto e2;		
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to create LMA memory sub-arenas", __func__));
+			goto e6;
 		}
 #endif
 
-
+		/* If additional psDeviceNode->pfnDevPx* callbacks are added, 
+		   update the corresponding virtualization-specific override
+		   in pvrsrv_vz.c:PVRSRVVzDeviceCreate() */
 		psDeviceNode->pfnDevPxAlloc = LMA_PhyContigPagesAlloc;
 		psDeviceNode->pfnDevPxFree = LMA_PhyContigPagesFree;
 		psDeviceNode->pfnDevPxMap = LMA_PhyContigPagesMap;
 		psDeviceNode->pfnDevPxUnMap = LMA_PhyContigPagesUnmap;
 		psDeviceNode->pfnDevPxClean = LMA_PhyContigPagesClean;
-		psDeviceNode->uiMMUPxLog2AllocGran = OSGetPageShift();
 		psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = PhysmemNewLocalRamBackedPMR;
 	}
 	else
@@ -1675,605 +1285,489 @@
 		psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL] = PhysmemNewOSRamBackedPMR;
 	}
 
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	/* Perform additional virtualization device registration if any */
-	PVRSRVVirtRegisterDevice(gpsSysConfig, psDevConfig, psDeviceNode);
-#endif
-
-	psDeviceNode->pszMMUPxPDumpMemSpaceName = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
 	psDeviceNode->uiMMUPxLog2AllocGran = OSGetPageShift();
 
-	/* Add the devnode to our list so we can unregister it later */
-	psPVRSRVData->apsRegisteredDevNodes[psPVRSRVData->ui32RegisteredDevices++] = psDeviceNode;
-
-	psDeviceNode->psDevConfig = psDevConfig;
-
-	/* all devices need a unique identifier */
-	AllocateDeviceID(psPVRSRVData, &psDeviceNode->sDevId.ui32DeviceIndex);
-
-	/* Device type and class will be setup during this callback */
-	eError = sRegisterDevice[psDevConfig->eDeviceType](psDeviceNode);
+	eError = ServerSyncInit(psDeviceNode);
 	if (eError != PVRSRV_OK)
 	{
-		OSFreeMem(psDeviceNode);
-		/*not nulling pointer, out of scope*/
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
-		eError = PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
-		goto e3;
+		goto e6;
 	}
 
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	/* Perform virtualization device creation */
+	PVRSRVVzDeviceCreate(psDeviceNode);
+#endif
 
-	PVR_DPF((PVR_DBG_MESSAGE, "Registered device %d of type %d", psDeviceNode->sDevId.ui32DeviceIndex, psDeviceNode->sDevId.eDeviceType));
-	PVR_DPF((PVR_DBG_MESSAGE, "Register bank address = 0x%08lx", (unsigned long)psDevConfig->sRegsCpuPBase.uiAddr));
+	/*
+	 * This is registered before doing device specific initialisation to ensure
+	 * generic device information is dumped first during a debug request.
+	 */
+	eError = PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hDbgReqNotify,
+											psDeviceNode,
+											_SysDebugRequestNotify,
+											DEBUG_REQUEST_SYS,
+											psDeviceNode);
+	PVR_LOG_IF_ERROR(eError, "PVRSRVRegisterDbgRequestNotify");
+
+	eError = HTBDeviceCreate(psDeviceNode);
+	PVR_LOG_IF_ERROR(eError, "HTBDeviceCreate");
+
+	psPVRSRVData->ui32RegisteredDevices++;
+
+#if defined(SUPPORT_RGX)
+	eError = RGXRegisterDevice(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register device", __func__));
+		eError = PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
+		goto e7;
+	}
+#endif
+
+#if defined(PVR_DVFS)
+	eError = InitDVFS(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to start DVFS", __func__));
+#if defined(SUPPORT_RGX)
+		DevDeInitRGX(psDeviceNode);
+#endif
+		goto e7;
+	}
+#endif
+
+#if defined(PVR_TESTING_UTILS)
+	TUtilsInit(psDeviceNode);
+#endif
+
+	dllist_init(&psDeviceNode->sMemoryContextPageFaultNotifyListHead);
+
+	/*
+	 * Initialise the Transport Layer.
+	 * Need to remember the RGX device node for use in the Transport Layer
+	 * when allocating stream buffers that are shared with clients.
+	 * Note however when the device is an LMA device our buffers will not
+	 * be in host memory but card memory.
+	 */
+	eError = TLInit(psDeviceNode);
+	PVR_LOG_IF_ERROR(eError, "TLInit");
+
+	PVR_DPF((PVR_DBG_MESSAGE, "Registered device %p", psDeviceNode));
+	PVR_DPF((PVR_DBG_MESSAGE, "Register bank address = 0x%08lx",
+			 (unsigned long)psDevConfig->sRegsCpuPBase.uiAddr));
 	PVR_DPF((PVR_DBG_MESSAGE, "IRQ = %d", psDevConfig->ui32IRQ));
-	
-	/* and finally insert the device into the dev-list */
-	List_PVRSRV_DEVICE_NODE_Insert(&psPVRSRVData->psDeviceNodeList, psDeviceNode);
 
-	/* set device state */
-	psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_ACTIVE;
+	/* Finally insert the device into the dev-list and set it as active */
+	List_PVRSRV_DEVICE_NODE_InsertTail(&psPVRSRVData->psDeviceNodeList,
+									   psDeviceNode);
+
+	*ppsDeviceNode = psDeviceNode;
 
 	return PVRSRV_OK;
-e3:
-	if (psDeviceNode->psLocalDevMemArena)
+
+#if defined(SUPPORT_RGX) || defined(PVR_DVFS)
+e7:
+	psPVRSRVData->ui32RegisteredDevices--;
+
+	if (psDeviceNode->hDbgReqNotify)
 	{
-		RA_Delete(psDeviceNode->psLocalDevMemArena);
+		PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
 	}
-e2:
-e1:
-	for(physHeapIndex=0; physHeapIndex < PVRSRV_DEVICE_PHYS_HEAP_LAST; physHeapIndex++)
+
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	/* Perform virtualization device destruction */
+	PVRSRVVzDeviceDestroy(psDeviceNode);
+#endif
+	ServerSyncDeinit(psDeviceNode);
+#endif
+e6:
+	{
+		IMG_UINT32 ui32RegionId;
+
+		for (ui32RegionId = 0;
+			 ui32RegionId < psDeviceNode->ui32NumOfLocalMemArenas;
+			 ui32RegionId++)
+		{
+			if (psDeviceNode->apsLocalDevMemArenas[ui32RegionId])
+			{
+				RA_Delete(psDeviceNode->apsLocalDevMemArenas[ui32RegionId]);
+			}
+		}
+	}
+
+e5:
+	for (physHeapIndex = 0;
+		 physHeapIndex < IMG_ARR_NUM_ELEMS(psDeviceNode->apsPhysHeap);
+		 physHeapIndex++)
 	{
 		if (psDeviceNode->apsPhysHeap[physHeapIndex])
 		{
 			PhysHeapRelease(psDeviceNode->apsPhysHeap[physHeapIndex]);
 		}
 	}
-	OSFreeMem(psDeviceNode);
-e0:
-	return eError;
-}
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced)
-{
-	PVRSRV_ERROR eError = PVRSRV_OK;
-
-	PVR_UNREFERENCED_PARAMETER(bForced);
-
-	if (gpsSysConfig->pfnSysPrePowerState)
+e4:
+	for (i = 0; i < psDeviceNode->ui32RegisteredPhysHeaps; i++)
 	{
-		eError = gpsSysConfig->pfnSysPrePowerState(eNewPowerState);
-	}
-	return eError;
-}
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced)
-{
-	PVRSRV_ERROR eError = PVRSRV_OK;
-
-	PVR_UNREFERENCED_PARAMETER(bForced);
-
-	if (gpsSysConfig->pfnSysPostPowerState)
-	{
-		eError = gpsSysConfig->pfnSysPostPowerState(eNewPowerState);
-	}
-	return eError;
-}
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode,
-													IMG_UINT32 *pui32DeviceIndex,
-													IMG_UINT32 ui32PhysHeapID)
-{
-	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-	PHYS_HEAP   *psPhysHeapTmp;
-	PVRSRV_DEVICE_PHYS_HEAP eDevPhysHeap;
-	PVRSRV_ERROR eError;
-
-	eError = PhysHeapAcquire(ui32PhysHeapID, &psPhysHeapTmp);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterExtDevice: Failed to acquire physical memory heap"));
-		goto e0;
-	}
-	if (PhysHeapGetType(psPhysHeapTmp) == PHYS_HEAP_TYPE_LMA)
-	{
-		eDevPhysHeap = PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL;
-	}
-	else
-	{
-		eDevPhysHeap = PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL;
-	}
-	psDeviceNode->apsPhysHeap[eDevPhysHeap] = psPhysHeapTmp;
-
-	/* allocate a unique device id */
-	eError = AllocateDeviceID(psPVRSRVData, &psDeviceNode->sDevId.ui32DeviceIndex);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterExtDevice: Failed to allocate Device ID"));
-		goto e1;
+		PhysHeapUnregister(psDeviceNode->papsRegisteredPhysHeaps[i]);
 	}
 
-	if (pui32DeviceIndex)
-	{
-		*pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
-	}
-
-	List_PVRSRV_DEVICE_NODE_Insert(&psPVRSRVData->psDeviceNodeList, psDeviceNode);
-
-	return PVRSRV_OK;
+	OSFreeMem(psDeviceNode->papsRegisteredPhysHeaps);
+e3:
+	OSLockDestroy(psDeviceNode->hPowerLock);
+e2:
+	PVRSRVUnregisterDbgTable(psDeviceNode);
 e1:
-	PhysHeapRelease(psDeviceNode->apsPhysHeap[eDevPhysHeap]);
+	psDevConfig->psDevNode = NULL;
+	SysDevDeInit(psDevConfig);
 e0:
+	OSFreeMem(psDeviceNode);
 	return eError;
 }
 
-void IMG_CALLCONV PVRSRVUnregisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+#if defined(SUPPORT_KERNEL_SRVINIT)
+static PVRSRV_ERROR _SetDeviceFlag(const PVRSRV_DEVICE_NODE *psDevice,
+                                  const void *psPrivate, IMG_BOOL bValue)
 {
-	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_DEVICE_PHYS_HEAP eDevPhysHeap;
+	PVRSRV_ERROR eResult = PVRSRV_OK;
+	IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
 
-	List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
-	(void)FreeDeviceID(psPVRSRVData, psDeviceNode->sDevId.ui32DeviceIndex);
-	for (eDevPhysHeap = 0; eDevPhysHeap < PVRSRV_DEVICE_PHYS_HEAP_LAST; eDevPhysHeap++)
+	if (!ui32Flag)
 	{
-		if (psDeviceNode->apsPhysHeap[eDevPhysHeap])
-		{
-			PhysHeapRelease(psDeviceNode->apsPhysHeap[eDevPhysHeap]);
-		}
+		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
+
+	eResult = RGXSetDeviceFlags((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
+	                            ui32Flag, bValue);
+
+	return eResult;
 }
 
-static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+static PVRSRV_ERROR _ReadDeviceFlag(const PVRSRV_DEVICE_NODE *psDevice,
+                                   const void *psPrivate, IMG_BOOL *pbValue)
 {
+	PVRSRV_ERROR eResult = PVRSRV_OK;
+	IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
+	IMG_UINT32 ui32State;
+
+	if (!ui32Flag)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eResult = RGXGetDeviceFlags((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
+	                            &ui32State);
+
+	if (PVRSRV_OK == eResult)
+	{
+		*pbValue = (ui32State & ui32Flag)? IMG_TRUE: IMG_FALSE;
+	}
+
+	return eResult;
+}
+static PVRSRV_ERROR _SetStateFlag(const PVRSRV_DEVICE_NODE *psDevice,
+                                  const void *psPrivate, IMG_BOOL bValue)
+{
+	PVRSRV_ERROR eResult = PVRSRV_OK;
+	IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
+
+	if (!ui32Flag)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* EnableHWR is a special case
+	 * only possible to disable after FW is running
+	 */
+	if (bValue && RGXFWIF_INICFG_HWR_EN == ui32Flag)
+	{
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+
+	eResult = RGXStateFlagCtrl((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
+	                           ui32Flag, NULL, bValue);
+
+	return eResult;
+}
+
+static PVRSRV_ERROR _ReadStateFlag(const PVRSRV_DEVICE_NODE *psDevice,
+                                   const void *psPrivate, IMG_BOOL *pbValue)
+{
+	PVRSRV_ERROR eResult = PVRSRV_OK;
+	IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
+	IMG_UINT32 ui32State;
+
+	if (!ui32Flag)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eResult = RGXStateFlagCtrl((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
+	                           0, &ui32State, IMG_FALSE);
+
+	if (PVRSRV_OK == eResult)
+	{
+		*pbValue = (ui32State & ui32Flag)? IMG_TRUE: IMG_FALSE;
+	}
+
+	return eResult;
+}
+
+PVRSRV_ERROR PVRSRVDeviceInitialise(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	IMG_BOOL bInitSuccesful = IMG_FALSE;
 	PVRSRV_ERROR eError;
-	PVRSRV_DEV_POWER_STATE ePowState;
 
-	ePowState = va_arg(va, PVRSRV_DEV_POWER_STATE);
-
-	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
-										 ePowState,
-										 IMG_TRUE);
-
-	if (eError != PVRSRV_OK)
+	if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_INIT)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (%s, device index: %d)", 
-						PVRSRVGetErrorStringKM(eError),
-						psDeviceNode->sDevId.ui32DeviceIndex));
-	}
-
-	return eError;
-}
-
-/*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
-static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_Any_va(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
-{
-	PVRSRV_ERROR eError;
-	IMG_UINT32 *pui32ClientBuildOptions;
-
-	pui32ClientBuildOptions = va_arg(va, IMG_UINT32*);
-
-	eError = PVRSRVDevInitCompatCheck(psDeviceNode, *pui32ClientBuildOptions);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
-	}
-	return eError;
-}
-
-static PVRSRV_ERROR PVRSRVFinaliseSystem_SetIdleState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
-{
-	PVRSRV_ERROR eError;
-	PVRSRV_DEV_POWER_STATE ePowState;
-
-	ePowState = va_arg(va, PVRSRV_DEV_POWER_STATE);
-
-	eError = PVRSRVDeviceIdleRequestKM(IMG_FALSE, psDeviceNode->sDevId.ui32DeviceIndex, &PVRSRVDeviceIsDefaultStateOFF, IMG_TRUE);
-	if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED))
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDeviceIdleRequestKM call (%s, device index: %d)",
-						PVRSRVGetErrorStringKM(eError),
-						psDeviceNode->sDevId.ui32DeviceIndex));
-	}
-
-	return eError;
-}
-/*!
-******************************************************************************
-
- @Function	PVRSRVFinaliseSystem
-
- @Description
-
- Final part of system initialisation.
-
- @Input	   ui32DevIndex : Index to the required device
-
- @Return   PVRSRV_ERROR  :
-
-******************************************************************************/
-PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful, IMG_UINT32 ui32ClientBuildOptions)
-{
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_ERROR		eError;
-	IMG_UINT32			i;
-	PVRSRV_DEVICE_NODE *psRGXDeviceNode = NULL;
-	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
-
-	if (bInitSuccessful)
-	{
-		for (i=0;i<psPVRSRVData->ui32RegisteredDevices;i++)
-		{
-			PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
-			if(psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
-			{
-				psRGXDeviceNode = psDeviceNode; 
-			}
-#if defined(SUPPORT_KERNEL_SRVINIT)
-			/* take the PMR lock, because there isn't a bridge call to take it */
-			PMRLock();
-#endif
-			eError = SyncPrimContextCreate(psDeviceNode,
-								  &psDeviceNode->hSyncPrimContext);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to create SyncPrimContext (%u)", eError));
-#if defined(SUPPORT_KERNEL_SRVINIT)
-				PMRUnlock();
-#endif
-				return eError;
-			}
-
-			/* Allocate general purpose sync primitive */
-			eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psDeviceNode->psSyncPrim, "pvrsrv dev general");
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to allocate sync primitive with error (%u)", eError));
-#if defined(SUPPORT_KERNEL_SRVINIT)
-				PMRUnlock();
-#endif
-				return eError;
-			}
-#if defined(SUPPORT_KERNEL_SRVINIT)
-			PMRUnlock();
-#endif
-		}
-
-		eError = PVRSRVPowerLock();
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem_SetPowerState_AnyCb: Failed to acquire power lock"));
-			return eError;
-		}
-
-		/* Always ensure a single power on command appears in the pdump.
-		 * This should be the only power related call outside of PDUMPPOWCMDSTART/END.
-		 * Place all devices into ON power state. */
-		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
-														&PVRSRVFinaliseSystem_SetPowerState_AnyCb,
-														PVRSRV_DEV_POWER_STATE_ON);
-		if (eError != PVRSRV_OK)
-		{
-			PVRSRVPowerUnlock();
-			return eError;
-		}
-
-		/* Verify firmware compatibility for devices */
-		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
-													&PVRSRVFinaliseSystem_CompatCheck_Any_va,
-													&ui32ClientBuildOptions);
-		if (eError != PVRSRV_OK)
-		{
-			PVRSRVPowerUnlock();
-			PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
-			return eError;
-		}
-
-		PDUMPPOWCMDSTART();
-		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
-		{ /* Force idle all devices whose default power state is off*/
-			eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
-													&PVRSRVFinaliseSystem_SetIdleState_AnyCb,
-													&ui32ClientBuildOptions);
-
-			if (eError == PVRSRV_OK)
-			{
-				break;
-			}
-			else if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
-			{
-				PVRSRV_ERROR		eError2;
-
-				PVRSRVPowerUnlock();
-				OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-				eError2 = PVRSRVPowerLock();
-
-				if (eError2 != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to acquire power lock"));
-					return eError2;
-				}
-			}
-			else
-			{
-				PVRSRVPowerUnlock();
-				return eError;
-			}
-
-		} END_LOOP_UNTIL_TIMEOUT();
-
-		/* Place all devices into their default power state. */
-		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
-														&PVRSRVFinaliseSystem_SetPowerState_AnyCb,
-														PVRSRV_DEV_POWER_STATE_DEFAULT);
-		PDUMPPOWCMDEND();
-
-		if (eError != PVRSRV_OK)
-		{
-			PVRSRVPowerUnlock();
-			return eError;
-		}
-
-		PVRSRVPowerUnlock();
-
-/* If PDUMP is enabled and RGX device is supported, then initialise the performance counters that can be further modified in PDUMP.
-   Then, before ending the init phase of the pdump, drain the commands put in the kCCB during the init phase */
-#if defined(SUPPORT_RGX) && defined(PDUMP)
-		if(psRGXDeviceNode)
-		{
-			PVRSRV_RGXDEV_INFO 	*psDevInfo = (PVRSRV_RGXDEV_INFO *) (psRGXDeviceNode->pvDevice);
-
-			eError = PVRSRVRGXInitHWPerfCountersKM(psRGXDeviceNode);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR, "PVSRVFinaliseSystem: failed to init hwperf counters(%d)", eError));
-				return eError;
-			}
-
-			eError = RGXPdumpDrainKCCB(psDevInfo, psDevInfo->psKernelCCBCtl->ui32WriteOffset);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR, "PVSRVFinaliseSystem: problem draining kCCB (%d)", eError));
-				return eError;
-			}
-		}
-#endif
-	}
-
-	/* Give PDump control a chance to end the init phase, depends on OS */
-	PDumpStopInitPhase(IMG_FALSE, IMG_TRUE);
-
-	return PVRSRV_OK;
-}
-
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode,IMG_UINT32 ui32ClientBuildOptions)
-{
-	/* Only check devices which specify a compatibility check callback */
-	if (psDeviceNode->pfnInitDeviceCompatCheck)
-		return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode, ui32ClientBuildOptions);
-	else
-		return PVRSRV_OK;
-}
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVAcquireDeviceDataKM
-
- @Description
-
- Matchs a device given a device type and a device index.
-
- @input	psDeviceNode :The device node to be matched.
-
- @Input	   va : Variable argument list with:
-			eDeviceType : Required device type. If type is unknown use ui32DevIndex
-						 to locate device data
-
- 			ui32DevIndex : Index to the required device obtained from the
-						PVRSRVEnumerateDevice function
-
- @Return   PVRSRV_ERROR  :
-
-******************************************************************************/
-static void * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
-{
-	PVRSRV_DEVICE_TYPE eDeviceType;
-	IMG_UINT32 ui32DevIndex;
-
-	eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
-	ui32DevIndex = va_arg(va, IMG_UINT32);
-
-	if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
-		psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
-		(eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
-		 psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
-	{
-		return psDeviceNode;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVAcquireDeviceDataKM
-
- @Description
-
- Returns device information
-
- @Input	   ui32DevIndex : Index to the required device obtained from the
-						PVRSRVEnumerateDevice function
-
- @Input	   eDeviceType : Required device type. If type is unknown use ui32DevIndex
-						 to locate device data
-
- @Output  *phDevCookie : Dev Cookie
-
-
- @Return   PVRSRV_ERROR  :
-
-******************************************************************************/
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32			ui32DevIndex,
-													 PVRSRV_DEVICE_TYPE	eDeviceType,
-													 IMG_HANDLE			*phDevCookie)
-{
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_DEVICE_NODE	*psDeviceNode;
-
-	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
-
-	/* Find device in the list */
-	psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-												&PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
-												eDeviceType,
-												ui32DevIndex);
-
-
-	if (!psDeviceNode)
-	{
-		/* device can't be found in the list so it isn't in the system */
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Device already initialised", __func__));
 		return PVRSRV_ERROR_INIT_FAILURE;
 	}
 
-/*FoundDevice:*/
-
-	/* return the dev cookie? */
-	if (phDevCookie)
+#if defined(SUPPORT_RGX)
+	eError = RGXInit(psDeviceNode);
+	if (eError != PVRSRV_OK)
 	{
-		*phDevCookie = (IMG_HANDLE)psDeviceNode;
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Initialisation of Rogue device failed (%s)",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
+		goto Exit;
+	}
+#endif
+
+	bInitSuccesful = IMG_TRUE;
+
+#if defined(SUPPORT_RGX)
+Exit:
+#endif
+	eError = PVRSRVDeviceFinalise(psDeviceNode, bInitSuccesful);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Services failed to finalise the device (%s)",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
 	}
 
-	return PVRSRV_OK;
+
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DisableClockGating,
+	                                  _ReadStateFlag, _SetStateFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXFWIF_INICFG_DISABLE_CLKGATING_EN));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DisableDMOverlap,
+	                                  _ReadStateFlag, _SetStateFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXFWIF_INICFG_DISABLE_DM_OVERLAP));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_AssertOnHWRTrigger,
+	                                  _ReadStateFlag, _SetStateFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_AssertOutOfMemory,
+	                                  _ReadStateFlag, _SetStateFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_CheckMList,
+	                                  _ReadStateFlag, _SetStateFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXFWIF_INICFG_CHECK_MLIST_EN));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_EnableHWR,
+	                                  _ReadStateFlag, _SetStateFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXFWIF_INICFG_HWR_EN));
+
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DisableFEDLogging,
+	                                  _ReadDeviceFlag, _SetDeviceFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_ZeroFreelist,
+	                                  _ReadDeviceFlag, _SetDeviceFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXKMIF_DEVICE_STATE_ZERO_FREELIST));
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DustRequestInject,
+	                                  _ReadDeviceFlag, _SetDeviceFlag,
+	                                  psDeviceNode,
+	                                  (void*)((uintptr_t)RGXKMIF_DEVICE_STATE_DUST_REQUEST_INJECT_EN));
+
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DisablePDumpPanic,
+	                                  RGXQueryPdumpPanicEnable, RGXSetPdumpPanicEnable,
+	                                  psDeviceNode,
+	                                  NULL);
+	return eError;
 }
+#endif /* defined(SUPPORT_KERNEL_SRVINIT) */
 
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseDeviceDataKM (IMG_HANDLE hDevCookie)
-{
-	PVR_UNREFERENCED_PARAMETER(hDevCookie);
-
-	/* 
-	  Empty release body as the lifetime of this resource accessed by 
-	  PVRSRVAcquireDeviceDataKM is linked to driver lifetime, not API allocation.
-	  This is one reason why this type crosses the bridge with a shared handle.
-	  Thus no server release action is required, just bridge action to ensure
-	  associated handle is freed.
-    */ 
-	return PVRSRV_OK;
-}
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVUnregisterDevice
-
- @Description
-
- This De-inits device
-
- @Input	   ui32DevIndex : Index to the required device
-
- @Return   PVRSRV_ERROR  :
-
-******************************************************************************/
-static PVRSRV_ERROR IMG_CALLCONV PVRSRVUnregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 	PVRSRV_DATA				*psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_DEVICE_PHYS_HEAP ePhysHeapIdx;
+	IMG_UINT32 				ui32RegionIdx;
+	IMG_UINT32				i;
 	PVRSRV_ERROR			eError;
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	IMG_BOOL				bForceUnload = IMG_FALSE;
 
-	eError = PVRSRVPowerLock();
+	if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+	{
+		bForceUnload = IMG_TRUE;
+	}
+#endif
+
+	psPVRSRVData->ui32RegisteredDevices--;
+
+	psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_DEINIT;
+
+#if defined(PVR_TESTING_UTILS)
+	TUtilsDeinit(psDeviceNode);
+#endif
+
+	/* Counter part to what gets done in PVRSRVDeviceFinalise */
+	if (psDeviceNode->hSyncPrimContext)
+	{
+		if (psDeviceNode->psSyncPrim)
+		{
+			/* Free general pupose sync primitive */
+			SyncPrimFree(psDeviceNode->psSyncPrim);
+			psDeviceNode->psSyncPrim = NULL;
+		}
+
+		if (psDeviceNode->psMMUCacheSyncPrim)
+		{
+			PVRSRV_CLIENT_SYNC_PRIM *psSync = psDeviceNode->psMMUCacheSyncPrim;
+
+			/* Important to set the device node pointer to NULL
+			 * before we free the sync-prim to make sure we don't
+			 * defer the freeing of the sync-prim's page tables itself.
+			 * The sync is used to defer the MMU page table
+			 * freeing. */
+			psDeviceNode->psMMUCacheSyncPrim = NULL;
+
+			/* Free general pupose sync primitive */
+			SyncPrimFree(psSync);
+
+		}
+
+		SyncPrimContextDestroy(psDeviceNode->hSyncPrimContext);
+		psDeviceNode->hSyncPrimContext = NULL;
+	}
+
+	eError = PVRSRVPowerLock(psDeviceNode);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed to acquire power lock"));
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire power lock", __func__));
 		return eError;
 	}
 
 	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 	{
-		/* Force idle device*/
-		eError = PVRSRVDeviceIdleRequestKM(IMG_FALSE,
-							psDeviceNode->sDevId.ui32DeviceIndex,
-							NULL,
-							IMG_TRUE);
-
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+		if (bForceUnload)
+		{
+			/*
+			 * Firmware probably not responding but we still want to unload the
+			 * driver.
+			 */
+			break;
+		}
+#endif
+		/* Force idle device */
+		eError = PVRSRVDeviceIdleRequestKM(psDeviceNode, NULL, IMG_TRUE);
 		if (eError == PVRSRV_OK)
 		{
 			break;
 		}
 		else if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
 		{
-			PVRSRV_ERROR	eError2;
+			PVRSRV_ERROR eError2;
 
-			PVRSRVPowerUnlock();
+			PVRSRVPowerUnlock(psDeviceNode);
+
 			OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-			eError2 = PVRSRVPowerLock();
+
+			eError2 = PVRSRVPowerLock(psDeviceNode);
 			if (eError2 != PVRSRV_OK)
 			{
-				PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed to acquire power lock"));
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire power lock",
+						 __func__));
 				return eError2;
 			}
 		}
 		else
 		{
-			PVRSRVPowerUnlock();
+			PVRSRVPowerUnlock(psDeviceNode);
 			return eError;
 		}
 	} END_LOOP_UNTIL_TIMEOUT();
-	/*
-		Power down the device if necessary.
-	 */
-	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+
+	/* Power down the device if necessary */
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
 										 PVRSRV_DEV_POWER_STATE_OFF,
 										 IMG_TRUE);
-
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed PVRSRVSetDevicePowerStateKM call (%s). Dump debug.", PVRSRVGetErrorStringKM(eError)));
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed PVRSRVSetDevicePowerStateKM call (%s). Dump debug.",
+				 __func__, PVRSRVGetErrorStringKM(eError)));
 
-		PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+		PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
 
-		/* If the driver is okay then return the error, otherwise we can ignore this error. */
+		/*
+		 * If the driver is okay then return the error, otherwise we can ignore
+		 * this error.
+		 */
 		if (PVRSRVGetPVRSRVData()->eServicesState == PVRSRV_SERVICES_STATE_OK)
 		{
 			return eError;
 		}
 		else
 		{
-			PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVUnregisterDevice: Will continue to unregister as driver status is not OK"));
+			PVR_DPF((PVR_DBG_MESSAGE,
+					 "%s: Will continue to unregister as driver status is not OK",
+					 __func__));
 		}
 	}
 
-	/*
-		De-init the device.
-	*/
-	sUnregisterDevice[psDeviceNode->sDevId.eDeviceType](psDeviceNode);
-
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	/* Perform additional virtualization device deregistration if any */
-	PVRSRVVirtUnregisterDevice(psDeviceNode);
+#if defined(SUPPORT_RGX)
+	DevDeInitRGX(psDeviceNode);
 #endif
 
-	/* Remove RA for local card memory */
-	if (psDeviceNode->psLocalDevMemArena)
+	HTBDeviceDestroy(psDeviceNode);
+
+	if (psDeviceNode->hDbgReqNotify)
 	{
-		RA_Delete(psDeviceNode->psLocalDevMemArena);
+		PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
 	}
 
-	/* remove node from list */
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	/* Perform virtualization device destruction */
+	PVRSRVVzDeviceDestroy(psDeviceNode);
+#endif
+
+	ServerSyncDeinit(psDeviceNode);
+
+	/* Remove RAs and RA names for local card memory */
+	for (ui32RegionIdx = 0;
+		 ui32RegionIdx < psDeviceNode->ui32NumOfLocalMemArenas;
+		 ui32RegionIdx++)
+	{
+		if (psDeviceNode->apsLocalDevMemArenas[ui32RegionIdx])
+		{
+			RA_Delete(psDeviceNode->apsLocalDevMemArenas[ui32RegionIdx]);
+		}
+
+		if (psDeviceNode->apszRANames[ui32RegionIdx])
+		{
+			OSFreeMem(psDeviceNode->apszRANames[ui32RegionIdx]);
+		}
+	}
+
+	OSFreeMem(psDeviceNode->apsLocalDevMemArenas);
+	OSFreeMem(psDeviceNode->apszRANames);
+
 	List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
 
-	/* deallocate id and memory */
-	(void)FreeDeviceID(psPVRSRVData, psDeviceNode->sDevId.ui32DeviceIndex);
-
-	for (ePhysHeapIdx = 0; ePhysHeapIdx < PVRSRV_DEVICE_PHYS_HEAP_LAST; ePhysHeapIdx++)
+	for (ePhysHeapIdx = 0;
+		 ePhysHeapIdx < IMG_ARR_NUM_ELEMS(psDeviceNode->apsPhysHeap);
+		 ePhysHeapIdx++)
 	{
 		if (psDeviceNode->apsPhysHeap[ePhysHeapIdx])
 		{
@@ -2281,12 +1775,409 @@
 		}
 	}
 
-	OSFreeMem(psDeviceNode);
-	/*not nulling pointer, out of scope*/
+	for (i = 0; i < psDeviceNode->ui32RegisteredPhysHeaps; i++)
+	{
+		PhysHeapUnregister(psDeviceNode->papsRegisteredPhysHeaps[i]);
+	}
 
-	return (PVRSRV_OK);
+	OSFreeMem(psDeviceNode->papsRegisteredPhysHeaps);
+
+#if defined(PVR_DVFS)
+	DeinitDVFS(psDeviceNode);
+#endif
+
+	OSLockDestroy(psDeviceNode->hPowerLock);
+
+	PVRSRVUnregisterDbgTable(psDeviceNode);
+
+	psDeviceNode->psDevConfig->psDevNode = NULL;
+	SysDevDeInit(psDeviceNode->psDevConfig);
+
+	/*
+	 * Clean up Transport Layer resources that remain. Done after RGX node clean
+	 * up as HWPerf stream is destroyed during this.
+	 */
+	TLDeInit(psDeviceNode);
+
+	OSFreeMem(psDeviceNode);
+
+	return PVRSRV_OK;
 }
 
+PVRSRV_ERROR LMA_PhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
+							PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr)
+{
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+	IMG_UINT32  ui32OSid = 0;
+#endif
+	RA_BASE_T uiCardAddr;
+	RA_LENGTH_T uiActualSize;
+	PVRSRV_ERROR eError;
+
+	RA_ARENA *pArena=psDevNode->apsLocalDevMemArenas[0];
+	IMG_UINT32 ui32Log2NumPages = 0;
+
+	PVR_ASSERT(uiSize != 0);
+	ui32Log2NumPages = OSGetOrder(uiSize);
+	uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+{
+	IMG_UINT32  ui32OSidReg = 0;
+	IMG_BOOL    bOSidAxiProt;
+
+	IMG_PID     pId = OSGetCurrentClientProcessIDKM();
+
+	RetrieveOSidsfromPidList(pId, &ui32OSid, &ui32OSidReg, &bOSidAxiProt);
+
+	pArena = psDevNode->psOSidSubArena[ui32OSid];
+}
+#endif
+
+	eError = RA_Alloc(pArena,
+	                  uiSize,
+	                  RA_NO_IMPORT_MULTIPLIER,
+	                  0,                         /* No flags */
+	                  OSGetPageSize(),
+	                  "LMA_PhyContigPagesAlloc",
+	                  &uiCardAddr,
+	                  &uiActualSize,
+	                  NULL);                     /* No private handle */
+
+	PVR_ASSERT(uiSize == uiActualSize);
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+{
+	PVR_DPF((PVR_DBG_MESSAGE,"(GPU Virtualization Validation): LMA_PhyContigPagesAlloc: Address:%llu, size:%llu", uiCardAddr,uiActualSize));
+}
+#endif
+
+	psMemHandle->u.ui64Handle = uiCardAddr;
+	psDevPAddr->uiAddr = (IMG_UINT64) uiCardAddr;
+
+	if (PVRSRV_OK == eError)
+	{
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+	    PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+	                                        uiSize,
+	                                        (IMG_UINT64)(uintptr_t) psMemHandle);
+#else
+		IMG_CPU_PHYADDR sCpuPAddr;
+		sCpuPAddr.uiAddr = psDevPAddr->uiAddr;
+
+		PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+		                             NULL,
+		                             sCpuPAddr,
+		                             uiSize,
+		                             NULL);
+#endif
+#endif
+		psMemHandle->ui32Order = ui32Log2NumPages;
+	}
+
+	return eError;
+}
+
+void LMA_PhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
+{
+	RA_BASE_T uiCardAddr = (RA_BASE_T) psMemHandle->u.ui64Handle;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+	PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+	                                      (IMG_UINT64)(uintptr_t) psMemHandle);
+#else
+		PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT64)uiCardAddr);
+#endif
+#endif
+	RA_Free(psDevNode->apsLocalDevMemArenas[0], uiCardAddr);
+	psMemHandle->ui32Order = 0;
+}
+
+PVRSRV_ERROR LMA_PhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
+							size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+							void **pvPtr)
+{
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_UINT32 ui32NumPages = (1 << psMemHandle->ui32Order);
+	PVR_UNREFERENCED_PARAMETER(psMemHandle);
+	PVR_UNREFERENCED_PARAMETER(uiSize);
+
+	PhysHeapDevPAddrToCpuPAddr(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], 1, &sCpuPAddr, psDevPAddr);
+	*pvPtr = OSMapPhysToLin(sCpuPAddr,
+							ui32NumPages * OSGetPageSize(),
+							PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE);
+	if (*pvPtr == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	else
+	{
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+		PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, ui32NumPages * OSGetPageSize());
+#else
+		{
+			PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
+										 *pvPtr,
+										 sCpuPAddr,
+										 ui32NumPages * OSGetPageSize(),
+										 NULL);
+		}
+#endif
+#endif
+		return PVRSRV_OK;
+	}
+}
+
+void LMA_PhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
+						void *pvPtr)
+{
+	IMG_UINT32 ui32NumPages = (1 << psMemHandle->ui32Order);
+	PVR_UNREFERENCED_PARAMETER(psMemHandle);
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+		PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, ui32NumPages * OSGetPageSize());
+#else
+	PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, (IMG_UINT64)(uintptr_t)pvPtr);
+#endif
+#endif
+
+	OSUnMapPhysToLin(pvPtr, ui32NumPages * OSGetPageSize(),
+					 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
+}
+
+PVRSRV_ERROR LMA_PhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
+                                     PG_HANDLE *psMemHandle,
+                                     IMG_UINT32 uiOffset,
+                                     IMG_UINT32 uiLength)
+{
+	/* No need to flush because we map as uncached */
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
+	PVR_UNREFERENCED_PARAMETER(psMemHandle);
+	PVR_UNREFERENCED_PARAMETER(uiOffset);
+	PVR_UNREFERENCED_PARAMETER(uiLength);
+
+	return PVRSRV_OK;
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVDeviceFinalise
+@Description  Performs the final parts of device initialisation.
+@Input        psDeviceNode            Device node of the device to finish
+                                      initialising
+@Input        bInitSuccessful         Whether or not device specific
+                                      initialisation was successful
+@Return       PVRSRV_ERROR     PVRSRV_OK on success and an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
+											   IMG_BOOL bInitSuccessful)
+{
+	PVRSRV_ERROR eError;
+
+	if (bInitSuccessful)
+	{
+		eError = SyncPrimContextCreate(psDeviceNode,
+									   &psDeviceNode->hSyncPrimContext);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to create sync prim context (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+			goto ErrorExit;
+		}
+
+		/* Allocate general purpose sync primitive */
+		eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+							   &psDeviceNode->psSyncPrim,
+							   "pvrsrv dev general");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to allocate sync primitive with error (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+			goto ErrorExit;
+		}
+
+		/* Allocate MMU cache invalidate sync */
+		eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+							   &psDeviceNode->psMMUCacheSyncPrim,
+							   "pvrsrv dev MMU cache");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to allocate sync primitive with error (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+			goto ErrorExit;
+		}
+
+		/* Next update value will be 1 since sync prim starts with 0 */
+		psDeviceNode->ui32NextMMUInvalidateUpdate = 1;
+
+		eError = PVRSRVPowerLock(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire power lock (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+			goto ErrorExit;
+		}
+
+		/*
+		 * Always ensure a single power on command appears in the pdump. This
+		 * should be the only power related call outside of PDUMPPOWCMDSTART
+		 * and PDUMPPOWCMDEND.
+		 */
+		eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+											 PVRSRV_DEV_POWER_STATE_ON, IMG_TRUE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to set device %p power state to 'on' (%s)",
+					 __func__, psDeviceNode, PVRSRVGetErrorStringKM(eError)));
+			PVRSRVPowerUnlock(psDeviceNode);
+			goto ErrorExit;
+		}
+
+		/* Verify firmware compatibility for device */
+		eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed compatibility check for device %p (%s)",
+					 __func__, psDeviceNode, PVRSRVGetErrorStringKM(eError)));
+			PVRSRVPowerUnlock(psDeviceNode);
+			PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+			goto ErrorExit;
+		}
+
+		PDUMPPOWCMDSTART();
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			/* Force the device to idle if its default power state is off */
+			eError = PVRSRVDeviceIdleRequestKM(psDeviceNode,
+											   &PVRSRVDeviceIsDefaultStateOFF,
+											   IMG_TRUE);
+			if (eError == PVRSRV_OK)
+			{
+				break;
+			}
+			else if (eError == PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
+			{
+				PVRSRVPowerUnlock(psDeviceNode);
+				OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+
+				eError = PVRSRVPowerLock(psDeviceNode);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR,
+							 "%s: Failed to acquire power lock (%s)",
+							 __func__, PVRSRVGetErrorStringKM(eError)));
+					goto ErrorExit;
+				}
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to idle device %p (%s)",
+						 __func__, psDeviceNode,
+						 PVRSRVGetErrorStringKM(eError)));
+				PVRSRVPowerUnlock(psDeviceNode);
+				goto ErrorExit;
+			}
+		} END_LOOP_UNTIL_TIMEOUT();
+
+		/* Place device into its default power state. */
+		eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+											 PVRSRV_DEV_POWER_STATE_DEFAULT,
+											 IMG_TRUE);
+		PDUMPPOWCMDEND();
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "%s: Failed to set device %p into its default power state (%s)",
+					 __func__, psDeviceNode, PVRSRVGetErrorStringKM(eError)));
+
+			PVRSRVPowerUnlock(psDeviceNode);
+			goto ErrorExit;
+		}
+
+		PVRSRVPowerUnlock(psDeviceNode);
+
+		/*
+		 * If PDUMP is enabled and RGX device is supported, then initialise the
+		 * performance counters that can be further modified in PDUMP. Then,
+		 * before ending the init phase of the pdump, drain the commands put in
+		 * the kCCB during the init phase.
+		 */
+#if defined(SUPPORT_RGX) && defined(PDUMP)
+		{
+			PVRSRV_RGXDEV_INFO *psDevInfo =
+				(PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
+
+			eError = PVRSRVRGXInitHWPerfCountersKM(psDeviceNode);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						 "%s: Failed to init hwperf counters (%s)",
+						 __func__, PVRSRVGetErrorStringKM(eError)));
+				goto ErrorExit;
+			}
+
+			eError = RGXPdumpDrainKCCB(psDevInfo,
+									   psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Problem draining kCCB (%s)",
+						 __func__, PVRSRVGetErrorStringKM(eError)));
+				goto ErrorExit;
+			}
+		}
+#endif
+
+		/* Now that the device(s) are fully initialised set them as active */
+		psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_ACTIVE;
+
+#if defined(SUPPORT_RGX) && defined(PVRSRV_GPUVIRT_GUESTDRV)
+		eError = RGXFWOSConfig((PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice));
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Cannot kick initialization configuration to the Device (%s)",
+					 __func__, PVRSRVGetErrorStringKM(eError)));
+
+			goto ErrorExit;
+		}
+#endif
+	}
+	else
+	{
+		/* Initialisation failed so set the device(s) into a bad state */
+		psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_BAD;
+		eError = PVRSRV_ERROR_NOT_INITIALISED;
+	}
+
+	/* Give PDump control a chance to end the init phase, depends on OS */
+	PDumpStopInitPhase(IMG_FALSE, IMG_TRUE);
+
+	return eError;
+
+ErrorExit:
+	/* Initialisation failed so set the device(s) into a bad state */
+	psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_BAD;
+
+	return eError;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/* Only check devices which specify a compatibility check callback */
+	if (psDeviceNode->pfnInitDeviceCompatCheck)
+		return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+	else
+		return PVRSRV_OK;
+}
 
 /*
 	PollForValueKM
@@ -2317,7 +2208,8 @@
 
 	LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
 	{
-		ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+		ui32ActualValue = OSReadHWReg32((void *)pui32LinMemAddr, 0) & ui32Mask;
+
 		if(ui32ActualValue == ui32Value)
 		{
 			return PVRSRV_OK;
@@ -2467,46 +2359,9 @@
 	return WaitForValueKM(pui32LinMemAddr, ui32Value, ui32Mask, IMG_TRUE);
 }
 
-void IMG_CALLCONV PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle)
+int PVRSRVGetDriverStatus(void)
 {
-	PVRSRV_DATA			*psPVRSRVData = PVRSRVGetPVRSRVData();
-#if !defined(NO_HARDWARE)
-	DLLIST_NODE			*psNode, *psNext;
-#endif
-
-	/* notify any registered device to check if block work items can now proceed */
-#if !defined(NO_HARDWARE)
-	OSWRLockAcquireRead(hNotifyLock);
-	dllist_foreach_node(&sCmdCompNotifyHead, psNode, psNext)
-	{
-		PVRSRV_CMDCOMP_NOTIFY *psNotify =
-			IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
-
-		/* A device has finished some processing, check if that unblocks other devices */
-		if (hCmdCompCallerHandle != psNotify->hCmdCompHandle)
-		{
-			psNotify->pfnCmdCompleteNotify(psNotify->hCmdCompHandle);
-		}
-	}
-	OSWRLockReleaseRead(hNotifyLock);
-#endif
-
-	/* signal global event object */
-	if (psPVRSRVData->hGlobalEventObject)
-	{
-		IMG_HANDLE hOSEventKM = psPVRSRVData->hGlobalEventObject;
-		if(hOSEventKM)
-		{
-			OSEventObjectSignal(hOSEventKM);
-		}
-	}
-}
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVKickDevicesKM(void)
-{
-	PVR_DPF((PVR_DBG_ERROR, "PVRSRVKickDevicesKM"));
-	PVRSRVCheckStatus(NULL);
-	return PVRSRV_OK;
+	return PVRSRVGetPVRSRVData()->eServicesState;
 }
 
 /*!
@@ -2545,54 +2400,42 @@
 }
 
 /*
-	PVRSRVSystemDebugInfo
- */
-PVRSRV_ERROR PVRSRVSystemDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-					void *pvDumpDebugFile)
-{
-	return SysDebugInfo(gpsSysConfig, pfnDumpDebugPrintf, pvDumpDebugFile);
-}
-
-/*
-	PVRSRVGetSystemName
-*/
-const IMG_CHAR *PVRSRVGetSystemName(void)
-{
-	return gpsSysConfig->pszSystemName;
-}
-
-/*
 	PVRSRVSystemHasCacheSnooping
 */
-IMG_BOOL PVRSRVSystemHasCacheSnooping(void)
+IMG_BOOL PVRSRVSystemHasCacheSnooping(PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
-	if (gpsSysConfig->eCacheSnoopingMode != PVRSRV_SYSTEM_SNOOP_NONE)
+	if (psDevConfig->eCacheSnoopingMode != PVRSRV_DEVICE_SNOOP_NONE)
 	{
 		return IMG_TRUE;
 	}
 	return IMG_FALSE;
 }
 
-IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(void)
+IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
-	if ((gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CPU_ONLY) ||
-		(gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CROSS))
+	if ((psDevConfig->eCacheSnoopingMode == PVRSRV_DEVICE_SNOOP_CPU_ONLY) ||
+		(psDevConfig->eCacheSnoopingMode == PVRSRV_DEVICE_SNOOP_CROSS))
 	{
 		return IMG_TRUE;
 	}
 	return IMG_FALSE;	
 }
 
-IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(void)
+IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
-	if ((gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_DEVICE_ONLY) ||
-		(gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CROSS))
+	if ((psDevConfig->eCacheSnoopingMode == PVRSRV_DEVICE_SNOOP_DEVICE_ONLY) ||
+		(psDevConfig->eCacheSnoopingMode == PVRSRV_DEVICE_SNOOP_CROSS))
 	{
 		return IMG_TRUE;
 	}
 	return IMG_FALSE;
 }
 
+IMG_BOOL PVRSRVSystemHasNonMappableLocalMemory(PVRSRV_DEVICE_CONFIG *psDevConfig)
+{
+	return psDevConfig->bHasNonMappableLocalMemory;
+}
+
 /*
 	PVRSRVSystemWaitCycles
 */
@@ -2619,361 +2462,93 @@
 	OSWaitus(ui32Delayus);
 }
 
-/*
-	PVRSRVRegisterCmdCompleteNotify
-*/
-PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify, PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+static void *
+PVRSRVSystemInstallDeviceLISR_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode,
+											va_list va)
 {
-	PVRSRV_CMDCOMP_NOTIFY *psNotify;
+	void *pvOSDevice = va_arg(va, void *);
 
-	if ((phNotify == NULL) || (pfnCmdCompleteNotify == NULL) || (hCmdCompHandle == NULL))
+	if (psDeviceNode->psDevConfig->pvOSDevice == pvOSDevice)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p, %p, %p)", __FUNCTION__, phNotify, pfnCmdCompleteNotify, hCmdCompHandle));
-		return PVRSRV_ERROR_INVALID_PARAMS;
+		return psDeviceNode;
 	}
 
-	psNotify = OSAllocMem(sizeof(*psNotify));
-	if (psNotify == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Not enough memory to allocate CmdCompleteNotify function", __FUNCTION__));
-		return PVRSRV_ERROR_OUT_OF_MEMORY;		
-	}
-
-	/* Set-up the notify data */
-	psNotify->hCmdCompHandle = hCmdCompHandle;
-	psNotify->pfnCmdCompleteNotify = pfnCmdCompleteNotify;
-
-	/* Add it to the list of Notify functions */
-	OSWRLockAcquireWrite(hNotifyLock);
-	dllist_add_to_tail(&sCmdCompNotifyHead, &psNotify->sListNode);
-	OSWRLockReleaseWrite(hNotifyLock);
-
-	*phNotify = psNotify;
-
-	return PVRSRV_OK;
+	return NULL;
 }
 
-/*
-	PVRSRVUnregisterCmdCompleteNotify
-*/
-PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify)
-{
-	PVRSRV_CMDCOMP_NOTIFY *psNotify = (PVRSRV_CMDCOMP_NOTIFY*) hNotify;
-
-	if (psNotify == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p)", __FUNCTION__, hNotify));
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-	/* remove the node from the list */
-	OSWRLockAcquireWrite(hNotifyLock);
-	dllist_remove_node(&psNotify->sListNode);
-	OSWRLockReleaseWrite(hNotifyLock);
-
-	/* free the notify structure that holds the node */
-	OSFreeMem(psNotify);
-
-	return PVRSRV_OK;
-
-}
-
-static void _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel,
-	DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile)
-{
-	PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA*) hDebugRequestHandle;
-
-	/* only dump info on the lowest verbosity level */
-	if (ui32VerbLevel != DEBUG_REQUEST_VERBOSITY_LOW)
-	{
-		return;
-	}
-
-	PVR_DUMPDEBUG_LOG("DDK info: %s (%s) %s", PVRVERSION_STRING, PVR_BUILD_TYPE, PVR_BUILD_DIR);
-	PVR_DUMPDEBUG_LOG("Time now: %015llu", OSClockus64());
-
-	/* Services state */
-	switch (psPVRSRVData->eServicesState)
-	{
-		case PVRSRV_SERVICES_STATE_OK:
-		{
-			PVR_DUMPDEBUG_LOG("Services State: OK");
-			break;
-		}
-		
-		case PVRSRV_SERVICES_STATE_BAD:
-		{
-			PVR_DUMPDEBUG_LOG("Services State: BAD");
-			break;
-		}
-		
-		default:
-		{
-			PVR_DUMPDEBUG_LOG("Services State: UNKNOWN (%d)", psPVRSRVData->eServicesState);
-			break;
-		}
-	}
-
-	/* Power state */
-	switch (psPVRSRVData->eCurrentPowerState)
-	{
-		case PVRSRV_SYS_POWER_STATE_OFF:
-		{
-			PVR_DUMPDEBUG_LOG("System Power State: OFF");
-			break;
-		}
-		case PVRSRV_SYS_POWER_STATE_ON:
-		{
-			PVR_DUMPDEBUG_LOG("System Power State: ON");
-			break;
-		}
-		default:
-		{
-			PVR_DUMPDEBUG_LOG("System Power State: UNKNOWN (%d)", psPVRSRVData->eCurrentPowerState);
-			break;
-		}
-	}
-
-	/* Dump system specific debug info */
-	PVRSRVSystemDebugInfo(pfnDumpDebugPrintf, pvDumpDebugFile);
-
-}
-
-/*
-	PVRSRVDebugRequest
-*/
-void IMG_CALLCONV PVRSRVDebugRequest(IMG_UINT32 ui32VerbLevel, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile)
-{
-	IMG_UINT32 i,j;
-
-	if (pvDumpDebugFile == NULL)
-	{
-		/* Only dump the call stack to the kernel log if the debug text is going there. */
-		OSDumpStack();
-	}
-
-	/* notify any registered device to check if block work items can now proceed */
-	/* Lock the lists */
-	OSWRLockAcquireRead(g_hDbgNotifyLock);
-
-	PVR_DUMPDEBUG_LOG("------------[ PVR DBG: START ]------------");
-
-	/* For each verbosity level */
-	for (j=0;j<(ui32VerbLevel+1);j++)
-	{
-		/* For each requester */
-		for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
-		{
-			DLLIST_NODE *psNode, *psNext;
-			dllist_foreach_node(&g_psDebugTable->asEntry[i].sListHead, psNode, psNext)
-			{
-				PVRSRV_DBGREQ_NOTIFY *psNotify =
-					IMG_CONTAINER_OF(psNode, PVRSRV_DBGREQ_NOTIFY, sListNode);
-				psNotify->pfnDbgRequestNotify(psNotify->hDbgRequestHandle, j, pfnDumpDebugPrintf, pvDumpDebugFile);
-			}
-		}
-	}
-	PVR_DUMPDEBUG_LOG("------------[ PVR DBG: END ]------------");
-
-	/* Unlock the lists */
-	OSWRLockReleaseRead(g_hDbgNotifyLock);
-}
-
-/*
-	PVRSRVRegisterDebugRequestNotify
-*/
-PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify, PFN_DBGREQ_NOTIFY pfnDbgRequestNotify, IMG_UINT32 ui32RequesterID, PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
-{
-	PVRSRV_DBGREQ_NOTIFY *psNotify;
-	PDLLIST_NODE psHead = NULL;
-	IMG_UINT32 i;
-	PVRSRV_ERROR eError;
-
-	if ((phNotify == NULL) || (pfnDbgRequestNotify == NULL))
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p, %p,)", __FUNCTION__, phNotify, pfnDbgRequestNotify));
-		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto fail_params;
-	}
-
-	psNotify = OSAllocMem(sizeof(*psNotify));
-	if (psNotify == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Not enough memory to allocate DbgRequestNotify structure", __FUNCTION__));
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto fail_alloc;
-	}
-
-	/* Set-up the notify data */
-	psNotify->hDbgRequestHandle = hDbgRequestHandle;
-	psNotify->pfnDbgRequestNotify = pfnDbgRequestNotify;
-	psNotify->ui32RequesterID = ui32RequesterID;
-
-	/* Lock down all the lists */
-	OSWRLockAcquireWrite(g_hDbgNotifyLock);
-
-	/* Find which list to add it to */
-	for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
-	{
-		if (g_psDebugTable->asEntry[i].ui32RequesterID == ui32RequesterID)
-		{
-			psHead = &g_psDebugTable->asEntry[i].sListHead;
-		}
-	}
-
-	if (psHead == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to find debug requester", __FUNCTION__));
-		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto fail_add;
-	}
-
-	/* Add it to the list of Notify functions */
-	dllist_add_to_tail(psHead, &psNotify->sListNode);
-
-	/* Unlock the lists */
-	OSWRLockReleaseWrite(g_hDbgNotifyLock);
-
-	*phNotify = psNotify;
-
-	return PVRSRV_OK;
-
-fail_add:
-	OSWRLockReleaseWrite(g_hDbgNotifyLock);
-	OSFreeMem(psNotify);
-fail_alloc:
-fail_params:
-	return eError;
-}
-
-/*
-	PVRSRVUnregisterCmdCompleteNotify
-*/
-PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
-{
-	PVRSRV_DBGREQ_NOTIFY *psNotify = (PVRSRV_DBGREQ_NOTIFY*) hNotify;
-
-	if (psNotify == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p)", __FUNCTION__, hNotify));
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-	/* remove the node from the list */
-	OSWRLockAcquireWrite(g_hDbgNotifyLock);
-	dllist_remove_node(&psNotify->sListNode);
-	OSWRLockReleaseWrite(g_hDbgNotifyLock);
-
-	/* free the notify structure that holds the node */
-	OSFreeMem(psNotify);
-
-	return PVRSRV_OK;
-}
-
-
-static PVRSRV_ERROR PVRSRVRegisterDbgTable(IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length, void **phTable)
-{
-	IMG_UINT32 i;
-	if (g_psDebugTable != NULL)
-	{
-		return PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED;
-	}
-
-	g_psDebugTable = OSAllocMem(sizeof(DEBUG_REQUEST_TABLE) + (sizeof(DEBUG_REQUEST_ENTRY) * (ui32Length-1)));
-	if (!g_psDebugTable)
-	{
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
-	}
-
-	g_psDebugTable->ui32RequestCount = ui32Length;
-
-	/* Init the list heads */
-	for (i=0;i<ui32Length;i++)
-	{
-		g_psDebugTable->asEntry[i].ui32RequesterID = paui32Table[i];
-		dllist_init(&g_psDebugTable->asEntry[i].sListHead);
-	}
-
-	*phTable = g_psDebugTable;
-	return PVRSRV_OK;
-}
-
-static void PVRSRVUnregisterDbgTable(void *hTable)
-{
-	IMG_UINT32 i;
-
-	PVR_ASSERT(hTable == g_psDebugTable);
-
-	for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
-	{
-		if (!dllist_is_empty(&g_psDebugTable->asEntry[i].sListHead))
-		{
-			PVR_DPF((PVR_DBG_ERROR, "PVRSRVUnregisterDbgTable: Found registered callback(s) on %d", i));
-		}
-	}
-	OSFREEMEM(g_psDebugTable);
-	g_psDebugTable = NULL;
-}
-
-PVRSRV_ERROR AcquireGlobalEventObjectServer(IMG_HANDLE *phGlobalEventObject)
+PVRSRV_ERROR PVRSRVSystemInstallDeviceLISR(void *pvOSDevice,
+										   IMG_UINT32 ui32IRQ,
+										   const IMG_CHAR *pszName,
+										   PFN_LISR pfnLISR,
+										   void *pvData,
+										   IMG_HANDLE *phLISRData)
 {
 	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+	PVRSRV_DEVICE_NODE *psDeviceNode;
 
-	*phGlobalEventObject = psPVRSRVData->hGlobalEventObject;
+	psDeviceNode =
+		List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+									   &PVRSRVSystemInstallDeviceLISR_Match_AnyVaCb,
+									   pvOSDevice);
+	if (!psDeviceNode)
+	{
+		/* Device can't be found in the list so it isn't in the system */
+		PVR_DPF((PVR_DBG_ERROR, "%s: device %p with irq %d is not present",
+				 __func__, pvOSDevice, ui32IRQ));
+		return PVRSRV_ERROR_INVALID_DEVICE;
+	}
 
-	return PVRSRV_OK;
+	return SysInstallDeviceLISR(psDeviceNode->psDevConfig->hSysData, ui32IRQ,
+								pszName, pfnLISR, pvData, phLISRData);
 }
 
-PVRSRV_ERROR ReleaseGlobalEventObjectServer(IMG_HANDLE hGlobalEventObject)
+PVRSRV_ERROR PVRSRVSystemUninstallDeviceLISR(IMG_HANDLE hLISRData)
 {
-	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-
-	PVR_ASSERT(psPVRSRVData->hGlobalEventObject == hGlobalEventObject);
-
-	return PVRSRV_OK;
+	return SysUninstallDeviceLISR(hLISRData);
 }
 
-PVRSRV_ERROR GetBIFTilingHeapXStride(IMG_UINT32 uiHeapNum, IMG_UINT32 *puiXStride)
+PVRSRV_ERROR
+PVRSRVSystemBIFTilingHeapGetXStride(PVRSRV_DEVICE_CONFIG *psDevConfig,
+									IMG_UINT32 uiHeapNum,
+									IMG_UINT32 *puiXStride)
 {
-	IMG_UINT32 uiMaxHeaps;
-
 	PVR_ASSERT(puiXStride != NULL);
 
-	GetNumBifTilingHeapConfigs(&uiMaxHeaps);
-
-	if(uiHeapNum < 1 || uiHeapNum > uiMaxHeaps) {
+	if (uiHeapNum < 1 || uiHeapNum > psDevConfig->ui32BIFTilingHeapCount)
+	{
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	*puiXStride = gpsSysConfig->pui32BIFTilingHeapConfigs[uiHeapNum - 1];
+	*puiXStride = psDevConfig->pui32BIFTilingHeapConfigs[uiHeapNum - 1];
 
 	return PVRSRV_OK;
 }
 
-PVRSRV_ERROR GetNumBifTilingHeapConfigs(IMG_UINT32 *puiNumHeaps)
+PVRSRV_ERROR
+PVRSRVSystemBIFTilingGetConfig(PVRSRV_DEVICE_CONFIG  *psDevConfig,
+                               RGXFWIF_BIFTILINGMODE *peBifTilingMode,
+                               IMG_UINT32            *puiNumHeaps)
 {
-	*puiNumHeaps = gpsSysConfig->ui32BIFTilingHeapCount;
+	*peBifTilingMode = psDevConfig->eBIFTilingMode;
+	*puiNumHeaps = psDevConfig->ui32BIFTilingHeapCount;
 	return PVRSRV_OK;
 }
 
-/*
-	PVRSRVResetHWRLogsKM
-*/
-PVRSRV_ERROR PVRSRVResetHWRLogsKM(CONNECTION_DATA * psConnection,
-                                  PVRSRV_DEVICE_NODE *psDeviceNode)
+#if defined(SUPPORT_GPUVIRT_VALIDATION) && defined(EMULATOR)
+void SetAxiProtOSid(IMG_UINT32 ui32OSid, IMG_BOOL bState)
 {
-	PVR_LOG(("User requested HWR logs reset"));
-
-	PVR_UNREFERENCED_PARAMETER(psConnection);
-	
-	if(psDeviceNode && psDeviceNode->pfnResetHWRLogs)
-	{
-		return psDeviceNode->pfnResetHWRLogs(psDeviceNode);
-	}
-
-	return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+    SysSetAxiProtOSid(ui32OSid, bState);
+    return ;
 }
 
+void SetTrustedDeviceAceEnabled(void)
+{
+    SysSetTrustedDeviceAceEnabled();
+
+    return ;
+}
+#endif
+
 /*****************************************************************************
  End of file (pvrsrv.c)
 *****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/pvrsrv.h b/drivers/staging/imgtec/rogue/pvrsrv.h
index 96bd4f3..0d6d70e 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv.h
@@ -44,7 +44,7 @@
 #define PVRSRV_H
 
 
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
 #include <services_kernel_client.h>
 #endif
@@ -53,14 +53,12 @@
 #include "power.h"
 #include "sysinfo.h"
 #include "physheap.h"
+#include "cache_ops.h"
 #include "pvr_notifier.h"
-
-/*!
- * For OSThreadDestroy(), which may require a retry
- * Try for 100 ms to destroy an OS thread before failing
- */
-#define OS_THREAD_DESTROY_TIMEOUT_US 100000ULL
-#define OS_THREAD_DESTROY_RETRY_COUNT 10
+#include "pvr_bridge.h"
+#if defined(SUPPORT_RGX)
+#include "rgx_bridge.h"
+#endif
 
 #include "connection_server.h"
 
@@ -68,12 +66,12 @@
 #include "virt_validation_defs.h"
 #endif
 
-typedef struct _SYS_DEVICE_ID_TAG
-{
-	IMG_UINT32	uiID;
-	IMG_BOOL	bInUse;
-
-} SYS_DEVICE_ID;
+/*!
+ * For OSThreadDestroy(), which may require a retry
+ * Try for 100 ms to destroy an OS thread before failing
+ */
+#define OS_THREAD_DESTROY_TIMEOUT_US 100000ULL
+#define OS_THREAD_DESTROY_RETRY_COUNT 10
 
 typedef struct _BUILD_INFO_
 {
@@ -97,33 +95,31 @@
 typedef struct PVRSRV_DATA_TAG
 {
 	DRIVER_INFO					sDriverInfo;
-    IMG_UINT32                  ui32NumDevices;      	   	/*!< number of devices in system */
-	SYS_DEVICE_ID				sDeviceID[SYS_DEVICE_COUNT];
-	PVRSRV_DEVICE_NODE			*apsRegisteredDevNodes[SYS_DEVICE_COUNT];
 	IMG_UINT32					ui32RegisteredDevices;
-	IMG_UINT32		 			ui32CurrentOSPowerState;	/*!< current OS specific power state */
 	PVRSRV_DEVICE_NODE			*psDeviceNodeList;			/*!< List head of device nodes */
-	struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
 
-	IMG_UINT32					ui32RegisteredPhysHeaps;
-	PHYS_HEAP					*apsRegisteredPhysHeaps[SYS_PHYS_HEAP_COUNT];
+	PVRSRV_SERVICES_STATE		eServicesState;				/*!< global driver state */
 
-    PVRSRV_POWER_DEV			*psPowerDeviceList;			/*!< list of devices registered with the power manager */
-	POS_LOCK					hPowerLock;					/*!< lock for power state transitions */
-   	PVRSRV_SYS_POWER_STATE		eCurrentPowerState;			/*!< current Kernel services power state */
-   	PVRSRV_SYS_POWER_STATE		eFailedPowerState;			/*!< Kernel services power state (Failed to transition to) */
-
-   	PVRSRV_SERVICES_STATE		eServicesState;				/*!< global driver state */
+	HASH_TABLE					*psProcessHandleBase_Table; /*!< Hash table with process handle bases */
+	POS_LOCK					hProcessHandleBase_Lock;	/*!< Lock for the process handle base table */
 
 	IMG_HANDLE					hGlobalEventObject;			/*!< OS Global Event Object */
 	IMG_UINT32					ui32GEOConsecutiveTimeouts;	/*!< OS Global Event Object Timeouts */
-	
+
 	PVRSRV_CACHE_OP				uiCacheOp;					/*!< Pending cache operations in the system */
+#if (CACHEFLUSH_KM_TYPE == CACHEFLUSH_KM_RANGEBASED_DEFERRED)
+	IMG_HANDLE					hCacheOpThread;				/*!< CacheOp thread */
+	IMG_HANDLE					hCacheOpThreadEventObject;	/*!< Event object to drive CacheOp thread */
+	IMG_HANDLE					hCacheOpUpdateEventObject;	/*!< Update event object to drive CacheOp fencing */
+	POS_LOCK					hCacheOpThreadWorkListLock;	/*!< Lock protecting the cleanup thread work list */
+	DLLIST_NODE					sCacheOpThreadWorkList;		/*!< List of work for the cleanup thread */
+	IMG_PID						CacheOpThreadPid;			/*!< CacheOp thread process id */
+#endif
 
 	IMG_HANDLE					hCleanupThread;				/*!< Cleanup thread */
 	IMG_HANDLE					hCleanupEventObject;		/*!< Event object to drive cleanup thread */
 	POS_LOCK					hCleanupThreadWorkListLock;	/*!< Lock protecting the cleanup thread work list */
-	DLLIST_NODE					sCleanupThreadWorkList;		/*!< List of work to do by the cleanup thread */
+	DLLIST_NODE					sCleanupThreadWorkList;		/*!< List of work for the cleanup thread */
 	IMG_PID						cleanupThreadPid;			/*!< Cleanup thread process id */
 
 	IMG_HANDLE					hDevicesWatchdogThread;		/*!< Devices Watchdog thread */
@@ -134,42 +130,15 @@
 	volatile IMG_UINT32			ui32DevicesWdWakeupCounter;	/* Need this for the unit tests. */
 #endif
 
+#ifdef SUPPORT_PVRSRV_GPUVIRT
+	IMG_HANDLE					hVzData;					/*! Additional virtualization data */
+#endif
+	
 	IMG_BOOL					bUnload;					/*!< Driver unload is in progress */
 } PVRSRV_DATA;
 
+typedef IMG_BOOL (*PFN_LISR)(void *pvData);
 
-typedef IMG_HANDLE PVRSRV_CMDCOMP_HANDLE;
-typedef void (*PFN_CMDCOMP_NOTIFY) (PVRSRV_CMDCOMP_HANDLE hCmdCompHandle);
-
-typedef struct PVRSRV_CMDCOMP_NOTIFY_TAG
-{
-	PVRSRV_CMDCOMP_HANDLE	hCmdCompHandle;
-	PFN_CMDCOMP_NOTIFY		pfnCmdCompleteNotify;
-
-	DLLIST_NODE					sListNode;
-} PVRSRV_CMDCOMP_NOTIFY;
-
-#define DEBUG_REQUEST_VERBOSITY_LOW		0
-#define DEBUG_REQUEST_VERBOSITY_MEDIUM	1
-#define DEBUG_REQUEST_VERBOSITY_HIGH	2
-
-#define DEBUG_REQUEST_VERBOSITY_MAX	(DEBUG_REQUEST_VERBOSITY_HIGH)
-
-typedef struct PVRSRV_DBGREQ_NOTIFY_TAG
-{
-	PVRSRV_DBGREQ_HANDLE	hDbgRequestHandle;
-	PFN_DBGREQ_NOTIFY		pfnDbgRequestNotify;
-	IMG_UINT32				ui32RequesterID;
-
-	DLLIST_NODE					sListNode;
-} PVRSRV_DBGREQ_NOTIFY;
-
-#define PVR_DUMP_DRIVER_INFO(x, y)					\
-		PVR_DUMPDEBUG_LOG("%s info: BuildOptions: 0x%08x BuildVersion: %d.%d BuildRevision: %8d BuildType: %s", (x), \
-								(y).ui32BuildOptions, \
-								PVRVERSION_UNPACK_MAJ((y).ui32BuildVersion), PVRVERSION_UNPACK_MIN((y).ui32BuildVersion), \
-								(y).ui32BuildRevision, \
-								(BUILD_TYPE_DEBUG == (y).ui32BuildType)?"debug":"release")
 /*!
 ******************************************************************************
 
@@ -182,30 +151,6 @@
 ******************************************************************************/
 PVRSRV_DATA *PVRSRVGetPVRSRVData(void);
 
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
-                                                   PVRSRV_DEVICE_TYPE *peDeviceType,
-                                                   PVRSRV_DEVICE_CLASS *peDeviceClass,
-                                                   IMG_UINT32 *pui32DeviceIndex);
-
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32			ui32DevIndex,
-													 PVRSRV_DEVICE_TYPE	eDeviceType,
-													 IMG_HANDLE			*phDevCookie);
-
-IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseDeviceDataKM (IMG_HANDLE hDevCookie);
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode,
-													IMG_UINT32 *pui32DeviceIndex,
-													IMG_UINT32 ui32PhysHeapID);
-
-void IMG_CALLCONV PVRSRVUnregisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced);
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced);
-
 PVRSRV_ERROR LMA_PhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
 							PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr);
 
@@ -218,7 +163,8 @@
 void LMA_PhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
 					void *pvPtr);
 
-PVRSRV_ERROR LMA_PhyContigPagesClean(PG_HANDLE *psMemHandle,
+PVRSRV_ERROR LMA_PhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
+                                     PG_HANDLE *psMemHandle,
                                      IMG_UINT32 uiOffset,
                                      IMG_UINT32 uiLength);
 
@@ -277,37 +223,13 @@
 
 /*!
 *****************************************************************************
- @Function	: PVRSRVSystemDebugInfo
-
- @Description	: Dump the system debug info
-
-@Input pfnDumpDebugPrintf : Used to specify the appropriate printf function.
-			     If this argument is NULL, then PVR_LOG() will
-			     be used as the default printing function.
-
-*****************************************************************************/
-PVRSRV_ERROR PVRSRVSystemDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-					void *pvDumpDebugFile);
-
-/*!
-*****************************************************************************
- @Function	: PVRSRVGetSystemName
-
- @Description	: Gets the system name string
-
- @Return : The system name
-*****************************************************************************/
-const IMG_CHAR *PVRSRVGetSystemName(void);
-
-/*!
-*****************************************************************************
  @Function	: PVRSRVSystemHasCacheSnooping
 
  @Description	: Returns whether the system has cache snooping
 
  @Return : IMG_TRUE if the system has cache snooping
 *****************************************************************************/
-IMG_BOOL PVRSRVSystemHasCacheSnooping(void);
+IMG_BOOL PVRSRVSystemHasCacheSnooping(PVRSRV_DEVICE_CONFIG *psDevConfig);
 
 /*!
 *****************************************************************************
@@ -317,7 +239,7 @@
 
  @Return : IMG_TRUE if the system has CPU cache snooping
 *****************************************************************************/
-IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(void);
+IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(PVRSRV_DEVICE_CONFIG *psDevConfig);
 
 /*!
 *****************************************************************************
@@ -327,7 +249,17 @@
 
  @Return : IMG_TRUE if the system has device cache snooping
 *****************************************************************************/
-IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(void);
+IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(PVRSRV_DEVICE_CONFIG *psDevConfig);
+
+/*!
+*****************************************************************************
+ @Function	: PVRSRVSystemHasNonMappableLocalMemory
+
+ @Description	: Returns whether the device has non-mappable part of local memory
+
+ @Return : IMG_TRUE if the device has non-mappable part of local memory
+*****************************************************************************/
+IMG_BOOL PVRSRVSystemHasNonMappableLocalMemory(PVRSRV_DEVICE_CONFIG *psDevConfig);
 
 /*!
 *****************************************************************************
@@ -338,165 +270,80 @@
 *****************************************************************************/
 void PVRSRVSystemWaitCycles(PVRSRV_DEVICE_CONFIG *psDevConfig, IMG_UINT32 ui32Cycles);
 
+PVRSRV_ERROR PVRSRVSystemInstallDeviceLISR(void *pvOSDevice,
+										   IMG_UINT32 ui32IRQ,
+										   const IMG_CHAR *pszName,
+										   PFN_LISR pfnLISR,
+										   void *pvData,
+										   IMG_HANDLE *phLISRData);
 
+PVRSRV_ERROR PVRSRVSystemUninstallDeviceLISR(IMG_HANDLE hLISRData);
+
+int PVRSRVGetDriverStatus(void);
 
 /*!
 *****************************************************************************
- @Function	: PVRSRVCheckStatus
+ @Function	: PVRSRVIsBridgeEnabled
 
- @Description	: Notify any registered cmd complete function (except if its
-				  hPrivData matches the hCmdCompHandle handler) and raise the global 
-				  event object. 
+ @Description	: Returns whether the given bridge group is enabled
 
- @Input hCmdCompHandle	: Identify the caller by the handler used when 
-						  registering for cmd complete. NULL calls all
-						  the notify functions.
-
+ @Return : IMG_TRUE if the given bridge group is enabled
 *****************************************************************************/
-void IMG_CALLCONV PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle);
+static inline IMG_BOOL PVRSRVIsBridgeEnabled(IMG_HANDLE hServices, IMG_UINT32 ui32BridgeGroup)
+{
+	PVR_UNREFERENCED_PARAMETER(hServices);
 
-PVRSRV_ERROR IMG_CALLCONV PVRSRVKickDevicesKM(void);
+#if defined(SUPPORT_RGX)
+	if(ui32BridgeGroup >= PVRSRV_BRIDGE_RGX_FIRST)
+	{
+		return ((1U << (ui32BridgeGroup - PVRSRV_BRIDGE_RGX_FIRST)) &
+							gui32RGXBridges) != 0;
+	}
+	else
+#endif /* SUPPORT_RGX */
+	{
+		return ((1U << (ui32BridgeGroup - PVRSRV_BRIDGE_FIRST)) &
+							gui32PVRBridges) != 0;
+	}
+}
 
 /*!
 *****************************************************************************
- @Function	: PVRSRVResetHWRLogsKM
-
- @Description	: Resets the HWR Logs buffer (the hardware recovery count is not reset)
-
- @Input psDeviceNode	: Pointer to the device
-
- @Return   PVRSRV_ERROR : PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
-*****************************************************************************
- */
-PVRSRV_ERROR PVRSRVResetHWRLogsKM(CONNECTION_DATA * psConnection,
-                                  PVRSRV_DEVICE_NODE *psDeviceNode);
-
-/*!
-*****************************************************************************
- @Function	: PVRSRVRegisterCmdCompleteNotify
-
- @Description	: Register a notify function which is called when some device
-				  finishes some work (that is, when someone calls to PVRSRVCheckStatus).
-
- @Input phNotify : Pointer to the Cmd complete notify handler
-
- @Input pfnCmdCompleteNotify : Notify function
-
- @Input hPrivData : Handler to data passed to the Notify function when called
-
-*****************************************************************************/
-PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify, PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, PVRSRV_CMDCOMP_HANDLE hPrivData);
-
-/*!
-*****************************************************************************
- @Function	: PVRSRVUnregisterCmdCompleteNotify
-
- @Description	: Unregister a previously registered notify func.
-
- @Input hNotify : Cmd complete notify handler registered previously
-
-*****************************************************************************/
-PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify);
-
-
-/*!
-*****************************************************************************
- @Function	: PVRSRVDebugRequest
-
- @Description	: Notify any registered debug request handler that a debug
-                  request has been made and at what level. It dumps information 
-		  for all debug handlers unlike RGXDumpDebugInfo
-
- @Input ui32VerbLevel	: The maximum verbosity level to dump
-
- @Input pfnDumpDebugPrintf : Used to specify the appropriate printf function.
-			     If this argument is NULL, then PVR_LOG() will
-			     be used as the default printing function.
-
-*****************************************************************************/
-void IMG_CALLCONV PVRSRVDebugRequest(IMG_UINT32 ui32VerbLevel, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile);
-
-/*!
-*****************************************************************************
- @Function	: PVRSRVRegisterDebugRequestNotify
-
- @Description	: Register a notify function which is called when a debug
-				  request is made into the driver (that is, when someone
-				  calls to PVRSRVDebugRequest). There are a number of levels
-				  of verbosity, starting at 0 and going to
-				  DEBUG_REQUEST_VERBOSITY_MAX. For each level that's required
-				  a new call to the notify function will be made.
-
- @Input phNotify : Pointer to the debug request notify handler
-
- @Input pfnDbgRequestNotify : Notify function
-
- @Input ui32RequesterID : Used to determine the order debug request callbacks get
-                          called in with the table passed into 
-
- @Input hDbgReqeustHandle : Handler to data passed to the Notify function when called
-
-*****************************************************************************/
-PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify, PFN_DBGREQ_NOTIFY pfnDbgRequestNotify, IMG_UINT32 ui32RequesterID, PVRSRV_DBGREQ_HANDLE hDbgReqeustHandle);
-
-/*!
-*****************************************************************************
- @Function	: PVRSRVUnregisterDebugRequestNotify
-
- @Description	: Unregister a previously registered notify func.
-
- @Input hNotify : Debug request notify handler registered previously
-
-*****************************************************************************/
-PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify);
-
-/*!
-*****************************************************************************
- @Function	: AcquireGlobalEventObjectServer
-
- @Description	: Acquire the global event object.
-
- @Output phGlobalEventObject : Handle to the global event object
-
-*****************************************************************************/
-PVRSRV_ERROR AcquireGlobalEventObjectServer(IMG_HANDLE *phGlobalEventObject);
-
-/*!
-*****************************************************************************
- @Function	: ReleaseGlobalEventObjectServer
-
- @Description	: Release the global event object.
-
- @Input hGlobalEventObject : Handle to the global event object
-
-*****************************************************************************/
-PVRSRV_ERROR ReleaseGlobalEventObjectServer(IMG_HANDLE hGlobalEventObject);
-
-
-/*!
-*****************************************************************************
- @Function	: GetBIFTilingHeapXStride
+ @Function	: PVRSRVSystemBIFTilingHeapGetXStride
 
  @Description	: return the default x-stride configuration for the given
                   BIF tiling heap number
 
+ @Input psDevConfig: Pointer to a device config
+
  @Input uiHeapNum: BIF tiling heap number, starting from 1
 
  @Output puiXStride: pointer to x-stride output of the requested heap
 
 *****************************************************************************/
-PVRSRV_ERROR GetBIFTilingHeapXStride(IMG_UINT32 uiHeapNum, IMG_UINT32 *puiXStride);
+PVRSRV_ERROR
+PVRSRVSystemBIFTilingHeapGetXStride(PVRSRV_DEVICE_CONFIG *psDevConfig,
+									IMG_UINT32 uiHeapNum,
+									IMG_UINT32 *puiXStride);
 
 /*!
 *****************************************************************************
- @Function	: GetNumBIFTilingHeaps
+ @Function              : PVRSRVSystemBIFTilingGetConfig
 
- @Description	: return the number of BIF tiling heaps on this system
+ @Description           : return the BIF tiling mode and number of BIF
+                          tiling heaps for the given device config
 
- @Output puiNumHeaps: pointer to uint to hold number of heaps
+ @Input psDevConfig     : Pointer to a device config
+
+ @Output peBifTilingMode: Pointer to a BIF tiling mode enum
+
+ @Output puiNumHeaps    : pointer to uint to hold number of heaps
 
 *****************************************************************************/
-PVRSRV_ERROR GetNumBifTilingHeapConfigs(IMG_UINT32 *puiNumHeaps);
+PVRSRV_ERROR
+PVRSRVSystemBIFTilingGetConfig(PVRSRV_DEVICE_CONFIG  *psDevConfig,
+                               RGXFWIF_BIFTILINGMODE *peBifTilingMode,
+                               IMG_UINT32            *puiNumHeaps);
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 /*!
@@ -518,6 +365,12 @@
 ***********************************************************************************/
 
 void PopulateLMASubArenas(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 aui32OSidMin[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS], IMG_UINT32 aui32OSidMax[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS]);
+
+#if defined(EMULATOR)
+	void SetAxiProtOSid(IMG_UINT32 ui32OSid, IMG_BOOL bState);
+	void SetTrustedDeviceAceEnabled(void);
+#endif
+
 #endif
 
 #endif /* PVRSRV_H */
diff --git a/drivers/staging/imgtec/rogue/debug_request_ids.h b/drivers/staging/imgtec/rogue/pvrsrv_apphint.h
similarity index 69%
copy from drivers/staging/imgtec/rogue/debug_request_ids.h
copy to drivers/staging/imgtec/rogue/pvrsrv_apphint.h
index f76c932..43eccef 100644
--- a/drivers/staging/imgtec/rogue/debug_request_ids.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_apphint.h
@@ -1,9 +1,7 @@
-/*************************************************************************/ /*!
+/**************************************************************************/ /*!
 @File
-@Title          Debug requester ID's
+@Title          PowerVR AppHint generic interface
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header contains the defines for the debug ID's for all the
-				services components
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -40,18 +38,29 @@
 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
- 
-#ifndef __DEBUG_REQUEST_IDS__
-#define __DEBUG_REQUEST_IDS__
+*/ /***************************************************************************/
 
-/* Services controlled devices should be 1st */
-#define DEBUG_REQUEST_RGX			(0)
-#define DEBUG_REQUEST_DC			(1)
-#define DEBUG_REQUEST_SERVERSYNC	(2)
-#define DEBUG_REQUEST_SYS           (3)
-#define DEBUG_REQUEST_ANDROIDSYNC   (4)
-#define DEBUG_REQUEST_DRMDISPLAY    (5)
-#define DEBUG_REQUEST_LINUXFENCE    (6)
+#if !defined(__PVRSRV_APPHINT_H__)
+#define __PVRSRV_APPHINT_H__
 
-#endif /* __DEBUG_REQUEST_IDS__ */
+#if defined(LINUX)
+
+#include "km_apphint.h"
+#define PVRSRVAppHintDumpState() pvr_apphint_dump_state()
+#define PVRSRVAppHintRegisterHandlersUINT64(i,q,s,d,p) pvr_apphint_register_handlers_uint64(i,q,s,d,p)
+#define PVRSRVAppHintRegisterHandlersUINT32(i,q,s,d,p) pvr_apphint_register_handlers_uint32(i,q,s,d,p)
+#define PVRSRVAppHintRegisterHandlersBOOL(i,q,s,d,p) pvr_apphint_register_handlers_bool(i,q,s,d,p)
+#define PVRSRVAppHintRegisterHandlersSTRING(i,q,s,d,p) pvr_apphint_register_handlers_string(i,q,s,d,p)
+
+#else
+
+#define PVRSRVAppHintDumpState()
+#define PVRSRVAppHintRegisterHandlersUINT64(i,q,s,d,p)
+#define PVRSRVAppHintRegisterHandlersUINT32(i,q,s,d,p)
+#define PVRSRVAppHintRegisterHandlersBOOL(i,q,s,d,p)
+#define PVRSRVAppHintRegisterHandlersSTRING(i,q,s,d,p)
+
+#endif
+
+#endif /* !defined(__PVRSRV_APPHINT_H__) */
+
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_cleanup.h b/drivers/staging/imgtec/rogue/pvrsrv_cleanup.h
index fba346e..fc0d432 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_cleanup.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_cleanup.h
@@ -59,6 +59,7 @@
 	CLEANUP_THREAD_FN pfnFree; /*!< function to be called */
 	void *pvData; /*!< private data for pfnFree */
 	IMG_UINT32 ui32RetryCount; /*!< number of times the callback should be re-tried when it returns error */
+	IMG_BOOL bDependsOnHW;
 } PVRSRV_CLEANUP_THREAD_WORK;
 
 /*!
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_device.h b/drivers/staging/imgtec/rogue/pvrsrv_device.h
index 87d18b7..c4a4e18 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_device.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_device.h
@@ -42,23 +42,21 @@
 #ifndef __PVRSRV_DEVICE_H__
 #define __PVRSRV_DEVICE_H__
 
-#include "servicesext.h"
-#include "pvrsrv_device_types.h"
 #include "img_types.h"
-#include "ra.h"
 #include "physheap.h"
+#include "pvrsrv_error.h"
 #include "rgx_fwif_km.h"
-#include "pmr.h"
-#include "lock.h"
-#if defined(PVR_DVFS)
+#include "servicesext.h"
+
+#if defined(PVR_DVFS) || defined(SUPPORT_PDVFS)
 #include "pvr_dvfs.h"
 #endif
 
 typedef struct _PVRSRV_DEVICE_CONFIG_ PVRSRV_DEVICE_CONFIG;
 
 /*
- *  The maximum number of physical heaps associated
- *  with a device
+ * All the heaps from which regular device memory allocations can be made in
+ * terms of their locality to the respective device.
  */
 typedef enum
 {
@@ -66,36 +64,52 @@
 	PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL = 1,
 	PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL = 2,
 	PVRSRV_DEVICE_PHYS_HEAP_LAST
-}PVRSRV_DEVICE_PHYS_HEAP;
+} PVRSRV_DEVICE_PHYS_HEAP;
 
 typedef enum
 {
-	PVRSRV_DEVICE_IRQ_ACTIVE_SYSDEFAULT = 0,
-	PVRSRV_DEVICE_IRQ_ACTIVE_LOW,
-	PVRSRV_DEVICE_IRQ_ACTIVE_HIGH
-}PVRSRV_DEVICE_IRQ_ACTIVE_LEVEL;
+	PVRSRV_DEVICE_LOCAL_MEMORY_ARENA_MAPPABLE = 0,
+	PVRSRV_DEVICE_LOCAL_MEMORY_ARENA_NON_MAPPABLE = 1,
+	PVRSRV_DEVICE_LOCAL_MEMORY_ARENA_LAST
+} PVRSRV_DEVICE_LOCAL_MEMORY_ARENA;
 
-typedef void (*PFN_MISR)(void *pvData);
+typedef enum _PVRSRV_DEVICE_SNOOP_MODE_
+{
+	PVRSRV_DEVICE_SNOOP_NONE = 0,
+	PVRSRV_DEVICE_SNOOP_CPU_ONLY,
+	PVRSRV_DEVICE_SNOOP_DEVICE_ONLY,
+	PVRSRV_DEVICE_SNOOP_CROSS,
+} PVRSRV_DEVICE_SNOOP_MODE;
 
-typedef IMG_BOOL (*PFN_LISR)(void *pvData);
+typedef IMG_UINT32
+(*PFN_SYS_DEV_CLK_FREQ_GET)(IMG_HANDLE hSysData);
 
-typedef IMG_UINT32 (*PFN_SYS_DEV_CLK_FREQ_GET)(IMG_HANDLE hSysData);
+typedef PVRSRV_ERROR
+(*PFN_SYS_DEV_PRE_POWER)(IMG_HANDLE hSysData,
+						 PVRSRV_DEV_POWER_STATE eNewPowerState,
+						 PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+						 IMG_BOOL bForced);
 
-typedef PVRSRV_ERROR (*PFN_SYS_DEV_PRE_POWER)(PVRSRV_DEV_POWER_STATE eNewPowerState,
-                                              PVRSRV_DEV_POWER_STATE eCurrentPowerState,
-											  IMG_BOOL bForced);
+typedef PVRSRV_ERROR
+(*PFN_SYS_DEV_POST_POWER)(IMG_HANDLE hSysData,
+						  PVRSRV_DEV_POWER_STATE eNewPowerState,
+						  PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+						  IMG_BOOL bForced);
 
+typedef void
+(*PFN_SYS_DEV_INTERRUPT_HANDLED)(PVRSRV_DEVICE_CONFIG *psDevConfig);
 
-typedef PVRSRV_ERROR (*PFN_SYS_DEV_POST_POWER)(PVRSRV_DEV_POWER_STATE eNewPowerState,
-                                               PVRSRV_DEV_POWER_STATE eCurrentPowerState,
-											   IMG_BOOL bForced);
+typedef PVRSRV_ERROR
+(*PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE)(IMG_HANDLE hSysData,
+									IMG_UINT64 ui64MemSize);
 
-typedef void (*PFN_SYS_DEV_INTERRUPT_HANDLED)(PVRSRV_DEVICE_CONFIG *psDevConfig);
-
-typedef PVRSRV_ERROR (*PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-														 IMG_UINT64 ui64MemSize);
+typedef void (*PFN_SYS_DEV_FEAT_DEP_INIT)(PVRSRV_DEVICE_CONFIG *, IMG_UINT64);
 
 #if defined(SUPPORT_TRUSTED_DEVICE)
+
+#define PVRSRV_DEVICE_FW_CODE_REGION          (0)
+#define PVRSRV_DEVICE_FW_COREMEM_CODE_REGION  (1)
+
 typedef struct _PVRSRV_TD_FW_PARAMS_
 {
 	const void *pvFirmware;
@@ -106,20 +120,30 @@
 	RGXFWIF_DEV_VIRTADDR sFWInitFWAddr;
 } PVRSRV_TD_FW_PARAMS;
 
-typedef PVRSRV_ERROR (*PFN_TD_SEND_FW_IMAGE)(PVRSRV_TD_FW_PARAMS *psTDFWParams);
-
+typedef PVRSRV_ERROR
+(*PFN_TD_SEND_FW_IMAGE)(IMG_HANDLE hSysData,
+						PVRSRV_TD_FW_PARAMS *psTDFWParams);
 
 typedef struct _PVRSRV_TD_POWER_PARAMS_
 {
-	IMG_DEV_PHYADDR sPCAddr;
+	IMG_DEV_PHYADDR sPCAddr; /* META only used param */
+
+	/* MIPS only used fields */
+	IMG_DEV_PHYADDR sGPURegAddr;
+	IMG_DEV_PHYADDR sBootRemapAddr;
+	IMG_DEV_PHYADDR sCodeRemapAddr;
+	IMG_DEV_PHYADDR sDataRemapAddr;
 } PVRSRV_TD_POWER_PARAMS;
 
-typedef PVRSRV_ERROR (*PFN_TD_SET_POWER_PARAMS)(PVRSRV_TD_POWER_PARAMS *psTDPowerParams);
+typedef PVRSRV_ERROR
+(*PFN_TD_SET_POWER_PARAMS)(IMG_HANDLE hSysData,
+						   PVRSRV_TD_POWER_PARAMS *psTDPowerParams);
 
-typedef PVRSRV_ERROR (*PFN_TD_RGXSTART)(void);
+typedef PVRSRV_ERROR
+(*PFN_TD_RGXSTART)(IMG_HANDLE hSysData);
 
-typedef PVRSRV_ERROR (*PFN_TD_RGXSTOP)(void);
-
+typedef PVRSRV_ERROR
+(*PFN_TD_RGXSTOP)(IMG_HANDLE hSysData);
 
 typedef struct _PVRSRV_TD_SECBUF_PARAMS_
 {
@@ -129,125 +153,123 @@
 	IMG_UINT64 *pui64SecBufHandle;
 } PVRSRV_TD_SECBUF_PARAMS;
 
-typedef PVRSRV_ERROR (*PFN_TD_SECUREBUF_ALLOC)(PVRSRV_TD_SECBUF_PARAMS *psTDSecBufParams);
+typedef PVRSRV_ERROR
+(*PFN_TD_SECUREBUF_ALLOC)(IMG_HANDLE hSysData,
+						  PVRSRV_TD_SECBUF_PARAMS *psTDSecBufParams);
 
-typedef PVRSRV_ERROR (*PFN_TD_SECUREBUF_FREE)(IMG_UINT64 ui64SecBufHandle);
-#endif
-
+typedef PVRSRV_ERROR
+(*PFN_TD_SECUREBUF_FREE)(IMG_HANDLE hSysData,
+						 IMG_UINT64 ui64SecBufHandle);
+#endif /* defined(SUPPORT_TRUSTED_DEVICE) */
 
 struct _PVRSRV_DEVICE_CONFIG_
 {
-	/*! Configuration flags */
-	IMG_UINT32			uiFlags;
+	/*! OS device passed to SysDevInit (linux: 'struct device') */
+	void *pvOSDevice;
 
-	/*! Name of the device (used when registering the IRQ) */
-	IMG_CHAR			*pszName;
+	/*!
+	 *! Service representation of pvOSDevice. Should be set to NULL when the
+	 *! config is created in SysDevInit. Set by Services once a device node has
+	 *! been created for this config and unset before SysDevDeInit is called.
+	 */
+	struct _PVRSRV_DEVICE_NODE_ *psDevNode;
 
-	/*! Type of device this is */
-	PVRSRV_DEVICE_TYPE		eDeviceType;
+	/*! Name of the device */
+	IMG_CHAR *pszName;
+
+	/*! Version of the device (optional) */
+	IMG_CHAR *pszVersion;
 
 	/*! Register bank address */
-	IMG_CPU_PHYADDR			sRegsCpuPBase;
+	IMG_CPU_PHYADDR sRegsCpuPBase;
 	/*! Register bank size */
-	IMG_UINT32			ui32RegsSize;
+	IMG_UINT32 ui32RegsSize;
 	/*! Device interrupt number */
-	IMG_UINT32			ui32IRQ;
+	IMG_UINT32 ui32IRQ;
 
-	/*! The device interrupt is shared */
-	IMG_BOOL			bIRQIsShared;
-
-	/*! IRQ polarity */
-	PVRSRV_DEVICE_IRQ_ACTIVE_LEVEL	eIRQActiveLevel;
+	PVRSRV_DEVICE_SNOOP_MODE eCacheSnoopingMode;
 
 	/*! Device specific data handle */
-	IMG_HANDLE			hDevData;
+	IMG_HANDLE hDevData;
 
-	/*! System specific data. This gets passed into system callback functions */
-	IMG_HANDLE			hSysData;
+	/*! System specific data that gets passed into system callback functions. */
+	IMG_HANDLE hSysData;
 
-	/*! ID of the Physical memory heap to use
-	 *! The first entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL])  will be used for allocations
-	 *!  where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL flag is not set. Normally this will be the PhysHeapID
-	 *!  of an LMA heap (but the configuration could specify a UMA heap here, if desired)
-	 *! The second entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]) will be used for allocations
-	 *!  where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL flag is set. Normally this will be the PhysHeapID
-	 *!  of a UMA heap (but the configuration could specify an LMA heap here, if desired)
-	 *! The third entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL]) will be used for allocations
-	 *!  where the PVRSRV_MEMALLOCFLAG_FW_LOCAL flag is set.
-	 *! In the event of there being only one Physical Heap, the configuration should specify the
-	 *!  same heap details in all entries */
-	IMG_UINT32			aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_LAST];
+	IMG_BOOL bHasNonMappableLocalMemory;
 
-	/*! Callback to inform the device we about to change power state */
-	PFN_SYS_DEV_PRE_POWER		pfnPrePowerState;
+	PHYS_HEAP_CONFIG *pasPhysHeaps;
+	IMG_UINT32 ui32PhysHeapCount;
 
-	/*! Callback to inform the device we have finished the power state change */
-	PFN_SYS_DEV_POST_POWER		pfnPostPowerState;
+	/*!
+	 *! ID of the Physical memory heap to use.
+	 *!
+	 *! The first entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL])
+	 *! will be used for allocations where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL
+	 *! flag is not set. Normally this will be the PhysHeapID of an LMA heap
+	 *! but the configuration could specify a UMA heap here (if desired).
+	 *!
+	 *! The second entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL])
+	 *! will be used for allocations where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL
+	 *! flag is set. Normally this will be the PhysHeapID of a UMA heap but
+	 *! the configuration could specify an LMA heap here (if desired).
+	 *!
+	 *! The third entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL])
+	 *! will be used for allocations where the PVRSRV_MEMALLOCFLAG_FW_LOCAL
+	 *! flag is set.
+	 *!
+	 *! In the event of there being only one Physical Heap, the configuration
+	 *! should specify the same heap details in all entries.
+	 */
+	IMG_UINT32 aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_LAST];
 
-	/*! Callback to obtain the clock frequency from the device */
-	PFN_SYS_DEV_CLK_FREQ_GET	pfnClockFreqGet;
+	RGXFWIF_BIFTILINGMODE eBIFTilingMode;
+	IMG_UINT32 *pui32BIFTilingHeapConfigs;
+	IMG_UINT32 ui32BIFTilingHeapCount;
 
-	/*! Callback to inform the device that an interrupt has been handled */
-	PFN_SYS_DEV_INTERRUPT_HANDLED	pfnInterruptHandled;
+	/*!
+	 *! Callbacks to change system device power state at the beginning and end
+	 *! of a power state change (optional).
+	 */
+	PFN_SYS_DEV_PRE_POWER pfnPrePowerState;
+	PFN_SYS_DEV_POST_POWER pfnPostPowerState;
 
-	/*! Callback to handle memory budgeting */
-	PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE	pfnCheckMemAllocSize;
+	/*! Callback to obtain the clock frequency from the device (optional). */
+	PFN_SYS_DEV_CLK_FREQ_GET pfnClockFreqGet;
+
+	/*!
+	 *! Callback to handle memory budgeting. Can be used to reject allocations
+	 *! over a certain size (optional).
+	 */
+	PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE pfnCheckMemAllocSize;
 
 #if defined(SUPPORT_TRUSTED_DEVICE)
-	/*! Callback to send FW image and FW boot time parameters
-	 *! to the trusted device */
-	PFN_TD_SEND_FW_IMAGE     pfnTDSendFWImage;
+	/*!
+	 *! Callback to send FW image and FW boot time parameters to the trusted
+	 *! device.
+	 */
+	PFN_TD_SEND_FW_IMAGE pfnTDSendFWImage;
 
-	/*! Callback to send parameters needed in a power transition
-	 *! to the trusted device */
-	PFN_TD_SET_POWER_PARAMS  pfnTDSetPowerParams;
+	/*!
+	 *! Callback to send parameters needed in a power transition to the trusted
+	 *! device.
+	 */
+	PFN_TD_SET_POWER_PARAMS pfnTDSetPowerParams;
 
 	/*! Callbacks to ping the trusted device to securely run RGXStart/Stop() */
-	PFN_TD_RGXSTART          pfnTDRGXStart;
-	PFN_TD_RGXSTOP           pfnTDRGXStop;
+	PFN_TD_RGXSTART pfnTDRGXStart;
+	PFN_TD_RGXSTOP pfnTDRGXStop;
 
 	/*! Callback to request allocation/freeing of secure buffers */
-	PFN_TD_SECUREBUF_ALLOC   pfnTDSecureBufAlloc;
-	PFN_TD_SECUREBUF_FREE    pfnTDSecureBufFree;
-#endif
+	PFN_TD_SECUREBUF_ALLOC pfnTDSecureBufAlloc;
+	PFN_TD_SECUREBUF_FREE pfnTDSecureBufFree;
+#endif /* defined(SUPPORT_TRUSTED_DEVICE) */
 
-	/*! Current breakpoint data master */
-	RGXFWIF_DM			eBPDM;
-	/*! A Breakpoint has been set */
-	IMG_BOOL			bBPSet;	
+	/*! Function that does device feature specific system layer initialisation */
+	PFN_SYS_DEV_FEAT_DEP_INIT	pfnSysDevFeatureDepInit;
 
-#if defined(PVR_DVFS)
-	PVRSRV_DVFS			sDVFS;
+#if defined(PVR_DVFS) || defined(SUPPORT_PDVFS)
+	PVRSRV_DVFS sDVFS;
 #endif
 };
 
-typedef PVRSRV_ERROR (*PFN_SYSTEM_PRE_POWER_STATE)(PVRSRV_SYS_POWER_STATE eNewPowerState);
-typedef PVRSRV_ERROR (*PFN_SYSTEM_POST_POWER_STATE)(PVRSRV_SYS_POWER_STATE eNewPowerState);
-
-typedef enum _PVRSRV_SYSTEM_SNOOP_MODE_ {
-	PVRSRV_SYSTEM_SNOOP_NONE = 0,
-	PVRSRV_SYSTEM_SNOOP_CPU_ONLY,
-	PVRSRV_SYSTEM_SNOOP_DEVICE_ONLY,
-	PVRSRV_SYSTEM_SNOOP_CROSS,
-} PVRSRV_SYSTEM_SNOOP_MODE;
-
-typedef struct _PVRSRV_SYSTEM_CONFIG_
-{
-	IMG_UINT32				uiSysFlags;
-	IMG_CHAR				*pszSystemName;
-	IMG_UINT32				uiDeviceCount;
-	PVRSRV_DEVICE_CONFIG	*pasDevices;
-	PFN_SYSTEM_PRE_POWER_STATE pfnSysPrePowerState;
-	PFN_SYSTEM_POST_POWER_STATE pfnSysPostPowerState;
-	PVRSRV_SYSTEM_SNOOP_MODE eCacheSnoopingMode;
-
-	PHYS_HEAP_CONFIG		*pasPhysHeaps;
-	IMG_UINT32				ui32PhysHeapCount;
-	IMG_UINT64				ui64DevMemPhysOffset;
-
-	IMG_UINT32              *pui32BIFTilingHeapConfigs;
-	IMG_UINT32              ui32BIFTilingHeapCount;
-} PVRSRV_SYSTEM_CONFIG;
-
-
 #endif /* __PVRSRV_DEVICE_H__*/
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_device_types.h b/drivers/staging/imgtec/rogue/pvrsrv_device_types.h
index de54d87..0439c34 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_device_types.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_device_types.h
@@ -47,63 +47,7 @@
 
 #define PVRSRV_MAX_DEVICES		16	/*!< Largest supported number of devices on the system */
 
-/*!
- ******************************************************************************
- * List of known device types.
- *****************************************************************************/
-typedef enum PVRSRV_DEVICE_TYPE
-{
-	PVRSRV_DEVICE_TYPE_UNKNOWN			= 0,  /*!< Unknown device type */
-	PVRSRV_DEVICE_TYPE_MBX1				= 1,  /*!< MBX1 */
-	PVRSRV_DEVICE_TYPE_MBX1_LITE		= 2,  /*!< MBX1 Lite */
-	PVRSRV_DEVICE_TYPE_M24VA			= 3,  /*!< M24VA */
-	PVRSRV_DEVICE_TYPE_MVDA2			= 4,  /*!< MVDA2 */
-	PVRSRV_DEVICE_TYPE_MVED1			= 5,  /*!< MVED1 */
-	PVRSRV_DEVICE_TYPE_MSVDX			= 6,  /*!< MSVDX */
-	PVRSRV_DEVICE_TYPE_SGX				= 7,  /*!< SGX */
-	PVRSRV_DEVICE_TYPE_VGX				= 8,  /*!< VGX */
-	PVRSRV_DEVICE_TYPE_EXT				= 9,  /*!< 3rd party devices take ext type */
-	PVRSRV_DEVICE_TYPE_RGX				= 10, /*!< RGX */
-
-    PVRSRV_DEVICE_TYPE_LAST             = 10, /*!< Last device type */
-
-	PVRSRV_DEVICE_TYPE_FORCE_I32		= 0x7fffffff /*!< Force enum to be 32-bit width */
-
-} PVRSRV_DEVICE_TYPE;
-
-
-/*!
- *****************************************************************************
- * List of known device classes.
- *****************************************************************************/
-typedef enum _PVRSRV_DEVICE_CLASS_
-{
-	PVRSRV_DEVICE_CLASS_3D				= 0 ,       /*!< 3D Device Class */
-	PVRSRV_DEVICE_CLASS_DISPLAY			= 1 ,       /*!< Display Device Class */
-	PVRSRV_DEVICE_CLASS_BUFFER			= 2 ,       /*!< Buffer Class */
-	PVRSRV_DEVICE_CLASS_VIDEO			= 3 ,       /*!< Video Device Class */
-
-	PVRSRV_DEVICE_CLASS_FORCE_I32 		= 0x7fffffff /* Force enum to be at least 32-bits wide */
-
-} PVRSRV_DEVICE_CLASS;
-
-
-/*!
- ******************************************************************************
- * Device identifier structure
- *****************************************************************************/
-typedef struct _PVRSRV_DEVICE_IDENTIFIER_
-{
-	PVRSRV_DEVICE_TYPE		eDeviceType;		/*!< Identifies the type of the device */
-	PVRSRV_DEVICE_CLASS		eDeviceClass;		/*!< Identifies more general class of device - display/3d/mpeg etc */
-	IMG_UINT32				ui32DeviceIndex;	/*!< Index of the device within the system */
-	IMG_CHAR				*pszPDumpDevName;	/*!< Pdump memory bank name */
-	IMG_CHAR				*pszPDumpRegName;	/*!< Pdump register bank name */
-
-} PVRSRV_DEVICE_IDENTIFIER;
-
-
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
 #include <services_kernel_client.h>
 #endif
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_devmem.h b/drivers/staging/imgtec/rogue/pvrsrv_devmem.h
index 0060179..b118855 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_devmem.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_devmem.h
@@ -55,7 +55,7 @@
 #include "pdumpdefs.h"
 #include "pvrsrv_error.h"
 #include "pvrsrv_memallocflags.h"
-#include "sync_external.h"
+#include <powervr/sync_external.h>
 #include "services_km.h" /* for PVRSRV_DEV_CONNECTION */
 
 
@@ -112,9 +112,8 @@
      
                 In order to derive the details of the MMU configuration for the
                 device, and for retrieving the "bridge handle" for communication
-                internally in services, is is necessary to pass in the
-                PVRSRV_DEV_DATA object as populated with a prior call to
-                PVRSRVAcquireDeviceData()
+                internally in services, it is necessary to pass in a
+                PVRSRV_DEV_CONNECTION.
 @Input          psDev           dev data
 @Output         phCtxOut        On success, the returned DevMem Context. The
                                 caller is responsible for providing storage
@@ -218,7 +217,7 @@
                         IMG_DEVMEM_SIZE_T uiSize,
                         IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
                         PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags,
-                        IMG_PCHAR pszText,
+                        const IMG_CHAR *pszText,
                         PVRSRV_MEMDESC *phMemDescOut);
 
 #define PVRSRVAllocDeviceMem(...) \
@@ -374,14 +373,17 @@
 
 @Output         puiSizePtr              Size of the created MemDesc
 
-@Return         PVRSRV_OK is succesful
+@Input          pszAnnotation           Annotation string for this allocation/import
+
+@Return         PVRSRV_OK is successful
 */
 /*****************************************************************************/
 PVRSRV_ERROR PVRSRVDevmemLocalImport(const PVRSRV_DEV_CONNECTION *psDevConnection,
 									 IMG_HANDLE hExtHandle,
 									 PVRSRV_MEMMAP_FLAGS_T uiFlags,
 									 PVRSRV_MEMDESC *phMemDescPtr,
-									 IMG_DEVMEM_SIZE_T *puiSizePtr);
+									 IMG_DEVMEM_SIZE_T *puiSizePtr,
+									 const IMG_CHAR *pszAnnotation);
 
 /*************************************************************************/ /*!
 @Function       PVRSRVDevmemGetImportUID
@@ -394,7 +396,7 @@
 */
 /*****************************************************************************/
 PVRSRV_ERROR PVRSRVDevmemGetImportUID(PVRSRV_MEMDESC hMemDesc,
-									  IMG_UINT64 *pui64UID);
+                                      IMG_UINT64 *pui64UID);
 
 /**************************************************************************/ /*!
 @Function       PVRSRVAllocExportableDevMem
@@ -410,57 +412,60 @@
 
                 Size must be a positive integer multiple of the page size
 @Input          uiLog2Align         Log2 of the alignment required
+@Input          uiLog2HeapPageSize  The page size to allocate. Must be a
+                                    multiple of the heap that this is going
+                                    to be mapped into.
 @Input          uiSize              the amount of memory to be allocated
 @Input          uiFlags             Allocation flags
-@Input          pszText     		Text to describe the allocation
+@Input          pszText             Text to describe the allocation
 @Output         hMemDesc
 @Return         PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
 */ /***************************************************************************/
 PVRSRV_ERROR
 PVRSRVAllocExportableDevMem(const PVRSRV_DEV_CONNECTION *psDevConnection,
-							IMG_DEVMEM_SIZE_T uiSize,
-							IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
-							PVRSRV_MEMALLOCFLAGS_T uiFlags,
-							IMG_PCHAR pszText,
-							PVRSRV_MEMDESC *hMemDesc);
+                            IMG_DEVMEM_SIZE_T uiSize,
+                            IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
+                            IMG_UINT32 uiLog2HeapPageSize,
+                            PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                            const IMG_CHAR *pszText,
+                            PVRSRV_MEMDESC *hMemDesc);
 
 /**************************************************************************/ /*!
 @Function       PVRSRVChangeSparseDevMem
-@Description	This function alters the underlying memory layout of the given
-				allocation by allocating/removing pages as requested
-				This function also re-writes the GPU & CPU Maps accordingly
-				The specific actions can be controlled by corresponding flags
-@Input			psMemDesc 			The memory layout that needs to be modified
-@Input			ui32AllocPageCount	New page allocation count
-@Input			pai32AllocIndices   New page allocation indices (page granularity)
-@Input			ui32FreePageCount   Number of pages that need to be freed
-@Input			pai32FreeIndices	Indices of the pages that need to be freed
-@Input			uiFlags				Flags that control the behaviour of the call
-@Output			pui32Status			Status out for minor tolerable errors
+@Description    This function alters the underlying memory layout of the given
+                allocation by allocating/removing pages as requested
+                This function also re-writes the GPU & CPU Maps accordingly
+                The specific actions can be controlled by corresponding flags
+
+@Input          psMemDesc           The memory layout that needs to be modified
+@Input          ui32AllocPageCount	New page allocation count
+@Input          pai32AllocIndices   New page allocation indices (page granularity)
+@Input          ui32FreePageCount   Number of pages that need to be freed
+@Input          pai32FreeIndices    Indices of the pages that need to be freed
+@Input          uiFlags             Flags that control the behaviour of the call
 @Return         PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
 */ /***************************************************************************/
 PVRSRV_ERROR
 PVRSRVChangeSparseDevMem(PVRSRV_MEMDESC psMemDesc,
-					IMG_UINT32 ui32AllocPageCount,
-					IMG_UINT32 *pai32AllocIndices,
-					IMG_UINT32 ui32FreePageCount,
-					IMG_UINT32 *pai32FreeIndices,
-					SPARSE_MEM_RESIZE_FLAGS uiFlags,
-					IMG_UINT32 *pui32Status);
+                         IMG_UINT32 ui32AllocPageCount,
+                         IMG_UINT32 *pai32AllocIndices,
+                         IMG_UINT32 ui32FreePageCount,
+                         IMG_UINT32 *pai32FreeIndices,
+                         SPARSE_MEM_RESIZE_FLAGS uiFlags);
 
 /**************************************************************************/ /*!
 @Function       PVRSRVAllocSparseDevMem2
 @Description    Allocate sparse memory without mapping into device memory context.
-				Sparse memory is used where you have an allocation that has a
-				logical size (i.e. the amount of VM space it will need when
-				mapping it into a device) that is larger than the amount of
-				physical memory that allocation will use. An example of this
-				is a NPOT texture where the twiddling algorithm requires you
-				to round the width and height to next POT and so you know there
-				will be pages that are never accessed.
+                Sparse memory is used where you have an allocation that has a
+                logical size (i.e. the amount of VM space it will need when
+                mapping it into a device) that is larger than the amount of
+                physical memory that allocation will use. An example of this
+                is a NPOT texture where the twiddling algorithm requires you
+                to round the width and height to next POT and so you know there
+                will be pages that are never accessed.
 
-				This memory is can to be exported and mapped into the device
-				memory context of other processes, or to CPU.
+                This memory is can to be exported and mapped into the device
+                memory context of other processes, or to CPU.
 
                 Size must be a positive integer multiple of the page size
 @Input          psDevConnection     Device to allocation the memory for
@@ -468,38 +473,40 @@
 @Input          uiChunkSize         The size of the chunk
 @Input          ui32NumPhysChunks   The number of physical chunks required
 @Input          ui32NumVirtChunks   The number of virtual chunks required
-@Input			pui32MappingTable	index based Mapping table
+@Input          pui32MappingTable	index based Mapping table
 @Input          uiLog2Align         Log2 of the required alignment
+@Input          uiLog2HeapPageSize  Log2 of the heap we map this into
 @Input          uiFlags             Allocation flags
-@Input          pszText     		Text to describe the allocation
+@Input          pszText             Text to describe the allocation
 @Output         hMemDesc
 @Return         PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
 */ /***************************************************************************/
 PVRSRV_ERROR
 PVRSRVAllocSparseDevMem2(const PVRSRV_DEVMEMCTX psDevMemCtx,
-						IMG_DEVMEM_SIZE_T uiSize,
-						IMG_DEVMEM_SIZE_T uiChunkSize,
-						IMG_UINT32 ui32NumPhysChunks,
-						IMG_UINT32 ui32NumVirtChunks,
-						IMG_UINT32 *pui32MappingTable,
-						IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
-						PVRSRV_MEMMAP_FLAGS_T uiFlags,
-						IMG_PCHAR pszText,
-						PVRSRV_MEMDESC *hMemDesc);
+                         IMG_DEVMEM_SIZE_T uiSize,
+                         IMG_DEVMEM_SIZE_T uiChunkSize,
+                         IMG_UINT32 ui32NumPhysChunks,
+                         IMG_UINT32 ui32NumVirtChunks,
+                         IMG_UINT32 *pui32MappingTable,
+                         IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
+                         IMG_UINT32 uiLog2HeapPageSize,
+                         PVRSRV_MEMMAP_FLAGS_T uiFlags,
+                         const IMG_CHAR *pszText,
+                         PVRSRV_MEMDESC *hMemDesc);
 
 /**************************************************************************/ /*!
 @Function       PVRSRVAllocSparseDevMem (DEPRECATED and will be removed in future)
 @Description    Allocate sparse memory without mapping into device memory context.
-				Sparse memory is used where you have an allocation that has a
-				logical size (i.e. the amount of VM space it will need when
-				mapping it into a device) that is larger than the amount of
-				physical memory that allocation will use. An example of this
-				is a NPOT texture where the twiddling algorithm requires you
-				to round the width and height to next POT and so you know there
-				will be pages that are never accessed.
+                Sparse memory is used where you have an allocation that has a
+                logical size (i.e. the amount of VM space it will need when
+                mapping it into a device) that is larger than the amount of
+                physical memory that allocation will use. An example of this
+                is a NPOT texture where the twiddling algorithm requires you
+                to round the width and height to next POT and so you know there
+                will be pages that are never accessed.
 
-				This memory is can to be exported and mapped into the device
-				memory context of other processes, or to CPU.
+                This memory is can to be exported and mapped into the device
+                memory context of other processes, or to CPU.
 
                 Size must be a positive integer multiple of the page size
                 This function is deprecated and should not be used in any new code
@@ -509,36 +516,37 @@
 @Input          uiChunkSize         The size of the chunk
 @Input          ui32NumPhysChunks   The number of physical chunks required
 @Input          ui32NumVirtChunks   The number of virtual chunks required
-@Input			pabMappingTable		boolean based Mapping table
+@Input          pabMappingTable     boolean based Mapping table
 @Input          uiLog2Align         Log2 of the required alignment
+@Input          uiLog2HeapPageSize  Log2 of the heap we map this into
 @Input          uiFlags             Allocation flags
-@Input          pszText     		Text to describe the allocation
+@Input          pszText             Text to describe the allocation
 @Output         hMemDesc
 @Return         PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
 */ /***************************************************************************/
 PVRSRV_ERROR
 PVRSRVAllocSparseDevMem(const PVRSRV_DEVMEMCTX psDevMemCtx,
-						IMG_DEVMEM_SIZE_T uiSize,
-						IMG_DEVMEM_SIZE_T uiChunkSize,
-						IMG_UINT32 ui32NumPhysChunks,
-						IMG_UINT32 ui32NumVirtChunks,
-						IMG_BOOL *pabMappingTable,
-						IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
-						DEVMEM_FLAGS_T uiFlags,
-						IMG_PCHAR pszText,
-						PVRSRV_MEMDESC *hMemDesc);
+                        IMG_DEVMEM_SIZE_T uiSize,
+                        IMG_DEVMEM_SIZE_T uiChunkSize,
+                        IMG_UINT32 ui32NumPhysChunks,
+                        IMG_UINT32 ui32NumVirtChunks,
+                        IMG_BOOL *pabMappingTable,
+                        IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
+                        IMG_UINT32 uiLog2HeapPageSize,
+                        DEVMEM_FLAGS_T uiFlags,
+                        const IMG_CHAR *pszText,
+                        PVRSRV_MEMDESC *hMemDesc);
 
 /**************************************************************************/ /*!
-@Function       PVRSRVGetLog2PageSize
+@Function       PVRSRVGetOSLog2PageSize
 @Description    Just call AFTER setting up the connection to the kernel module
                 otherwise it will run into an assert.
-                Gives the log2 of the page size that is currently utilised by
-                devmem.
+                Gives the log2 of the page size that is utilised by the OS.
 
 @Return         The page size
 */ /***************************************************************************/
 
-IMG_UINT32 PVRSRVGetLog2PageSize(void);
+IMG_UINT32 PVRSRVGetOSLog2PageSize(void);
 
 /**************************************************************************/ /*!
 @Function       PVRSRVGetHeapLog2PageSize
@@ -553,18 +561,23 @@
 PVRSRVGetHeapLog2PageSize(PVRSRV_HEAP hHeap, IMG_UINT32* puiLog2PageSize);
 
 /**************************************************************************/ /*!
-@Function       PVRSRVGetHeapLog2ImportAlignment
-@Description    Queries the import alignment of a passed heap.
+@Function       PVRSRVGetHeapTilingProperties
+@Description    Queries the import alignment and tiling stride conversion
+                factor of a passed heap.
 
-@Input          hHeap                   Heap that is queried
-@Output         puiLog2ImportAlignment  Log2 import alignment will be
-                                        returned in this
+@Input          hHeap                      Heap that is queried
+@Output         puiLog2ImportAlignment     Log2 import alignment will be
+                                           returned in this
+@Output         puiLog2TilingStrideFactor  Log2 alignment to tiling stride
+                                           conversion factor will be returned
+                                           in this
 
 @Return         PVRSRV_OK on success. Otherwise, a PVRSRV error code
 */ /***************************************************************************/
 PVRSRV_ERROR
-PVRSRVGetHeapLog2ImportAlignment(PVRSRV_HEAP hHeap,
-                                 IMG_UINT32* puiLog2ImportAlignment);
+PVRSRVGetHeapTilingProperties(PVRSRV_HEAP hHeap,
+                              IMG_UINT32* puiLog2ImportAlignment,
+                              IMG_UINT32* puiLog2TilingStrideFactor);
 
 /**************************************************************************/ /*!
 @Function PVRSRVMakeLocalImportHandle
@@ -750,9 +763,6 @@
 
 @Return         PVRSRV_ERROR:   PVRSRV_OK on success.
 
-                                PVRSRV_ERROR_NOT_SUPPORTED if the PMR
-                                factory does not allow unpinning.
-
                                 PVRSRV_ERROR_INVALID_PARAMS if the passed
                                 allocation is not a multiple of the heap page
                                 size but was allocated with
@@ -771,6 +781,19 @@
 
 
 /**************************************************************************/ /*!
+@Function       PVRSRVDevmemGetSize
+@Description    Returns the allocated size for this device-memory.
+
+@Input          hMemDesc handle to memory allocation
+@Output         puiSize return value for size
+@Return         PVRSRV_OK on success or
+                PVRSRV_ERROR_INVALID_PARAMS
+*/ /***************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVDevmemGetSize(PVRSRV_MEMDESC hMemDesc, IMG_DEVMEM_SIZE_T* puiSize);
+
+
+/**************************************************************************/ /*!
 @Function       PVRSRVExportDevMemContext
 @Description    Makes the given memory context available to other processes that
                 can get a handle to it via PVRSRVAcquireRemoteDevmemContext.
@@ -843,6 +866,26 @@
 extern void
 PVRSRVReleaseRemoteDevMemContext(PVRSRV_REMOTE_DEVMEMCTX hRemoteCtx);
 
+/*************************************************************************/ /*!
+@Function       PVRSRVRegisterDevmemPageFaultNotify
+@Description    Registers to be notified when a page fault occurs on a
+                specific device memory context.
+@Input          psDevmemCtx     The context to be notified about.
+@Return         PVRSRV_ERROR.
+*/ /**************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVRegisterDevmemPageFaultNotify(PVRSRV_DEVMEMCTX psDevmemCtx);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVUnregisterDevmemPageFaultNotify
+@Description    Unegisters to be notified when a page fault occurs on a
+                specific device memory context.
+@Input          psDevmemCtx     The context to be unregistered from.
+@Return         PVRSRV_ERROR.
+*/ /**************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVUnregisterDevmemPageFaultNotify(PVRSRV_DEVMEMCTX psDevmemCtx);
+
 #if defined __cplusplus
 };
 #endif
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_errors.h b/drivers/staging/imgtec/rogue/pvrsrv_errors.h
index b00f28d..09dd43a 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_errors.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_errors.h
@@ -128,6 +128,7 @@
 PVRE(PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED)
 PVRE(PVRSRV_ERROR_DEVICEMEM_NO_MAPPING)
 PVRE(PVRSRV_ERROR_DEVICEMEM_INVALID_PMR_FLAGS)
+PVRE(PVRSRV_ERROR_DEVICEMEM_INVALID_LMA_HEAP)
 PVRE(PVRSRV_ERROR_INVALID_MMU_TYPE)
 PVRE(PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND)
 PVRE(PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT)
@@ -226,6 +227,7 @@
 PVRE(PVRSRV_ERROR_INIT2_PHASE_FAILED)
 PVRE(PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE)
 PVRE(PVRSRV_ERROR_NO_DC_DEVICES_FOUND)
+PVRE(PVRSRV_ERROR_DC_DEVICE_INACCESSIBLE)
 PVRE(PVRSRV_ERROR_DC_INVALID_MAXDEPTH)
 PVRE(PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE)
 PVRE(PVRSRV_ERROR_UNABLE_TO_UNREGISTER_DEVICE)
@@ -251,6 +253,9 @@
 PVRE(PVRSRV_ERROR_HANDLE_BATCH_IN_USE)
 PVRE(PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE)
 PVRE(PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_RETRIEVE_HASH_VALUE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_REMOVE_HASH_VALUE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_INSERT_HASH_VALUE)
 PVRE(PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED)
 PVRE(PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE)
 PVRE(PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP)
@@ -321,8 +326,8 @@
 PVRE(PVRSRV_ERROR_INVALID_PB_CONFIG)
 PVRE(PVRSRV_ERROR_META_THREAD0_NOT_ENABLED)
 PVRE(PVRSRV_ERROR_NOT_AUTHENTICATED)
-PVRE(PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL)
-PVRE(PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_REQUEST_TDFWCODE_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_INIT_TDFWCODE_PAGES_FAIL)
 PVRE(PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL)
 PVRE(PVRSRV_ERROR_INIT_TDSECUREBUF_PAGES_FAIL)
 PVRE(PVRSRV_ERROR_MUTEX_ALREADY_CREATED)
@@ -339,8 +344,32 @@
 PVRE(PVRSRV_ERROR_SYSTEM_LOCAL_MEMORY_INIT_FAIL)
 PVRE(PVRSRV_ERROR_FW_IMAGE_MISMATCH)
 PVRE(PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
-PVRE(PVRSRV_ERROR_BUFFER_TOO_SMALL)
+PVRE(PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL)
+PVRE(PVRSRV_ERROR_RPM_PBSIZE_ALREADY_MAX)
+PVRE(PVRSRV_ERROR_NONZERO_REFCOUNT)
 PVRE(PVRSRV_ERROR_SETAFFINITY_FAILED)
 PVRE(PVRSRV_ERROR_INTERNAL_ERROR)
+PVRE(PVRSRV_ERROR_BRIDGE_EFAULT)
+PVRE(PVRSRV_ERROR_BRIDGE_EINVAL)
+PVRE(PVRSRV_ERROR_BRIDGE_ENOMEM)
+PVRE(PVRSRV_ERROR_BRIDGE_ERANGE)
+PVRE(PVRSRV_ERROR_BRIDGE_EPERM)
+PVRE(PVRSRV_ERROR_BRIDGE_ENOTTY)
+PVRE(PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED)
 PVRE(PVRSRV_ERROR_PROBE_DEFER)
+PVRE(PVRSRV_ERROR_INVALID_ALIGNMENT)
+PVRE(PVRSRV_ERROR_CLOSE_FAILED)
 PVRE(PVRSRV_ERROR_NOT_INITIALISED)
+PVRE(PVRSRV_ERROR_CONVERSION_FAILED)
+PVRE(PVRSRV_ERROR_RA_REQUEST_ALLOC_FAIL)
+PVRE(PVRSRV_ERROR_RA_INSERT_RESOURCE_SPAN_FAILED)
+PVRE(PVRSRV_ERROR_RA_ATTEMPT_ALLOC_ALIGNED_FAILED)
+PVRE(PVRSRV_ERROR_OBJECT_STILL_REFERENCED)
+PVRE(PVRSRV_ERROR_BVNC_UNSUPPORTED)
+PVRE(PVRSRV_ERROR_INVALID_BVNC_PARAMS)
+PVRE(PVRSRV_ERROR_ALIGNMENT_ARRAY_NOT_AVAILABLE)
+PVRE(PVRSRV_ERROR_DEVICEMEM_ADDITIONAL_HEAPS_IN_CONTEXT)
+PVRE(PVRSRV_ERROR_PID_ALREADY_REGISTERED)
+PVRE(PVRSRV_ERROR_PID_NOT_REGISTERED)
+PVRE(PVRSRV_ERROR_SIGNAL_FAILED)
+
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_memallocflags.h b/drivers/staging/imgtec/rogue/pvrsrv_memallocflags.h
index 684ab09..abff6d9 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_memallocflags.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_memallocflags.h
@@ -54,14 +54,34 @@
 #endif
 typedef IMG_UINT32 PVRSRV_MEMALLOCFLAGS_T;
 
+/*
+ * --- MAPPING FLAGS ---
+ * | 0-3    | 4-7    | 8-10        | 11-13       | 14          |
+ * | GPU-RW | CPU-RW | GPU-Caching | CPU-Caching | KM-Mappable |
+ *
+ * --- MISC FLAGS ---
+ * | 15    | 16        | 17       | 18  | 19                | 20              |
+ * | Defer | CPU-Local | FW-Local | SVM | Sparse-Dummy-Page | CPU-Cache-Clean |
+ *
+ * --- DEV CONTROL FLAGS ---
+ * | 24-27        |
+ * | Device-Flags |
+ *
+ * --- MEMSET FLAGS ---
+ * | 29             | 30          | 31            |
+ * | Poison-On-Free | P.-On-Alloc | Zero-On-Alloc |
+ *
+ */
+
 /*!
  *  **********************************************************
  *  *                                                        *
  *  *                       MAPPING FLAGS                    *
  *  *                                                        *
  *  **********************************************************
- *
- * PVRSRV_MEMALLOCFLAG_GPU_READABLE
+ */
+
+/*! PVRSRV_MEMALLOCFLAG_GPU_READABLE
  *
  * This flag affects the device MMU protection flags, and specifies
  * that the memory may be read by the GPU (is this always true?)
@@ -90,10 +110,9 @@
  * and (b) when we separate the creation of the PMR from the mapping.
  */
 #define PVRSRV_MEMALLOCFLAG_GPU_READABLE 		(1U<<0)
-#define PVRSRV_CHECK_GPU_READABLE(uiFlags) 		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_READABLE) != 0)
+#define PVRSRV_CHECK_GPU_READABLE(uiFlags) 		(((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_READABLE) != 0)
 
-/*!
- * PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE
+/*! PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE
  *
  * This flag affects the device MMU protection flags, and specifies
  * that the memory may be written by the GPU
@@ -108,33 +127,33 @@
  *
  * This is a dual purpose flag.  It specifies that memory is permitted
  * to be written by the GPU, and also requests that the allocation is
- * mapped into the GPU as a writeable mapping (see note above about
+ * mapped into the GPU as a writable mapping (see note above about
  * permission vs. mapping mode, and why this flag causes permissions
  * to be inferred from mapping mode on first allocation)
  *
  * N.B.  This flag has no relevance to the CPU's MMU mapping, if any,
  * and would therefore not enforce read-only mapping on CPU.
  */
-#define PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE       (1U<<1) /*!< mapped as writeable to the GPU */
-#define PVRSRV_CHECK_GPU_WRITEABLE(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE) != 0)
+#define PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE       (1U<<1) /*!< mapped as writable to the GPU */
+#define PVRSRV_CHECK_GPU_WRITEABLE(uiFlags)				(((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE) != 0)
 
 #define PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED  (1U<<2) /*!< can be mapped is GPU readable in another GPU mem context */
-#define PVRSRV_CHECK_GPU_READ_PERMITTED(uiFlags) 		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED) != 0)
+#define PVRSRV_CHECK_GPU_READ_PERMITTED(uiFlags) 		(((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED) != 0)
 
 #define PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED (1U<<3) /*!< can be mapped is GPU writable in another GPU mem context */
-#define PVRSRV_CHECK_GPU_WRITE_PERMITTED(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED) != 0)
+#define PVRSRV_CHECK_GPU_WRITE_PERMITTED(uiFlags)		(((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED) != 0)
 
 #define PVRSRV_MEMALLOCFLAG_CPU_READABLE        (1U<<4) /*!< mapped as readable to the CPU */
-#define PVRSRV_CHECK_CPU_READABLE(uiFlags) 				((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_READABLE) != 0)
+#define PVRSRV_CHECK_CPU_READABLE(uiFlags) 				(((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_READABLE) != 0)
 
-#define PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE       (1U<<5) /*!< mapped as writeable to the CPU */
-#define PVRSRV_CHECK_CPU_WRITEABLE(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE) != 0)
+#define PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE       (1U<<5) /*!< mapped as writable to the CPU */
+#define PVRSRV_CHECK_CPU_WRITEABLE(uiFlags)				(((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE) != 0)
 
 #define PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED  (1U<<6) /*!< can be mapped is CPU readable in another CPU mem context */
-#define PVRSRV_CHECK_CPU_READ_PERMITTED(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED) != 0)
+#define PVRSRV_CHECK_CPU_READ_PERMITTED(uiFlags)		(((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED) != 0)
 
 #define PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED (1U<<7) /*!< can be mapped is CPU writable in another CPU mem context */
-#define PVRSRV_CHECK_CPU_WRITE_PERMITTED(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED) != 0)
+#define PVRSRV_CHECK_CPU_WRITE_PERMITTED(uiFlags)		(((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED) != 0)
 
 
 /*
@@ -157,35 +176,36 @@
 	needs to be determined.
 */
 
-/*!
+/*! PVRSRV_MEMALLOCFLAG_GPU_UNCACHED
+
    GPU domain. Request uncached memory. This means that any writes to memory
   allocated with this flag are written straight to memory and thus are coherent
   for any device in the system.
 */
 #define PVRSRV_MEMALLOCFLAG_GPU_UNCACHED         		(0U<<8)
-#define PVRSRV_CHECK_GPU_UNCACHED(uiFlags)		 		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_UNCACHED) != 0)
+#define PVRSRV_CHECK_GPU_UNCACHED(uiFlags)		 		(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_UNCACHED)
 
-/*!
-   GPU domain. Use write combiner (if supported) to combine sequential writes 
+/*! PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE
+
+   GPU domain. Use write combiner (if supported) to combine sequential writes
    together to reduce memory access by doing burst writes.
 */
 #define PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE    		(1U<<8)
-#define PVRSRV_CHECK_GPU_WRITE_COMBINE(uiFlags)	 		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE) != 0)
+#define PVRSRV_CHECK_GPU_WRITE_COMBINE(uiFlags)	 		(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE)
 
-/*!
-    GPU domain. This flag affects the device MMU protection flags.
- 
-    This flag ensures that the GPU and the CPU will always be coherent.
-    This is done by either by snooping each others caches or, if this is
-    not supported, by making the allocation uncached. Please note that
-    this will _not_ guaranty coherency with memory so if this memory
-    is accessed by another device (eg display controller) a flush will
-    be required.
+/*! PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT
+
+    GPU domain. This flag affects the GPU MMU protection flags.
+    The allocation will be cached.
+    Services will try to set the coherent bit in the GPU MMU tables so the
+    GPU cache is snooping the CPU cache. If coherency is not supported the
+    caller is responsible to ensure the caches are up to date.
 */
 #define PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT   		(2U<<8)
-#define PVRSRV_CHECK_GPU_CACHE_COHERENT(uiFlags) 		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT) != 0)
+#define PVRSRV_CHECK_GPU_CACHE_COHERENT(uiFlags) 		(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT)
 
-/*!
+/*! PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT
+
    GPU domain. Request cached memory, but not coherent (i.e. no cache snooping).
    This means that if the allocation needs to transition from one device
    to another services has to be informed so it can flush/invalidate the 
@@ -195,36 +215,23 @@
     expansion.
 */
 #define PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT 		(3U<<8)
-#define PVRSRV_CHECK_GPU_CACHE_INCOHERENT(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT) != 0)
+#define PVRSRV_CHECK_GPU_CACHE_INCOHERENT(uiFlags)		(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT)
 
-/*!
-    GPU domain.
- 
-	Request cached cached coherent memory. This is like 
-	PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT but doesn't fall back on
-	uncached memory if the system doesn't support cache-snooping
-	but rather returns an error.
-*/
-#define PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT   (4U<<8)
-#define PVRSRV_CHECK_GPU_CACHED_CACHE_COHERENT(uiFlags)	((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT) != 0)
+/*! PVRSRV_MEMALLOCFLAG_GPU_CACHED
 
-/*!
-	GPU domain.
-
-	This flag is for internal use only and is used to indicate
-	that the underlying allocation should be cached on the GPU
-	after all the snooping and coherent checks have been done
+    GPU domain. This flag is for internal use only and is used to indicate
+    that the underlying allocation should be cached on the GPU
+    after all the snooping and coherent checks have been done
 */
 #define PVRSRV_MEMALLOCFLAG_GPU_CACHED					(7U<<8)
-#define PVRSRV_CHECK_GPU_CACHED(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHED) != 0)
+#define PVRSRV_CHECK_GPU_CACHED(uiFlags)				(PVRSRV_GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHED)
 
-/*!
-	GPU domain.
-	
-	GPU cache mode mask
+/*! PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK
+
+    GPU domain. GPU cache mode mask
 */
 #define PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK  		(7U<<8)
-#define PVRSRV_GPU_CACHE_MODE(uiFlags)					(uiFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK)
+#define PVRSRV_GPU_CACHE_MODE(uiFlags)					((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK)
 
 
 /*
@@ -233,93 +240,100 @@
 
 	The following defines are used to control the CPU cache bit field.
 	The defines are mutually exclusive.
-	
+
 	A helper macro, PVRSRV_CPU_CACHE_MODE, is provided to obtain just the CPU cache
 	bit field from the flags. This should be used whenever the CPU cache mode
 	needs to be determined.
 */
 
-/*!
+/*! PVRSRV_MEMALLOCFLAG_CPU_UNCACHED
+
    CPU domain. Request uncached memory. This means that any writes to memory
-  allocated with this flag are written straight to memory and thus are coherent
-  for any device in the system.
+    allocated with this flag are written straight to memory and thus are coherent
+    for any device in the system.
 */
 #define PVRSRV_MEMALLOCFLAG_CPU_UNCACHED         		(0U<<11)
-#define PVRSRV_CHECK_CPU_UNCACHED(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_UNCACHED) != 0)
+#define PVRSRV_CHECK_CPU_UNCACHED(uiFlags)				(PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_UNCACHED)
 
-/*!
-   CPU domain. Use write combiner (if supported) to combine sequential writes 
+/*! PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE
+
+   CPU domain. Use write combiner (if supported) to combine sequential writes
    together to reduce memory access by doing burst writes.
 */
 #define PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE 		   	(1U<<11)
-#define PVRSRV_CHECK_CPU_WRITE_COMBINE(uiFlags)			((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE) != 0)
+#define PVRSRV_CHECK_CPU_WRITE_COMBINE(uiFlags)			(PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE)
 
-/*!
-    CPU domain. This flag affects the device MMU protection flags.
- 
-    This flag ensures that the GPU and the CPU will always be coherent.
-    This is done by either by snooping each others caches or, if this is
-    not supported, by making the allocation uncached. Please note that
-    this will _not_ guaranty coherency with memory so if this memory
-    is accessed by another device (eg display controller) a flush will
-    be required.
+/*! PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT
+
+    CPU domain. This flag affects the CPU MMU protection flags.
+    The allocation will be cached.
+    Services will try to set the coherent bit in the CPU MMU tables so the
+    CPU cache is snooping the GPU cache. If coherency is not supported the
+    caller is responsible to ensure the caches are up to date.
 */
 #define PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT   		(2U<<11)
-#define PVRSRV_CHECK_CPU_CACHE_COHERENT(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) != 0)
+#define PVRSRV_CHECK_CPU_CACHE_COHERENT(uiFlags)		(PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT)
 
-/*!
-   CPU domain. Request cached memory, but not coherent (i.e. no cache snooping).
-   This means that if the allocation needs to transition from one device
-   to another services has to be informed so it can flush/invalidate the 
-   appropriate caches.
+/*! PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT
+
+    CPU domain. Request cached memory, but not coherent (i.e. no cache snooping).
+    This means that if the allocation needs to transition from one device
+    to another services has to be informed so it can flush/invalidate the
+    appropriate caches.
 
     Note: We reserve 3 bits in the CPU/GPU cache mode to allow for future
     expansion.
 */
 #define PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT 		(3U<<11)
-#define PVRSRV_CHECK_CPU_CACHE_INCOHERENT(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT) != 0)
+#define PVRSRV_CHECK_CPU_CACHE_INCOHERENT(uiFlags)		(PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT)
 
-/*!
-    CPU domain.
- 
-	Request cached cached coherent memory. This is like 
-	PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT but doesn't fall back on
-	uncached memory if the system doesn't support cache-snooping
-	but rather returns an error.
-*/
-#define PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT   (4U<<11)
-#define PVRSRV_CHECK_CPU_CACHED_CACHE_COHERENT(uiFlags)	((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT) != 0)
+/*! PVRSRV_MEMALLOCFLAG_CPU_CACHED
 
-/*!
-	CPU domain.
-
-	This flag is for internal use only and is used to indicate
-	that the underlying allocation should be cached on the CPU
-	after all the snooping and coherent checks have been done
+    CPU domain. This flag is for internal use only and is used to indicate
+    that the underlying allocation should be cached on the CPU
+    after all the snooping and coherent checks have been done
 */
 #define PVRSRV_MEMALLOCFLAG_CPU_CACHED					(7U<<11)
-#define PVRSRV_CHECK_CPU_CACHED(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHED) != 0)
+#define PVRSRV_CHECK_CPU_CACHED(uiFlags)				(PVRSRV_CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHED)
 
 /*!
-	CPU domain.
-	
-	CPU cache mode mask
+	CPU domain. CPU cache mode mask
 */
 #define PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK  		(7U<<11)
-#define PVRSRV_CPU_CACHE_MODE(uiFlags)					(uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK)
+#define PVRSRV_CPU_CACHE_MODE(uiFlags)					((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK)
 
 /* Helper flags for usual cases */
-#define PVRSRV_MEMALLOCFLAG_UNCACHED             		(PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | PVRSRV_MEMALLOCFLAG_CPU_UNCACHED) /*!< Memory will be uncached */
-#define PVRSRV_CHECK_UNCACHED(uiFlags)					((uiFlags & PVRSRV_MEMALLOCFLAG_UNCACHED) != 0)
 
-#define PVRSRV_MEMALLOCFLAG_WRITE_COMBINE        		(PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE | PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE)   /*!< Memory will be write-combined */
-#define PVRSRV_CHECK_WRITE_COMBINE(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_WRITE_COMBINE) != 0)
+/*! PVRSRV_MEMALLOCFLAG_UNCACHED
+ * Memory will be uncached on CPU and GPU
+ */
+#define PVRSRV_MEMALLOCFLAG_UNCACHED             		(PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | PVRSRV_MEMALLOCFLAG_CPU_UNCACHED)
+#define PVRSRV_CHECK_UNCACHED(uiFlags)					(PVRSRV_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_UNCACHED)
 
-#define PVRSRV_MEMALLOCFLAG_CACHE_COHERENT       		(PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT | PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT)  /*!< Memory will be cache-coherent */
-#define PVRSRV_CHECK_CACHE_COHERENT(uiFlags)			((uiFlags & PVRSRV_MEMALLOCFLAG_CACHE_COHERENT) != 0)
+/*! PVRSRV_MEMALLOCFLAG_WRITE_COMBINE
+ * Memory will be write-combined on CPU and GPU
+ */
+#define PVRSRV_MEMALLOCFLAG_WRITE_COMBINE        		(PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE | PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE)
+#define PVRSRV_CHECK_WRITE_COMBINE(uiFlags)				(PVRSRV_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_WRITE_COMBINE)
 
-#define PVRSRV_MEMALLOCFLAG_CACHE_INCOHERENT     		(PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT | PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT) /*!< Memory will be cache-incoherent */
-#define PVRSRV_CHECK_CACHE_INCOHERENT(uiFlags)			((uiFlags & PVRSRV_MEMALLOCFLAG_CACHE_INCOHERENT) != 0)
+/*! PVRSRV_MEMALLOCFLAG_CACHE_COHERENT
+ * Memory will be cached on CPU and GPU
+ * Services will try to set the correct flags in the MMU tables.
+ * In case there is no coherency support the caller has to ensure caches are up to date
+ */
+#define PVRSRV_MEMALLOCFLAG_CACHE_COHERENT       		(PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT | PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT)
+#define PVRSRV_CHECK_CACHE_COHERENT(uiFlags)			(PVRSRV_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CACHE_COHERENT)
+
+/*! PVRSRV_MEMALLOCFLAG_CACHE_INCOHERENT
+ * Memory will be cache-incoherent on CPU and GPU
+ */
+#define PVRSRV_MEMALLOCFLAG_CACHE_INCOHERENT     		(PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT | PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT)
+#define PVRSRV_CHECK_CACHE_INCOHERENT(uiFlags)			(PVRSRV_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CACHE_INCOHERENT)
+
+/*!
+	Cache mode mask
+*/
+#define PVRSRV_CACHE_MODE(uiFlags)						(PVRSRV_GPU_CACHE_MODE(uiFlags) | PVRSRV_CPU_CACHE_MODE(uiFlags))
 
 
 /*!
@@ -347,7 +361,7 @@
     some platforms.
  */
 #define PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE 		(1U<<14)
-#define PVRSRV_CHECK_KERNEL_CPU_MAPPABLE(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE) != 0)
+#define PVRSRV_CHECK_KERNEL_CPU_MAPPABLE(uiFlags)		(((uiFlags) & PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE) != 0)
 
 
 
@@ -363,7 +377,7 @@
  *
  */
 #define PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC			(1U<<15)
-#define PVRSRV_CHECK_ON_DEMAND(uiFlags)					((uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) != 0)
+#define PVRSRV_CHECK_ON_DEMAND(uiFlags)					(((uiFlags) & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) != 0)
 
 /*!
     PVRSRV_MEMALLOCFLAG_CPU_LOCAL
@@ -374,7 +388,7 @@
     the GPU, so LMA allocation (if available) is preferable.
  */
 #define PVRSRV_MEMALLOCFLAG_CPU_LOCAL 					(1U<<16)
-#define PVRSRV_CHECK_CPU_LOCAL(uiFlags)					((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_LOCAL) != 0)
+#define PVRSRV_CHECK_CPU_LOCAL(uiFlags)					(((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_LOCAL) != 0)
 
 
 /*!
@@ -384,15 +398,33 @@
     the FW.
  */
 #define PVRSRV_MEMALLOCFLAG_FW_LOCAL 					(1U<<17)
-#define PVRSRV_CHECK_FW_LOCAL(uiFlags)					((uiFlags & PVRSRV_MEMALLOCFLAG_FW_LOCAL) != 0)
+#define PVRSRV_CHECK_FW_LOCAL(uiFlags)					(((uiFlags) & PVRSRV_MEMALLOCFLAG_FW_LOCAL) != 0)
 
-/*
- * PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING
- *
- * Indicates the particular memory thats being allocated is sparse
- * and the sparse regions should not be backed by dummy page */
-#define PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING		(1U << 18)
-#define PVRSRV_IS_SPARSE_DUMMY_BACKING_REQUIRED(uiFlags)		((uiFlags & PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING) == 0)
+/*! PVRSRV_MEMALLOCFLAG_SVM
+
+    Indicates that the allocation will be accessed by the
+    CPU and GPU using the same virtual address, i.e. for
+	all SVM allocs, IMG_CPU_VIRTADDR == IMG_DEV_VIRTADDR
+ */
+#define PVRSRV_MEMALLOCFLAG_SVM_ALLOC 					(1U<<18)
+#define PVRSRV_CHECK_SVM_ALLOC(uiFlags)					(((uiFlags) & PVRSRV_MEMALLOCFLAG_SVM_ALLOC) != 0)
+
+/*! PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING
+
+    Indicates the particular memory that's being allocated is sparse
+    and the sparse regions should not be backed by dummy page */
+#define PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING		(1U << 19)
+#define PVRSRV_IS_SPARSE_DUMMY_BACKING_REQUIRED(uiFlags)		(((uiFlags) & PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING) == 0)
+
+/*! PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN
+
+    Services is going to clean the cache for the allocated memory.
+    For performance reasons avoid usage if allocation is written to by the CPU anyway
+    before the next GPU kick.
+ */
+#define PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN				(1U<<20)
+#define PVRSRV_CHECK_CPU_CACHE_CLEAN(uiFlags)			(((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN) != 0)
+
 
 /*
  *
@@ -424,36 +456,34 @@
  * actions.
  */
 
-/*!
-    PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC
-    Ensures that the memory allocated is initialized with zeroes.
+/*! PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC
+
+    Ensures that the memory allocated is initialised with zeroes.
  */
 #define PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC 				(1U<<31)
-#define PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags)				((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) != 0)
+#define PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags)				(((uiFlags) & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) != 0)
 #define PVRSRV_GET_ZERO_ON_ALLOC_FLAG(uiFlags)			((uiFlags) & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
 
-/*!
-    VRSRV_MEMALLOCFLAG_POISON_ON_ALLOC
+/*! PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC
 
     Scribbles over the allocated memory with a poison value
 
     Not compatible with ZERO_ON_ALLOC
 
     Poisoning is very deliberately _not_ reflected in PDump as we want
-    a simulation to cry loudly if the initialised data propogates to a
+    a simulation to cry loudly if the initialised data propagates to a
     result.
  */
 #define PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC 			(1U<<30)
-#define PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags) 			((uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC) != 0)
+#define PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags) 			(((uiFlags) & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC) != 0)
 
-/*!
-    PVRSRV_MEMALLOCFLAG_POISON_ON_FREE
+/*! PVRSRV_MEMALLOCFLAG_POISON_ON_FREE
 
     Causes memory to be trashed when freed, as a lazy man's security
     measure.
  */
 #define PVRSRV_MEMALLOCFLAG_POISON_ON_FREE (1U<<29)
-#define PVRSRV_CHECK_POISON_ON_FREE(uiFlags)			((uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE) != 0)
+#define PVRSRV_CHECK_POISON_ON_FREE(uiFlags)			(((uiFlags) & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE) != 0)
 
 /*
  *
@@ -465,9 +495,9 @@
  *
  * (Bits 24 to 27)
  *
- * Some services controled devices have device specific control
+ * Some services controlled devices have device specific control
  * bits in their page table entries, we need to allow these flags
- * to be passed down the memory managament layers so the user
+ * to be passed down the memory management layers so the user
  * can control these bits.
  */
 
@@ -477,6 +507,22 @@
 			(((n) << PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET) & \
 			PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK)
 
+
+/*!
+ * Secure buffer mask -- Flags in the mask are allowed for secure buffers
+ * because they are not related to CPU mappings.
+ */
+#define PVRSRV_MEMALLOCFLAGS_SECBUFMASK  ~(PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN | \
+                                           PVRSRV_MEMALLOCFLAG_SVM_ALLOC | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED)
+
+
+
 /*!
   PMR flags mask -- for internal services use only.  This is the set
   of flags that will be passed down and stored with the PMR, this also
@@ -484,8 +530,10 @@
   at PMRMap time.
 */
 #define PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK  (PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK | \
-											PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                            PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN | \
+                                            PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
                                             PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                            PVRSRV_MEMALLOCFLAG_SVM_ALLOC | \
                                             PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
                                             PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
                                             PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK | \
@@ -495,10 +543,6 @@
                                             PVRSRV_MEMALLOCFLAG_FW_LOCAL | \
                                             PVRSRV_MEMALLOCFLAG_CPU_LOCAL)
 
-#if ((~(PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK) & PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK) != 0)
-#error PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK is not a subset of PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK
-#endif
-
 /*!
   RA differentiation mask
 
@@ -508,21 +552,17 @@
   pair of allocations are permitted to live in the same page table.
   Allocations whose flags differ in any of these places would be
   allocated from separate RA Imports and therefore would never coexist
-  in the same page
-*/
-#define PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK (PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
-                                                      PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
-                                                      PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
-                                                      PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
-                                                      PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK | \
-                                                      PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK | \
-                                                      PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
-                                                      PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK | \
-                                                      PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
+  in the same page.
+  Special cases are zeroing and poisoning of memory. The caller is responsible
+  to set the sub-allocations to the value he wants it to be. To differentiate
+  between zeroed and poisoned RA Imports does not make sense because the
+  memory might be reused.
 
-#if ((~(PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK) & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK) != 0)
-#error PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK is not a subset of PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK
-#endif
+*/
+#define PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK (PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK \
+                                                      & \
+                                                      ~(PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC   | \
+                                                        PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
 
 /*!
   Flags that affect _allocation_
@@ -533,13 +573,10 @@
   Flags that affect _mapping_
 */
 #define PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK   (PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK | \
-													PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK | \
+                                                    PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK | \
+                                                    PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
                                                     PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC | \
+                                                    PVRSRV_MEMALLOCFLAG_SVM_ALLOC | \
                                                     PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING)
 
 #if ((~(PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK) & PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK) != 0)
@@ -550,34 +587,21 @@
 /*!
   Flags that affect _physical allocations_ in the DevMemX API
  */
-#define PVRSRV_MEMALLOCFLAGS_DEVMEMX_PHYSICAL_MASK (PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+#define PVRSRV_MEMALLOCFLAGS_DEVMEMX_PHYSICAL_MASK (PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
                                                     PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED | \
                                                     PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED | \
+                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN | \
                                                     PVRSRV_MEMALLOCFLAG_CPU_LOCAL | \
                                                     PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
                                                     PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
-                                                    PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_UNCACHED | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHED | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT | \
-                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT)
+                                                    PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
 
 /*!
   Flags that affect _virtual allocations_ in the DevMemX API
  */
-#define PVRSRV_MEMALLOCFLAGS_DEVMEMX_VIRTUAL_MASK  (PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+#define PVRSRV_MEMALLOCFLAGS_DEVMEMX_VIRTUAL_MASK  (PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK | \
                                                     PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_CACHED | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT | \
-                                                    PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT)
+                                                    PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED)
 
 #endif /* #ifndef PVRSRV_MEMALLOCFLAGS_H */
 
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_surface.h b/drivers/staging/imgtec/rogue/pvrsrv_surface.h
index 7ee23aa..f078e98 100644
--- a/drivers/staging/imgtec/rogue/pvrsrv_surface.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_surface.h
@@ -1,10 +1,10 @@
 /*************************************************************************/ /*!
 @File
 @Title          Device class external
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @Description    Defines DC specific structures which are externally visible
                 (i.e. visible to clients of services), but are also required
                 within services.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -47,93 +47,153 @@
 #define _PVRSRV_SURFACE_H_
 
 #include "img_types.h"
-#include "fbc_types.h"
+#include <powervr/buffer_attribs.h>
 
-#define PVRSRV_SURFACE_TRANSFORM_NONE	   (0 << 0)
-#define PVRSRV_SURFACE_TRANSFORM_FLIP_H    (1 << 0)
-#define PVRSRV_SURFACE_TRANSFORM_FLIP_V    (1 << 1)
-#define PVRSRV_SURFACE_TRANSFORM_ROT_90    (1 << 2)
-#define PVRSRV_SURFACE_TRANSFORM_ROT_180   ((1 << 0) + (1 << 1))
-#define PVRSRV_SURFACE_TRANSFORM_ROT_270   ((1 << 0) + (1 << 1) + (1 << 2))
+#define PVRSRV_SURFACE_TRANSFORM_NONE      (0 << 0)		/*!< No transformation */
+#define PVRSRV_SURFACE_TRANSFORM_FLIP_H    (1 << 0)		/*!< Flip horizontally */
+#define PVRSRV_SURFACE_TRANSFORM_FLIP_V    (1 << 1)		/*!< Flip vertically   */
+#define PVRSRV_SURFACE_TRANSFORM_ROT_90    (1 << 2)							/*!< Rotate  90 degree clockwise */
+#define PVRSRV_SURFACE_TRANSFORM_ROT_180   ((1 << 0) + (1 << 1))			/*!< Rotate 180 degree clockwise */
+#define PVRSRV_SURFACE_TRANSFORM_ROT_270   ((1 << 0) + (1 << 1) + (1 << 2))	/*!< Rotate 270 degree clockwise */
 
-#define PVRSRV_SURFACE_BLENDING_NONE	   0
-#define PVRSRV_SURFACE_BLENDING_PREMULT	   1
-#define PVRSRV_SURFACE_BLENDING_COVERAGE   2
+#define PVRSRV_SURFACE_BLENDING_NONE       0	/*!< Use no blending       */
+#define PVRSRV_SURFACE_BLENDING_PREMULT    1	/*!< Use blending with pre-multiplier*/
+#define PVRSRV_SURFACE_BLENDING_COVERAGE   2	/*!< Use coverage blending */
 
+/*!
+ *	Modes of memory layouts for surfaces.
+ *
+ *   Enum: #_PVRSRV_SURFACE_MEMLAYOUT_
+ *   Typedef: ::PVRSRV_SURFACE_MEMLAYOUT
+ */
 typedef enum _PVRSRV_SURFACE_MEMLAYOUT_  {
 	PVRSRV_SURFACE_MEMLAYOUT_STRIDED = 0,		/*!< Strided memory buffer */
-	PVRSRV_SURFACE_MEMLAYOUT_FBC,				/*!< Frame buffer compressed buffer */
-	PVRSRV_SURFACE_MEMLAYOUT_BIF_PAGE_TILED,	/*!< BIF page tiled buffer */
+	PVRSRV_SURFACE_MEMLAYOUT_FBC,				/*!< Compressed frame buffer */
+	PVRSRV_SURFACE_MEMLAYOUT_BIF_PAGE_TILED,	/*!< Buffer Interface page tiled buffer */
 } PVRSRV_SURFACE_MEMLAYOUT;
 
+/*!
+ * Frame Buffer Compression layout.
+ * Defines the FBC mode to use.
+ *
+ *   Structure: #_PVRSRV_SURFACE_FBC_LAYOUT_
+ *   Typedef: ::PVRSRV_SURFACE_FBC_LAYOUT
+ */
 typedef struct _PVRSRV_SURFACE_FBC_LAYOUT_ {
-	FB_COMPRESSION	eFBCompressionMode;
+	/*! The compression mode for this surface*/
+	IMG_FB_COMPRESSION	eFBCompressionMode;
 } PVRSRV_SURFACE_FBC_LAYOUT;
 
+/*!
+ * Pixel and memory format of a surface
+ *
+ *   Structure: #_PVRSRV_SURFACE_FORMAT_
+ *   Typedef: ::PVRSRV_SURFACE_FORMAT
+ */
 typedef struct _PVRSRV_SURFACE_FORMAT_
 {
+	/*! Enum value of type IMG_PIXFMT for the pixel format */
 	IMG_UINT32					ePixFormat;
+
+	/*! Enum surface memory layout */
 	PVRSRV_SURFACE_MEMLAYOUT	eMemLayout;
+
+	/*! Special layout options for the surface.
+	 * Needs services support.
+	 * Depends on eMemLayout.*/
 	union {
 		PVRSRV_SURFACE_FBC_LAYOUT	sFBCLayout;
 	} u;
 } PVRSRV_SURFACE_FORMAT;
 
+/*!
+ * Width and height of a surface
+ *
+ *   Structure: #_PVRSRV_SURFACE_DIMS_
+ *   Typedef: ::PVRSRV_SURFACE_DIMS
+ */
 typedef struct _PVRSRV_SURFACE_DIMS_
 {
-	IMG_UINT32		ui32Width;
-	IMG_UINT32		ui32Height;
+	IMG_UINT32		ui32Width;		/*!< Width in pixels*/
+	IMG_UINT32		ui32Height;		/*!< Height in pixels*/
 } PVRSRV_SURFACE_DIMS;
 
+/*!
+ * Dimension and format details of a surface
+ *
+ *   Structure: #_PVRSRV_SURFACE_INFO_
+ *   Typedef: ::PVRSRV_SURFACE_INFO
+ */
 typedef struct _PVRSRV_SURFACE_INFO_
 {
-	PVRSRV_SURFACE_DIMS		sDims;
-	PVRSRV_SURFACE_FORMAT	sFormat;
+	PVRSRV_SURFACE_DIMS		sDims;		/*!< Width and height */
+	PVRSRV_SURFACE_FORMAT	sFormat;	/*!< Memory format */
 } PVRSRV_SURFACE_INFO;
 
+/*!
+ * Defines a rectangle on a surface
+ *
+ *   Structure: #_PVRSRV_SURFACE_RECT_
+ *   Typedef: ::PVRSRV_SURFACE_RECT
+ */
 typedef struct _PVRSRV_SURFACE_RECT_
 {
-	IMG_INT32				i32XOffset;
-	IMG_INT32				i32YOffset;
-	PVRSRV_SURFACE_DIMS		sDims;
+	IMG_INT32				i32XOffset;	/*!< X offset from origin in pixels */
+	IMG_INT32				i32YOffset;	/*!< Y offset from origin in pixels */
+	PVRSRV_SURFACE_DIMS		sDims;		/*!< Rectangle dimensions */
 } PVRSRV_SURFACE_RECT;
 
+/*!
+ * Surface configuration details
+ *
+ *   Structure: #_PVRSRV_SURFACE_CONFIG_INFO_
+ *   Typedef: ::PVRSRV_SURFACE_CONFIG_INFO
+ */
 typedef struct _PVRSRV_SURFACE_CONFIG_INFO_
 {
-	/*!< Crop applied to surface (BEFORE transformation) */
+	/*! Crop applied to surface (BEFORE transformation) */
 	PVRSRV_SURFACE_RECT		sCrop;
 
-	/*!< Region of screen to display surface in (AFTER scaling) */
+	/*! Region of screen to display surface in (AFTER scaling) */
 	PVRSRV_SURFACE_RECT		sDisplay;
 
-	/*!< Surface rotation / flip / mirror */
+	/*! Surface transformation none/flip/rotate.
+	 * Use PVRSRV_SURFACE_TRANSFORM_xxx macros
+	 */
 	IMG_UINT32				ui32Transform;
 
-	/*!< Alpha blending mode e.g. none / premult / coverage */
+	/*! Alpha blending mode e.g. none/premult/coverage.
+	 * Use PVRSRV_SURFACE_BLENDING_xxx macros
+	 */
 	IMG_UINT32				eBlendType;
 
-	/*!< Custom data for the display engine */
+	/*! Custom data for the display engine */
 	IMG_UINT32				ui32Custom;
 
-	/*!< Plane alpha */
+	/*! Alpha value for this plane */
 	IMG_UINT8				ui8PlaneAlpha;
+
+	/*! Reserved for later use */
 	IMG_UINT8				ui8Reserved1[3];
 } PVRSRV_SURFACE_CONFIG_INFO;
 
+/*!
+ * Contains information about a panel
+ */
 typedef struct _PVRSRV_PANEL_INFO_
 {
-	PVRSRV_SURFACE_INFO sSurfaceInfo;
-	IMG_UINT32			ui32RefreshRate;
-	IMG_UINT32			ui32XDpi;
-	IMG_UINT32			ui32YDpi;
+	PVRSRV_SURFACE_INFO sSurfaceInfo;		/*!< Panel surface details */
+	IMG_UINT32			ui32RefreshRate;	/*!< Panel refresh rate in Hz */
+	IMG_UINT32			ui32XDpi;			/*!< Panel DPI in x direction */
+	IMG_UINT32			ui32YDpi;			/*!< Panel DPI in y direction */
 } PVRSRV_PANEL_INFO;
 
-/*
+/*!
 	Helper function to create a Config Info based on a Surface Info
 	to do a flip with no scale, transformation etc.
 */
 static INLINE void SurfaceConfigFromSurfInfo(PVRSRV_SURFACE_INFO *psSurfaceInfo,
-												 PVRSRV_SURFACE_CONFIG_INFO *psConfigInfo)
+                                             PVRSRV_SURFACE_CONFIG_INFO *psConfigInfo)
 {
 	psConfigInfo->sCrop.sDims = psSurfaceInfo->sDims;
 	psConfigInfo->sCrop.i32XOffset = 0;
diff --git a/drivers/staging/imgtec/rogue/cache_generic.h b/drivers/staging/imgtec/rogue/pvrsrv_sync_km.h
similarity index 81%
rename from drivers/staging/imgtec/rogue/cache_generic.h
rename to drivers/staging/imgtec/rogue/pvrsrv_sync_km.h
index b3f0a00..fe81607 100644
--- a/drivers/staging/imgtec/rogue/cache_generic.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_sync_km.h
@@ -1,6 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Title         PVR synchronization interface
+@Copyright     Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description   Types for server side code
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -38,19 +40,17 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
+#ifndef PVRSRV_SYNC_KM_H
+#define PVRSRV_SYNC_KM_H
+#if defined (__cplusplus)
+extern "C" {
+#endif
 
-#ifndef _CACHE_GENERIC_H_
-#define _CACHE_GENERIC_H_
+/* Implementation independent types for passing fence/timeline to KM */
+typedef int32_t PVRSRV_TIMELINE_KM;
+typedef int32_t PVRSRV_FENCE_KM;
 
-#include "img_types.h"
-#include "cache_external.h"
-#include "device.h"
-#include "pvrsrv_error.h"
-#include "pmr.h"
-
-PVRSRV_ERROR CacheOpQueue(PMR *psPMR,
-						  IMG_DEVMEM_OFFSET_T uiOffset,
-						  IMG_DEVMEM_SIZE_T uiSize,
-						  PVRSRV_CACHE_OP uiCacheOp);
-
-#endif	/* _CACHE_GENERIC_H_ */
+#if defined (__cplusplus)
+}
+#endif
+#endif	/* PVRSRV_SYNC_KM_H */
diff --git a/drivers/staging/imgtec/rogue/pvrsrv_tlcommon.h b/drivers/staging/imgtec/rogue/pvrsrv_tlcommon.h
new file mode 100644
index 0000000..766d044
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/pvrsrv_tlcommon.h
@@ -0,0 +1,196 @@
+/*************************************************************************/ /*!
+@File
+@Title          Services Transport Layer common types and definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Transport layer common types and definitions included into
+                both user mode and kernel mode source.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __PVR_TLCOMMON_H__
+#define __PVR_TLCOMMON_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+
+
+/*! Handle type for stream descriptor objects as created by this API */
+typedef IMG_HANDLE PVRSRVTL_SD;
+
+/*! Maximum stream name length including the null byte */
+#define PRVSRVTL_MAX_STREAM_NAME_SIZE	40U
+
+/*! Packet lengths are always rounded up to a multiple of 8 bytes */
+#define PVRSRVTL_PACKET_ALIGNMENT		8U
+#define PVRSRVTL_ALIGN(x) 				((x+PVRSRVTL_PACKET_ALIGNMENT-1) & ~(PVRSRVTL_PACKET_ALIGNMENT-1))
+
+
+/*! A packet is made up of a header structure followed by the data bytes.
+ * There are 3 types of packet: normal (has data), data lost and padding,
+ * see packet flags. Header kept small to reduce data overhead.
+ *
+ * if the ORDER of the structure members is changed, please UPDATE the 
+ *   PVRSRVTL_PACKET_FLAG_OFFSET macro.
+ */
+typedef struct _PVRSRVTL_PACKETHDR_
+{
+	IMG_UINT32 uiTypeSize;	/*!< Type & number of bytes following header */
+	IMG_UINT32 uiReserved;	/*!< Reserve, packets and data must be 8 byte aligned */
+
+	/* First bytes of TL packet data follow header ... */
+} PVRSRVTL_PACKETHDR, *PVRSRVTL_PPACKETHDR;
+
+/* Structure must always be a size multiple of 8 as stream buffer
+ * still an array of IMG_UINT32s.
+ */
+static_assert((sizeof(PVRSRVTL_PACKETHDR) & (PVRSRVTL_PACKET_ALIGNMENT-1)) == 0,
+			  "sizeof(PVRSRVTL_PACKETHDR) must be a multiple of 8");
+
+/*! Packet header mask used to extract the size from the uiTypeSize member.
+ * Do not use directly, see GET macros.
+ */
+#define PVRSRVTL_PACKETHDR_SIZE_MASK    0x0000FFFFU
+#define PVRSRVTL_MAX_PACKET_SIZE        (PVRSRVTL_PACKETHDR_SIZE_MASK & ~0xFU)
+
+
+/*! Packet header mask used to extract the type from the uiTypeSize member.
+ * Do not use directly, see GET macros.
+ */
+#define PVRSRVTL_PACKETHDR_TYPE_MASK    0xFF000000U
+#define PVRSRVTL_PACKETHDR_TYPE_OFFSET  24U
+
+/*! Packet type enumeration.
+ */
+typedef enum _PVRSRVTL_PACKETTYPE_
+{
+	/*! Undefined packet */
+	PVRSRVTL_PACKETTYPE_UNDEF = 0,
+
+	/*! Normal packet type. Indicates data follows the header.
+	 */
+	PVRSRVTL_PACKETTYPE_DATA = 1,
+
+	/*! When seen this packet type indicates that at this moment in the stream
+	 * packet(s) were not able to be accepted due to space constraints and that
+	 * recent data may be lost - depends on how the producer handles the
+	 * error. Such packets have no data, data length is 0.
+	 */
+	PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED = 2,
+
+	/*! Packets with this type set are padding packets that contain undefined
+	 * data and must be ignored/skipped by the client. They are used when the
+	 * circular stream buffer wraps around and there is not enough space for
+	 * the data at the end of the buffer. Such packets have a length of 0 or
+	 * more.
+	 */
+	PVRSRVTL_PACKETTYPE_PADDING = 3,
+
+	/*! This packet type conveys to the stream consumer that the stream producer
+	 * has reached the end of data for that data sequence. The TLDaemon
+	 * has several options for processing these packets that can be selected
+	 * on a per stream basis.
+	 */
+	PVRSRVTL_PACKETTYPE_MARKER_EOS = 4,
+
+	PVRSRVTL_PACKETTYPE_LAST = PVRSRVTL_PACKETTYPE_MARKER_EOS
+} PVRSRVTL_PACKETTYPE;
+
+/* The SET_PACKET_* macros rely on the order the PVRSRVTL_PACKETHDR members are declared:
+ * uiFlags is the upper half of a structure consisting of 2 uint16 quantities.
+ */
+#define PVRSRVTL_SET_PACKET_DATA(len)       (len) | (PVRSRVTL_PACKETTYPE_DATA                     << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
+#define PVRSRVTL_SET_PACKET_PADDING(len)    (len) | (PVRSRVTL_PACKETTYPE_PADDING                  << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
+#define PVRSRVTL_SET_PACKET_WRITE_FAILED    (0)   | (PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
+#define PVRSRVTL_SET_PACKET_HDR(len,type)   (len) | ((type)                                       << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
+
+/*! Returns the number of bytes of data in the packet. p may be any address type
+ * */
+#define GET_PACKET_DATA_LEN(p)	\
+	((IMG_UINT32) ((PVRSRVTL_PPACKETHDR)(p))->uiTypeSize & PVRSRVTL_PACKETHDR_SIZE_MASK)
+
+
+/*! Returns a IMG_BYTE* pointer to the first byte of data in the packet */
+#define GET_PACKET_DATA_PTR(p)	\
+	((IMG_PBYTE) ( ((size_t)p) + sizeof(PVRSRVTL_PACKETHDR)) )
+
+/*! Given a PVRSRVTL_PPACKETHDR address, return the address of the next pack
+ *  It is up to the caller to determine if the new address is within the packet
+ *  buffer.
+ */
+#define GET_NEXT_PACKET_ADDR(p) \
+	((PVRSRVTL_PPACKETHDR) ( ((IMG_UINT8 *)p) + sizeof(PVRSRVTL_PACKETHDR) + \
+	(((((PVRSRVTL_PPACKETHDR)p)->uiTypeSize & PVRSRVTL_PACKETHDR_SIZE_MASK) + \
+	(PVRSRVTL_PACKET_ALIGNMENT-1)) & (~(PVRSRVTL_PACKET_ALIGNMENT-1)) ) ))
+
+/*! Turns the packet address p into a PVRSRVTL_PPACKETHDR pointer type
+ */
+#define GET_PACKET_HDR(p)		((PVRSRVTL_PPACKETHDR)(p))
+
+/*! Get the type of the packet. p is of type PVRSRVTL_PPACKETHDR
+ */
+#define GET_PACKET_TYPE(p)		(((p)->uiTypeSize & PVRSRVTL_PACKETHDR_TYPE_MASK)>>PVRSRVTL_PACKETHDR_TYPE_OFFSET)
+
+
+/*! Flags for use with PVRSRVTLOpenStream
+ * 0x01 - Do not block in PVRSRVTLAcquireData() when no bytes are available
+ * 0x02 - When the stream does not exist wait for a bit (2s) in
+ *        PVRSRVTLOpenStream() and then exit with a timeout error if it still
+ *        does not exist.
+ * 0x04 - Open stream for write only operations.
+ *        If flag is not used stream is opened as read-only. This flag is
+ *        required if one wants to call reserve/commit/write function on the
+ *        stream descriptor. Read from on the stream descriptor opened
+ *        with this flag will fail.
+ */
+#define PVRSRV_STREAM_FLAG_NONE                        (0U)
+#define PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING         (1U<<0)
+#define PVRSRV_STREAM_FLAG_OPEN_WAIT                   (1U<<1)
+#define PVRSRV_STREAM_FLAG_OPEN_WO                     (1U<<2)
+#define PVRSRV_STREAM_FLAG_DISABLE_PRODUCER_CALLBACK   (1U<<3)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_TLCOMMON_H__ */
+/******************************************************************************
+ End of file (pvrsrv_tlcommon.h)
+******************************************************************************/
+
diff --git a/drivers/staging/imgtec/rogue/pvr_bridge_io.h b/drivers/staging/imgtec/rogue/pvrsrv_tlstreams.h
similarity index 78%
rename from drivers/staging/imgtec/rogue/pvr_bridge_io.h
rename to drivers/staging/imgtec/rogue/pvrsrv_tlstreams.h
index 9ee0993..e6bd12e 100644
--- a/drivers/staging/imgtec/rogue/pvr_bridge_io.h
+++ b/drivers/staging/imgtec/rogue/pvrsrv_tlstreams.h
@@ -1,8 +1,9 @@
 /*************************************************************************/ /*!
 @File
-@Title          PVR Bridge IO Functionality
+@Title          Services Transport Layer stream names
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Header for the PVR Bridge code
+@Description    Transport layer common types and definitions included into
+                both user mode and kernel mode source.
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,17 +42,22 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef __PVR_BRIDGE_IO_H__
-#define __PVR_BRIDGE_IO_H__
+#ifndef _PVRSRV_TLSTREAMS_H_
+#define _PVRSRV_TLSTREAMS_H_
 
-#include <linux/ioctl.h>
 
-#define PVRSRV_IOC_GID      'g'
-#define PVRSRV_IOWR(INDEX)  _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
-#define PVRSRV_GET_BRIDGE_ID(X)	_IOC_NR(X)
+#define PVRSRV_TL_HWPERF_RGX_FW_STREAM      "hwperf"
+#define PVRSRV_TL_HWPERF_HOST_SERVER_STREAM "hwperf_host"
 
-#endif /* __PVR_BRIDGE_IO_H__ */
+/* Host HWPerf client stream names are of the form 'hwperf_client_<pid>' */
+#define PVRSRV_TL_HWPERF_HOST_CLIENT_STREAM         "hwperf_client_"
+#define PVRSRV_TL_HWPERF_HOST_CLIENT_STREAM_FMTSPEC "hwperf_client_%u"
+
+
+
+#endif /* _PVRSRV_TLSTREAMS_H_ */
 
 /******************************************************************************
- End of file
+ End of file (pvrsrv_tlstreams.h)
 ******************************************************************************/
+
diff --git a/drivers/staging/imgtec/rogue/ra.c b/drivers/staging/imgtec/rogue/ra.c
index 1f684b7..fb0a74e 100644
--- a/drivers/staging/imgtec/rogue/ra.c
+++ b/drivers/staging/imgtec/rogue/ra.c
@@ -89,6 +89,7 @@
 
 #include "hash.h"
 #include "ra.h"
+#include "pvrsrv_memallocflags.h"
 
 #include "osfunc.h"
 #include "allocmem.h"
@@ -97,7 +98,7 @@
 
 /* The initial, and minimum size of the live address -> boundary tag
    structure hash table. The value 64 is a fairly arbitrary
-   choice. The hash table resizes on demand so the value choosen is
+   choice. The hash table resizes on demand so the value chosen is
    not critical. */
 #define MINIMUM_HASH_SIZE (64)
 
@@ -167,9 +168,10 @@
 	RA_LENGTH_T uQuantum;
 
 	/* import interface, if provided */
-	IMG_BOOL (*pImportAlloc)(RA_PERARENA_HANDLE h,
+	PVRSRV_ERROR (*pImportAlloc)(RA_PERARENA_HANDLE h,
 							 RA_LENGTH_T uSize,
 							 IMG_UINT32 uFlags,
+							 const IMG_CHAR *pszAnnotation,
 							 RA_BASE_T *pBase,
 							 RA_LENGTH_T *pActualSize,
                              RA_PERISPAN_HANDLE *phPriv);
@@ -213,12 +215,13 @@
 @Input          _pRef - user reference
 @Input          _uflags - allocation flags
 @Input          _pBase - receives allocated base
-@Return         IMG_FALSE, this function always fails to allocate.
+@Return         PVRSRV_ERROR_RA_REQUEST_ALLOC_FAIL, this function always fails to allocate.
 */ /**************************************************************************/
-static IMG_BOOL
+static PVRSRV_ERROR
 _RequestAllocFail (RA_PERARENA_HANDLE _h,
                    RA_LENGTH_T _uSize,
                    IMG_UINT32 _uFlags,
+                   const IMG_CHAR *_pszAnnotation,
                    RA_BASE_T *_pBase,
                    RA_LENGTH_T *_pActualSize,
                    RA_PERISPAN_HANDLE *_phPriv)
@@ -229,8 +232,9 @@
 	PVR_UNREFERENCED_PARAMETER (_phPriv);
 	PVR_UNREFERENCED_PARAMETER (_uFlags);
 	PVR_UNREFERENCED_PARAMETER (_pBase);
+	PVR_UNREFERENCED_PARAMETER (_pszAnnotation);
 
-	return IMG_FALSE;
+	return PVRSRV_ERROR_RA_REQUEST_ALLOC_FAIL;
 }
 
 
@@ -999,9 +1003,10 @@
 RA_Create (IMG_CHAR *name,
 		   RA_LOG2QUANTUM_T uLog2Quantum,
 		   IMG_UINT32 ui32LockClass,
-		   IMG_BOOL (*imp_alloc)(RA_PERARENA_HANDLE h, 
+		   PVRSRV_ERROR (*imp_alloc)(RA_PERARENA_HANDLE h, 
                                  RA_LENGTH_T uSize,
                                  RA_FLAGS_T _flags, 
+                                 const IMG_CHAR *pszAnnotation,
                                  /* returned data */
                                  RA_BASE_T *pBase,
                                  RA_LENGTH_T *pActualSize,
@@ -1074,6 +1079,7 @@
 RA_Delete (RA_ARENA *pArena)
 {
 	IMG_UINT32 uIndex;
+	IMG_BOOL bWarn = IMG_TRUE;
 
 	PVR_ASSERT(pArena != NULL);
 
@@ -1094,10 +1100,15 @@
 
 		if (pBT->type != btt_free)
 		{
-			PVR_DPF ((PVR_DBG_ERROR, "RA_Delete: allocations still exist in the arena that is being destroyed"));
-			PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
-			PVR_DPF ((PVR_DBG_ERROR, "RA_Delete: base = 0x%llx size=0x%llx",
+			if (bWarn)
+			{
+				PVR_DPF ((PVR_DBG_ERROR, "%s: Allocations still exist in the arena that is being destroyed", __func__));
+				PVR_DPF ((PVR_DBG_ERROR, "%s: Likely Cause: client drivers not freeing allocations before destroying devmem context", __func__));
+				PVR_DPF ((PVR_DBG_ERROR, "%s: base = 0x%llx size=0x%llx", __func__,
 					  (unsigned long long)pBT->base, (unsigned long long)pBT->uSize));
+				PVR_DPF ((PVR_DBG_ERROR, "%s: This warning will be issued only once for the first allocation found!", __func__));
+				bWarn = IMG_FALSE;
+			}
 		}
 		else
 		{
@@ -1154,6 +1165,12 @@
 		return IMG_FALSE;
 	}
 
+	if(uSize == 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RA_Add: invalid size 0 added to arena %s", pArena->name));
+		return IMG_FALSE;
+	}
+
 	OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass);
 	PVR_ASSERT(is_arena_valid(pArena));
 	PVR_DPF ((PVR_DBG_MESSAGE, "RA_Add: name='%s', "
@@ -1183,32 +1200,34 @@
 @Output         pActualSize       The actual size of resource segment
                                   allocated, typcially rounded up by quantum.
 @Output         phPriv            The user reference associated with allocated resource span.
-@Input          uFlags            Flags influencing allocation policy.
+@Input          uImportFlags            Flags influencing allocation policy.
 @Input          uAlignment        The uAlignment constraint required for the
                                   allocated segment, use 0 if uAlignment not required, otherwise
                                   must be a power of 2.
 @Output         base              Allocated base resource
-@Return         IMG_TRUE - success
-                IMG_FALSE - failure
+@Return         PVRSRV_OK - success
 */ /**************************************************************************/
-IMG_INTERNAL IMG_BOOL
+IMG_INTERNAL PVRSRV_ERROR
 RA_Alloc (RA_ARENA *pArena,
 		  RA_LENGTH_T uRequestSize,
 		  IMG_UINT8 uImportMultiplier,
-		  RA_FLAGS_T uFlags,
+		  RA_FLAGS_T uImportFlags,
 		  RA_LENGTH_T uAlignment,
+		  const IMG_CHAR *pszAnnotation,
 		  RA_BASE_T *base,
 		  RA_LENGTH_T *pActualSize,
 		  RA_PERISPAN_HANDLE *phPriv)
 {
+	PVRSRV_ERROR eError;
 	IMG_BOOL bResult;
 	RA_LENGTH_T uSize = uRequestSize;
+	RA_FLAGS_T uFlags = (uImportFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK);
 
 	if (pArena == NULL || uImportMultiplier == 0 || uSize == 0)
 	{
 		PVR_DPF ((PVR_DBG_ERROR,
-				"RA_Alloc: One of the necessary parameters is 0"));
-		return IMG_FALSE;
+		          "RA_Alloc: One of the necessary parameters is 0"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
 	OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass);
@@ -1223,10 +1242,10 @@
 	PVR_ASSERT((uAlignment == 0) || (uAlignment & (uAlignment - 1)) == 0);
 
 	PVR_DPF ((PVR_DBG_MESSAGE,
-			  "RA_Alloc: arena='%s', size=0x%llx(0x%llx), "
-              "alignment=0x%llx", pArena->name,
-			  (unsigned long long)uSize, (unsigned long long)uRequestSize,
-			  (unsigned long long)uAlignment));
+	          "RA_Alloc: arena='%s', size=0x%llx(0x%llx), "
+	          "alignment=0x%llx", pArena->name,
+	          (unsigned long long)uSize, (unsigned long long)uRequestSize,
+	          (unsigned long long)uAlignment));
 
 	/* if allocation failed then we might have an import source which
 	   can provide more resource, else we will have to fail the
@@ -1234,7 +1253,7 @@
 	bResult = _AttemptAllocAligned (pArena, uSize, uFlags, uAlignment, base, phPriv);
 	if (!bResult)
 	{
-        IMG_HANDLE hPriv;
+		IMG_HANDLE hPriv;
 		RA_BASE_T import_base;
 		RA_LENGTH_T uImportSize = uSize;
 
@@ -1246,16 +1265,24 @@
 		{
 			uImportSize += (uAlignment - pArena->uQuantum);
 		}
+
 		/* apply over-allocation multiplier after all alignment adjustments */
 		uImportSize *= uImportMultiplier;
 
 		/* ensure that we import according to the quanta of this arena */
 		uImportSize = (uImportSize + pArena->uQuantum - 1) & ~(pArena->uQuantum - 1);
 
-		bResult =
-			pArena->pImportAlloc (pArena->pImportHandle, uImportSize, uFlags,
-                                  &import_base, &uImportSize, &hPriv);
-		if (bResult)
+		eError = pArena->pImportAlloc (pArena->pImportHandle,
+		                               uImportSize, uImportFlags,
+		                               pszAnnotation,
+		                               &import_base, &uImportSize,
+		                               &hPriv);
+		if (PVRSRV_OK != eError)
+		{
+			OSLockRelease(pArena->hLock);
+			return eError;
+		}
+		else
 		{
 			BT *pBT;
 			pBT = _InsertResourceSpan (pArena, import_base, uImportSize, uFlags);
@@ -1268,22 +1295,22 @@
 				pArena->pImportFree(pArena->pImportHandle, import_base, hPriv);
 
 				PVR_DPF ((PVR_DBG_MESSAGE, "RA_Alloc: name='%s', "
-                          "size=0x%llx failed!", pArena->name,
-						  (unsigned long long)uSize));
+				          "size=0x%llx failed!", pArena->name,
+				          (unsigned long long)uSize));
 				/* RA_Dump (arena); */
+
 				OSLockRelease(pArena->hLock);
-				return IMG_FALSE;
+				return PVRSRV_ERROR_RA_INSERT_RESOURCE_SPAN_FAILED;
 			}
 
-
-            pBT->hPriv = hPriv;
+			pBT->hPriv = hPriv;
 
 			bResult = _AttemptAllocAligned(pArena, uSize, uFlags, uAlignment, base, phPriv);
 			if (!bResult)
 			{
 				PVR_DPF ((PVR_DBG_ERROR,
-						  "RA_Alloc: name='%s' second alloc failed!",
-						  pArena->name));
+				          "RA_Alloc: name='%s' second alloc failed!",
+				          pArena->name));
 
 				/*
 				  On failure of _AttemptAllocAligned() depending on the exact point
@@ -1291,6 +1318,9 @@
 				  left untouched. If the later, we need to return it.
 				*/
 				_FreeBT(pArena, pBT);
+
+				OSLockRelease(pArena->hLock);
+				return PVRSRV_ERROR_RA_ATTEMPT_ALLOC_ALIGNED_FAILED;
 			}
 			else
 			{
@@ -1298,8 +1328,8 @@
 				if (*base < import_base  ||  *base > (import_base + uImportSize))
 				{
 					PVR_DPF ((PVR_DBG_ERROR,
-							  "RA_Alloc: name='%s' alloc did not occur in the imported span!",
-							  pArena->name));
+					          "RA_Alloc: name='%s' alloc did not occur in the imported span!",
+					          pArena->name));
 
 					/*
 					  Remove the imported span which should not be in use (if it is then
@@ -1318,7 +1348,7 @@
 	PVR_ASSERT(is_arena_valid(pArena));
 
 	OSLockRelease(pArena->hLock);
-	return bResult;
+	return PVRSRV_OK;
 }
 
 
@@ -1357,6 +1387,12 @@
 		PVR_ASSERT (pBT->base == base);
 		_FreeBT (pArena, pBT);
 	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RA_Free: no resource span found for given base (0x%llX) in arena %s",
+										(unsigned long long) base,
+											pArena->name));
+	}
 
 	PVR_ASSERT(is_arena_valid(pArena));
 	OSLockRelease(pArena->hLock);
diff --git a/drivers/staging/imgtec/rogue/ra.h b/drivers/staging/imgtec/rogue/ra.h
index efa54e5..cfccd59 100644
--- a/drivers/staging/imgtec/rogue/ra.h
+++ b/drivers/staging/imgtec/rogue/ra.h
@@ -85,14 +85,6 @@
  */
 typedef IMG_UINT32 RA_FLAGS_T;
 
-struct _RA_SEGMENT_DETAILS_
-{
-	RA_LENGTH_T      uiSize;
-	IMG_CPU_PHYADDR sCpuPhyAddr;
-	IMG_HANDLE      hSegment;
-};
-typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
-
 /**
  *  @Function   RA_Create
  *
@@ -114,9 +106,10 @@
            /* subsequent imports: */
            RA_LOG2QUANTUM_T uLog2Quantum,
            IMG_UINT32 ui32LockClass,
-           IMG_BOOL (*imp_alloc)(RA_PERARENA_HANDLE _h,
+           PVRSRV_ERROR (*imp_alloc)(RA_PERARENA_HANDLE _h,
                                  RA_LENGTH_T uSize,
                                  RA_FLAGS_T uFlags,
+                                 const IMG_CHAR *pszAnnotation,
                                  RA_BASE_T *pBase,
                                  RA_LENGTH_T *pActualSize,
                                  RA_PERISPAN_HANDLE *phPriv),
@@ -175,20 +168,22 @@
  *          Use RA_NO_IMPORT_MULTIPLIER to import the exact size.
  *  @Output pActualSize - the actual_size of resource segment allocated,
  *          typcially rounded up by quantum.
- *  @Input  uFlags - flags influencing allocation policy.
+ *  @Input  uImportFlags - flags influencing allocation policy.
  *  @Input  uAlignment - the alignment constraint required for the
  *          allocated segment, use 0 if alignment not required.
+ *  @Input  pszAnnotation - a string to describe the allocation
  *  @Output pBase - allocated base resource
  *  @Output phPriv - the user reference associated with allocated
  *          resource span.
- *  @Return IMG_TRUE - success, IMG_FALSE - failure
+ *  @Return PVRSRV_OK - success
  */
-IMG_BOOL
+PVRSRV_ERROR
 RA_Alloc (RA_ARENA *pArena, 
           RA_LENGTH_T uSize,
           IMG_UINT8 uImportMultiplier,
           RA_FLAGS_T uFlags,
           RA_LENGTH_T uAlignment,
+          const IMG_CHAR *pszAnnotation,
           RA_BASE_T *pBase,
           RA_LENGTH_T *pActualSize,
           RA_PERISPAN_HANDLE *phPriv);
diff --git a/drivers/staging/imgtec/rogue/rgx_bridge.h b/drivers/staging/imgtec/rogue/rgx_bridge.h
index a7a9c53..167983e 100644
--- a/drivers/staging/imgtec/rogue/rgx_bridge.h
+++ b/drivers/staging/imgtec/rogue/rgx_bridge.h
@@ -50,31 +50,65 @@
 extern "C" {
 #endif
 
+#include "rgx_fwif.h"
+
+#define RGXFWINITPARAMS_VERSION   1
+#define RGXFWINITPARAMS_EXTENSION 128
+
+/* Parameters for RGXFirmwareInit */
+typedef struct __RGX_FW_INIT_IN_PARAMS__
+{
+	IMG_UINT32               ui32Version;
+	IMG_BOOL                 bEnableSignatureChecks;
+	IMG_UINT32               ui32SignatureChecksBufSize;
+	IMG_UINT32               ui32HWPerfFWBufSizeKB;
+	IMG_UINT64               ui64HWPerfFilter;
+	IMG_UINT32               ui32ConfigFlags;
+	IMG_UINT32               ui32LogType;
+	IMG_UINT32               ui32FilterFlags;
+	IMG_UINT32               ui32JonesDisableMask;
+	IMG_UINT32               ui32HWRDebugDumpLimit;
+	RGXFWIF_COMPCHECKS_BVNC  sClientBVNC;
+	RGXFWIF_COMPCHECKS_BVNC  sFirmwareBVNC;
+	IMG_UINT32               ui32HWPerfCountersDataSize;
+	RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf;
+	FW_PERF_CONF             eFirmwarePerf;
+	/* Available for future extensions */
+	IMG_BYTE                 abUnused[RGXFWINITPARAMS_EXTENSION];
+} RGX_FW_INIT_IN_PARAMS;
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 #include "common_rgxinit_bridge.h"
-#include "common_rgxta3d_bridge.h"
-#if defined(RGX_FEATURE_COMPUTE)
-#include "common_rgxcmp_bridge.h"
 #endif
+#include "common_rgxta3d_bridge.h"
+#include "common_rgxcmp_bridge.h"
+
+#include "common_rgxtq2_bridge.h"
 #include "common_rgxtq_bridge.h"
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
 #include "common_breakpoint_bridge.h"
+#endif
 #include "common_debugmisc_bridge.h"
 #if defined(PDUMP)
 #include "common_rgxpdump_bridge.h"
 #endif
 #include "common_rgxhwperf_bridge.h"
-#if defined(RGX_FEATURE_RAY_TRACING)
 #include "common_rgxray_bridge.h"
-#endif
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
 #include "common_regconfig_bridge.h"
+#endif
 #include "common_timerquery_bridge.h"
 #include "common_rgxkicksync_bridge.h"
 
-/* 
+#include "common_rgxsignals_bridge.h"
+
+
+/*
  * Bridge Cmd Ids
  */
 
 /* *REMEMBER* to update PVRSRV_BRIDGE_RGX_LAST if you add/remove a bridge
- * group! 
+ * group!
  * Also you need to ensure all PVRSRV_BRIDGE_RGX_xxx_DISPATCH_FIRST
  * offsets follow on from the previous bridge group's commands!
  *
@@ -85,30 +119,34 @@
  * assigned value of 0.
  */
 
-/* The RGX bridge groups start at 128 rather than follow-on from the other
+/* The RGX bridge groups start at 128 (PVRSRV_BRIDGE_RGX_FIRST) rather than follow-on from the other
  * non-device bridge groups (meaning that they then won't be displaced if
  * other non-device bridge groups are added)
  */
 
+#define PVRSRV_BRIDGE_RGX_FIRST                  128UL
+
 /* 128: RGX TQ interface functions */
 #define PVRSRV_BRIDGE_RGXTQ                      128UL
 #define PVRSRV_BRIDGE_RGXTQ_DISPATCH_FIRST       (PVRSRV_BRIDGE_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXTQ_DISPATCH_LAST        (PVRSRV_BRIDGE_RGXTQ_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXTQ_CMD_LAST)
 
+
 /* 129: RGX Compute interface functions */
 #define PVRSRV_BRIDGE_RGXCMP                     129UL
-#if defined(RGX_FEATURE_COMPUTE)
 #	define PVRSRV_BRIDGE_RGXCMP_DISPATCH_FIRST   (PVRSRV_BRIDGE_RGXTQ_DISPATCH_LAST + 1)
 #	define PVRSRV_BRIDGE_RGXCMP_DISPATCH_LAST    (PVRSRV_BRIDGE_RGXCMP_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXCMP_CMD_LAST)
-#else
-#	define PVRSRV_BRIDGE_RGXCMP_DISPATCH_FIRST   0
-#	define PVRSRV_BRIDGE_RGXCMP_DISPATCH_LAST    (PVRSRV_BRIDGE_RGXTQ_DISPATCH_LAST)
-#endif
+
 
 /* 130: RGX Initialisation interface functions */
 #define PVRSRV_BRIDGE_RGXINIT                    130UL
-#define PVRSRV_BRIDGE_RGXINIT_DISPATCH_FIRST     (PVRSRV_BRIDGE_RGXCMP_DISPATCH_LAST +1)
-#define PVRSRV_BRIDGE_RGXINIT_DISPATCH_LAST      (PVRSRV_BRIDGE_RGXINIT_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXINIT_CMD_LAST)
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+#	define PVRSRV_BRIDGE_RGXINIT_DISPATCH_FIRST  (PVRSRV_BRIDGE_RGXCMP_DISPATCH_LAST +1)
+#	define PVRSRV_BRIDGE_RGXINIT_DISPATCH_LAST   (PVRSRV_BRIDGE_RGXINIT_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXINIT_CMD_LAST)
+#else
+#	define PVRSRV_BRIDGE_RGXINIT_DISPATCH_FIRST  0
+#	define PVRSRV_BRIDGE_RGXINIT_DISPATCH_LAST   (PVRSRV_BRIDGE_RGXCMP_DISPATCH_LAST)
+#endif
 
 /* 131: RGX TA/3D interface functions */
 #define PVRSRV_BRIDGE_RGXTA3D                    131UL
@@ -117,8 +155,13 @@
 
 /* 132: RGX Breakpoint interface functions */
 #define PVRSRV_BRIDGE_BREAKPOINT                 132UL
+#if !defined(EXCLUDE_BREAKPOINT_BRIDGE)
 #define PVRSRV_BRIDGE_BREAKPOINT_DISPATCH_FIRST  (PVRSRV_BRIDGE_RGXTA3D_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_BREAKPOINT_DISPATCH_LAST   (PVRSRV_BRIDGE_BREAKPOINT_DISPATCH_FIRST + PVRSRV_BRIDGE_BREAKPOINT_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_BREAKPOINT_DISPATCH_FIRST  0
+#define PVRSRV_BRIDGE_BREAKPOINT_DISPATCH_LAST   (PVRSRV_BRIDGE_RGXTA3D_DISPATCH_LAST)
+#endif
 
 /* 133: RGX Debug/Misc interface functions */
 #define PVRSRV_BRIDGE_DEBUGMISC                  133UL
@@ -142,18 +185,18 @@
 
 /* 136: RGX Ray Tracing interface functions */
 #define PVRSRV_BRIDGE_RGXRAY                     136UL
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define PVRSRV_BRIDGE_RGXRAY_DISPATCH_FIRST      (PVRSRV_BRIDGE_RGXHWPERF_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXRAY_DISPATCH_LAST       (PVRSRV_BRIDGE_RGXRAY_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXRAY_CMD_LAST)
-#else
-#define PVRSRV_BRIDGE_RGXRAY_DISPATCH_FIRST      0
-#define PVRSRV_BRIDGE_RGXRAY_DISPATCH_LAST       (PVRSRV_BRIDGE_RGXHWPERF_DISPATCH_LAST)
-#endif
 
 /* 137: RGX Register Configuration interface functions */
 #define PVRSRV_BRIDGE_REGCONFIG                  137UL
+#if !defined(EXCLUDE_REGCONFIG_BRIDGE)
 #define PVRSRV_BRIDGE_REGCONFIG_DISPATCH_FIRST   (PVRSRV_BRIDGE_RGXRAY_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_REGCONFIG_DISPATCH_LAST    (PVRSRV_BRIDGE_REGCONFIG_DISPATCH_FIRST + PVRSRV_BRIDGE_REGCONFIG_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_REGCONFIG_DISPATCH_FIRST   0
+#define PVRSRV_BRIDGE_REGCONFIG_DISPATCH_LAST    (PVRSRV_BRIDGE_RGXRAY_DISPATCH_LAST)
+#endif
 
 /* 138: RGX Timer Query interface functions */
 #define PVRSRV_BRIDGE_TIMERQUERY                 138UL
@@ -165,13 +208,66 @@
 #define PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_FIRST (PVRSRV_BRIDGE_TIMERQUERY_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST  (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXKICKSYNC_CMD_LAST)
 
+/* 140: RGX signals interface */
+#define PVRSRV_BRIDGE_RGXSIGNALS                140UL
+#define PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_FIRST (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_LAST  (PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXSIGNALS_CMD_LAST)
 
-#define PVRSRV_BRIDGE_RGX_LAST                   (PVRSRV_BRIDGE_RGXKICKSYNC)
-#define PVRSRV_BRIDGE_RGX_DISPATCH_LAST          (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST)
+
+#define PVRSRV_BRIDGE_RGXTQ2                      141UL
+#define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST       (PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_LAST + 1)
+#define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST        (PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXTQ2_CMD_LAST)
+
+#define PVRSRV_BRIDGE_RGX_LAST                   (PVRSRV_BRIDGE_RGXTQ2)
+#define PVRSRV_BRIDGE_RGX_DISPATCH_LAST          (PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST)
+
+/* bit mask representing the enabled RGX bridges */
+
+static const IMG_UINT32 gui32RGXBridges =
+	  (1U << (PVRSRV_BRIDGE_RGXTQ - PVRSRV_BRIDGE_RGX_FIRST))
+#if defined(RGX_FEATURE_COMPUTE)
+	| (1U << (PVRSRV_BRIDGE_RGXCMP - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	| (1U << (PVRSRV_BRIDGE_RGXINIT - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_RGXTA3D - PVRSRV_BRIDGE_RGX_FIRST))
+#if defined(SUPPORT_BREAKPOINT)
+	| (1U << (PVRSRV_BRIDGE_BREAKPOINT - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+#if defined(SUPPORT_DEBUGMISC)
+	| (1U << (PVRSRV_BRIDGE_DEBUGMISC - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+#if defined(PDUMP)
+	| (1U << (PVRSRV_BRIDGE_RGXPDUMP - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_RGXHWPERF - PVRSRV_BRIDGE_RGX_FIRST))
+#if defined(RGX_FEATURE_RAY_TRACING)
+	| (1U << (PVRSRV_BRIDGE_RGXRAY - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+#if defined(SUPPORT_REGCONFIG)
+	| (1U << (PVRSRV_BRIDGE_REGCONFIG - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+#if defined(SUPPORT_TIMERQUERY)
+	| (1U << (PVRSRV_BRIDGE_TIMERQUERY - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_RGXKICKSYNC - PVRSRV_BRIDGE_RGX_FIRST))
+#if defined(RGX_FEATURE_SIGNAL_SNOOPING)
+	| (1U << (PVRSRV_BRIDGE_RGXSIGNALS - PVRSRV_BRIDGE_RGX_FIRST))
+#endif
+	| (1U << (PVRSRV_BRIDGE_RGXTQ2 - PVRSRV_BRIDGE_RGX_FIRST));
+
+/* bit field representing which RGX bridge groups may optionally not
+ * be present in the server
+ */
+
+#define RGX_BRIDGES_OPTIONAL \
+	( \
+		0 /* no RGX bridges are currently optional */ \
+	)
 
 #if defined (__cplusplus)
 }
 #endif
 
 #endif /* __RGX_BRIDGE_H__ */
-
diff --git a/drivers/staging/imgtec/rogue/rgx_common.h b/drivers/staging/imgtec/rogue/rgx_common.h
index 7ff25fd..541f14d 100644
--- a/drivers/staging/imgtec/rogue/rgx_common.h
+++ b/drivers/staging/imgtec/rogue/rgx_common.h
@@ -68,34 +68,55 @@
 				  "Offset of " #_a "." #_b " is not properly aligned")
 
 
-/*! The number of performance counters in each layout block */
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#define RGX_HWPERF_CNTRS_IN_BLK 6
-#define RGX_HWPERF_CNTRS_IN_BLK_MIN 4
-#else
-#define RGX_HWPERF_CNTRS_IN_BLK 4
-#define RGX_HWPERF_CNTRS_IN_BLK_MIN 4
+/* The following enum assumes only one of RGX_FEATURE_TLA or RGX_FEATURE_FASTRENDER_DM feature
+ * is present. In case this is no more true, fail build to fix code */
+#if defined (RGX_FEATURE_TLA) && defined (RGX_FEATURE_FASTRENDER_DM)
+#error "Both RGX_FEATURE_TLA and RGX_FEATURE_FASTRENDER_DM defined. Fix code to handle this!"
 #endif
 
-
 /*! The master definition for data masters known to the firmware of RGX.
+ * When a new DM is added to this enum, relevant entry should be added to
+ * RGX_HWPERF_DM enum list.
  * The DM in a V1 HWPerf packet uses this definition. */
 typedef enum _RGXFWIF_DM_
 {
 	RGXFWIF_DM_GP			= 0,
-	RGXFWIF_DM_2D			= 1,
+
+	/* Either TDM or 2D DM is present. The above build time error is present to verify this */
+	RGXFWIF_DM_2D			= 1, /* when RGX_FEATURE_TLA defined */
+	RGXFWIF_DM_TDM			= 1, /* when RGX_FEATURE_FASTRENDER_DM defined */
+
 	RGXFWIF_DM_TA			= 2,
 	RGXFWIF_DM_3D			= 3,
 	RGXFWIF_DM_CDM			= 4,
-#if defined(RGX_FEATURE_RAY_TRACING)
+
+	/* present on Ray cores only */
 	RGXFWIF_DM_RTU			= 5,
 	RGXFWIF_DM_SHG			= 6,
-#endif
+
 	RGXFWIF_DM_LAST,
 
 	RGXFWIF_DM_FORCE_I32  = 0x7fffffff   /*!< Force enum to be at least 32-bits wide */
 } RGXFWIF_DM;
 
+typedef enum _RGX_KICK_TYPE_DM_
+{
+	RGX_KICK_TYPE_DM_GP			= 1 << 0,
+	RGX_KICK_TYPE_DM_TDM_2D		= 1 << 1,
+	RGX_KICK_TYPE_DM_TA			= 1 << 2,
+	RGX_KICK_TYPE_DM_3D			= 1 << 3,
+	RGX_KICK_TYPE_DM_CDM		= 1 << 4,
+	RGX_KICK_TYPE_DM_RTU		= 1 << 5,
+	RGX_KICK_TYPE_DM_SHG		= 1 << 6,
+	RGX_KICK_TYPE_DM_TQ2D		= 1 << 7,
+	RGX_KICK_TYPE_DM_TQ3D		= 1 << 8,
+	RGX_KICK_TYPE_DM_LAST		= 1 << 9
+} RGX_KICK_TYPE_DM;
+
+/* Maximum number of DM in use: GP, 2D/TDM, TA, 3D, CDM, SHG, RTU */
+#define RGXFWIF_DM_DEFAULT_MAX	(7)
+
+#if !defined(__KERNEL__)
 #if defined(RGX_FEATURE_RAY_TRACING)
 #define RGXFWIF_DM_MAX_MTS 8
 #else
@@ -103,25 +124,37 @@
 #endif
 
 #if defined(RGX_FEATURE_RAY_TRACING)
-/* Maximum number of DM in use: GP, 2D, TA, 3D, CDM, SHG, RTU */
+/* Maximum number of DM in use: GP, 2D/TDM, TA, 3D, CDM, SHG, RTU */
 #define RGXFWIF_DM_MAX			(7)
 #else
+/* Maximum number of DM in use: GP, 2D/TDM, TA, 3D, CDM*/
 #define RGXFWIF_DM_MAX			(5)
 #endif
+#define RGXFWIF_HWDM_MAX		(RGXFWIF_DM_MAX)
+#else
+	#define RGXFWIF_DM_MIN_MTS_CNT (6)
+	#define RGXFWIF_RAY_TRACING_DM_MTS_CNT (2)
+	#define RGXFWIF_DM_MIN_CNT			(5)
+	#define RGXFWIF_RAY_TRACING_DM_CNT	(2)
+	#define RGXFWIF_DM_MAX	(RGXFWIF_DM_MIN_CNT + RGXFWIF_RAY_TRACING_DM_CNT)
+#endif
 
 /* Min/Max number of HW DMs (all but GP) */
 #if defined(RGX_FEATURE_TLA)
 #define RGXFWIF_HWDM_MIN		(1)
 #else
+#if defined(RGX_FEATURE_FASTRENDER_DM)
+#define RGXFWIF_HWDM_MIN		(1)
+#else
 #define RGXFWIF_HWDM_MIN		(2)
 #endif
-#define RGXFWIF_HWDM_MAX		(RGXFWIF_DM_MAX)
+#endif
 
 /*!
  ******************************************************************************
  * RGXFW Compiler alignment definitions
  *****************************************************************************/
-#if defined(__GNUC__)
+#if defined(__GNUC__) || defined(HAS_GNUC_ATTRIBUTES)
 #define RGXFW_ALIGN			__attribute__ ((aligned (8)))
 #elif defined(_MSC_VER)
 #define RGXFW_ALIGN			__declspec(align(8))
diff --git a/drivers/staging/imgtec/rogue/rgx_compat_bvnc.c b/drivers/staging/imgtec/rogue/rgx_compat_bvnc.c
index 2762d96..c361c1d 100644
--- a/drivers/staging/imgtec/rogue/rgx_compat_bvnc.c
+++ b/drivers/staging/imgtec/rogue/rgx_compat_bvnc.c
@@ -1,10 +1,8 @@
 /*************************************************************************/ /*!
-@File
-@Title          Functions for BVNC manipulating
-
+@File           rgx_compact_bvnc.c
+@Title          BVNC compatibility check utilities
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Utility functions used internally by device memory management
-                code.
+@Description    Utility functions used for packing BNC and V.
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -43,108 +41,178 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-/******************************************************************************
- * RGX Version packed into 24-bit (BNC) and string (V) to be used by Compatibility Check
- *****************************************************************************/
-
 #include "rgx_compat_bvnc.h"
+#if defined(RGX_FIRMWARE)
+#include "rgxfw_utils.h"
+#elif !defined(RGX_BUILD_BINARY)
+#include "pvr_debug.h"
+#endif
 
-void rgx_bvnc_packed(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
-					 IMG_UINT32 ui32B, IMG_CHAR *pszV, IMG_UINT32 ui32N, IMG_UINT32 ui32C)
+#if defined(RGX_FIRMWARE)
+#define PVR_COMPAT_ASSERT RGXFW_ASSERT
+#elif !defined(RGX_BUILD_BINARY)
+#define PVR_COMPAT_ASSERT PVR_ASSERT
+#else
+#include <assert.h>
+#define PVR_COMPAT_ASSERT assert
+#endif
+
+/**************************************************************************//**
+ * C library strlen function.
+ *****************************************************************************/
+static INLINE IMG_UINT32 OSStringLength(const IMG_CHAR* pszInput)
 {
-#if 0
-	IMG_UINT32 i = ui32OutVMaxLen;
-#endif
-	IMG_UINT32 ui32InVLen = 0;
-	IMG_UINT32 ui32V = 0;
+	const IMG_CHAR* pszTemp = pszInput;
 
-	*pui32OutBNC = (((ui32B & 0xFF) << 16) | ((ui32N & 0xFF) << 8) |
-												(ui32C & 0xFF));
+	while (*pszTemp)
+		pszTemp++;
 
-	/* Using dword accesses instead of byte accesses when forming V part of BVNC */
-	ui32OutVMaxLen = ui32OutVMaxLen;
-	while (pszV[ui32InVLen])
-	{
-		ui32V |= ((((IMG_UINT32)pszV[ui32InVLen]) & 0xFF) << (ui32InVLen*8));
-		ui32InVLen++;
-	}
-
-	*((IMG_UINT32 *)pszOutV) = ui32V;
-
-#if 0
-	for (i = 0; i < (ui32OutVMaxLen + 1); i++)
-		pszOutV[i] = '\0';
-
-	while ((ui32OutVMaxLen > 0) && *pszV)
-	{
-		*pszOutV++ = *pszV++;
-		ui32OutVMaxLen--;
-	}
-#endif
+	return (pszTemp - pszInput);
 }
 
-void rgx_bvnc_pack_hw(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
-					  IMG_UINT32 ui32B, IMG_CHAR *pszFwV, IMG_UINT32 ui32V, IMG_UINT32 ui32N, IMG_UINT32 ui32C)
+/**************************************************************************//**
+ * Utility function for packing BNC
+ *****************************************************************************/
+static INLINE IMG_UINT64 rgx_bnc_pack(IMG_UINT32 ui32B, IMG_UINT32 ui32N,
+														IMG_UINT32 ui32C)
 {
-	IMG_UINT32 i = ui32OutVMaxLen;
-	IMG_CHAR *pszPointer;
+	/*
+	 * Test for input B, N and C exceeding max bit width.
+	 */
+	PVR_COMPAT_ASSERT((ui32B & (~(RGX_BVNC_PACK_MASK_B >> RGX_BVNC_PACK_SHIFT_B))) == 0);
+	PVR_COMPAT_ASSERT((ui32N & (~(RGX_BVNC_PACK_MASK_N >> RGX_BVNC_PACK_SHIFT_N))) == 0);
+	PVR_COMPAT_ASSERT((ui32C & (~(RGX_BVNC_PACK_MASK_C >> RGX_BVNC_PACK_SHIFT_C))) == 0);
 
-	*pui32OutBNC = (((ui32B & 0xFF) << 16) | ((ui32N & 0xFF) << 8) |
-												(ui32C & 0xFF));
+	return (((IMG_UINT64)ui32B << RGX_BVNC_PACK_SHIFT_B) |
+			((IMG_UINT64)ui32N << RGX_BVNC_PACK_SHIFT_N) |
+			((IMG_UINT64)ui32C << RGX_BVNC_PACK_SHIFT_C));
+}
 
-	for (i = 0; i < (ui32OutVMaxLen + 1); i++)
-		pszOutV[i] = '\0';
+/**************************************************************************//**
+ * Utility function for packing BNC and V to be used by compatibility check.
+ * BNC is packed into 48 bit format.
+ * If the array pointed to by pszV is a string that is shorter than 
+ * ui32OutVMaxLen characters, null characters are appended to the copy in the
+ * array pointed to by pszOutV, until 'ui32OutVMaxLen' characters in all have
+ * been written.
+ *
+ * @param:      pui64OutBNC       Output containing packed BNC.
+ * @param       pszOutV           Output containing version string.
+ * @param       ui32OutVMaxLen    Max characters that can be written to 
+                                  pszOutV (excluding terminating null character)
+ * @param       ui32B             Input 'B' value
+ * @param       pszV              Input 'V' string
+ * @param       ui32N             Input 'N' value
+ * @param       ui32C             Input 'C' value
+ * @return      None
+ *****************************************************************************/
+void rgx_bvnc_packed(IMG_UINT64 *pui64OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+					 IMG_UINT32 ui32B, IMG_CHAR *pszV, IMG_UINT32 ui32N, IMG_UINT32 ui32C)
+{
+	*pui64OutBNC = rgx_bnc_pack(ui32B, ui32N, ui32C);
 
-	/* find out whether pszFwV is integer number or not */
-	pszPointer = pszFwV;
-	while (*pszPointer)
+	if (!pszOutV)
+		return;
+
+	if (pszV)
 	{
-		if ((*pszPointer < '0') || (*pszPointer > '9'))
-		{
-			break;
-		}
-		pszPointer++;
-	}
+		/*
+		 * Assert can fail for two reasons
+		 * 1. Caller is passing invalid 'V' string or
+		 * 2. Dest buffer does not have enough memory allocated for max 'V' size.
+		 */
+		PVR_COMPAT_ASSERT(OSStringLength(pszV) <= ui32OutVMaxLen);
 
-	if (*pszPointer)
-	{
-		/* pszFwV is not a number, so taking V from it */
-		pszPointer = pszFwV;
-		while ((ui32OutVMaxLen > 0) && *pszPointer)
-		{
-			*pszOutV++ = *pszPointer++;
-			ui32OutVMaxLen--;
-		}
-	}
-	else
-	{
-		/* pszFwV is a number, taking V from ui32V */
-		IMG_CHAR aszBuf[4];
-
-		pszPointer = aszBuf;
-
-		if (ui32V > 99)
-			pszPointer+=3;
-		else if (ui32V > 9)
-			pszPointer+=2;
-		else
-			pszPointer+=1;
-
-		*pszPointer-- = '\0';
-		*pszPointer = '0';
-
-		while (ui32V > 0)
-		{
-			*pszPointer-- = (ui32V % 10) + '0';
-			ui32V /= 10;
-		}
 		
-		pszPointer = aszBuf;
-		while ((ui32OutVMaxLen > 0) && *pszPointer)
+		for (; ui32OutVMaxLen > 0 && *pszV != '\0'; --ui32OutVMaxLen)
 		{
-			*pszOutV++ = *pszPointer++;
-			ui32OutVMaxLen--;
+			/* When copying the V, omit any characters as these would cause
+			 * the compatibility check against the V read from HW to fail
+			 */
+			if (*pszV && (*pszV >= '0') && (*pszV <='9'))
+			{
+				*pszOutV++ = *pszV++;
+			}
+			else
+			{
+				pszV++;
+			}
 		}
 	}
+
+	do
+	{
+		*pszOutV++ = '\0';
+	}while(ui32OutVMaxLen-- > 0);
+}
+
+/**************************************************************************//**
+ * Utility function for packing BNC and V to be used by compatibility check.
+ * Input B,N and C is packed into 48 bit format.
+ * Input V is converted into string. If number of characters required to
+ * represent 16 bit wide version number is less than ui32OutVMaxLen, than null
+ * characters are appended to pszOutV, until ui32OutVMaxLen characters in all 
+ * have been written.
+ *
+ * @param:      pui64OutBNC       Output containing packed BNC.
+ * @param       pszOutV           Output containing version string.
+ * @param       ui32OutVMaxLen    Max characters that can be written to 
+                                  pszOutV (excluding terminating null character)
+ * @param       ui32B             Input 'B' value (16 bit wide)
+ * @param       ui32V             Input 'V' value (16 bit wide)
+ * @param       ui32N             Input 'N' value (16 bit wide)
+ * @param       ui32C             Input 'C' value (16 bit wide)
+ * @return     .None
+ *****************************************************************************/
+void rgx_bvnc_pack_hw(IMG_UINT64 *pui64OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+					  IMG_UINT32 ui32B, IMG_UINT32 ui32V, IMG_UINT32 ui32N, IMG_UINT32 ui32C)
+{
+	/*
+	 * Allocate space for max digits required to represent 16 bit wide version
+	 * number (including NULL terminating character).
+	 */
+	IMG_CHAR aszBuf[6];
+	IMG_CHAR *pszPointer = aszBuf;
+
+	*pui64OutBNC = rgx_bnc_pack(ui32B, ui32N, ui32C);
+
+	if (!pszOutV)
+		return;
+
+	/*
+	 * Function only supports 16 bits wide version number.
+	 */
+	PVR_COMPAT_ASSERT((ui32V & ~0xFFFF) == 0);
+
+	if (ui32V > 9999)
+		pszPointer+=5;
+	else if (ui32V > 999)
+		pszPointer+=4;
+	else if (ui32V > 99)
+		pszPointer+=3;
+	else if (ui32V > 9)
+		pszPointer+=2;
+	else
+		pszPointer+=1;
+	
+	*pszPointer-- = '\0';
+	*pszPointer = '0';
+	
+	while (ui32V > 0)
+	{
+		*pszPointer-- = (ui32V % 10) + '0';
+		ui32V /= 10;
+	}
+
+	for (pszPointer = aszBuf; ui32OutVMaxLen > 0 && *pszPointer != '\0'; --ui32OutVMaxLen)
+		*pszOutV++ = *pszPointer++;
+
+	/*
+	 * Append NULL characters.
+	 */
+	do
+	{
+		*pszOutV++ = '\0';
+	}while(ui32OutVMaxLen-- > 0);
 }
 
diff --git a/drivers/staging/imgtec/rogue/rgx_compat_bvnc.h b/drivers/staging/imgtec/rogue/rgx_compat_bvnc.h
index cee2d09..51e5d76 100644
--- a/drivers/staging/imgtec/rogue/rgx_compat_bvnc.h
+++ b/drivers/staging/imgtec/rogue/rgx_compat_bvnc.h
@@ -48,19 +48,50 @@
 
 #include "img_types.h"
 
+/* 64bit endian converting macros */
+#if defined(__BIG_ENDIAN__)
+#define RGX_INT64_TO_BE(N) (N)
+#define RGX_INT64_FROM_BE(N) (N)
+#define RGX_INT32_TO_BE(N) (N)
+#define RGX_INT32_FROM_BE(N) (N)
+#else
+#define RGX_INT64_TO_BE(N)        \
+	((((N) >> 56)   & 0xff)       \
+	 | (((N) >> 40) & 0xff00)     \
+	 | (((N) >> 24) & 0xff0000)   \
+	 | (((N) >> 8)  & 0xff000000) \
+	 | ((N)                << 56) \
+	 | (((N) & 0xff00)     << 40) \
+	 | (((N) & 0xff0000)   << 24) \
+	 | (((N) & 0xff000000) << 8))
+#define RGX_INT64_FROM_BE(N) RGX_INT64_TO_BE(N)
+
+#define RGX_INT32_TO_BE(N)   \
+	((((N) >> 24)  & 0xff)   \
+	 | (((N) >> 8) & 0xff00) \
+	 | ((N)           << 24) \
+	 | (((N & 0xff00) << 8)))
+#define RGX_INT32_FROM_BE(N) RGX_INT32_TO_BE(N)
+#endif
+
 /******************************************************************************
  * RGX Version packed into 24-bit (BNC) and string (V) to be used by Compatibility Check
  *****************************************************************************/
 
-#define RGX_BVNC_PACK_MASK_B 0x00FF0000
-#define RGX_BVNC_PACK_MASK_N 0x0000FF00
-#define RGX_BVNC_PACK_MASK_C 0x000000FF
+#define RGX_BVNC_PACK_SHIFT_B 32
+#define RGX_BVNC_PACK_SHIFT_N 16
+#define RGX_BVNC_PACK_SHIFT_C 0
 
-#define RGX_BVNC_PACKED_EXTR_B(BVNC) (((BVNC).ui32BNC >> 16) & 0xFF)
+#define RGX_BVNC_PACK_MASK_B (IMG_UINT64_C(0x0000FFFF00000000))
+#define RGX_BVNC_PACK_MASK_N (IMG_UINT64_C(0x00000000FFFF0000))
+#define RGX_BVNC_PACK_MASK_C (IMG_UINT64_C(0x000000000000FFFF))
+
+#define RGX_BVNC_PACKED_EXTR_B(BVNC) ((IMG_UINT32)(((BVNC).ui64BNC & RGX_BVNC_PACK_MASK_B) >> RGX_BVNC_PACK_SHIFT_B))
 #define RGX_BVNC_PACKED_EXTR_V(BVNC) ((BVNC).aszV)
-#define RGX_BVNC_PACKED_EXTR_N(BVNC) (((BVNC).ui32BNC >> 8) & 0xFF)
-#define RGX_BVNC_PACKED_EXTR_C(BVNC) (((BVNC).ui32BNC >> 0) & 0xFF)
+#define RGX_BVNC_PACKED_EXTR_N(BVNC) ((IMG_UINT32)(((BVNC).ui64BNC & RGX_BVNC_PACK_MASK_N) >> RGX_BVNC_PACK_SHIFT_N))
+#define RGX_BVNC_PACKED_EXTR_C(BVNC) ((IMG_UINT32)(((BVNC).ui64BNC & RGX_BVNC_PACK_MASK_C) >> RGX_BVNC_PACK_SHIFT_C))
 
+#if !defined(RGX_SKIP_BVNC_CHECK)
 #define RGX_BVNC_EQUAL(L,R,all,version,lenmax,bnc,v) do {													\
 										(lenmax) = IMG_FALSE;												\
 										(bnc) = IMG_FALSE;													\
@@ -72,7 +103,7 @@
 										}																	\
 										if (lenmax)															\
 										{																	\
-											(bnc) = ((L).ui32BNC == (R).ui32BNC);							\
+											(bnc) = ((L).ui64BNC == (R).ui64BNC);							\
 										}																	\
 										if (bnc)															\
 										{																	\
@@ -82,11 +113,20 @@
 										}																	\
 										(all) = (version) && (lenmax) && (bnc) && (v);						\
 									} while (0)
+#else
+#define RGX_BVNC_EQUAL(L,R,all,version,lenmax,bnc,v)														\
+						(all) 		= IMG_TRUE;																\
+						(version) 	= IMG_TRUE;																\
+						(lenmax) 	= IMG_TRUE;																\
+						(bnc) 		= IMG_TRUE;																\
+						(v) 		= IMG_TRUE;																\
 
-void rgx_bvnc_packed(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+#endif
+
+void rgx_bvnc_packed(IMG_UINT64 *pui64OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
 					 IMG_UINT32 ui32B, IMG_CHAR *pszV, IMG_UINT32 ui32N, IMG_UINT32 ui32C);
-void rgx_bvnc_pack_hw(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
-					  IMG_UINT32 ui32B, IMG_CHAR *pszFwV, IMG_UINT32 ui32V, IMG_UINT32 ui32N, IMG_UINT32 ui32C);
+void rgx_bvnc_pack_hw(IMG_UINT64 *pui64OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+					  IMG_UINT32 ui32B, IMG_UINT32 ui32V, IMG_UINT32 ui32N, IMG_UINT32 ui32C);
 
 #endif /*  __RGX_COMPAT_BVNC_H__ */
 
diff --git a/drivers/staging/imgtec/rogue/rgx_firmware_processor.h b/drivers/staging/imgtec/rogue/rgx_firmware_processor.h
index 97a53f8..2b2daef 100644
--- a/drivers/staging/imgtec/rogue/rgx_firmware_processor.h
+++ b/drivers/staging/imgtec/rogue/rgx_firmware_processor.h
@@ -48,10 +48,45 @@
 
 #include "km/rgxdefs_km.h"
 
-#if defined(RGX_FEATURE_META)
 #include "rgx_meta.h"
-#else
 #include "rgx_mips.h"
+
+/* Processor independent need to be defined here common for all processors */
+typedef enum
+{
+	FW_PERF_CONF_NONE = 0,
+	FW_PERF_CONF_ICACHE = 1,
+	FW_PERF_CONF_DCACHE = 2,
+	FW_PERF_CONF_POLLS = 3,
+	FW_PERF_CONF_CUSTOM_TIMER = 4,
+	FW_PERF_CONF_JTLB_INSTR = 5,
+	FW_PERF_CONF_INSTRUCTIONS = 6
+} FW_PERF_CONF;
+
+#if !defined(__KERNEL__)
+	#if defined(RGX_FEATURE_MIPS)
+
+		#define FW_CORE_ID_VALUE                                      RGXMIPSFW_CORE_ID_VALUE
+		#define RGXFW_PROCESSOR                                       RGXFW_PROCESSOR_MIPS
+
+		/* Firmware to host interrupts defines */
+		#define RGXFW_CR_IRQ_STATUS                                   RGX_CR_MIPS_WRAPPER_IRQ_STATUS
+		#define RGXFW_CR_IRQ_STATUS_EVENT_EN                          RGX_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN
+		#define RGXFW_CR_IRQ_CLEAR                                    RGX_CR_MIPS_WRAPPER_IRQ_CLEAR
+		#define RGXFW_CR_IRQ_CLEAR_MASK                               RGX_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN
+
+	#else
+
+		#define RGXFW_PROCESSOR         RGXFW_PROCESSOR_META
+
+		/* Firmware to host interrupts defines */
+		#define RGXFW_CR_IRQ_STATUS           RGX_CR_META_SP_MSLVIRQSTATUS
+		#define RGXFW_CR_IRQ_STATUS_EVENT_EN  RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN
+		#define RGXFW_CR_IRQ_CLEAR            RGX_CR_META_SP_MSLVIRQSTATUS
+		#define RGXFW_CR_IRQ_CLEAR_MASK       (RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK & \
+													RGX_CR_META_SP_MSLVIRQSTATUS_MASKFULL)
+
+	#endif
 #endif
 
 #endif /* RGX_FIRMWARE_PROCESSOR_H */
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif.h b/drivers/staging/imgtec/rogue/rgx_fwif.h
index 78f26e80..04d01f9 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif.h
@@ -46,7 +46,6 @@
 
 #include "rgx_firmware_processor.h"
 #include "rgx_fwif_shared.h"
-#include "pvr_tlcommon.h"
 
 /*************************************************************************/ /*!
  Logging type
@@ -71,7 +70,7 @@
 #define RGXFWIF_LOG_TYPE_MASK			0x80003FFF
 
 /* String used in pvrdebug -h output */
-#define RGXFWIF_LOG_GROUPS_STRING_LIST   "main,mts,cleanup,csw,bif,pm,rtd,spm,pow,hwr,hwp"
+#define RGXFWIF_LOG_GROUPS_STRING_LIST   "main,mts,cleanup,csw,bif,pm,rtd,spm,pow,hwr,hwp,rpm,dma,debug"
 
 /* Table entry to map log group strings to log type value */
 typedef struct {
@@ -83,7 +82,8 @@
   Macro for use with the RGXFWIF_LOG_GROUP_MAP_ENTRY type to create a lookup
   table where needed. Keep log group names short, no more than 20 chars.
 */
-#define RGXFWIF_LOG_GROUP_NAME_VALUE_MAP { "main",    RGXFWIF_LOG_TYPE_GROUP_MAIN }, \
+#define RGXFWIF_LOG_GROUP_NAME_VALUE_MAP { "none",    RGXFWIF_LOG_TYPE_NONE }, \
+                                         { "main",    RGXFWIF_LOG_TYPE_GROUP_MAIN }, \
                                          { "mts",     RGXFWIF_LOG_TYPE_GROUP_MTS }, \
                                          { "cleanup", RGXFWIF_LOG_TYPE_GROUP_CLEANUP }, \
                                          { "csw",     RGXFWIF_LOG_TYPE_GROUP_CSW }, \
@@ -94,7 +94,7 @@
                                          { "pow",     RGXFWIF_LOG_TYPE_GROUP_POW }, \
                                          { "hwr",     RGXFWIF_LOG_TYPE_GROUP_HWR }, \
                                          { "hwp",     RGXFWIF_LOG_TYPE_GROUP_HWP }, \
-                                         { "rpm",	  RGXFWIF_LOG_TYPE_GROUP_RPM }, \
+                                         { "rpm",     RGXFWIF_LOG_TYPE_GROUP_RPM }, \
                                          { "dma",     RGXFWIF_LOG_TYPE_GROUP_DMA }, \
                                          { "debug",   RGXFWIF_LOG_TYPE_GROUP_DEBUG }
 
@@ -123,21 +123,24 @@
 typedef void (*PFN_RGXFW_LOG) (const IMG_CHAR* pszFmt, ...);
 
 
+/************************************************************************
+* RGX FW signature checks
+************************************************************************/
+#define RGXFW_SIG_BUFFER_SIZE_MIN       (1024)
+
 /*!
  ******************************************************************************
  * HWPERF
  *****************************************************************************/
 /* Size of the Firmware L1 HWPERF buffer in bytes (2MB). Accessed by the
  * Firmware and host driver. */
-#define RGXFW_HWPERF_L1_SIZE_MIN		(0x004000)
-#define RGXFW_HWPERF_L1_SIZE_DEFAULT    (0x200000)
-#define RGXFW_HWPERF_L1_SIZE_MAX        (0xC00000)
+#define RGXFW_HWPERF_L1_SIZE_MIN        (16U)
+#define RGXFW_HWPERF_L1_SIZE_DEFAULT    (2048U)
+#define RGXFW_HWPERF_L1_SIZE_MAX        (12288U)
 
-/* This padding value must always be greater than or equal to
- * RGX_HWPERF_V2_MAX_PACKET_SIZE for all valid BVNCs. This is asserted in
- * rgxsrvinit.c. This macro is defined with a constant to avoid a KM
- * dependency */
-#define RGXFW_HWPERF_L1_PADDING_DEFAULT (0x800)
+/* This padding value must always be large enough to hold the biggest
+ * variable sized packet. */
+#define RGXFW_HWPERF_L1_PADDING_DEFAULT (RGX_HWPERF_MAX_PACKET_SIZE)
 
 
 /*!
@@ -151,7 +154,11 @@
 /*! Total size of RGXFWIF_TRACEBUF dword (needs to be a multiple of RGXFW_TRACE_BUFFER_LINESIZE) */
 #define RGXFW_TRACE_BUFFER_SIZE		(400*RGXFW_TRACE_BUFFER_LINESIZE)
 #define RGXFW_TRACE_BUFFER_ASSERT_SIZE 200
+#if defined(RGXFW_META_SUPPORT_2ND_THREAD)
+#define RGXFW_THREAD_NUM 2
+#else
 #define RGXFW_THREAD_NUM 1
+#endif
 
 #define RGXFW_POLL_TYPE_SET 0x80000000
 
@@ -191,15 +198,15 @@
 
 /* Firmware HWR states */
 #define RGXFWIF_HWR_HARDWARE_OK		(0x1 << 0)	/*!< Tells if the HW state is ok or locked up */
-#define RGXFWIF_HWR_FREELIST_OK		(0x1 << 1)	/*!< Tells if the freelists are ok or being reconstructed */
 #define RGXFWIF_HWR_ANALYSIS_DONE	(0x1 << 2)	/*!< Tells if the analysis of a GPU lockup has already been performed */
 #define RGXFWIF_HWR_GENERAL_LOCKUP	(0x1 << 3)	/*!< Tells if a DM unrelated lockup has been detected */
+#define RGXFWIF_HWR_DM_RUNNING_OK	(0x1 << 4)	/*!< Tells if at least one DM is running without being close to a lockup */
+#define RGXFWIF_HWR_DM_STALLING		(0x1 << 5)	/*!< Tells if at least one DM is close to lockup */
 typedef IMG_UINT32 RGXFWIF_HWR_STATEFLAGS;
 
 /* Firmware per-DM HWR states */
 #define RGXFWIF_DM_STATE_WORKING 					(0x00)		/*!< DM is working if all flags are cleared */
 #define RGXFWIF_DM_STATE_READY_FOR_HWR 				(0x1 << 0)	/*!< DM is idle and ready for HWR */
-#define RGXFWIF_DM_STATE_NEEDS_FL_RECONSTRUCTION	(0x1 << 1)	/*!< DM need FL reconstruction before resuming processing */
 #define RGXFWIF_DM_STATE_NEEDS_SKIP					(0x1 << 2)	/*!< DM need to skip to next cmd before resuming processing */
 #define RGXFWIF_DM_STATE_NEEDS_PR_CLEANUP			(0x1 << 3)	/*!< DM need partial render cleanup before resuming processing */
 #define RGXFWIF_DM_STATE_NEEDS_TRACE_CLEAR			(0x1 << 4)	/*!< DM need to increment Recovery Count once fully recovered */
@@ -207,6 +214,13 @@
 #define RGXFWIF_DM_STATE_INNOCENT_LOCKUP			(0x1 << 6)	/*!< DM was innocently affected by another lockup which caused HWR */
 #define RGXFWIF_DM_STATE_GUILTY_OVERRUNING			(0x1 << 7)	/*!< DM was identified as over-running and causing HWR */
 #define RGXFWIF_DM_STATE_INNOCENT_OVERRUNING		(0x1 << 8)	/*!< DM was innocently affected by another DM over-running which caused HWR */
+
+/* Per-OSid States */
+#define RGXFW_OS_STATE_ACTIVE_OS						(1 << 0)    /*!< Non active operating systems should not be served by the FW */
+#define RGXFW_OS_STATE_FREELIST_OK						(1 << 1)    /*!< Pending freelist reconstruction from that particular OS */
+#define RGXFW_OS_STATE_OFFLOADING						(1 << 2)    /*!< Transient state while all the OS resources in the FW are cleaned up */
+#define RGXFW_OS_STATE_GROW_REQUEST_PENDING				(1 << 3)    /*!< Signifies whether a request to grow a freelist is pending completion */
+
 typedef IMG_UINT32 RGXFWIF_HWR_RECOVERYFLAGS;
 
 typedef struct _RGXFWIF_TRACEBUF_
@@ -215,23 +229,23 @@
 	volatile RGXFWIF_POW_STATE		ePowState;
 	RGXFWIF_TRACEBUF_SPACE	sTraceBuf[RGXFW_THREAD_NUM];
 
-	IMG_UINT16				aui16HwrDmLockedUpCount[RGXFWIF_DM_MAX];
-	IMG_UINT16				aui16HwrDmOverranCount[RGXFWIF_DM_MAX];
-	IMG_UINT16				aui16HwrDmRecoveredCount[RGXFWIF_DM_MAX];
-	IMG_UINT16				aui16HwrDmFalseDetectCount[RGXFWIF_DM_MAX];
+	IMG_UINT32				aui32HwrDmLockedUpCount[RGXFWIF_DM_DEFAULT_MAX];
+	IMG_UINT32				aui32HwrDmOverranCount[RGXFWIF_DM_DEFAULT_MAX];
+	IMG_UINT32				aui32HwrDmRecoveredCount[RGXFWIF_DM_DEFAULT_MAX];
+	IMG_UINT32				aui32HwrDmFalseDetectCount[RGXFWIF_DM_DEFAULT_MAX];
 	IMG_UINT32				ui32HwrCounter;
 
 	IMG_UINT32				aui32CrPollAddr[RGXFW_THREAD_NUM];
 	IMG_UINT32				aui32CrPollMask[RGXFW_THREAD_NUM];
 
 	RGXFWIF_HWR_STATEFLAGS		ui32HWRStateFlags;
-	RGXFWIF_HWR_RECOVERYFLAGS	aui32HWRRecoveryFlags[RGXFWIF_HWDM_MAX];
+	RGXFWIF_HWR_RECOVERYFLAGS	aui32HWRRecoveryFlags[RGXFWIF_DM_DEFAULT_MAX];
 
 	volatile IMG_UINT32		ui32HWPerfRIdx;
 	volatile IMG_UINT32		ui32HWPerfWIdx;
 	volatile IMG_UINT32		ui32HWPerfWrapCount;
-	IMG_UINT32				ui32HWPerfSize;      /* Constant after setup, needed in FW */
-	IMG_UINT32				ui32HWPerfDropCount; /* The number of times the FW drops a packet due to buffer full */
+	IMG_UINT32				ui32HWPerfSize;       /* Constant after setup, needed in FW */
+	IMG_UINT32				ui32HWPerfDropCount;  /* The number of times the FW drops a packet due to buffer full */
 
 	/* These next three items are only valid at runtime when the FW is built
 	 * with RGX_HWPERF_UTILIZATION & RGX_HWPERF_DROP_TRACKING defined
@@ -240,7 +254,7 @@
 	IMG_UINT32				ui32FirstDropOrdinal;/* The ordinal of the first packet the FW dropped */
 	IMG_UINT32              ui32LastDropOrdinal; /* The ordinal of the last packet the FW dropped */
 
-	volatile IMG_UINT32			ui32InterruptCount;
+	volatile IMG_UINT32			aui32InterruptCount[RGXFW_THREAD_NUM]; /*!< Interrupt count from Threads > */
 	IMG_UINT32				ui32KCCBCmdsExecuted;
 	IMG_UINT64 RGXFW_ALIGN			ui64StartIdleTime;
 	IMG_UINT32				ui32PowMonEnergy;	/* Non-volatile power monitor energy count */
@@ -248,6 +262,10 @@
 #define RGXFWIF_MAX_PCX 16
 	IMG_UINT32				ui32T1PCX[RGXFWIF_MAX_PCX];
 	IMG_UINT32				ui32T1PCXWOff;
+
+	IMG_UINT32                  ui32OSStateFlags[RGXFW_NUM_OS];		/*!< State flags for each Operating System > */
+
+	IMG_UINT32				ui32MMUFlushCounter;
 } UNCACHED_ALIGN RGXFWIF_TRACEBUF;
 
 
@@ -321,28 +339,22 @@
 	RGX_HWRTYPE_UNKNOWNFAILURE  = 0,
 	RGX_HWRTYPE_OVERRUN         = 1,
 	RGX_HWRTYPE_POLLFAILURE     = 2,
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 	RGX_HWRTYPE_BIF0FAULT       = 3,
 	RGX_HWRTYPE_BIF1FAULT       = 4,
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 	RGX_HWRTYPE_TEXASBIF0FAULT	= 5,
-#endif
-#if defined(RGX_FEATURE_RAY_TRACING)
 	RGX_HWRTYPE_DPXMMUFAULT		= 6,
-#endif
-#else
 	RGX_HWRTYPE_MMUFAULT        = 7,
 	RGX_HWRTYPE_MMUMETAFAULT    = 8,
-#endif
 } RGX_HWRTYPE;
 
-#define RGXFWIF_BIFFAULTBIT_GET(ui32BIFMMUStatus) \
-		((ui32BIFMMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_CLRMSK) >> RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_SHIFT)
-#define RGXFWIF_MMUFAULTBIT_GET(ui32BIFMMUStatus) \
-		((ui32BIFMMUStatus & ~RGX_CR_MMU_FAULT_STATUS_FAULT_CLRMSK) >> RGX_CR_MMU_FAULT_STATUS_FAULT_SHIFT)
-
 #define RGXFWIF_HWRTYPE_BIF_BANK_GET(eHWRType) ((eHWRType == RGX_HWRTYPE_BIF0FAULT) ? 0 : 1 )
 
+#define RGXFWIF_HWRTYPE_PAGE_FAULT_GET(eHWRType) ((eHWRType == RGX_HWRTYPE_BIF0FAULT      ||       \
+                                                   eHWRType == RGX_HWRTYPE_BIF1FAULT      ||       \
+                                                   eHWRType == RGX_HWRTYPE_TEXASBIF0FAULT ||       \
+                                                   eHWRType == RGX_HWRTYPE_MMUFAULT       ||       \
+                                                   eHWRType == RGX_HWRTYPE_MMUMETAFAULT) ? 1 : 0 )
+
 typedef struct _RGX_BIFINFO_
 {
 	IMG_UINT64	RGXFW_ALIGN		ui64BIFReqStatus;
@@ -382,6 +394,10 @@
 	IMG_UINT32             ui32HWRRecoveryFlags;
 	RGX_HWRTYPE            eHWRType;
 	RGXFWIF_DM             eDM;
+	IMG_UINT64 RGXFW_ALIGN ui64CRTimeOfKick;
+	IMG_UINT64 RGXFW_ALIGN ui64CRTimeHWResetStart;
+	IMG_UINT64 RGXFW_ALIGN ui64CRTimeHWResetFinish;
+	IMG_UINT64 RGXFW_ALIGN ui64CRTimeFreelistReady;
 } UNCACHED_ALIGN RGX_HWRINFO;
 
 #define RGXFWIF_HWINFO_MAX_FIRST 8							/* Number of first HWR logs recorded (never overwritten by newer logs) */
@@ -408,44 +424,48 @@
  ******************************************************************************
  * RGX firmware Init Config Data
  *****************************************************************************/
-#define RGXFWIF_INICFG_CTXSWITCH_TA_EN		(0x1 << 0)
-#define RGXFWIF_INICFG_CTXSWITCH_3D_EN		(0x1 << 1)
-#define RGXFWIF_INICFG_CTXSWITCH_CDM_EN		(0x1 << 2)
-#define RGXFWIF_INICFG_CTXSWITCH_MODE_RAND	(0x1 << 3)
-#define RGXFWIF_INICFG_CTXSWITCH_SRESET_EN	(0x1 << 4)
-#define RGXFWIF_INICFG_RSVD					(0x1 << 5)
-#define RGXFWIF_INICFG_POW_RASCALDUST		(0x1 << 6)
-#define RGXFWIF_INICFG_HWPERF_EN			(0x1 << 7)
-#define RGXFWIF_INICFG_HWR_EN				(0x1 << 8)
-#define RGXFWIF_INICFG_CHECK_MLIST_EN		(0x1 << 9)
-#define RGXFWIF_INICFG_DISABLE_CLKGATING_EN (0x1 << 10)
-#define RGXFWIF_INICFG_POLL_COUNTERS_EN		(0x1 << 11)
+#define RGXFWIF_INICFG_CTXSWITCH_TA_EN				(0x1 << 0)
+#define RGXFWIF_INICFG_CTXSWITCH_3D_EN				(0x1 << 1)
+#define RGXFWIF_INICFG_CTXSWITCH_CDM_EN				(0x1 << 2)
+#define RGXFWIF_INICFG_CTXSWITCH_MODE_RAND			(0x1 << 3)
+#define RGXFWIF_INICFG_CTXSWITCH_SRESET_EN			(0x1 << 4)
+#define RGXFWIF_INICFG_RSVD							(0x1 << 5)
+#define RGXFWIF_INICFG_POW_RASCALDUST				(0x1 << 6)
+#define RGXFWIF_INICFG_HWPERF_EN					(0x1 << 7)
+#define RGXFWIF_INICFG_HWR_EN						(0x1 << 8)
+#define RGXFWIF_INICFG_CHECK_MLIST_EN				(0x1 << 9)
+#define RGXFWIF_INICFG_DISABLE_CLKGATING_EN 		(0x1 << 10)
+#define RGXFWIF_INICFG_POLL_COUNTERS_EN				(0x1 << 11)
 #define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX		(RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INDEX << 12)
 #define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE	(RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INSTANCE << 12)
 #define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST		(RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_LIST << 12)
 #define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_CLRMSK	(0xFFFFCFFFU)
 #define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT		(12)
-#define RGXFWIF_INICFG_SHG_BYPASS_EN		(0x1 << 14)
-#define RGXFWIF_INICFG_RTU_BYPASS_EN		(0x1 << 15)
-#define RGXFWIF_INICFG_REGCONFIG_EN		(0x1 << 16)
-#define RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY	(0x1 << 17)
-#define RGXFWIF_INICFG_HWP_DISABLE_FILTER	(0x1 << 18)
-#define RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN	(0x1 << 19)
-#define RGXFWIF_INICFG_CDM_KILL_MODE_RAND_EN	(0x1 << 20)
-#define RGXFWIF_INICFG_DISABLE_DM_OVERLAP	(0x1 << 21)
-#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_FAST		(RGXFWIF_CTXSWITCH_PROFILE_FAST_EN << 22)
-#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_MEDIUM		(RGXFWIF_CTXSWITCH_PROFILE_MEDIUM_EN << 22)
-#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_SLOW		(RGXFWIF_CTXSWITCH_PROFILE_SLOW_EN << 22)
-#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_NODELAY	(RGXFWIF_CTXSWITCH_PROFILE_NODELAY_EN << 22)
-#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK		(0x7 << 22)
+#define RGXFWIF_INICFG_SHG_BYPASS_EN				(0x1 << 14)
+#define RGXFWIF_INICFG_RTU_BYPASS_EN				(0x1 << 15)
+#define RGXFWIF_INICFG_REGCONFIG_EN					(0x1 << 16)
+#define RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY		(0x1 << 17)
+#define RGXFWIF_INICFG_HWP_DISABLE_FILTER			(0x1 << 18)
+#define RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN			(0x1 << 19)
+#define RGXFWIF_INICFG_CDM_KILL_MODE_RAND_EN		(0x1 << 20)
+#define RGXFWIF_INICFG_DISABLE_DM_OVERLAP			(0x1 << 21)
 #define RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT		(22)
-#define RGXFWIF_INICFG_METAT1_SHIFT         (25)
-#define RGXFWIF_INICFG_METAT1_MAIN          (RGX_META_T1_MAIN  << RGXFWIF_INICFG_METAT1_SHIFT)
-#define RGXFWIF_INICFG_METAT1_DUMMY         (RGX_META_T1_DUMMY << RGXFWIF_INICFG_METAT1_SHIFT)
-#define RGXFWIF_INICFG_METAT1_ENABLED       (RGXFWIF_INICFG_METAT1_MAIN | RGXFWIF_INICFG_METAT1_DUMMY)
-#define RGXFWIF_INICFG_METAT1_MASK          (RGXFWIF_INICFG_METAT1_ENABLED >> RGXFWIF_INICFG_METAT1_SHIFT)
-#define RGXFWIF_INICFG_NEXT					(0x0 << 27) /* to be used for the next inicfg */
-#define RGXFWIF_INICFG_ALL					(0x07FFFFDFU)
+#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_FAST		(RGXFWIF_CTXSWITCH_PROFILE_FAST_EN << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
+#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_MEDIUM		(RGXFWIF_CTXSWITCH_PROFILE_MEDIUM_EN << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
+#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_SLOW		(RGXFWIF_CTXSWITCH_PROFILE_SLOW_EN << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
+#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_NODELAY	(RGXFWIF_CTXSWITCH_PROFILE_NODELAY_EN << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
+#define RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK		(0x7 << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
+#define RGXFWIF_INICFG_METAT1_SHIFT					(25)
+#define RGXFWIF_INICFG_METAT1_MAIN					(RGX_META_T1_MAIN  << RGXFWIF_INICFG_METAT1_SHIFT)
+#define RGXFWIF_INICFG_METAT1_DUMMY					(RGX_META_T1_DUMMY << RGXFWIF_INICFG_METAT1_SHIFT)
+#define RGXFWIF_INICFG_METAT1_ENABLED				(RGXFWIF_INICFG_METAT1_MAIN | RGXFWIF_INICFG_METAT1_DUMMY)
+#define RGXFWIF_INICFG_METAT1_MASK					(RGXFWIF_INICFG_METAT1_ENABLED >> RGXFWIF_INICFG_METAT1_SHIFT)
+#define RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER		(0x1 << 27)
+#define RGXFWIF_INICFG_WORKEST_V1					(0x1 << 28)
+#define RGXFWIF_INICFG_WORKEST_V2					(0x1 << 29)
+#define RGXFWIF_INICFG_PDVFS_V1						(0x1 << 30)
+#define RGXFWIF_INICFG_PDVFS_V2						(0x1 << 31)
+#define RGXFWIF_INICFG_ALL							(0xFFFFFFDFU)
 
 #define RGXFWIF_SRVCFG_DISABLE_PDP_EN 		(0x1 << 31)
 #define RGXFWIF_SRVCFG_ALL					(0x80000000U)
@@ -477,9 +497,9 @@
 
 typedef enum
 {
-	RGX_META_T1_OFF   = 0x0,
-	RGX_META_T1_MAIN  = 0x1,
-	RGX_META_T1_DUMMY = 0x2
+	RGX_META_T1_OFF   = 0x0,           /*!< No thread 1 running (unless 2nd thread is used for HWPerf) */
+	RGX_META_T1_MAIN  = 0x1,           /*!< Run the main thread 0 code on thread 1 (and vice versa if 2nd thread is used for HWPerf) */
+	RGX_META_T1_DUMMY = 0x2            /*!< Run dummy test code on thread 1 */
 } RGX_META_T1_CONF;
 
 /*!
@@ -490,8 +510,7 @@
 typedef enum _RGXFWIF_DM_STATE_
 {
 	RGXFWIF_DM_STATE_NORMAL			= 0,
-	RGXFWIF_DM_STATE_LOCKEDUP		= 1,
-
+	RGXFWIF_DM_STATE_LOCKEDUP		= 1
 } RGXFWIF_DM_STATE;
 
 typedef struct
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks.h b/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks.h
index 1e1b3e5..c10b282 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks.h
@@ -50,17 +50,19 @@
 
 /*!
  ******************************************************************************
- * Alignment checks array
+ * Alignment UM/FW checks array
  *****************************************************************************/
 
+#define RGXFW_ALIGN_CHECKS_UM_MAX 128
+
 #define RGXFW_ALIGN_CHECKS_INIT0						\
 		sizeof(RGXFWIF_TRACEBUF),						\
 		offsetof(RGXFWIF_TRACEBUF, ui32LogType),		\
 		offsetof(RGXFWIF_TRACEBUF, sTraceBuf),			\
-		offsetof(RGXFWIF_TRACEBUF, aui16HwrDmLockedUpCount),	\
-		offsetof(RGXFWIF_TRACEBUF, aui16HwrDmOverranCount),	\
-		offsetof(RGXFWIF_TRACEBUF, aui16HwrDmRecoveredCount),	\
-		offsetof(RGXFWIF_TRACEBUF, aui16HwrDmFalseDetectCount),	\
+		offsetof(RGXFWIF_TRACEBUF, aui32HwrDmLockedUpCount),	\
+		offsetof(RGXFWIF_TRACEBUF, aui32HwrDmOverranCount),	\
+		offsetof(RGXFWIF_TRACEBUF, aui32HwrDmRecoveredCount),	\
+		offsetof(RGXFWIF_TRACEBUF, aui32HwrDmFalseDetectCount),	\
 														\
 		/* RGXFWIF_CMDTA checks */						\
 		sizeof(RGXFWIF_CMDTA),							\
@@ -70,13 +72,10 @@
 		sizeof(RGXFWIF_CMD3D),							\
 		offsetof(RGXFWIF_CMD3D, s3DRegs),				\
 														\
-		/* RGXFWIF_CMDTRANSFER checks */				\
-		sizeof(RGXFWIF_CMDTRANSFER),					\
-		offsetof(RGXFWIF_CMDTRANSFER, sTransRegs),		\
+		/* RGXFWIF_CMDTRANSFER checks */                \
+		sizeof(RGXFWIF_CMDTRANSFER),                    \
+		offsetof(RGXFWIF_CMDTRANSFER, sTransRegs),      \
 														\
-		/* RGXFWIF_CMD2D checks */						\
-		sizeof(RGXFWIF_CMD2D),							\
-		offsetof(RGXFWIF_CMD2D, s2DRegs),				\
 														\
 		/* RGXFWIF_CMD_COMPUTE checks */				\
 		sizeof(RGXFWIF_CMD_COMPUTE),					\
@@ -114,24 +113,72 @@
 
 
 #if defined(RGX_FEATURE_RAY_TRACING)
-#define RGXFW_ALIGN_CHECKS_INIT							\
-		RGXFW_ALIGN_CHECKS_INIT0,						\
-		sizeof(RGXFWIF_RPM_FREELIST), 					\
-		offsetof(RGXFWIF_RPM_FREELIST, sFreeListDevVAddr),\
-		offsetof(RGXFWIF_RPM_FREELIST, sRPMPageListDevVAddr),\
-		offsetof(RGXFWIF_RPM_FREELIST, ui32MaxPages),\
-		offsetof(RGXFWIF_RPM_FREELIST, ui32CurrentPages),\
+#define RGXFW_ALIGN_CHECKS_INIT1                           \
+		RGXFW_ALIGN_CHECKS_INIT0,                          \
+		sizeof(RGXFWIF_RPM_FREELIST),                      \
+		offsetof(RGXFWIF_RPM_FREELIST, sFreeListDevVAddr), \
+		offsetof(RGXFWIF_RPM_FREELIST, ui32MaxPages),      \
+		offsetof(RGXFWIF_RPM_FREELIST, ui32CurrentPages),  \
 		offsetof(RGXFWIF_RPM_FREELIST, ui32GrowPages)
-
 #else
-#define RGXFW_ALIGN_CHECKS_INIT		RGXFW_ALIGN_CHECKS_INIT0
-
+#define RGXFW_ALIGN_CHECKS_INIT1		RGXFW_ALIGN_CHECKS_INIT0
 #endif /* RGX_FEATURE_RAY_TRACING */
 
+
+#if defined(RGX_FEATURE_TLA)
+#define RGXFW_ALIGN_CHECKS_INIT2                   \
+		RGXFW_ALIGN_CHECKS_INIT1,                  \
+		/* RGXFWIF_CMD2D checks */                 \
+		sizeof(RGXFWIF_CMD2D),                     \
+		offsetof(RGXFWIF_CMD2D, s2DRegs)
+#else
+#define RGXFW_ALIGN_CHECKS_INIT2		RGXFW_ALIGN_CHECKS_INIT1
+#endif	/* RGX_FEATURE_TLA */
+
+
+#if defined(RGX_FEATURE_FASTRENDER_DM)
+#define RGXFW_ALIGN_CHECKS_INIT                    \
+		RGXFW_ALIGN_CHECKS_INIT2,                  \
+		/* RGXFWIF_CMDTDM checks */                \
+		sizeof(RGXFWIF_CMDTDM),                    \
+		offsetof(RGXFWIF_CMDTDM, sTDMRegs)
+#else
+#define RGXFW_ALIGN_CHECKS_INIT		RGXFW_ALIGN_CHECKS_INIT2
+#endif /* ! RGX_FEATURE_FASTRENDER_DM */
+
+
+
+/*!
+ ******************************************************************************
+ * Alignment KM checks array
+ *****************************************************************************/
+
+#define RGXFW_ALIGN_CHECKS_INIT_KM                          \
+		sizeof(RGXFWIF_INIT),                               \
+		offsetof(RGXFWIF_INIT, sFaultPhysAddr),             \
+		offsetof(RGXFWIF_INIT, sPDSExecBase),               \
+		offsetof(RGXFWIF_INIT, sUSCExecBase),               \
+		offsetof(RGXFWIF_INIT, psKernelCCBCtl),             \
+		offsetof(RGXFWIF_INIT, psKernelCCB),                \
+		offsetof(RGXFWIF_INIT, psFirmwareCCBCtl),           \
+		offsetof(RGXFWIF_INIT, psFirmwareCCB),              \
+		offsetof(RGXFWIF_INIT, asSigBufCtl),                \
+		offsetof(RGXFWIF_INIT, sTraceBufCtl),              \
+		offsetof(RGXFWIF_INIT, sRGXCompChecks),             \
+		                                                    \
+		/* RGXFWIF_FWRENDERCONTEXT checks */                \
+		sizeof(RGXFWIF_FWRENDERCONTEXT),                    \
+		offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),      \
+		offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext),      \
+		                                                    \
+		sizeof(RGXFWIF_FWCOMMONCONTEXT),                    \
+		offsetof(RGXFWIF_FWCOMMONCONTEXT, psFWMemContext),  \
+		offsetof(RGXFWIF_FWCOMMONCONTEXT, sRunNode),        \
+		offsetof(RGXFWIF_FWCOMMONCONTEXT, psCCB),           \
+		offsetof(RGXFWIF_FWCOMMONCONTEXT, ui64MCUFenceAddr)
+
 #endif /*  __RGX_FWIF_ALIGNCHECKS_H__ */
 
 /******************************************************************************
  End of file (rgx_fwif_alignchecks.h)
 ******************************************************************************/
-
-
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks_km.h b/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks_km.h
deleted file mode 100644
index d3650dc..0000000
--- a/drivers/staging/imgtec/rogue/rgx_fwif_alignchecks_km.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX fw interface alignment checks
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Checks to avoid disalignment in RGX fw data structures shared with the host
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#if !defined (__RGX_FWIF_ALIGNCHECKS_KM_H__)
-#define __RGX_FWIF_ALIGNCHECKS_KM_H__
-
-/* for the offsetof macro */
-#include <stddef.h>
-
-/*!
- ******************************************************************************
- * Alignment checks array
- *****************************************************************************/
-
-#define RGXFW_ALIGN_CHECKS_INIT_KM                          \
-		sizeof(RGXFWIF_INIT),                               \
-		offsetof(RGXFWIF_INIT, sFaultPhysAddr),             \
-		offsetof(RGXFWIF_INIT, sPDSExecBase),               \
-		offsetof(RGXFWIF_INIT, sUSCExecBase),               \
-		offsetof(RGXFWIF_INIT, psKernelCCBCtl),             \
-		offsetof(RGXFWIF_INIT, psKernelCCB),                \
-		offsetof(RGXFWIF_INIT, psFirmwareCCBCtl),           \
-		offsetof(RGXFWIF_INIT, psFirmwareCCB),              \
-		offsetof(RGXFWIF_INIT, asSigBufCtl),                \
-		offsetof(RGXFWIF_INIT, psTraceBufCtl),              \
-		offsetof(RGXFWIF_INIT, sRGXCompChecks),             \
-		                                                    \
-		/* RGXFWIF_FWRENDERCONTEXT checks */                \
-		sizeof(RGXFWIF_FWRENDERCONTEXT),                    \
-		offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),      \
-		offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext),      \
-		                                                    \
-		sizeof(RGXFWIF_FWCOMMONCONTEXT),                    \
-		offsetof(RGXFWIF_FWCOMMONCONTEXT, psFWMemContext),  \
-		offsetof(RGXFWIF_FWCOMMONCONTEXT, sRunNode),        \
-		offsetof(RGXFWIF_FWCOMMONCONTEXT, psCCB),           \
-		offsetof(RGXFWIF_FWCOMMONCONTEXT, ui64MCUFenceAddr)
-
-#endif /*  __RGX_FWIF_ALIGNCHECKS_KM_H__ */
-
-/******************************************************************************
- End of file (rgx_fwif_alignchecks_km.h)
-******************************************************************************/
-
-
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_client.h b/drivers/staging/imgtec/rogue/rgx_fwif_client.h
deleted file mode 100644
index 9a647d7..0000000
--- a/drivers/staging/imgtec/rogue/rgx_fwif_client.h
+++ /dev/null
@@ -1,699 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX firmware interface structures
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX firmware interface structures used by srvclient
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#if !defined (__RGX_FWIF_CLIENT_H__)
-#define __RGX_FWIF_CLIENT_H__
-
-#include "img_types.h"
-#include "rgxdefs_km.h"
-
-#include "rgx_fwif_alignchecks.h"
-#include "rgx_fwif_shared.h"
-#include "rgx_fwif_defines.h"
-
-
-/* Indicates the number of RTDATAs per RTDATASET */
-#define RGXMKIF_NUM_RTDATAS			2
-
-
-#define RGXMKIF_RENDERFLAGS_NORENDER			0x00000001UL	/*!< Only run the TA phase on the hardware, on terminate
-																	 free the parameters and dummy process 3D phase */
-#define RGXMKIF_RENDERFLAGS_ABORT				0x00000002UL	/*!< The scene has been aborted free the parameters and dummy
-																	 process to completion */
-#define RGXMKIF_RENDERFLAGS_RENDERMIDSCENE		0x00000004UL	/*!< Indicates this is a midscene render and the render resources
-																	 should not be released */
-#define RGXMKIF_RENDERFLAGS_NODEALLOC			0x00000008UL	/*!< Do not free the parameter memory when rendering. Typically	
-																	 used when doing z-only renders */
-#define RGXMKIF_RENDERFLAGS_ZONLYRENDER			0x00000010UL	/*!< This render is only being used to generate z buffer data
-																	 so some registers need to be tweaked (e.g. TE_PSG, ISP_ZLSCTL).
-																     Setting this flag will cause the TA to terminate the control streams,
-																	 but keep the TPC entries. This is so more primitives can be sent if needed and
-																	 added to the control streams ready for any more renders of this scene. */
-#define RGXMKIF_RENDERFLAGS_GETVISRESULTS		0x00000020UL	/*!< This render has visibility result associated with it.
-																	 Setting this flag will cause the firmware to collect the visibility results */
-#define RGXMKIF_RENDERFLAGS_ACCUMVISRESULTS		0x00000040UL	/*!< Setting this flag will cause the firmware to accumulate (sum)
-																	 the visibility results */
-#define RGXMKIF_RENDERFLAGS_DEPTHBUFFER			0x00000080UL	/*!< Indicates whether a depth buffer is present */
-#define RGXMKIF_RENDERFLAGS_STENCILBUFFER		0x00000100UL	/*!< Indicates whether a stencil buffer is present */ 
-#define RGXMKIF_RENDERFLAGS_TA_DEPENDENCY		0x00000200UL	/*!< Update 3D dependancy sync object after the render has completed */
-#define RGXMKIF_RENDERFLAGS_RENDERSCENE			0x00000400UL	/*!< Update HWRTDataset completed ops after the render has completed */
-#define	RGXMKIF_RENDERFLAGS_FLUSH_SLC			0x00000800UL	/*!< Flush the system cache after the render has completed */
-#define RGXMKIF_RENDERFLAGS_BBOX_RENDER			0x00001000UL	/*!< This is a bounding box render */
-#define RGXMKIF_RENDERFLAGS_SECURE				0x00002000UL	/*!< This render needs DRM Security */
-#define RGXMKIF_RENDERFLAGS_ABORT_NOFREE		0x00004000UL	/*!< This flags goes in hand with ABORT and excplicity ensure no mem free is issued in case of first TA kick */
-#define RGXMKIF_RENDERFLAGS_DISABLE_PIXELMERGE	0x00008000UL	/*!< Force disabling of pixel merging */
-#if defined(FIX_HW_BRN_51537)
-#define RGXMKIF_RENDERFLAGS_CSRM_MAX_COEFFS		0x00020000UL	/*!< Force 4 lines of coeffs on render */
-#endif
-
-/*
-	The host must indicate if this is the first and/or last command to
-	be issued for the specified task
-*/
-#define RGXMKIF_TAFLAGS_FIRSTKICK				0x00000001UL
-#define RGXMKIF_TAFLAGS_LASTKICK				0x00000002UL
-/*
-	When a mid-scene render has been kicked this flag tells the pcore code
-	to wait for it to complete before kicking TA
-*/
-#define RGXMKIF_TAFLAGS_RESUMEMIDSCENE			0x00000004UL
-
-/*
-	Tells the primary core that we are sending another ta command after a
-	mid-scene render which freed the associated parameters so a ta context
-	reset is required.
-*/
-#define RGXMKIF_TAFLAGS_RESUMEDAFTERFREE		0x00000008UL
-
-/*
-	Invalidate the USE cache before this TA kick.
-*/
-#define RGXMKIF_TAFLAGS_INVALIDATEUSECACHE		0x00000010UL
-
-/*
-	Invalidate the PDS cache before this TA kick.
-*/
-#define RGXMKIF_TAFLAGS_INVALIDATEPDSCACHE		0x00000020UL
-
-/*
-	Flush the data cache before this ta kick.
-*/
-#define RGXMKIF_TAFLAGS_INVALIDATEDATACACHE		0x00000040UL
-
-/*
-	Indicates that complex geometry is used during the TA stream
-*/
-#define RGXMKIF_TAFLAGS_CMPLX_GEOMETRY_PRESENT	0x00000080UL
-
-/*
- * 	Indicates the particular TA needs to be aborted
- */
-#define RGXMKIF_TAFLAGS_TA_ABORT			0x00000100UL
-/*
-	Flags to check 3D dependency sync object
-*/
-#define RGXMKIF_TAFLAGS_DEPENDENT_TA			0x00000400UL
-
-#if defined(RGX_FEATURE_SPM_CONTEXT_SWITCH)
-#define RGXMKIF_TAFLAGS_TA_SPM_DRAINED			0x00001000UL
-#endif
-
-/* Flags to indicate this cmd has an update to the PB */
-#define RGXMKIF_TAFLAGS_PB_THRESHOLD_UPDATE		0x00010000UL
-#if !defined(DISABLE_RGX_PB_GROW_SHRINK) && defined(SUPPORT_PERCONTEXT_FREELIST)
-#define RGXMKIF_TAFLAGS_PB_GROW					0x00020000UL
-#define RGXMKIF_TAFLAGS_PB_SHRINK				0x00040000UL
-#define RGXMKIF_TAFLAGS_PB_UPDATE_MASK			(RGXMKIF_TAFLAGS_PB_GROW | \
-												 RGXMKIF_TAFLAGS_PB_SHRINK | \
-												 RGXMKIF_TAFLAGS_PB_THRESHOLD_UPDATE)
-#else
-#define RGXMKIF_TAFLAGS_PB_UPDATE_MASK			(RGXMKIF_TAFLAGS_PB_THRESHOLD_UPDATE)
-#endif
-
-#define RGXMKIF_TAFLAGS_SECURE					0x00080000UL
-
-#if defined(FIX_HW_BRN_37918) || (defined(FIX_HW_BRN_38059) && !defined(HW_ERN_36400))
-#define FIX_HW_VCE_PAUSE
-/*
-	Indicates that the VCE needs to be halted and restarted as per the WA
-*/
-#define RGXMKIF_TAFLAGS_APPLY_VCE_PAUSE			0x00100000UL
-#endif
-#if defined(FIX_HW_BRN_51537)
-/*
- * 	Indicates that the CSRM should be reconfigured to support maximum coeff
- *  space before this command is scheduled.
- */
-#define RGXMKIF_TAFLAGS_CSRM_MAX_COEFFS			0x00200000UL
-#endif
-
-
-/* flags for transfer queue commands */
-#define RGXMKIF_CMDTRANSFER_FLAG_SECURE			0x00000001UL
-
-/* flags for 2D commands */
-#define RGXMKIF_CMD2D_FLAG_SECURE				0x00000001
-#define RGXMKIF_CMD2D_FLAG_SRC_FBCDC			0x00000002
-#define RGXMKIF_CMD2D_FLAG_DST_FBCDC			0x00000004
-
-/* flags for compute commands */
-#define RGXMKIF_COMPUTE_FLAG_SECURE				0x00000001
-
-/* flags for ray commands */
-#define RGXFWIF_RAY_FLAG_SECURE					0x00000001
-#define RGXFWIF_RAY_NULL_CMDRTU					0x00000001
-/*
-	The host must indicate if this is the first and/or last command to
-	be issued for the specified task
-*/
-#define RGXMKIF_SHGFLAGS_FIRSTKICK				0x00000001UL
-#define RGXMKIF_SHGFLAGS_LASTKICK				0x00000002UL
-
-/*****************************************************************************
- Parameter/HWRTData control structures.
-*****************************************************************************/
-
-/*!
-	Configuration registers which need to be loaded by the firmware before a TA
-	kick can be started.
-*/
-typedef struct _RGXFWIF_TAREGISTERS_
-{
-	IMG_UINT64	uTAReg_PM_MTILE_ARRAY;
-	IMG_UINT64	uTAReg_PPP_CTRL;
-	IMG_UINT64	uTAReg_PPP_WCLAMP;
-	IMG_UINT64	uTAReg_TE_PSG;
-	IMG_UINT64	uTAReg_TE_PSGREGION_ADDR;
-	IMG_UINT64	uTAReg_VDM_CTRL_STREAM_BASE;
-	IMG_UINT64	uTAReg_VDM_CTRL_STREAM_TERMINATE;
-	IMG_UINT64	uTAReg_VDM_SYNC_PDS_DATA_BASE;
-	IMG_UINT64	uTAReg_TA_RTC_ADDR_BASE;
-	IMG_UINT64	uTAReg_TPU_BORDER_COLOUR_TABLE;
-	IMG_UINT64	uTAReg_TPU_YUV_CSC_COEFFICIENTS;
-#if defined(RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS)
-	IMG_UINT64  uTAReg_TPU_CEM_VDM;
-#else
-    IMG_UINT64  uTAReg_TPU;
-#endif
-	IMG_UINT64  uTAReg_TPU_ARRAYS_VDM;
-
-#if defined(RGX_FEATURE_TESSELLATION)
-	IMG_UINT64	uTAReg_PDS_COEFF_FREE_PROG;
-#endif
-	
-#if defined(RGX_FEATURE_VDM_DRAWINDIRECT)
-	IMG_UINT64	uTAReg_VDM_DRAW_INDIRECT0;
-	IMG_UINT32	uTAReg_VDM_DRAW_INDIRECT1;
-#endif
-
-// 	IMG_UINT32	ui32USELDRedirect;/*!< USE LD redirect register value */
-// 	IMG_UINT32	ui32USESTRange;/*!< USE ST Range control register value */
-} RGXFWIF_TAREGISTERS, *PRGXFWIF_TAREGISTERS;
-
-typedef struct _RGXFWIF_TAREGISTERS_CSWITCH_
-{
-	IMG_UINT64	uTAReg_VDM_CONTEXT_STATE_BASE_ADDR;
-#if defined(FIX_HW_VCE_PAUSE)
-	IMG_UINT64	uTAReg_VDM_CONTEXT_STATE_RESUME_ADDR;
-#endif
-	IMG_UINT64	uTAReg_TA_CONTEXT_STATE_BASE_ADDR;
-
-	struct
-	{
-		IMG_UINT64	uTAReg_VDM_CONTEXT_STORE_TASK0;
-		IMG_UINT64	uTAReg_VDM_CONTEXT_STORE_TASK1;
-		IMG_UINT64	uTAReg_VDM_CONTEXT_STORE_TASK2;
-		
-		/* VDM resume state update controls */
-		IMG_UINT64	uTAReg_VDM_CONTEXT_RESUME_TASK0;
-		IMG_UINT64	uTAReg_VDM_CONTEXT_RESUME_TASK1;
-		IMG_UINT64	uTAReg_VDM_CONTEXT_RESUME_TASK2;
-		
-	#if defined(RGX_FEATURE_VDM_OBJECT_LEVEL_LLS)
-		IMG_UINT64	uTAReg_VDM_CONTEXT_STORE_TASK3;
-		IMG_UINT64	uTAReg_VDM_CONTEXT_STORE_TASK4;
-
-		IMG_UINT64	uTAReg_VDM_CONTEXT_RESUME_TASK3;
-		IMG_UINT64	uTAReg_VDM_CONTEXT_RESUME_TASK4;
-	#endif
-	} asTAState[2];
-
-} RGXFWIF_TAREGISTERS_CSWITCH, *PRGXFWIF_TAREGISTERS_CSWITCH;
-
-/*!
-	Configuration registers which need to be loaded by the firmware before the
-	dummy region header is issued.
-*/
-typedef struct _RGXFWIF_BRN44455_TAREGISTERS_
-{
-	IMG_UINT64	uTAReg_TE_PSGREGION_ADDR;
-} RGXFWIF_BRN44455_TAREGISTERS, *PRGXFWIF_BRN44455_TAREGISTERS;
-
-/*!
-	Configuration registers which need to be loaded by the firmware before any
-	VDM kick is issued on cores affected by this BRN.
-*/
-typedef struct _RGXFWIF_BRN52563_TAREGISTERS_
-{
-	IMG_UINT64	uTAReg_VDM_CONTEXT_SYNC_BASE_ADDR;			/*!< Base address for the VDM PDS context store sync */
-	IMG_UINT64	uTAReg_DDM_CONTEXT_SYNC_BASE_ADDR;			/*!< Base address for the DDM PDS context store sync */
-	IMG_UINT64	uTAReg_DDM_CONTEXT_STORE_SYNC_BASE_ADDR;	/*!< Base address for the DDM USC context store sync */
-	IMG_UINT32	ui32BufferSize;
-} RGXFWIF_BRN52563_TAREGISTERS, *PRGXFWIF_BRN52563_TAREGISTERS;
-
-/*!
-	TA command. The RGX TA can be used to tile a whole scene's objects
-	as per TA behaviour on RGX.
-*/
-typedef struct _RGXFWIF_CMDTA_
-{
-	RGXFWIF_TAREGISTERS			RGXFW_ALIGN sTARegs;/*!< TA registers */
-	RGXFWIF_TAREGISTERS_CSWITCH	RGXFW_ALIGN sTARegsCSwitch;/*!< TA registers for ctx switch */
-	IMG_UINT32					ui32Flags; /*!< command control flags */
-	IMG_UINT32					ui32FrameNum;/*!< associated frame number */
-	RGXFWIF_DEV_VIRTADDR		sHWRTData; /* RTData associated with this command, this is used for context selection and for storing out HW-context, when TA is switched out for continuing later */
-	RGXFWIF_DEV_VIRTADDR		sZBuffer;	/* Z-Buffer */
-	RGXFWIF_DEV_VIRTADDR		sSBuffer;	/* S-Buffer */
-	RGXFWIF_UFO					sPartialRenderTA3DFence; /* Holds the TA/3D fence value to allow the 3D partial render command to go through */
-	RGXFWIF_UFO					sPartialRenderHardwareSyncFence; /* Holds the HardwareSync fence value to allow the 3D partial render command to go through */
-	IMG_UINT32					ui32MaxDeadlineMS;/*!< Max HWR deadline limit in ms */
-#if defined(FIX_HW_BRN_44455)
-	RGXFWIF_BRN44455_TAREGISTERS	RGXFW_ALIGN sBRN44455TARegs;/*!< TA registers for BRN44455 workaround */
-#endif
-#if defined(FIX_HW_BRN_52563)
-	RGXFWIF_BRN52563_TAREGISTERS	RGXFW_ALIGN	sBRN52563TARegs;/*!< TA registers for BRN52563 workaround */
-#endif
-
-} RGXFWIF_CMDTA,*PRGXFWIF_CMDTA;
-
-
-/*!
-	Configuration registers common to the RTU and 3D REFS
- */
-typedef struct _RGXFWIF_COMMON_RTU_REGISTERS_
-{
-	IMG_UINT64 uDPXReg_RQ_RAY_SETUP;
-	IMG_UINT64 uDPXReg_RS_CTRL0;
-	IMG_UINT64 uDPXReg_RS_CTRL1;
-	IMG_UINT64 uDPXReg_RS_CTRL4;
-	IMG_UINT64 uDPXReg_RS_CTRL16;
-
-	IMG_UINT64 uDPXReg_RS_CTRL_DUMP_ADDR;
-	IMG_UINT64 uDPXReg_RS_CTRL_DUMP_SIZE;
-
-	IMG_UINT64 uDPXReg_BF_CTRL;
-
-	IMG_UINT64 uDPXReg_PRIM_TABLE_SIZE;
-	IMG_UINT64 uDPXReg_BIF_PRIMITIVE_BASE_ADDRESS;
-	IMG_UINT64 uDPXReg_FBA_MAIN_CTRL;
-	IMG_UINT64 uDPXReg_FILTER_CTRL;
-	IMG_UINT64 uDPXReg_FILTER_CTRL1;
-	IMG_UINT64 uDPXReg_FBA_AP_BASE[DPX_MAX_FBA_AP];
-	IMG_UINT64 uDPXReg_FBA_AP_CTRL[DPX_MAX_FBA_AP];
-	IMG_UINT64 uDPXReg_FBA_AP_MAP;
-	IMG_UINT64 uDPXReg_BIF_ROOTID_BASE;
-	IMG_UINT32 auDPXReg_FBA_FILTER_RAM[DPX_MAX_FBA_FILTER_WIDTH * DPX_MAX_FBA_FILTER_WIDTH];
-} RGXFWIF_COMMON_RTU_REGISTERS, * PRGXFWIF_COMMON_RTU_REGISTERS;
-
-
-typedef struct _RGXFWIF_COMMON_RTU_SETUP_
-{
-	IMG_UINT32            ui32FBAFilterTableSize; /*!< Controls number of valid entries in uDPXReg_FBA_FILTER_RAM */
-	IMG_BOOL			  bInvalidateRootBIDCache; /*!< Decide whether to force the RQ to stop sending rays to the RU and invalidate any ROOTBID lookup entries */
-} RGXFWIF_COMMON_RTU_SETUP, * PRGXFWIF_COMMON_RTU_SETUP;
-
-
-/*!
-	Configuration registers which need to be loaded by the firmware before ISP
-	can be started.
-*/
-typedef struct _RGXFWIF_3DREGISTERS_
-{
-	IMG_UINT64	u3DReg_USC_PIXEL_OUTPUT_CTRL;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER0;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER1;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER2;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER3;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER4;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER5;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER6;
-	IMG_UINT64  u3DReg_USC_CLEAR_REGISTER7;
-	IMG_UINT64	u3DReg_ISP_MTILE_BASE;
-	IMG_UINT64	u3DReg_ISP_MTILE_SIZE;
-	IMG_UINT64	u3DReg_ISP_GRIDOFFSET;
-	IMG_UINT64	u3DReg_ISP_MULTISAMPLECTL;
-	IMG_UINT64	u3DReg_ISP_SCISSOR_BASE;
-	IMG_UINT64	u3DReg_ISP_DBIAS_BASE;
-	IMG_UINT64	u3DReg_ISP_BGOBJDEPTH;
-	IMG_UINT64	u3DReg_ISP_BGOBJVALS;
-    IMG_UINT64  u3DReg_ISP_AA;
-    IMG_UINT64  u3DReg_ISP_OCLQRY_BASE;
-    IMG_UINT64  u3DReg_ISP_ZLSCTL;
-    IMG_UINT64  u3DReg_ISP_MASK_LOAD_BASE;
-    IMG_UINT64  u3DReg_ISP_MASK_STORE_BASE;
-    IMG_UINT64  u3DReg_ISP_ZLOAD_BASE;
-    IMG_UINT64  u3DReg_ISP_ZSTORE_BASE;
-    IMG_UINT64  u3DReg_ISP_STENCIL_LOAD_BASE;
-    IMG_UINT64  u3DReg_ISP_STENCIL_STORE_BASE;
-	IMG_UINT64  u3DReg_ISP_ZLS_PIXELS;
-    IMG_UINT64	u3DReg_ISP_RGN;
-    IMG_UINT64  u3DReg_ISP_CTL;
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-    IMG_UINT64  u3DReg_ISP_XTP_PIPE_ENABLE;
-#endif
-    IMG_UINT64  u3DReg_FB_CDC_ZLS;
-	IMG_UINT64	u3DReg_PM_3D_FSTACK_BASE;
-	IMG_UINT64	u3DReg_PM_3D_FSTACK;
-	IMG_UINT64	u3DReg_EVENT_PIXEL_PDS_CODE;
-	IMG_UINT64	u3DReg_EVENT_PIXEL_PDS_DATA;
-	IMG_UINT64	u3DReg_EVENT_PIXEL_PDS_INFO;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT0;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT0;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT0;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT1;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT1;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT1;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT2;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT2;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT2;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT3;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT3;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT3;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT4;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT4;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT4;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT5;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT5;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT5;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT6;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT6;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT6;
-	IMG_UINT64	u3DReg_PBE_WORD0_MRT7;
-	IMG_UINT64	u3DReg_PBE_WORD1_MRT7;
-	IMG_UINT64	u3DReg_PBE_WORD2_MRT7;
-	IMG_UINT64  u3DReg_PBE;
-	IMG_UINT64  u3DReg_TPU_BORDER_COLOUR_TABLE;
-	IMG_UINT64	u3DReg_TPU_YUV_CSC_COEFFICIENTS;
-	IMG_UINT64  u3DReg_TPU;
-	IMG_UINT64  u3DReg_TPU_ARRAYS;
-	IMG_UINT64  u3DReg_TPUMADDCtrl;
-	IMG_UINT64	u3DReg_PDS_BGND0_BASE;
-	IMG_UINT64	u3DReg_PDS_BGND1_BASE;
-	IMG_UINT64	u3DReg_PDS_BGND2_BASE;
-	IMG_UINT64	u3DReg_PDS_BGND3_SIZEINFO;
-	IMG_UINT64	u3DReg_PDS_PR_BGND0_BASE;
-	IMG_UINT64	u3DReg_PDS_PR_BGND1_BASE;
-	IMG_UINT64	u3DReg_PDS_PR_BGND2_BASE;
-	IMG_UINT64	u3DReg_PDS_PR_BGND3_SIZEINFO;
-	IMG_UINT64	u3DReg_RGX_CR_BLACKPEARL_FIX;
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-	IMG_UINT64  u3DReg_PIXEL_PHANTOM;
-#endif
-
-} RGXFWIF_3DREGISTERS, *PRGXFWIF_3DREGISTERS;
-
-typedef struct _RGXFWIF_CMD3D_
-{
-	RGXFWIF_3DREGISTERS		RGXFW_ALIGN s3DRegs;		/*!< 3D registers */
-	IMG_UINT32				ui32Flags; /*!< command control flags */
-	IMG_UINT32				ui32FrameNum;/*!< associated frame number */
-	RGXFWIF_DEV_VIRTADDR	sHWRTData; /* RTData associated with this command, this is used for context selection and for storing out HW-context, when TA is switched out for continuing later */
-	RGXFWIF_DEV_VIRTADDR	sZBuffer;	/* Z-Buffer */
-	RGXFWIF_DEV_VIRTADDR	sSBuffer;	/* S-Buffer */
-	IMG_UINT32				ui32ZLSStride; /* Stride IN BYTES for Z-Buffer in case of RTAs */
-	IMG_UINT32				ui32SLSStride; /* Stride IN BYTES for S-Buffer in case of RTAs */
-	IMG_UINT32				ui32MaxDeadlineMS;/*!< Max HWR deadline limit in ms */
-} RGXFWIF_CMD3D,*PRGXFWIF_CMD3D;
-
-typedef struct _RGXFWIF_TRANSFERREGISTERS_
-{
-	IMG_UINT64 uTransReg_ISP_BGOBJVALS;
-	IMG_UINT64 uTransReg_ISP_BGOBJDEPTH;
-
-	IMG_UINT64 uTransReg_USC_PIXEL_OUTPUT_CTRL;
-	IMG_UINT64 uTransReg_USC_CLEAR_REGISTER0;
-
-	IMG_UINT64 uTransReg_PDS_BGND0_BASE;
-	IMG_UINT64 uTransReg_PDS_BGND1_BASE;
-	IMG_UINT64 uTransReg_PDS_BGND2_BASE;
-	IMG_UINT64 uTransReg_PDS_BGND3_SIZEINFO;
-
-	IMG_UINT64 uTransReg_TPU_BORDER_COLOUR_TABLE;
-	IMG_UINT64 uTransReg_TPU_YUV_CSC_COEFFICIENTS;
-
-	IMG_UINT64 uTransReg_ISP_RENDER;
-	IMG_UINT64 uTransReg_ISP_MTILE_SIZE;
-	IMG_UINT64 uTransReg_ISP_MTILE_BASE;
-	IMG_UINT64 uTransReg_ISP_PIXEL_BASE;
-	IMG_UINT64 uTransReg_ISP_RENDER_ORIGIN;
-	IMG_UINT64 uTransReg_ISP_CTL;
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-    IMG_UINT64  uTransReg_ISP_XTP_PIPE_ENABLE;
-#endif
-	IMG_UINT64 uTransReg_ISP_AA;
-
-	IMG_UINT64 uTransReg_EVENT_PIXEL_PDS_INFO;
-	IMG_UINT64 uTransReg_EVENT_PIXEL_PDS_CODE;
-	IMG_UINT64 uTransReg_EVENT_PIXEL_PDS_DATA;
-
-	IMG_UINT64 uTransReg_PBE_WORDX_MRTY[9]; /* TQ_MAX_RENDER_TARGETS * PBE_STATE_SIZE */
-
-} RGXFWIF_TRANSFERREGISTERS, *PRGXFWIF_TRANSFERREGISTERS;
-
-
-
-typedef struct _RGXFWIF_CMDTRANSFER_
-{
-	RGXFWIF_TRANSFERREGISTERS			RGXFW_ALIGN sTransRegs;
-
-	IMG_UINT32				ui32FrameNum;
-	IMG_UINT32				ui32Flags;/*!< flags */
-
-} RGXFWIF_CMDTRANSFER, *PRGXFWIF_CMDTRANSFER;
-
-
-typedef struct _RGXFWIF_TLAREGISTERS_
-{ 
-	IMG_UINT64	u2DReg_TLA_CMD_STREAM;
-	IMG_UINT64	u2DReg_TLA_FBC_MEM_SRC_REGION;
-	IMG_UINT64	u2DReg_TLA_FBC_MEM_SRC_CTRL;
-	IMG_UINT64	u2DReg_TLA_FBC_MEM_DST_REGION;
-	IMG_UINT64	u2DReg_TLA_FBC_MEM_DST_CTRL;
-#if defined(FIX_HW_BRN_57193)
-	IMG_UINT64	u2DReg_BRN57193_TLA_CMD_STREAM;
-#endif
-} RGXFWIF_2DREGISTERS, *PRGXFWIF_2DREGISTERS;
-
-typedef struct _RGXFWIF_CMD2D_
-{
-	RGXFWIF_2DREGISTERS		RGXFW_ALIGN s2DRegs;
-
-	IMG_UINT32 				ui32FrameNum;
-	IMG_UINT32				ui32Flags;/*!< flags */
-
-} RGXFWIF_CMD2D, *PRGXFWIF_CMD2D;
-
-/*****************************************************************************
- Host interface structures.
-*****************************************************************************/
-
-#define		RGXMKIF_HWCFLAGS_NEWCONTEXT			0x00000001
-#define 	RGXMKIF_HWCFLAGS_DUMMYTRANSFER		0x00000002
-#define 	RGXMKIF_HWCFLAGS_DUMMY2D			0x00000004
-#if defined(RGX_FEATURE_SPM_CONTEXT_SWITCH)
-#define 	RGXMKIF_HWCFLAGS_DRAIN_USED			0x00000008
-#endif
-
-/*!
-	Configuration registers which need to be loaded by the firmware before CDM
-	can be started.
-*/
-typedef struct _RGXFWIF_CDM_REGISTERS_
-{
-	IMG_UINT64	uCDMReg_CDM_CTRL_STREAM_BASE;
-	IMG_UINT64	uCDMReg_TPU_BORDER_COLOUR_TABLE;
-	IMG_UINT64	uCDMReg_COMPUTE_THREAD_BARRIER;
-
-
-	IMG_UINT64  uCDMReg_PDS_CTRL;
-
-	IMG_UINT64  uCDMReg_TPU_YUV_CSC_COEFFICIENTS;
-
-#if defined(RGX_FEATURE_COMPUTE_MORTON_CAPABLE)
-	IMG_UINT64	uCDMReg_CDM_ITEM;
-#endif
-#if defined(RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS)
-	IMG_UINT64  uCDMReg_TPU_CEM_CDM;
-#else
-	IMG_UINT64  uCDMReg_TPU;
-#endif
-	IMG_UINT64  uCDMReg_TPU_ARRAYS_CDM;
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-	IMG_UINT64  uCDMReg_COMPUTE_CLUSTER;
-#endif
-
-#if defined(RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS)
-	IMG_UINT64 uCDMReg_TPU_TAG_CDM_CTRL;
-#endif
-} RGXFWIF_CDM_REGISTERS;
-
-typedef struct _RGXFWIF_CDM_REGISTERS_CSWITCH_
-{
-	IMG_UINT64	uCDMReg_CDM_CONTEXT_STATE_BASE_ADDR;
-	IMG_UINT64	uCDMReg_CDM_CONTEXT_PDS0;
-	IMG_UINT64	uCDMReg_CDM_CONTEXT_PDS1;
-	IMG_UINT64  uCDMReg_CDM_TERMINATE_PDS;
-	IMG_UINT64  uCDMReg_CDM_TERMINATE_PDS1;
-#if defined(RGX_SW_COMPUTE_PDS_BARRIER) && (RGX_NUM_PHANTOMS == 2)
-	IMG_UINT64  uCDMReg_CDM_TERMINATE_PDS_PH2;	/* PDS task variant which synchronises 2 phantoms. Not used in FW */
-	IMG_UINT64  uCDMReg_CDM_TERMINATE_PDS1_PH2;
-#endif
-
-	/* CDM resume controls */
-	IMG_UINT64	uCDMReg_CDM_RESUME_PDS0;
-	IMG_UINT64	uCDMReg_CDM_RESUME_PDS1;
-#if defined(RGX_FEATURE_COMPUTE_MORTON_CAPABLE)
-	IMG_UINT64	uCDMReg_CDM_CONTEXT_PDS0_B;
-	IMG_UINT64	uCDMReg_CDM_RESUME_PDS0_B;
-#endif
-
-} RGXFWIF_CDM_REGISTERS_CSWITCH;
-
-#if defined(FIX_HW_BRN_54441)
-typedef struct _RGXFWIF_CDM_54441_REGISTERS_
-{
-	IMG_UINT64	uCDMReg_CDM_CTRL_STREAM_TERMINATE;
-} RGXFWIF_CDM_54441_REGISTERS;
-#endif
-
-/*!
-	RGX Compute command.
-*/
-typedef struct _RGXFWIF_CMD_COMPUTE_
-{
-	RGXFWIF_CDM_REGISTERS			RGXFW_ALIGN sCDMRegs;	/*!< CDM registers */
-	RGXFWIF_CDM_REGISTERS_CSWITCH	RGXFW_ALIGN sCDMRegsCSwitch;/*!< CDM registers for ctx switch */
-#if defined(FIX_HW_BRN_54441)
-	RGXFWIF_CDM_54441_REGISTERS		RGXFW_ALIGN	sBRN54441CDMRegs;
-#endif
-
-	IMG_UINT32				ui32Flags;	/*!< Control flags */
-	IMG_UINT32				ui32MaxDeadlineMS; /*!< Max HWR deadline limit in ms */
-} RGXFWIF_CMD_COMPUTE;
-
-
-
-
-/*!
-	Configuration registers which need to be loaded by the firmware
-	before a VRDM kick can be started.
-*/
-typedef struct _RGXFWIF_VRDMREGISTERS_
-{
-	IMG_UINT64  uVRDMReg_SHF_MIN_X_EXTENTS;
-	IMG_UINT64  uVRDMReg_SHF_MIN_Y_EXTENTS;
-	IMG_UINT64  uVRDMReg_SHF_MIN_Z_EXTENTS;
-	IMG_UINT64  uVRDMReg_SHF_MAX_X_EXTENTS;
-	IMG_UINT64  uVRDMReg_SHF_MAX_Y_EXTENTS;
-	IMG_UINT64  uVRDMReg_SHF_MAX_Z_EXTENTS;
-
-	IMG_UINT64  uVRDMReg_SHG_CTRL0;
-	IMG_UINT64  uVRDMReg_SHG_CTRL1;
-	
-	IMG_UINT64  uVRDMReg_SHF_CTRL;
-	
-	IMG_UINT64  uVRDMReg_BF_CTRL;
-	
-	IMG_UINT64  uVRDMReg_VRM_CTRL_STREAM_BASE;
-	IMG_UINT64  uVRDMReg_VRM_SYNC_PDS_DATA_BASE;
-	IMG_UINT64  uVRDMReg_TPU_BORDER_COLOUR_TABLE;
-
-	IMG_UINT64  uVRDMReg_PRIM_TABLE_BASE; /*!< primitive table base address */
-	IMG_UINT64	uVRDMReg_PRIM_TABLE_SIZE; /*!< primitive table size (bytes) */
-
-	IMG_UINT64  uVRDMReg_RPM_PAGE_TABLE_BASE;
-	
-	IMG_UINT64	uVRDMReg_RPM_SHF_FPL;
-	IMG_UINT64	uVRDMReg_RPM_SHG_FPL;
-
-} RGXFWIF_VRDMREGISTERS, *PRGXFWIF_VRDMREGISTERS;
-
-
-/*!
-	RGX VRDM command.
-*/
-typedef struct _RGXFWIF_CMD_VRDM_
-{
-	RGXFWIF_VRDMREGISTERS RGXFW_ALIGN sVRDMRegs;	/*!< VRDM registers */
-	IMG_UINT32            ui32Flags;				/*!< Control flags */
-	IMG_UINT32            ui32FrameNum;/*!< associated frame number */
-#if defined(RGX_FEATURE_RAY_TRACING)
-	RGXFWIF_DEV_VIRTADDR  asFWRPMFreeList[RGXFW_MAX_RPM_FREELISTS];	/*!< FW address for SHF/SHG free list */
-	RGXFWIF_DEV_VIRTADDR  sHWFrameData; /* Frame Data associated with this command, this is used for RPM abort handling */
-#endif
-} RGXFWIF_CMDVRDM;
-
-
-#if !(defined(__linux__) && defined(__KERNEL__))
-/*!
-	Configuration registers which need to be loaded by the firmware before a RTU
-	kick can be started. Add REFS related registers to
-	RGXFWIF_COMMON_RTU_REGISTERS instead.
-*/
-typedef struct _RGXFWIF_RTU_REGISTERS_
-{
-	IMG_UINT64 uDPXReg_RS_CTRL_FRAME_ENGINE_ADDR;
-	IMG_UINT64 uDPXReg_RS_CTRL_CANCEL_TASK;
-	IMG_UINT64 uDPXReg_FRAME_ENGINE_FREE_THRESH;
-} RGXFWIF_RTU_REGISTERS, *PRGXFWIF_RTU_REGISTERS;
-
-/*!
-	RGX DPX command.
-*/
-typedef struct _RGXFWIF_CMD_RTU_
-{
-	RGXFWIF_RTU_REGISTERS        RGXFW_ALIGN sRTURegs;
-	RGXFWIF_COMMON_RTU_REGISTERS RGXFW_ALIGN sRTUCommonRegs;
-
-	RGXFWIF_COMMON_RTU_SETUP sRTUCommonSetup; /* bits shared with REFS */
-	
-	IMG_UINT32            ui32Flags;	/*!< Control flags */
-	IMG_UINT32            ui32FrameNum;/*!< associated frame number */
-	RGXFWIF_DEV_VIRTADDR  sHWFrameData; /* Frame Data associated with this command, this is used for RPM abort handling */
-} RGXFWIF_CMDRTU;
-
-/*!
-	RGX FC command.
-*/
-typedef struct _RGXFWIF_CMD_RTU_FC_
-{
-	IMG_UINT32				ui32Woff;
-	IMG_UINT32				ui32FrameContextID;
-	IMG_UINT32            	ui32Flags;	/*!< Control flags */
-} RGXFWIF_CMDRTU_FC;
-#endif	/* !(defined(__linux__) && defined(__KERNEL__)) */
-
-#endif /*  __RGX_FWIF_CLIENT_H__ */
-
-/******************************************************************************
- End of file (rgx_fwif_client.h)
-******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_defines.h b/drivers/staging/imgtec/rogue/rgx_fwif_defines.h
deleted file mode 100644
index e2dde7a..0000000
--- a/drivers/staging/imgtec/rogue/rgx_fwif_defines.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX firmware interface defines
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX firmware interface defines used by srvclient and ogl
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-#if !defined (__RGX_FWIF_DEFINES_H__)
-#define __RGX_FWIF_DEFINES_H__
-
-/******************************************************************************
- kernel/client functions:
-******************************************************************************/
-
-/* 
- * Minimum PB size supported by RGX and Services.
- * 
- * This is based on the fact that the reissue FIFO is 9 pages deep.
- * 
- * Minimum PB = 272K + (NUM_TE_PIPES-1)*16K + (NUM_VCE_PIPES-1)*64K + IF_PM_PREALLOC(NUM_TE_PIPES*16K + NUM_VCE_PIPES*16K)
- */
-#if defined(RGX_FEATURE_SCALABLE_TE_ARCH)
-#define		RGX_PM_FLPAGES_FOR_SCALABLE_TE		((RGX_FEATURE_SCALABLE_TE_ARCH-1)*4)
-#else
-#define		RGX_PM_FLPAGES_FOR_SCALABLE_TE		(0*4)
-#endif
-
-#if defined(RGX_FEATURE_SCALABLE_VCE)
-#define		RGX_PM_FLPAGES_FOR_SCALABLE_VCE		((RGX_FEATURE_SCALABLE_VCE-1)*16)
-#else
-#define		RGX_PM_FLPAGES_FOR_SCALABLE_VCE		(0*16)
-#endif
-
-#if defined(HW_ERN_46066)
-/* With PM Pre-Alloc each requester can take an additional page, for VCE2 + TE2 config, it is 64KB. */
-#if defined(RGX_FEATURE_SCALABLE_TE_ARCH)
-#define		RGX_PM_FLPAGES_FOR_TE_PREALLOC		(RGX_FEATURE_SCALABLE_TE_ARCH*4)
-#else
-#define		RGX_PM_FLPAGES_FOR_TE_PREALLOC		(1*4)
-#endif
-#if defined(RGX_FEATURE_SCALABLE_VCE)
-#define		RGX_PM_FLPAGES_FOR_VCE_PREALLOC		(RGX_FEATURE_SCALABLE_VCE*4)
-#else
-#define		RGX_PM_FLPAGES_FOR_VCE_PREALLOC		(1*4)
-#endif
-#else
-#define		RGX_PM_FLPAGES_FOR_TE_PREALLOC		(0*4)
-#define		RGX_PM_FLPAGES_FOR_VCE_PREALLOC		(0*4)
-#endif
-
-#if defined(SUPPORT_MMU_FREELIST)
-#define		RGX_PM_MIN_FLSIZE	   				((RGX_PM_FLPAGES_FOR_SCALABLE_TE  +    \
-                                                  RGX_PM_FLPAGES_FOR_SCALABLE_VCE +    \
-                                                  RGX_PM_FLPAGES_FOR_TE_PREALLOC  +    \
-                                                  RGX_PM_FLPAGES_FOR_VCE_PREALLOC +    \
-                                                  53) * RGX_BIF_PM_PHYSICAL_PAGE_SIZE)
-#define		RGX_PM_MMU_MIN_FLSIZE				(16 * RGX_BIF_PM_PHYSICAL_PAGE_SIZE)
-#else
-#define		RGX_PM_MIN_FLSIZE					((RGX_PM_FLPAGES_FOR_SCALABLE_TE  +    \
-                                                  RGX_PM_FLPAGES_FOR_SCALABLE_VCE +    \
-                                                  RGX_PM_FLPAGES_FOR_TE_PREALLOC  +    \
-                                                  RGX_PM_FLPAGES_FOR_VCE_PREALLOC +    \
-                                                  68) * RGX_BIF_PM_PHYSICAL_PAGE_SIZE)
-#endif
-
-#endif /*  __RGX_FWIF_DEFINES_H__ */
-
-/******************************************************************************
- End of file (rgx_fwif_defines.h)
-******************************************************************************/
-
-
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_hwperf.h b/drivers/staging/imgtec/rogue/rgx_fwif_hwperf.h
index 20d0e2f..dff11d2e 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_hwperf.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_hwperf.h
@@ -50,48 +50,15 @@
 
 /*****************************************************************************/
 
-/* Function pointer type for functions to check dynamic power state of counter blocks */
-typedef IMG_BOOL (*PFN_RGXFW_HWPERF_CNTBLK_POWERED)(RGX_HWPERF_CNTBLK_ID eBlkType, IMG_UINT8 ui8UnitId);
-
-/* This structure encodes properties of a type of performance counter block.
- * The structure is sometimes referred to as a block type descriptor. These
- * properties contained in this structure represent the columns in the
- * block type model table variable below. There values vary depending on
- * the build BVNC and core type.
- * Each direct block has a unique type descriptor and each indirect group has
- * a type descriptor. */
-typedef struct _RGXFW_HWPERF_CNTBLK_TYPE_MODEL_
-{
-	/* Could use RGXFW_ALIGN_DCACHEL here but then we would waste 40% of the cache line? */
-	IMG_UINT32 uiCntBlkIdBase;         /* The starting block id for this block type */
-	IMG_UINT32 uiIndirectReg;          /* 0 if direct type otherwise the indirect control register to select indirect unit */
-	IMG_UINT32 uiPerfReg;              /* RGX_CR_*_PERF register for this block type */
-	IMG_UINT32 uiSelect0BaseReg;       /* RGX_CR_*_PERF_SELECT0 register for this block type */
-	IMG_UINT32 uiBitSelectPreserveMask;/* Select register bits to preserve on programming, HW_ERN_41805 */
-	IMG_UINT32 uiCounter0BaseReg;      /* RGX_CR_*_PERF_COUNTER_0 register for this block type */
-	IMG_UINT8  uiNumCounters;          /* Number of counters in this block type */
-	IMG_UINT8  uiNumUnits;             /* Number of instances of this block type in the core */
-	IMG_UINT8  uiSelectRegModeShift;   /* Mode field shift value of select registers */
-	IMG_UINT8  uiSelectRegOffsetShift; /* Interval between select registers, either 8 bytes or 16, hence << 3 or << 4 */
-	IMG_CHAR   pszBlockNameComment[30];              /* Name of the PERF register. Used while dumping the perf counters to pdumps */
-	PFN_RGXFW_HWPERF_CNTBLK_POWERED pfnIsBlkPowered; /* A function to determine dynamic power state for the block type */
-} RGXFW_HWPERF_CNTBLK_TYPE_MODEL;
-
-/* Used to instantiate a null row in the block type model table below where the
- * block is not supported for a given build BVNC. This is needed as the blockid
- * to block type lookup uses the table as well and clients may try to access blocks
- * not in the hardware. */
-#define RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(_blkid) {_blkid, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", NULL}
-
 /* Structure to hold a block's parameters for passing between the BG context
  * and the IRQ context when applying a configuration request. */
 typedef struct _RGXFWIF_HWPERF_CTL_BLK_
 {
-	IMG_BOOL				bValid;
+	IMG_BOOL                bValid;
 	IMG_BOOL                bEnabled;
 	IMG_UINT32              eBlockID;
 	IMG_UINT32              uiCounterMask;
-	IMG_UINT64  RGXFW_ALIGN aui64CounterCfg[RGX_HWPERF_CNTRS_IN_BLK];
+	IMG_UINT64  RGXFW_ALIGN aui64CounterCfg[RGX_CNTBLK_COUNTERS_MAX];
 }  RGXFWIF_HWPERF_CTL_BLK;
 
 /* Structure used to hold the configuration of the non-mux counters blocks */
@@ -101,17 +68,17 @@
 	IMG_UINT32            aui32SelectedCountersIDs[RGX_HWPERF_MAX_CUSTOM_CNTRS];
 } RGXFW_HWPERF_SELECT;
 
-/* Structure to hold the whole configuration request details for all blocks */
-#define RGXFWIF_HWPERF_CTL_MAX_BLK_CFGS (RGX_CNTBLK_ID_DIRECT_LAST+RGX_HWPERF_MAX_INDIRECT_ADDR_BLKS)
+/* Structure to hold the whole configuration request details for all blocks
+ * The block masks and counts are used to optimise reading of this data. */
 typedef struct _RGXFWIF_HWPERF_CTL_
 {
-	IMG_BOOL             bResetOrdinal;
-	IMG_UINT32           ui32EnabledBlksCount; /* Number of blocks enabled in the proceeding array.
-	                                            * Used to optimise the no counters HW event function. */
-	RGXFWIF_HWPERF_CTL_BLK sBlkCfg[RGXFWIF_HWPERF_CTL_MAX_BLK_CFGS];
-	IMG_UINT32           ui32SelectedCountersBlockMask; /* Provide an optimisation for the checking of the configured
-	                                                       blocks for non-mutex counters */
-	RGXFW_HWPERF_SELECT RGXFW_ALIGN SelCntr[RGX_HWPERF_MAX_CUSTOM_BLKS];
+	IMG_BOOL                           bResetOrdinal;
+
+	IMG_UINT32                         ui32SelectedCountersBlockMask;
+	RGXFW_HWPERF_SELECT RGXFW_ALIGN    SelCntr[RGX_HWPERF_MAX_CUSTOM_BLKS];
+
+	IMG_UINT32                         ui32EnabledBlksCount;
+	RGXFWIF_HWPERF_CTL_BLK RGXFW_ALIGN sBlkCfg[RGX_HWPERF_MAX_DEFINED_BLKS];
 } UNCACHED_ALIGN RGXFWIF_HWPERF_CTL;
 
 /* NOTE: The switch statement in this function must be kept in alignment with
@@ -139,7 +106,6 @@
 		case RGX_CNTBLK_ID_BF:
 		case RGX_CNTBLK_ID_BT:
 		case RGX_CNTBLK_ID_RT:
-		case RGX_CNTBLK_ID_BX_TU:
 		case RGX_CNTBLK_ID_SH:
 		{
 			i32Idx = eBlockID;
@@ -154,7 +120,8 @@
 		case RGX_CNTBLK_ID_TPU_MCU6:
 		case RGX_CNTBLK_ID_TPU_MCU7:
 		{
-			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST + (eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
 			break;
 		}
 		case RGX_CNTBLK_ID_USC0:
@@ -165,72 +132,99 @@
 		case RGX_CNTBLK_ID_USC5:
 		case RGX_CNTBLK_ID_USC6:
 		case RGX_CNTBLK_ID_USC7:
-        case RGX_CNTBLK_ID_USC8:
-        case RGX_CNTBLK_ID_USC9:
-        case RGX_CNTBLK_ID_USC10:
-        case RGX_CNTBLK_ID_USC11:
-        case RGX_CNTBLK_ID_USC12:
-        case RGX_CNTBLK_ID_USC13:
-        case RGX_CNTBLK_ID_USC14:
-        case RGX_CNTBLK_ID_USC15:
+		case RGX_CNTBLK_ID_USC8:
+		case RGX_CNTBLK_ID_USC9:
+		case RGX_CNTBLK_ID_USC10:
+		case RGX_CNTBLK_ID_USC11:
+		case RGX_CNTBLK_ID_USC12:
+		case RGX_CNTBLK_ID_USC13:
+		case RGX_CNTBLK_ID_USC14:
+		case RGX_CNTBLK_ID_USC15:
 		{
-			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST + RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST +
-					(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU, 7) +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
 			break;
 		}
 		case RGX_CNTBLK_ID_TEXAS0:
 		case RGX_CNTBLK_ID_TEXAS1:
-        case RGX_CNTBLK_ID_TEXAS2:
-        case RGX_CNTBLK_ID_TEXAS3:
+		case RGX_CNTBLK_ID_TEXAS2:
+		case RGX_CNTBLK_ID_TEXAS3:
 		case RGX_CNTBLK_ID_TEXAS4:
 		case RGX_CNTBLK_ID_TEXAS5:
 		case RGX_CNTBLK_ID_TEXAS6:
 		case RGX_CNTBLK_ID_TEXAS7:
 		{
-			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST + RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST +
-					RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER + (eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(USC, 15) +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
 			break;
 		}
 		case RGX_CNTBLK_ID_RASTER0:
 		case RGX_CNTBLK_ID_RASTER1:
-        case RGX_CNTBLK_ID_RASTER2:
-        case RGX_CNTBLK_ID_RASTER3:
+		case RGX_CNTBLK_ID_RASTER2:
+		case RGX_CNTBLK_ID_RASTER3:
 		{
-			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST + RGX_HWPERF_PHANTOM_DUST_BLKS * RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST +
-			    RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER + (RGX_HWPERF_PHANTOM_NONDUST_BLKS-1) * RGX_HWPERF_INDIRECT_BY_PHANTOM
-			    + (eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(USC, 15) +
+						RGX_CNTBLK_INDIRECT_COUNT(TEXAS, 7) +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
 			break;
 		}
 		case RGX_CNTBLK_ID_BLACKPEARL0:
-        case RGX_CNTBLK_ID_BLACKPEARL1:
-        case RGX_CNTBLK_ID_BLACKPEARL2:
-        case RGX_CNTBLK_ID_BLACKPEARL3:
+		case RGX_CNTBLK_ID_BLACKPEARL1:
+		case RGX_CNTBLK_ID_BLACKPEARL2:
+		case RGX_CNTBLK_ID_BLACKPEARL3:
 		{
-			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST + RGX_HWPERF_PHANTOM_DUST_BLKS * RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST +
-                RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER + (RGX_HWPERF_PHANTOM_NONDUST_BLKS-1) * RGX_HWPERF_INDIRECT_BY_PHANTOM
-                + (eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
-            break;
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(USC, 15) +
+						RGX_CNTBLK_INDIRECT_COUNT(TEXAS, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(RASTER, 3) +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			break;
 		}
 		case RGX_CNTBLK_ID_PBE0:
-        case RGX_CNTBLK_ID_PBE1:
-        case RGX_CNTBLK_ID_PBE2:
-        case RGX_CNTBLK_ID_PBE3:
-        case RGX_CNTBLK_ID_PBE4:
-        case RGX_CNTBLK_ID_PBE5:
-        case RGX_CNTBLK_ID_PBE6:
-        case RGX_CNTBLK_ID_PBE7:
-        case RGX_CNTBLK_ID_PBE8:
-        case RGX_CNTBLK_ID_PBE9:
-        case RGX_CNTBLK_ID_PBE10:
-        case RGX_CNTBLK_ID_PBE11:
-        case RGX_CNTBLK_ID_PBE12:
-        case RGX_CNTBLK_ID_PBE13:
-        case RGX_CNTBLK_ID_PBE14:
-        case RGX_CNTBLK_ID_PBE15:
+		case RGX_CNTBLK_ID_PBE1:
+		case RGX_CNTBLK_ID_PBE2:
+		case RGX_CNTBLK_ID_PBE3:
+		case RGX_CNTBLK_ID_PBE4:
+		case RGX_CNTBLK_ID_PBE5:
+		case RGX_CNTBLK_ID_PBE6:
+		case RGX_CNTBLK_ID_PBE7:
+		case RGX_CNTBLK_ID_PBE8:
+		case RGX_CNTBLK_ID_PBE9:
+		case RGX_CNTBLK_ID_PBE10:
+		case RGX_CNTBLK_ID_PBE11:
+		case RGX_CNTBLK_ID_PBE12:
+		case RGX_CNTBLK_ID_PBE13:
+		case RGX_CNTBLK_ID_PBE14:
+		case RGX_CNTBLK_ID_PBE15:
 		{
-			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST + RGX_HWPERF_PHANTOM_DUST_BLKS * RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST +
-                RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER + RGX_HWPERF_PHANTOM_NONDUST_BLKS * RGX_HWPERF_INDIRECT_BY_PHANTOM
-                + (eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(USC, 15) +
+						RGX_CNTBLK_INDIRECT_COUNT(TEXAS, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(RASTER, 3) +
+						RGX_CNTBLK_INDIRECT_COUNT(BLACKPEARL, 3) +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
+			break;
+		}
+		case RGX_CNTBLK_ID_BX_TU0:
+		case RGX_CNTBLK_ID_BX_TU1:
+		case RGX_CNTBLK_ID_BX_TU2:
+		case RGX_CNTBLK_ID_BX_TU3:
+		{
+			i32Idx = RGX_CNTBLK_ID_DIRECT_LAST +
+						RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(USC, 15) +
+						RGX_CNTBLK_INDIRECT_COUNT(TEXAS, 7) +
+						RGX_CNTBLK_INDIRECT_COUNT(RASTER, 3) +
+						RGX_CNTBLK_INDIRECT_COUNT(BLACKPEARL, 3) +
+						RGX_CNTBLK_INDIRECT_COUNT(PBE, 15) +
+						(eBlockID & RGX_CNTBLK_ID_UNIT_MASK);
 			break;
 		}
 		default:
@@ -238,7 +232,7 @@
 			return NULL;
 		}
 	}
-	if ((i32Idx < 0) || (i32Idx >= RGXFWIF_HWPERF_CTL_MAX_BLK_CFGS))
+	if ((i32Idx < 0) || (i32Idx >= RGX_HWPERF_MAX_DEFINED_BLKS))
 	{
 		return NULL;
 	}
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_km.h b/drivers/staging/imgtec/rogue/rgx_fwif_km.h
index 78bf977..140f4d2b 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_km.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_km.h
@@ -51,29 +51,47 @@
 #include "dllist.h"
 #include "rgx_firmware_processor.h"
 
-#if !defined(RGXFW_NUM_OS)
-		/* Default number of OSIDs is 1 unless configuration is virtualized hypervisor build */
-		#if defined(SUPPORT_PVRSRV_GPUVIRT) && !defined(PVRSRV_GPUVIRT_GUESTDRV) && (PVRSRV_GPUVIRT_NUM_OSID +1> 1)
-				#define RGXFW_NUM_OS        PVRSRV_GPUVIRT_NUM_OSID
-		#else
-				#define RGXFW_NUM_OS        1
-		#endif
+#if	!defined(__KERNEL__)
+/* The following defines the offsets for the KCCB, KCCBCtl, FWCCB and FWCCBCtl
+ * for the various guests in a virtualisation environment. It is assumed that each
+ * guest is built the same way and so all their offsets will match. If the code
+ * at host level changes and the offsets change, the defines here need to be updated.
+ */
+
+#if defined(RGX_FEATURE_META)
+#define RGXFWIF_GUEST_OFFSET_KCCB           (RGXFW_SEGMMU_DATA_BASE_ADDRESS | \
+                                             RGXFW_SEGMMU_DATA_META_CACHED | \
+                                             RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED | \
+                                             0x2000U)
+#define RGXFWIF_GUEST_OFFSET_KCCBCTL        (RGXFW_SEGMMU_DATA_BASE_ADDRESS | \
+                                             RGXFW_SEGMMU_DATA_META_UNCACHED | \
+                                             RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED | \
+											 0x0280U)
+#define RGXFWIF_GUEST_OFFSET_FWCCB          (RGXFW_SEGMMU_DATA_BASE_ADDRESS | \
+                                             RGXFW_SEGMMU_DATA_META_UNCACHED | \
+                                             RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED | \
+											 0x0300U)
+#define RGXFWIF_GUEST_OFFSET_FWCCBCTL       (RGXFW_SEGMMU_DATA_BASE_ADDRESS | \
+                                             RGXFW_SEGMMU_DATA_META_UNCACHED | \
+                                             RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED | \
+											 0x02C0U)
+#else
+/* In case of MIPS we will need to define proper values for these offsets */
+#define RGXFWIF_GUEST_OFFSET_KCCB           (0x0)
+#define RGXFWIF_GUEST_OFFSET_KCCBCTL        (0x0)
+#define RGXFWIF_GUEST_OFFSET_FWCCB          (0x0)
+#define RGXFWIF_GUEST_OFFSET_FWCCBCTL       (0x0)
+#endif
+
 #endif
 
 #if defined(RGX_FIRMWARE)
-typedef IMG_UINT32							*PRGXFWIF_SIGBUFFER;
-typedef struct _RGXFWIF_TRACEBUF_			*PRGXFWIF_TRACEBUF;
-typedef IMG_UINT8							*PRGXFWIF_HWPERFBUF;
-typedef struct _RGXFWIF_HWRINFOBUF_			*PRGXFWIF_HWRINFOBUF;
-typedef struct _RGXFWIF_RUNTIME_CFG_		*PRGXFWIF_RUNTIME_CFG;
-typedef struct _RGXFWIF_GPU_UTIL_FWCB_		*PRGXFWIF_GPU_UTIL_FWCB;
-typedef struct _RGXFWIF_REG_CFG_			*PRGXFWIF_REG_CFG;
-typedef struct _RGXFWIF_HWPERF_CTL_			*PRGXFWIF_HWPERF_CTL;
-typedef struct _RGX_HWPERF_CONFIG_CNTBLK_	*PRGX_HWPERF_CONFIG_CNTBLK;
-typedef IMG_UINT32							*PRGX_HWPERF_SELECT_CUSTOM_CNTRS;
 typedef DLLIST_NODE							RGXFWIF_DLLIST_NODE;
-typedef IMG_UINT32							*PRGXFWIF_ALIGNCHECK;
 #else
+typedef struct {RGXFWIF_DEV_VIRTADDR p;
+                  RGXFWIF_DEV_VIRTADDR n;}	RGXFWIF_DLLIST_NODE;
+#endif
+
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_SIGBUFFER;
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_TRACEBUF;
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_HWPERFBUF;
@@ -84,12 +102,6 @@
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_HWPERF_CTL;
 typedef RGXFWIF_DEV_VIRTADDR				PRGX_HWPERF_CONFIG_CNTBLK;
 typedef RGXFWIF_DEV_VIRTADDR				PRGX_HWPERF_SELECT_CUSTOM_CNTRS;
-typedef struct {RGXFWIF_DEV_VIRTADDR p;
-				  RGXFWIF_DEV_VIRTADDR n;}	RGXFWIF_DLLIST_NODE;
-typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_ALIGNCHECK;
-
-#endif
-
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_CCB_CTL;
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_CCB;
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_FWMEMCONTEXT;
@@ -99,6 +111,8 @@
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_COMMONCTX_STATE;
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_RF_CMD;
 typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_COMPCHECKS;
+typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_ALIGNCHECK;
+typedef RGXFWIF_DEV_VIRTADDR				PRGXFWIF_CORE_CLK_RATE;
 
 /*!
  * This number is used to represent an invalid page catalogue physical address
@@ -106,7 +120,7 @@
 #define RGXFWIF_INVALID_PC_PHYADDR 0xFFFFFFFFFFFFFFFFLLU
 
 /*!
-	Firmware memory context.
+    Firmware memory context.
 */
 typedef struct _RGXFWIF_FWMEMCONTEXT_
 {
@@ -118,6 +132,7 @@
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
     IMG_UINT32              ui32OSid;
+    IMG_BOOL                bOSidAxiProt;
 #endif
 
 } UNCACHED_ALIGN RGXFWIF_FWMEMCONTEXT;
@@ -130,7 +145,8 @@
 #define	RGXFWIF_CONTEXT_RENDERFLAGS_NEED_RESUME		(0x00000002)
 #define RGXFWIF_CONTEXT_CDMFLAGS_NEED_RESUME		(0x00000004)
 #define RGXFWIF_CONTEXT_SHGFLAGS_NEED_RESUME		(0x00000008)
-#define RGXFWIF_CONTEXT_ALLFLAGS_NEED_RESUME		(0x0000000F)
+#define RGXFWIF_CONTEXT_TDMFLAGS_CONTEXT_STORED		(0x00000010)
+#define RGXFWIF_CONTEXT_ALLFLAGS_NEED_RESUME		(0x0000001F)
 
 
 typedef struct _RGXFWIF_TACTX_STATE_
@@ -138,7 +154,7 @@
 	/* FW-accessible TA state which must be written out to memory on context store */
 	IMG_UINT64	RGXFW_ALIGN uTAReg_VDM_CALL_STACK_POINTER;		 /* To store in mid-TA */
 	IMG_UINT64	RGXFW_ALIGN uTAReg_VDM_CALL_STACK_POINTER_Init;	 /* Initial value (in case is 'lost' due to a lock-up */
-	IMG_UINT64	RGXFW_ALIGN uTAReg_VDM_BATCH;	
+	IMG_UINT64	RGXFW_ALIGN uTAReg_VDM_BATCH;
 	IMG_UINT64	RGXFW_ALIGN uTAReg_VBS_SO_PRIM0;
 	IMG_UINT64	RGXFW_ALIGN uTAReg_VBS_SO_PRIM1;
 	IMG_UINT64	RGXFW_ALIGN uTAReg_VBS_SO_PRIM2;
@@ -152,11 +168,7 @@
 typedef struct _RGXFWIF_3DCTX_STATE_
 {
 	/* FW-accessible ISP state which must be written out to memory on context store */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	IMG_UINT32	RGXFW_ALIGN au3DReg_ISP_STORE[8];
-#else
 	IMG_UINT32	RGXFW_ALIGN au3DReg_ISP_STORE[64];
-#endif
 	IMG_UINT64	RGXFW_ALIGN u3DReg_PM_DEALLOCATED_MASK_STATUS;
 	IMG_UINT64	RGXFW_ALIGN u3DReg_PM_PDS_MTILEFREE_STATUS;
 } UNCACHED_ALIGN RGXFWIF_3DCTX_STATE;
@@ -174,9 +186,6 @@
 	/* FW-accessible TA state which must be written out to memory on context store */
 	IMG_UINT64	RGXFW_ALIGN uVRDMReg_VRM_CALL_STACK_POINTER;
 	IMG_UINT64	RGXFW_ALIGN uVRDMReg_VRM_BATCH;
-	
-	/* Number of kicks on this context */
-	IMG_UINT32  ui32NumKicks;
 } UNCACHED_ALIGN RGXFWIF_VRDMCTX_STATE;
 
 
@@ -188,9 +197,7 @@
 	/* CCB details for this firmware context */
 	PRGXFWIF_CCCB_CTL		psCCBCtl;				/*!< CCB control */
 	PRGXFWIF_CCCB			psCCB;					/*!< CCB base */
-#if defined(RGX_FEATURE_META_DMA)
 	RGXFWIF_DMA_ADDR		sCCBMetaDMAAddr;
-#endif
 
 	/*
 		Used by the bg context only
@@ -201,16 +208,16 @@
 		Used by the irq context only
 	*/
 	RGXFWIF_DLLIST_NODE		sRunNode;				/*!< List entry for the run list */
-	
+
 	PRGXFWIF_FWMEMCONTEXT	psFWMemContext;			/*!< Memory context */
 
 	/* Context suspend state */
 	PRGXFWIF_COMMONCTX_STATE	RGXFW_ALIGN psContextState;		/*!< TA/3D context suspend state, read/written by FW */
-	
+
 	/* Framework state
 	 */
 	PRGXFWIF_RF_CMD		RGXFW_ALIGN psRFCmd;		/*!< Register updates for Framework */
-	
+
 	/*
 	 * 	Flags e.g. for context switching
 	 */
@@ -222,13 +229,19 @@
 	/* References to the host side originators */
 	IMG_UINT32				ui32ServerCommonContextID;			/*!< the Server Common Context */
 	IMG_UINT32				ui32PID;							/*!< associated process ID */
-	
+
 	/* Statistic updates waiting to be passed back to the host... */
 	IMG_BOOL				bStatsPending;						/*!< True when some stats are pending */
 	IMG_INT32				i32StatsNumStores;					/*!< Number of stores on this context since last update */
 	IMG_INT32				i32StatsNumOutOfMemory;				/*!< Number of OOMs on this context since last update */
 	IMG_INT32				i32StatsNumPartialRenders;			/*!< Number of PRs on this context since last update */
 	RGXFWIF_DM				eDM;								/*!< Data Master type */
+	IMG_UINT64        RGXFW_ALIGN           ui64WaitSignalAddress;        /*!< Device Virtual Address of the signal the context is waiting on */
+	RGXFWIF_DLLIST_NODE                     sWaitSignalNode;              /*!< List entry for the wait-signal list */
+	RGXFWIF_DLLIST_NODE		RGXFW_ALIGN  sBufStalledNode;		/*!< List entry for the buffer stalled list */
+	IMG_UINT64    		    RGXFW_ALIGN  ui64CBufQueueCtrlAddr;	/*!< Address of the circular buffer queue pointers */
+	IMG_UINT64    		    RGXFW_ALIGN  ui64ResumeSignalAddr;	/*!< Address of the Services Signal for resuming the buffer */
+	IMG_BOOL    		    bReadOffsetNeedsReset;				/*!< Following HWR circular buffer read-offset needs resetting */
 } UNCACHED_ALIGN RGXFWIF_FWCOMMONCONTEXT;
 
 /*!
@@ -242,11 +255,20 @@
 	/*
 	 * Note: The following fields keep track of OOM and partial render statistics.
 	 * Because these data structures are allocated cache-incoherent,
-	 * and because these fields are updated by the firmware, 
+	 * and because these fields are updated by the firmware,
 	 * the host will read valid values only after an SLC flush/inval.
 	 * This is only guaranteed to happen while destroying the render-context.
 	 */
-	IMG_UINT32			ui32TotalNumPartialRenders; /*!< Total number of partial renders */
+
+	/* The following variable has been reused to avoid breaking compatibility.
+	 *
+	 * It was previously:
+	 * IMG_UINT32 ui32TotalNumPartialRenders; Total number of partial renders
+	 *
+	 * And is changed to:
+	 */
+	IMG_UINT32			ui32WorkEstCCBSubmitted; /*!< Number of commands submitted to the WorkEst FW CCB */
+
 	IMG_UINT32			ui32TotalNumOutOfMemory;	/*!< Total number of OOMs */
 
 } UNCACHED_ALIGN RGXFWIF_FWRENDERCONTEXT;
@@ -256,18 +278,28 @@
 */
 typedef struct _RGXFWIF_FWRAYCONTEXT_
 {
+	IMG_UINT32				ui32ActiveFCMask; /* move here to avoid that fwrayctx and shgctx have the same addr */
+	IMG_UINT32				ui32NextFC;
 	RGXFWIF_FWCOMMONCONTEXT	sSHGContext;				/*!< Firmware context for the SHG */
 	RGXFWIF_FWCOMMONCONTEXT	sRTUContext;				/*!< Firmware context for the RTU */
 	PRGXFWIF_CCCB_CTL		psCCBCtl[DPX_MAX_RAY_CONTEXTS];
 	PRGXFWIF_CCCB			psCCB[DPX_MAX_RAY_CONTEXTS];
-	IMG_UINT32				ui32NextFC;
-	IMG_UINT32				ui32ActiveFCMask;
 } UNCACHED_ALIGN RGXFWIF_FWRAYCONTEXT;
 
 #define RGXFWIF_INVALID_FRAME_CONTEXT (0xFFFFFFFF)
 
 /*!
-    BIF requester selection
+	BIF tiling mode
+*/
+typedef enum _RGXFWIF_BIFTILINGMODE_
+{
+	RGXFWIF_BIFTILINGMODE_NONE      = 0,
+	RGXFWIF_BIFTILINGMODE_256x16    = 0,
+	RGXFWIF_BIFTILINGMODE_512x8     = 1
+} RGXFWIF_BIFTILINGMODE;
+
+/*!
+	BIF requester selection
 */
 typedef enum _RGXFWIF_BIFREQ_
 {
@@ -275,6 +307,7 @@
 	RGXFWIF_BIFREQ_3D		= 1,
 	RGXFWIF_BIFREQ_CDM		= 2,
 	RGXFWIF_BIFREQ_2D		= 3,
+	RGXFWIF_BIFREQ_TDM		= 3,
 	RGXFWIF_BIFREQ_HOST		= 4,
 	RGXFWIF_BIFREQ_RTU		= 5,
 	RGXFWIF_BIFREQ_SHG		= 6,
@@ -310,30 +343,41 @@
  ******************************************************************************
  * Kernel CCB command structure for RGX
  *****************************************************************************/
-#if !defined(RGX_FEATURE_SLC_VIVT)
 
-#define RGXFWIF_MMUCACHEDATA_FLAGS_PT      (0x1) /* BIF_CTRL_INVAL_PT_EN */
-#define RGXFWIF_MMUCACHEDATA_FLAGS_PD      (0x2) /* BIF_CTRL_INVAL_PD_EN */
-#define RGXFWIF_MMUCACHEDATA_FLAGS_PC      (0x4) /* BIF_CTRL_INVAL_PC_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PT      (0x1) /* MMU_CTRL_INVAL_PT_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PD      (0x2) /* MMU_CTRL_INVAL_PD_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PC      (0x4) /* MMU_CTRL_INVAL_PC_EN */
+
+#if !defined(__KERNEL)
+
+#if !defined(RGX_FEATURE_SLC_VIVT)
 #define RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB   (0x10) /* can't use PM_TLB0 bit from BIFPM_CTRL reg because it collides with PT bit from BIF_CTRL reg */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_TLB     (RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB | 0x8) /* BIF_CTRL_INVAL_TLB1_EN */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_CTX(C)  (0x0) /* not used */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL (0x0) /* not used */
 
 #else /* RGX_FEATURE_SLC_VIVT */
-#define RGXFWIF_MMUCACHEDATA_FLAGS_PT      (0x1) /* MMU_CTRL_INVAL_PT_EN */
-#define RGXFWIF_MMUCACHEDATA_FLAGS_PD      (0x2) /* MMU_CTRL_INVAL_PD_EN */
-#define RGXFWIF_MMUCACHEDATA_FLAGS_PC      (0x4) /* MMU_CTRL_INVAL_PC_EN */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB   (0x0) /* not used */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_TLB     (0x0) /* not used */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_CTX(C)  ((C) << 0x3) /* MMU_CTRL_INVAL_CONTEXT_SHIFT */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL (0x800) /* MMU_CTRL_INVAL_ALL_CONTEXTS_EN */
 #endif
 
+#else
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB   (0x10) /* can't use PM_TLB0 bit from BIFPM_CTRL reg because it collides with PT bit from BIF_CTRL reg */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_TLB     (RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB | 0x8) /* BIF_CTRL_INVAL_TLB1_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_CTX(C)  ((C) << 0x3) /* MMU_CTRL_INVAL_CONTEXT_SHIFT */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL (0x800) /* MMU_CTRL_INVAL_ALL_CONTEXTS_EN */
+#endif
+
+#define RGXFWIF_MMUCACHEDATA_FLAGS_INTERRUPT (0x4000000) /* indicates FW should interrupt the host */
+
 typedef struct _RGXFWIF_MMUCACHEDATA_
 {
 	PRGXFWIF_FWMEMCONTEXT		psMemoryContext;
 	IMG_UINT32					ui32Flags;
+	RGXFWIF_DEV_VIRTADDR		sMMUCacheSync;
+	IMG_UINT32					ui32MMUCacheSyncUpdateValue;
 } RGXFWIF_MMUCACHEDATA;
 
 typedef struct _RGXFWIF_SLCBPCTLDATA_
@@ -364,8 +408,10 @@
 {
 	PRGXFWIF_FWCOMMONCONTEXT	psContext;			/*!< address of the firmware context */
 	IMG_UINT32					ui32CWoffUpdate;	/*!< Client CCB woff update */
-	IMG_UINT32		ui32NumCleanupCtl;		/*!< number of CleanupCtl pointers attached */
-	PRGXFWIF_CLEANUP_CTL	apsCleanupCtl[RGXFWIF_KCCB_CMD_KICK_DATA_MAX_NUM_CLEANUP_CTLS]; /*!< CleanupCtl structures associated with command */
+	IMG_UINT32					ui32NumCleanupCtl;		/*!< number of CleanupCtl pointers attached */
+	PRGXFWIF_CLEANUP_CTL		apsCleanupCtl[RGXFWIF_KCCB_CMD_KICK_DATA_MAX_NUM_CLEANUP_CTLS]; /*!< CleanupCtl structures associated with command */
+	PRGXFWIF_WORKLOAD_DATA		sWorkloadDataFWAddress;   /*!< deprecated, kept for compatibility. */
+	IMG_UINT32					ui32WorkEstCmdHeaderOffset; /*!< offset to the CmdHeader which houses the workload estimation kick data. */
 } RGXFWIF_KCCB_CMD_KICK_DATA;
 
 typedef struct _RGXFWIF_KCCB_CMD_FENCE_DATA_
@@ -395,10 +441,8 @@
 		PRGXFWIF_HWRTDATA 			psHWRTData;				/*!< HW RT to cleanup */
 		PRGXFWIF_FREELIST 			psFreelist;				/*!< Freelist to cleanup */
 		PRGXFWIF_ZSBUFFER 			psZSBuffer;				/*!< ZS Buffer to cleanup */
-#if defined(RGX_FEATURE_RAY_TRACING)
 		PRGXFWIF_RAY_FRAME_DATA		psHWFrameData;			/*!< RPM/RTU frame data to cleanup */
 		PRGXFWIF_RPM_FREELIST 		psRPMFreelist;			/*!< RPM Freelist to cleanup */
-#endif
 	} uCleanupData;
 	RGXFWIF_DEV_VIRTADDR						sSyncObjDevVAddr;		/*!< sync primitive used to indicate state of the request */
 } RGXFWIF_CLEANUP_REQUEST;
@@ -411,6 +455,12 @@
 	RGXFWIF_POW_APM_LATENCY_CHANGE
 } RGXFWIF_POWER_TYPE;
 
+typedef enum
+{
+	RGXFWIF_OS_ONLINE = 1,
+	RGXFWIF_OS_OFFLINE
+} RGXFWIF_OS_STATE_CHANGE;
+
 typedef struct _RGXFWIF_POWER_REQUEST_
 {
 	RGXFWIF_POWER_TYPE				ePowType;				/*!< Type of power request */
@@ -421,6 +471,8 @@
 		IMG_BOOL					bCancelForcedIdle;		/*!< If the operation is to cancel previously forced idle */
 		IMG_UINT32					ui32ActivePMLatencyms;		/*!< Number of milliseconds to set APM latency */
 	} uPoweReqData;
+	IMG_BOOL						bNotifyTimeout;			/*!< Notify the FW that the host has timed out waiting for a response to an idling.
+															     It's placed here as an extension of the struct for backwards compatibility reasons */
 } RGXFWIF_POWER_REQUEST;
 
 typedef struct _RGXFWIF_SLCFLUSHINVALDATA_
@@ -431,6 +483,18 @@
 	RGXFWIF_DM  eDM;                    /*!< DM to flush entries for (only useful when bDMContext == TRUE) */
 } RGXFWIF_SLCFLUSHINVALDATA;
 
+typedef struct _RGXFWIF_STATEFLAG_CTRL_
+{
+	IMG_BOOL    bSetNotClear; /*!< Set or clear config flags */
+	IMG_UINT32  ui32Config;   /*!< Mask of config flags to change */
+	RGXFWIF_DEV_VIRTADDR sSyncObjDevVAddr;	/*!< sync primitive used to return the status */
+} RGXFWIF_STATEFLAG_CTRL;
+
+typedef struct _RGXFWIF_HCS_CTL_
+{
+	IMG_UINT32  ui32HCSDeadlineMS;  /* New number of milliseconds C/S is allowed to last */
+} RGXFWIF_HCS_CTL;
+
 typedef struct _RGXFWIF_HWPERF_CTRL_
 {
 	IMG_BOOL	 			bToggle; 	/*!< Toggle masked bits or apply full mask? */
@@ -439,8 +503,8 @@
 
 typedef struct _RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS_
 {
-	IMG_UINT32				ui32NumBlocks; 	/*!< Number of RGX_HWPERF_CONFIG_CNTBLK in the array */
-	PRGX_HWPERF_CONFIG_CNTBLK pasBlockConfigs;	/*!< Address of the RGX_HWPERF_CONFIG_CNTBLK array */
+	IMG_UINT32                ui32NumBlocks;    /*!< Number of RGX_HWPERF_CONFIG_CNTBLK in the array */
+	PRGX_HWPERF_CONFIG_CNTBLK sBlockConfigs;    /*!< Address of the RGX_HWPERF_CONFIG_CNTBLK array */
 } RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS;
 
 typedef struct _RGXFWIF_CORECLKSPEEDCHANGE_DATA_
@@ -460,9 +524,9 @@
 
 typedef struct _RGXFWIF_HWPERF_SELECT_CUSTOM_CNTRS_
 {
-	IMG_UINT16 ui16CustomBlock;
-	IMG_UINT16 ui16NumCounters;
-	PRGX_HWPERF_SELECT_CUSTOM_CNTRS pui32CustomCounterIDs;
+	IMG_UINT16                      ui16CustomBlock;
+	IMG_UINT16                      ui16NumCounters;
+	PRGX_HWPERF_SELECT_CUSTOM_CNTRS sCustomCounterIDs;
 } RGXFWIF_HWPERF_SELECT_CUSTOM_CNTRS;
 
 typedef struct _RGXFWIF_ZSBUFFER_BACKING_DATA_
@@ -471,6 +535,11 @@
 	IMG_UINT32				bDone;								/*!< action backing/unbacking succeeded */
 } RGXFWIF_ZSBUFFER_BACKING_DATA;
 
+typedef struct
+{
+	IMG_UINT32 ui32IsolationPriorityThreshold;
+} RGXFWIF_OSID_ISOLATION_GROUP_DATA;
+
 /*
  * Flags to pass in the unused bits of the page size grow request
  */
@@ -492,6 +561,54 @@
 	IMG_UINT32			aui32FreelistIDs[MAX_HW_TA3DCONTEXTS * RGXFW_MAX_FREELISTS];
 } RGXFWIF_FREELISTS_RECONSTRUCTION_DATA;
 
+
+typedef struct _RGXFWIF_SIGNAL_UPDATE_DATA_
+{
+	IMG_DEV_VIRTADDR RGXFW_ALIGN       sDevSignalAddress; /*!< device virtual address of the updated signal */
+	PRGXFWIF_FWMEMCONTEXT              psFWMemContext; /*!< Memory context */
+} UNCACHED_ALIGN RGXFWIF_SIGNAL_UPDATE_DATA;
+
+
+typedef struct _RGXFWIF_WRITE_OFFSET_UPDATE_DATA_
+{
+	PRGXFWIF_FWCOMMONCONTEXT  psContext; /*!< Context to that may need to be resumed following write offset update */
+} UNCACHED_ALIGN RGXFWIF_WRITE_OFFSET_UPDATE_DATA;
+
+typedef struct _RGXFWIF_WORKEST_FWCCB_CMD_
+{
+	IMG_UINT64 RGXFW_ALIGN ui64ReturnDataIndex; /*!< Index for return data array */
+	IMG_UINT64 RGXFW_ALIGN ui64CyclesTaken;     /*!< The cycles the workload took on the hardware */
+} RGXFWIF_WORKEST_FWCCB_CMD;
+
+
+/*!
+ ******************************************************************************
+ * Proactive DVFS Structures
+ *****************************************************************************/
+#define NUM_OPP_VALUES 16
+
+typedef struct _PDVFS_OPP_
+{
+	IMG_UINT32			ui32Volt; /* V  */
+	IMG_UINT32			ui32Freq; /* Hz */
+} UNCACHED_ALIGN PDVFS_OPP;
+
+typedef struct _RGXFWIF_PDVFS_OPP_
+{
+	PDVFS_OPP		asOPPValues[NUM_OPP_VALUES];
+	IMG_UINT32		ui32MaxOPPPoint;
+} UNCACHED_ALIGN RGXFWIF_PDVFS_OPP;
+
+typedef struct _RGXFWIF_PDVFS_OPP_DATA_
+{
+	RGXFWIF_PDVFS_OPP sPDFVSOppInfo;
+} UNCACHED_ALIGN RGXFWIF_PDVFS_OPP_DATA;
+
+typedef struct _RGXFWIF_PDVFS_MAX_FREQ_DATA_
+{
+	IMG_UINT32 ui32MaxOPPPoint;
+} UNCACHED_ALIGN RGXFWIF_PDVFS_MAX_FREQ_DATA;
+
 /*!
  ******************************************************************************
  * Register configuration structures
@@ -530,6 +647,24 @@
 	RGXFWIF_DEV_VIRTADDR              sFirmwareCCB;
 } UNCACHED_ALIGN RGXFWIF_REGISTER_GUESTOS_OFFSETS;
 
+/* OSid Scheduling Priority Change */
+typedef struct _RGXFWIF_OSID_PRIORITY_DATA_
+{
+	IMG_UINT32			ui32OSidNum;
+	IMG_UINT32			ui32Priority;
+} RGXFWIF_OSID_PRIORITY_DATA;
+
+typedef struct
+{
+	IMG_UINT32 ui32OSid;
+	RGXFWIF_OS_STATE_CHANGE eNewOSState;
+} UNCACHED_ALIGN RGXFWIF_OS_STATE_CHANGE_DATA;
+
+typedef struct
+{
+	PRGXFWIF_INIT		sOSInit;
+}  RGXFW_ALIGN RGXFWIF_OS_CONFIG_DATA;
+
 typedef enum _RGXFWIF_KCCB_CMD_TYPE_
 {
 	RGXFWIF_KCCB_CMD_KICK						= 101,
@@ -554,11 +689,22 @@
 	RGXFWIF_KCCB_CMD_HWPERF_SELECT_CUSTOM_CNTRS = 122, /*!< Configure the custom counters for HWPerf */
 	RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS_DIRECT	= 123, /*!< Configure, clear and enable multiple HWPerf blocks during the init process*/
 	RGXFWIF_KCCB_CMD_LOGTYPE_UPDATE             = 124, /*!< Ask the firmware to update its cached ui32LogType value from the (shared) tracebuf control structure */
-	RGXFWIF_KCCB_CMD_SET_GUESTOS_OFFSETS		= 125, /*!< Register the kccb offsets of a guestOS with the FW and enable checking its queues */
+	RGXFWIF_KCCB_CMD_WORKEST_CLEAR_BUFFER		= 125,
+	RGXFWIF_KCCB_CMD_PDVFS_PASS_OPP				= 126,
+	RGXFWIF_KCCB_CMD_PDVFS_LIMIT_MAX_FREQ				= 127,
+	RGXFWIF_KCCB_CMD_PDVFS_REQUEST_REACTIVE_UPDATE	= 129,
+	RGXFWIF_KCCB_CMD_DOPPLER_MEMORY_GROW		= 130,
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	RGXFWIF_FWCCB_CMD_DOPPLER_MEMORY_GROW		= 130,
-#endif
+	RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE       = 131, /*!< Informs the firmware that the host has performed a signal update */
+
+	RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE	= 132, /*!< Informs the firmware that the host has added more data to a CDM2 Circular Buffer */
+
+	RGXFWIF_KCCB_CMD_OSID_PRIORITY_CHANGE       = 133, /*!< Changes the relative scheduling priority for a particular OSid. It can only be serviced for the Host DDK */
+	RGXFWIF_KCCB_CMD_STATEFLAGS_CTRL            = 134, /*!< Set or clear firmware state flags */
+	RGXFWIF_KCCB_CMD_HCS_SET_DEADLINE           = 135, /*!< Set hard context switching deadline */
+	RGXFWIF_KCCB_CMD_OS_ISOLATION_GROUP_CHANGE  = 136, /*!< Changes the configuration of (or even disables) the OSid Isolation scheduling group. It can only be serviced for the Host DDK */
+	RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE  = 137, /*!< Informs the FW that a Guest OS has come online / offline. It can only be serviced for the Host DDK */
+	RGXFWIF_KCCB_CMD_OS_CFG_INIT                = 138, /*!< First kick of the DDK which initializes all OS specific data on the FW */
 } RGXFWIF_KCCB_CMD_TYPE;
 
 /* Kernel CCB command packet */
@@ -587,6 +733,16 @@
 		RGXFWIF_FREELISTS_RECONSTRUCTION_DATA	sFreeListsReconstructionData;	/*!< Feedback for Freelists reconstruction */
 		RGXFWIF_REGCONFIG_DATA				sRegConfigData;			/*!< Data for custom register configuration */
 		RGXFWIF_REGISTER_GUESTOS_OFFSETS    sRegisterGuestOsOffests;/*!< Data for registering a guestOS with the FW */
+		RGXFWIF_SIGNAL_UPDATE_DATA          sSignalUpdateData;      /*!< Data for informing the FW about the signal update */
+		RGXFWIF_WRITE_OFFSET_UPDATE_DATA    sWriteOffsetUpdateData; /*!< Data for informing the FW about the write offset update */
+		RGXFWIF_PDVFS_OPP_DATA				sPDVFSOppData;
+		RGXFWIF_PDVFS_MAX_FREQ_DATA			sPDVFSMaxFreqData;
+		RGXFWIF_OSID_PRIORITY_DATA			sCmdOSidPriorityData;	/*!< Data for updating an OSid priority */
+		RGXFWIF_STATEFLAG_CTRL				sStateFlagCtrl;			/*!< Data for StateFlag control command */
+		RGXFWIF_HCS_CTL						sHCSCtrl;				/*!< Data for Hard Context Switching */
+		RGXFWIF_OSID_ISOLATION_GROUP_DATA   sCmdOSidIsolationData;  /*!< Data for updating the OSid isolation group */
+		RGXFWIF_OS_STATE_CHANGE_DATA        sCmdOSOnlineStateData;  /*!< Data for updating the Guest Online states */
+		RGXFWIF_OS_CONFIG_DATA              sCmdOSConfigData;       /*!< Data for the OS-specific initialization part of the FW */
 	} UNCACHED_ALIGN uCmdData;
 } UNCACHED_ALIGN RGXFWIF_KCCB_CMD;
 
@@ -620,9 +776,10 @@
 	IMG_UINT32						ui32ServerCommonContextID;	/*!< Context affected by the reset */
 	RGXFWIF_CONTEXT_RESET_REASON	eResetReason;				/*!< Reason for reset */
 	IMG_UINT32						ui32ResetJobRef;			/*!< Job ref running at the time of reset */
+	IMG_BOOL						bPageFault;					/*!< Did a page fault happen */
+	IMG_UINT64 RGXFW_ALIGN			ui64PCAddress;				/*!< At what page catalog address */
 } RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA;
 
-
 typedef enum _RGXFWIF_FWCCB_CMD_TYPE_
 {
 	RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING				= 101, 	/*!< Requests ZSBuffer to be backed with physical pages */
@@ -632,6 +789,11 @@
 	RGXFWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION	= 105,	/*!< Notifies host of a HWR event on a context */
 	RGXFWIF_FWCCB_CMD_DEBUG_DUMP					= 106,	/*!< Requests an on-demand debug dump */
 	RGXFWIF_FWCCB_CMD_UPDATE_STATS					= 107,	/*!< Requests an on-demand update on process stats */
+
+	RGXFWIF_FWCCB_CMD_DOPPLER_MEMORY_GROW			= 108, 	/*!< Requests an on-demand RPM freelist grow */
+	RGXFWIF_FWCCB_CMD_WORKLOAD_FINISHED				= 109,	/*!< Supplies data for the workload matching algorithm */
+	RGXFWIF_FWCCB_CMD_CORE_CLK_RATE_CHANGE			= 110,
+	RGXFWIF_FWCCB_CMD_PDVFS_FREEMEM					= 111,
 } RGXFWIF_FWCCB_CMD_TYPE;
 
 typedef enum
@@ -653,6 +815,30 @@
     IMG_PID									pidOwner;					/*!< The pid of the process whose stats are being updated */
     IMG_INT32								i32AdjustmentValue;			/*!< Adjustment to be made to the statistic */
 } RGXFWIF_FWCCB_CMD_UPDATE_STATS_DATA;
+/*!
+ ******************************************************************************
+ * Workload Estimation Structures
+ *****************************************************************************/
+
+typedef struct
+{
+	IMG_UINT64 RGXFW_ALIGN /*uintptr_t DEVMEM_MEMDESC*/	ui64WorkloadDataMemdesc;
+} RGXFWIF_FWCCB_CMD_WORKLOAD_FINISHED_DATA;
+
+/*!
+ ******************************************************************************
+ * Proactive DVFS Structures
+ *****************************************************************************/
+
+typedef struct _RGXFWIF_FWCCB_CMD_CORE_CLK_RATE_CHANGE_DATA_
+{
+	IMG_UINT32 ui32CoreClkRate;
+} UNCACHED_ALIGN RGXFWIF_FWCCB_CMD_CORE_CLK_RATE_CHANGE_DATA;
+
+typedef struct _RGXFWIF_FWCCB_CMD_PDVFS_FREEMEM_DATA_
+{
+	IMG_UINT64 RGXFW_ALIGN ui64MemDesc;
+} UNCACHED_ALIGN RGXFWIF_FWCCB_CMD_PDVFS_FREEMEM_DATA;
 
 typedef struct _RGXFWIF_FWCCB_CMD_
 {
@@ -663,7 +849,10 @@
 		RGXFWIF_FWCCB_CMD_FREELIST_GS_DATA					sCmdFreeListGS;					/*!< Data for on-demand freelist grow/shrink */
 		RGXFWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION_DATA		sCmdFreeListsReconstruction;	/*!< Data for freelists reconstruction */
 		RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA				sCmdContextResetNotification;	/*!< Data for context reset notification */
-        RGXFWIF_FWCCB_CMD_UPDATE_STATS_DATA                 sCmdUpdateStatsData;            /*!< Data for updating process stats */
+		RGXFWIF_FWCCB_CMD_UPDATE_STATS_DATA                 sCmdUpdateStatsData;            /*!< Data for updating process stats */
+		RGXFWIF_FWCCB_CMD_WORKLOAD_FINISHED_DATA			sCmdWorkEstWorkloadFinished;			/*!< Data for workload matching */
+		RGXFWIF_FWCCB_CMD_CORE_CLK_RATE_CHANGE_DATA			sCmdCoreClkRateChange;
+		RGXFWIF_FWCCB_CMD_PDVFS_FREEMEM_DATA				sCmdPDVFSFreeMem;
 	} RGXFW_ALIGN uCmdData;
 } RGXFW_ALIGN RGXFWIF_FWCCB_CMD;
 
@@ -675,7 +864,7 @@
  *****************************************************************************/
 typedef struct _RGXFWIF_SIGBUF_CTL_
 {
-	PRGXFWIF_SIGBUFFER		psBuffer;			/*!< Ptr to Signature Buffer memory */
+	PRGXFWIF_SIGBUFFER		sBuffer;			/*!< Ptr to Signature Buffer memory */
 	IMG_UINT32				ui32LeftSizeInRegs;	/*!< Amount of space left for storing regs in the buffer */
 } UNCACHED_ALIGN RGXFWIF_SIGBUF_CTL;
 
@@ -685,11 +874,11 @@
  *****************************************************************************/
 typedef struct _RGXFWIF_RUNTIME_CFG_
 {
-	IMG_UINT32				ui32ActivePMLatencyms;		/* APM latency in ms before signalling IDLE to the host */
-	IMG_BOOL				bActivePMLatencyPersistant;	/* If set, APM latency does not reset to system default each GPU power transition */
-	IMG_UINT32				ui32CoreClockSpeed;			/* Core clock speed, currently only used to calculate timer ticks */
-	IMG_UINT32				ui32DefaultDustsNumInit;	/* Last number of dusts change requested by the host */
-	PRGXFWIF_HWPERFBUF			pui8HWPerfBuf;			/* On-demand allocated HWPerf buffer address, to be passed to the FW */
+	IMG_UINT32         ui32ActivePMLatencyms;      /* APM latency in ms before signalling IDLE to the host */
+	IMG_BOOL           bActivePMLatencyPersistant; /* If set, APM latency does not reset to system default each GPU power transition */
+	IMG_UINT32         ui32CoreClockSpeed;         /* Core clock speed, currently only used to calculate timer ticks */
+	IMG_UINT32         ui32DefaultDustsNumInit;    /* Last number of dusts change requested by the host */
+	PRGXFWIF_HWPERFBUF sHWPerfBuf;                 /* On-demand allocated HWPerf buffer address, to be passed to the FW */
 } RGXFWIF_RUNTIME_CFG;
 
 /*!
@@ -729,37 +918,39 @@
 
 typedef struct _RGXFWIF_INIT_
 {
-	IMG_DEV_PHYADDR 		RGXFW_ALIGN sFaultPhysAddr;
+	IMG_DEV_PHYADDR         RGXFW_ALIGN sFaultPhysAddr;
 
-	IMG_DEV_VIRTADDR		RGXFW_ALIGN sPDSExecBase;
-	IMG_DEV_VIRTADDR		RGXFW_ALIGN sUSCExecBase;
-	IMG_DEV_VIRTADDR		RGXFW_ALIGN sResultDumpBase;
-	IMG_DEV_VIRTADDR		RGXFW_ALIGN sDPXControlStreamBase;
-	IMG_DEV_VIRTADDR		RGXFW_ALIGN sRTUHeapBase;
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sPDSExecBase;
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sUSCExecBase;
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sResultDumpBase;
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sDPXControlStreamBase;
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sRTUHeapBase;
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sTDMTPUYUVCeoffsHeapBase;
 
-	IMG_BOOL				bFirstTA;
-	IMG_BOOL				bFirstRender;
-	IMG_BOOL				bFrameworkAfterInit;
-	IMG_BOOL				bEnableHWPerf;
+	IMG_BOOL                bFirstTA;
+	IMG_BOOL                bFirstRender;
+	IMG_BOOL                bFrameworkAfterInit;
 	IMG_BOOL                bDisableFilterHWPerfCustomCounter;
-	IMG_UINT32				uiPowerSync;
-	IMG_UINT32				ui32FilterFlags;
+	RGXFWIF_DEV_VIRTADDR    sPowerSync;
+	IMG_UINT32              ui32FilterFlags;
 
 	/* Kernel CCB */
-	PRGXFWIF_CCB_CTL		psKernelCCBCtl;
-	PRGXFWIF_CCB			psKernelCCB;
+	PRGXFWIF_CCB_CTL        psKernelCCBCtl;
+	PRGXFWIF_CCB            psKernelCCB;
 
 	/* Firmware CCB */
-	PRGXFWIF_CCB_CTL		psFirmwareCCBCtl;
-	PRGXFWIF_CCB			psFirmwareCCB;
+	PRGXFWIF_CCB_CTL        psFirmwareCCBCtl;
+	PRGXFWIF_CCB            psFirmwareCCB;
 
-	RGXFWIF_SIGBUF_CTL		asSigBufCtl[RGXFWIF_DM_MAX];
+	RGXFWIF_SIGBUF_CTL	asSigBufCtl[RGXFWIF_DM_DEFAULT_MAX];
 
-	IMG_BOOL				bEnableLogging;
-	IMG_UINT32				ui32ConfigFlags;	/*!< Configuration flags from host */
-	IMG_UINT32				ui32BreakpointTemps;
-	IMG_UINT32				ui32BreakpointShareds;
-	IMG_UINT32				ui32HWRDebugDumpLimit;
+	IMG_BOOL                bEnableLogging;
+	IMG_UINT32              ui32ConfigFlags;        /*!< Configuration flags from host */
+	IMG_UINT32              ui32BreakpointTemps;
+	IMG_UINT32              ui32BreakpointShareds;
+	IMG_UINT32              ui32HWRDebugDumpLimit;
+
+	RGXFWIF_BIFTILINGMODE   eBifTilingMode;
 	struct
 	{
 		IMG_UINT64 uiBase;
@@ -767,54 +958,61 @@
 		IMG_UINT64 uiXStride;
 	}                       RGXFW_ALIGN sBifTilingCfg[RGXFWIF_NUM_BIF_TILING_CONFIGS];
 
-	PRGXFWIF_RUNTIME_CFG	psRuntimeCfg;
+	PRGXFWIF_RUNTIME_CFG    sRuntimeCfg;
 
-	PRGXFWIF_TRACEBUF		psTraceBufCtl;
-	IMG_UINT64	RGXFW_ALIGN ui64HWPerfFilter;
+	PRGXFWIF_TRACEBUF       sTraceBufCtl;
+	IMG_UINT64              RGXFW_ALIGN ui64HWPerfFilter;
 
-	PRGXFWIF_HWRINFOBUF		psRGXFWIfHWRInfoBufCtl;
-	PRGXFWIF_GPU_UTIL_FWCB	psGpuUtilFWCbCtl;
-	PRGXFWIF_REG_CFG		psRegCfg;
-	PRGXFWIF_HWPERF_CTL		psHWPerfCtl;
+	PRGXFWIF_HWRINFOBUF     sRGXFWIfHWRInfoBufCtl;
+	PRGXFWIF_GPU_UTIL_FWCB  sGpuUtilFWCbCtl;
+	PRGXFWIF_REG_CFG        sRegCfg;
+	PRGXFWIF_HWPERF_CTL     sHWPerfCtl;
 
-	PRGXFWIF_ALIGNCHECK		paui32AlignChecks;
+	RGXFWIF_DEV_VIRTADDR    sAlignChecks;
 
 	/* Core clock speed at FW boot time */
 	IMG_UINT32              ui32InitialCoreClockSpeed;
 
 	/* APM latency in ms before signalling IDLE to the host */
-	IMG_UINT32				ui32ActivePMLatencyms;
+	IMG_UINT32              ui32ActivePMLatencyms;
 
 	/* Flag to be set by the Firmware after successful start */
-	IMG_BOOL				bFirmwareStarted;
+	IMG_BOOL                bFirmwareStarted;
 
-	IMG_UINT32				ui32MarkerVal;
+	IMG_UINT32              ui32MarkerVal;
 
-	IMG_UINT32				ui32FirmwareStartedTimeStamp;
+	IMG_UINT32              ui32FirmwareStartedTimeStamp;
 
-	IMG_UINT32				ui32JonesDisableMask;
+	IMG_UINT32              ui32JonesDisableMask;
 
 	/* Compatibility checks to be populated by the Firmware */
-	RGXFWIF_COMPCHECKS		sRGXCompChecks;
+	RGXFWIF_COMPCHECKS      sRGXCompChecks;
 
-	RGXFWIF_DMA_ADDR		sCorememDataStore;
+	RGXFWIF_DMA_ADDR        sCorememDataStore;
 
-	FW_PERF_CONF			eFirmwarePerf;
+	FW_PERF_CONF            eFirmwarePerf;
 
-#if defined(RGX_FEATURE_SLC_VIVT)
-	IMG_DEV_VIRTADDR		RGXFW_ALIGN sSLC3FenceDevVAddr;
-#endif
+	IMG_DEV_VIRTADDR        RGXFW_ALIGN sSLC3FenceDevVAddr;
 
-#if defined(RGX_FIRMWARE)
-	IMG_BYTE                *pbT1Stack;
-#else
-	RGXFWIF_DEV_VIRTADDR    pbT1Stack;
-#endif
+	RGXFWIF_DEV_VIRTADDR    sT1Stack;
+
+	RGXFWIF_PDVFS_OPP       sPDVFSOPPInfo;
+
+	/**
+	 * FW Pointer to memory containing core clock rate in Hz.
+	 * Firmware (PDVFS) updates the memory when running on non primary FW thread
+	 * to communicate to host driver.
+	 */
+	PRGXFWIF_CORE_CLK_RATE  sCoreClockRate;
 
 #if defined(PDUMP)
-	RGXFWIF_PID_FILTER sPIDFilter;
+	RGXFWIF_PID_FILTER      sPIDFilter;
 #endif
 
+	/* Workload Estimation Firmware CCB */
+	PRGXFWIF_CCB_CTL        psWorkEstFirmwareCCBCtl;
+	PRGXFWIF_CCB            psWorkEstFirmwareCCB;
+
 } UNCACHED_ALIGN RGXFWIF_INIT;
 
 
@@ -824,7 +1022,7 @@
  *****************************************************************************/
 typedef struct _RGXFWIF_CMD_PRIORITY_
 {
-	IMG_UINT32				ui32Priority;
+    IMG_UINT32				ui32Priority;
 } RGXFWIF_CMD_PRIORITY;
 
 #endif /*  __RGX_FWIF_KM_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_resetframework.h b/drivers/staging/imgtec/rogue/rgx_fwif_resetframework.h
index 25ee674..dceeb48 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_resetframework.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_resetframework.h
@@ -48,7 +48,13 @@
 
 typedef struct _RGXFWIF_RF_REGISTERS_
 {
+#if RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT == 2
+	IMG_UINT64	uCDMReg_CDM_CB_QUEUE;
+	IMG_UINT64	uCDMReg_CDM_CB_BASE;
+	IMG_UINT64	uCDMReg_CDM_CB;
+#else
 	IMG_UINT64  uCDMReg_CDM_CTRL_STREAM_BASE;
+#endif
 } RGXFWIF_RF_REGISTERS;
 
 #define RGXFWIF_RF_FLAG_ENABLE 0x00000001 /*!< enables the reset framework in the firmware */
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_sf.h b/drivers/staging/imgtec/rogue/rgx_fwif_sf.h
index b2a35cf..c3baa29 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_sf.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_sf.h
@@ -89,108 +89,158 @@
  */
 #define RGXFW_LOG_SFIDLIST \
 /*id, gid,              id name,        string,                           # arguments */ \
-X( 0, RGXFW_GROUP_NULL, RGXFW_SF_FIRST, "You should not use this string", 0) \
+X( 0, RGXFW_GROUP_NULL, RGXFW_SF_FIRST, "You should not use this string\n", 0) \
 \
-X( 1, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK3D, "Kick 3D: FWCtx 0x%08.8X @ %d, RTD 0x%08x. Partial render:%d, CSW resume:%d, prio:%d\n", 6) \
-X( 2, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_FINISHED, "3D finished, HWRTData0State=%d, HWRTData1State=%d\n", 2) \
-X( 3, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK3D_TQ, "Kick 3D TQ: FWCtx 0x%08.8X @ %d, CSW resume:%d, prio: %d\n", 4) \
-X( 4, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_TQ_FINISHED, "3D Transfer finished\n", 0) \
-X( 5, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_COMPUTE, "Kick Compute: FWCtx 0x%08.8X @ %d, prio: %d\n", 3) \
-X( 6, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_FINISHED, "Compute finished\n", 0) \
-X( 7, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICKTA, "Kick TA: FWCtx 0x%08.8X @ %d, RTD 0x%08x. First kick:%d, Last kick:%d, CSW resume:%d, prio:%d\n", 7) \
-X( 8, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_FINISHED, "TA finished\n", 0) \
-X( 9, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_RESTART_AFTER_PRENDER, "Restart TA after partial render\n", 0) \
-X(10, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_RESUME_WOUT_PRENDER, "Resume TA without partial render\n", 0) \
-X(11, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OOM, "Out of memory! Context 0x%08x, HWRTData 0x%x\n", 2) \
-X(12, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TLA, "Kick TLA: FWCtx 0x%08.8X @ %d, prio:%d\n", 3) \
-X(13, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TLA_FINISHED, "TLA finished\n", 0) \
-X(14, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CCCB_WOFF_UPDATE, "cCCB Woff update = %d, DM = %d, FWCtx = 0x%08.8X\n", 3) \
-X(16, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK_START, "UFO Checks for FWCtx %08.8X @ %d\n", 2) \
-X(17, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK, "UFO Check: [%08.8X] is %08.8X requires %08.8X\n", 3) \
-X(18, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK_SUCCEEDED, "UFO Checks succeeded\n", 0) \
-X(19, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_PR_CHECK, "UFO PR-Check: [%08.8X] is %08.8X requires %08.8X\n", 3) \
-X(20, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK_START, "UFO SPM PR-Checks for FWCtx %08.8X\n", 1) \
-X(21, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK_DEPRECATED, "UFO SPM special PR-Check: [%08.8X] is %08.8X requires >= ????????, [%08.8X] is ???????? requires %08.8X\n", 4) \
-X(22, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_UPDATE_START, "UFO Updates for FWCtx %08.8X @ %d\n", 2) \
-X(23, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_UPDATE, "UFO Update: [%08.8X] = %08.8X\n", 2) \
-X(24, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ASSERT_FAILED, "ASSERT Failed: line %d of: \n", 1) \
-X(25, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_LOCKUP_DEPRECATED, "HWR: Lockup detected on DM%d, FWCtx: %08.8X\n", 2) \
-X(26, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_RESET_FW_DEPRECATED, "HWR: Reset fw state for DM%d, FWCtx: %08.8X, MemCtx: %08.8X\n", 3) \
-X(27, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_RESET_HW_DEPRECATED, "HWR: Reset HW\n", 0) \
-X(28, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_TERMINATED_DEPRECATED, "HWR: Lockup recovered.\n", 0) \
-X(29, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_FALSE_LOCKUP_DEPRECATED, "HWR: False lockup detected for DM%u\n", 1) \
-X(30, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ALIGN_FAILED, "Alignment check %d failed: host = %X, fw = %X\n", 3) \
-X(31, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_GP_USC_TRIGGERED, "GP USC triggered\n", 0) \
-X(32, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_OVERALLOC_REGS, "Overallocating %u temporary registers and %u shared registers for breakpoint handler\n", 2) \
-X(33, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_SET_DEPRECATED, "Setting breakpoint: Addr 0x%08.8X\n", 1) \
-X(34, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_STORE, "Store breakpoint state\n", 0) \
-X(35, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_UNSET, "Unsetting BP Registers\n", 0) \
-X(36, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_NONZERO_RT, "Active RTs expected to be zero, actually %u\n", 1) \
-X(37, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTC_PRESENT, "RTC present, %u active render targets\n", 1) \
-X(38, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_EST_POWER, "Estimated Power 0x%x\n", 1) \
-X(39, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTA_TARGET, "RTA render target %u\n", 1) \
-X(40, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTA_KICK_RENDER, "Kick RTA render %u of %u\n", 2) \
-X(41, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_SIZES_CHECK, "HWR sizes check %d failed: addresses = %d, sizes = %d\n", 3) \
-X(42, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_DUSTS_ENABLE_DEPRECATED, "Pow: DUSTS_ENABLE = 0x%X\n", 1) \
-X(43, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_HWREQ_DEPRECATED, "Pow: On(1)/Off(0): %d, Units: 0x%08.8X\n", 2) \
-X(44, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_DUSTS_CHANGE_DEPRECATED, "Pow: Changing number of dusts from %d to %d\n", 2) \
-X(45, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_SIDEKICK_IDLE_DEPRECATED, "Pow: Sidekick ready to be powered down\n", 0) \
-X(46, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_DUSTS_CHANGE_REQ_DEPRECATED, "Pow: Request to change num of dusts to %d (bPowRascalDust=%d)\n", 2) \
-X(47, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PARTIALRENDER_WITHOUT_ZSBUFFER_STORE, "No ZS Buffer used for partial render (store)\n", 0) \
-X(48, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PARTIALRENDER_WITHOUT_ZSBUFFER_LOAD, "No Depth/Stencil Buffer used for partial render (load)\n", 0) \
-X(49, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_SET_LOCKUP_DEPRECATED, "HWR: Lock-up DM%d FWCtx: %08.8X \n", 2) \
-X(50, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_REG_VALUE_DEPRECATED, "MLIST%d checker: CatBase TE=0x%08x (%d Pages), VCE=0x%08x (%d Pages), ALIST=0x%08x, IsTA=%d\n", 7) \
-X(51, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_MLIST_VALUE, "MLIST%d checker: MList[%d] = 0x%08x\n", 3) \
-X(52, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_OK, "MLIST%d OK\n", 1) \
-X(53, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_EMPTY, "MLIST%d is empty\n", 1) \
-X(54, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_REG_VALUE, "MLIST%d checker: CatBase TE=0x%08X%08X, VCE=0x%08x%08X, ALIST=0x%08x%08X, IsTA=%d\n", 8) \
-X(55, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_40480KICK, "3D OQ flush kick\n", 0) \
-X(56, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWP_UNSUPPORTED_BLOCK, "HWPerf block ID (0x%x) unsupported by device\n", 1) \
-X(57, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_SET, "Setting breakpoint: Addr 0x%08.8X DM%u\n", 2) \
-X(58, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RTU_DEPRECATED, "Kick RTU: FWCtx 0x%08.8X @ %d, prio: %d\n", 3) \
-X(59, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTU_FINISHED, "RDM finished on context %u\n", 1) \
-X(60, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_SHG, "Kick SHG: FWCtx 0x%08.8X @ %d, prio: %d\n", 3) \
-X(61, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SHG_FINISHED, "SHG finished\n", 0) \
-X(62, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FBA_FINISHED, "FBA finished on context %u\n", 1) \
-X(63, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK_FAILED, "UFO Checks failed\n", 0) \
-X(64, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KILLDM_START, "Kill DM%d start\n", 1) \
-X(65, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KILLDM_COMPLETE, "Kill DM%d complete\n", 1) \
-X(66, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FC_CCB_UPDATE, "FC%u cCCB Woff update = %u\n", 2) \
-X(67, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RTU, "Kick RTU: FWCtx 0x%08.8X @ %d, prio: %d, Frame Context: %d\n", 4) \
-X(68, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIDEKICK_INIT, "Sidekick init\n", 0) \
-X(69, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RD_INIT, "Rascal+Dusts init (# dusts mask: %X)\n", 1) \
-X(70, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_REGTIMES, "Register access cycles: read: %d cycles, write: %d cycles, iterations: %d\n", 3) \
-X(71, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_REGCONFIG_ADD, "Register configuration added. Address: 0x%x Value: 0x%x%x\n", 3) \
-X(72, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_REGCONFIG_SET, "Register configuration applied to type %d. (0:pow on, 1:Rascal/dust init, 2-5: TA,3D,CDM,TLA, 6:All)\n", 1) \
-X(73, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TPC_FLUSH, "Perform TPC flush.\n", 0) \
-X(74, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_HIT_LOCKUP, "GPU has locked up (see HWR logs for more info)\n", 0) \
-X(75, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_HIT_OUTOFTIME, "HWR has been triggered - GPU has overrun its deadline (see HWR logs)\n", 0) \
-X(76, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_HIT_POLLFAILURE, "HWR has been triggered - GPU has failed a poll (see HWR logs)\n", 0) \
-X(77, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DOPPLER_OOM, "Doppler out of memory event for FC %u\n", 1) \
-X(78, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK1, "UFO SPM special PR-Check: [%08.8X] is %08.8X requires >= %08.8X\n", 3) \
-X(79, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK2, "UFO SPM special PR-Check: [%08.8X] is %08.8X requires %08.8X\n", 3) \
-X(80, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TIMESTAMP, "TIMESTAMP -> [%08.8X]\n", 1) \
-X(81, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_RMW_UPDATE_START, "UFO RMW Updates for FWCtx %08.8X @ %d\n", 2) \
-X(82, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_RMW_UPDATE, "UFO Update: [%08.8X] = %08.8X\n", 2) \
-X(83, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_NULLCMD, "Kick Null cmd: FWCtx 0x%08.8X @ %d\n", 2) \
-X(84, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RPM_OOM, "RPM Out of memory! Context 0x%08x, SH requestor %d\n", 2) \
-X(85, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTU_ABORT_DISCARD, "Discard RTU due to RPM abort: FWCtx 0x%08.8X @ %d, prio: %d, Frame Context: %d\n", 4) \
-X(86, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEFERRED, "Deferring DM%u from running context 0x%08x @ %d (deferred DMs = 0x%08x)\n", 4) \
-X(87, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEFERRED_WAITING_TURN, "Deferring DM%u from running context 0x%08x @ %d to let other deferred DMs run (deferred DMs = 0x%08x)\n", 4) \
-X(88, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEFERRED_NO_LONGER, "No longer deferring DM%u from running context = 0x%08x @ %d (deferred DMs = 0x%08x)\n", 4) \
-X(89, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_WAITING_FOR_FWCCB_DEPRECATED, "FWCCB for DM%u is full, we will have to wait for space! (Roff = %u, Woff = %u)\n", 3) \
-X(90, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_WAITING_FOR_FWCCB, "FWCCB for OSid %u is full, we will have to wait for space! (Roff = %u, Woff = %u)\n", 3) \
-X(91, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SYNC_PART, "Host Sync Partition marker: %d\n", 1) \
-X(92, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SYNC_PART_RPT, "Host Sync Partition repeat: %d\n", 1) \
-X(93, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CLOCK_SPEED_CHANGE, "Core clock set to %d Hz\n", 1) \
-X(94, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CSRM_RECONFIG, "Reconfigure CSRM: special coeff support enable %d.\n", 1) \
-X(95, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_REQ_MAX_COEFFS, "TA requires max coeff mode, deferring: %d.\n", 1) \
-X(96, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PIX_REQ_MAX_COEFFS, "3D requires max coeff mode, deferring: %d.\n", 1) \
+X( 1,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_3D_DEPRECATED, "Kick 3D: FWCtx 0x%08.8X @ %d, RTD 0x%08x. Partial render:%d, CSW resume:%d, prio:%d\n", 6) \
+X( 2,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_FINISHED, "3D finished, HWRTData0State=%d, HWRTData1State=%d\n", 2) \
+X( 3,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK3D_TQ_DEPRECATED, "Kick 3D TQ: FWCtx 0x%08.8X @ %d, CSW resume:%d, prio: %d\n", 4) \
+X( 4,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_TQ_FINISHED, "3D Transfer finished\n", 0) \
+X( 5,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_COMPUTE_DEPRECATED, "Kick Compute: FWCtx 0x%08.8X @ %d, prio: %d\n", 3) \
+X( 6,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_FINISHED, "Compute finished\n", 0) \
+X( 7,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TA_DEPRECATED, "Kick TA: FWCtx 0x%08.8X @ %d, RTD 0x%08x. First kick:%d, Last kick:%d, CSW resume:%d, prio:%d\n", 7) \
+X( 8,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_FINISHED, "TA finished\n", 0) \
+X( 9,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_RESTART_AFTER_PRENDER, "Restart TA after partial render\n", 0) \
+X(10,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_RESUME_WOUT_PRENDER, "Resume TA without partial render\n", 0) \
+X(11,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OOM, "Out of memory! Context 0x%08x, HWRTData 0x%x\n", 2) \
+X(12,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TLA_DEPRECATED, "Kick TLA: FWCtx 0x%08.8X @ %d, prio:%d\n", 3) \
+X(13,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TLA_FINISHED, "TLA finished\n", 0) \
+X(14,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CCCB_WOFF_UPDATE, "cCCB Woff update = %d, DM = %d, FWCtx = 0x%08.8X\n", 3) \
+X(16,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK_START, "UFO Checks for FWCtx %08.8X @ %d\n", 2) \
+X(17,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK, "UFO Check: [%08.8X] is %08.8X requires %08.8X\n", 3) \
+X(18,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK_SUCCEEDED, "UFO Checks succeeded\n", 0) \
+X(19,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_PR_CHECK, "UFO PR-Check: [%08.8X] is %08.8X requires >= %08.8X\n", 3) \
+X(20,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK_START, "UFO SPM PR-Checks for FWCtx %08.8X\n", 1) \
+X(21,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK_DEPRECATED, "UFO SPM special PR-Check: [%08.8X] is %08.8X requires >= ????????, [%08.8X] is ???????? requires %08.8X\n", 4) \
+X(22,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_UPDATE_START, "UFO Updates for FWCtx %08.8X @ %d\n", 2) \
+X(23,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_UPDATE, "UFO Update: [%08.8X] = %08.8X\n", 2) \
+X(24,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ASSERT_FAILED, "ASSERT Failed: line %d of: \n", 1) \
+X(25,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_LOCKUP_DEPRECATED, "HWR: Lockup detected on DM%d, FWCtx: %08.8X\n", 2) \
+X(26,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_RESET_FW_DEPRECATED, "HWR: Reset fw state for DM%d, FWCtx: %08.8X, MemCtx: %08.8X\n", 3) \
+X(27,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_RESET_HW_DEPRECATED, "HWR: Reset HW\n", 0) \
+X(28,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_TERMINATED_DEPRECATED, "HWR: Lockup recovered.\n", 0) \
+X(29,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_FALSE_LOCKUP_DEPRECATED, "HWR: False lockup detected for DM%u\n", 1) \
+X(30,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ALIGN_FAILED, "Alignment check %d failed: host = %X, fw = %X\n", 3) \
+X(31,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_GP_USC_TRIGGERED, "GP USC triggered\n", 0) \
+X(32,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_OVERALLOC_REGS, "Overallocating %u temporary registers and %u shared registers for breakpoint handler\n", 2) \
+X(33,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_SET_DEPRECATED, "Setting breakpoint: Addr 0x%08.8X\n", 1) \
+X(34,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_STORE, "Store breakpoint state\n", 0) \
+X(35,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_UNSET, "Unsetting BP Registers\n", 0) \
+X(36,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_NONZERO_RT, "Active RTs expected to be zero, actually %u\n", 1) \
+X(37,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTC_PRESENT, "RTC present, %u active render targets\n", 1) \
+X(38,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_EST_POWER, "Estimated Power 0x%x\n", 1) \
+X(39,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTA_TARGET, "RTA render target %u\n", 1) \
+X(40,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTA_KICK_RENDER, "Kick RTA render %u of %u\n", 2) \
+X(41,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_SIZES_CHECK, "HWR sizes check %d failed: addresses = %d, sizes = %d\n", 3) \
+X(42,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_DUSTS_ENABLE_DEPRECATED, "Pow: DUSTS_ENABLE = 0x%X\n", 1) \
+X(43,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_HWREQ_DEPRECATED, "Pow: On(1)/Off(0): %d, Units: 0x%08.8X\n", 2) \
+X(44,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_DUSTS_CHANGE_DEPRECATED, "Pow: Changing number of dusts from %d to %d\n", 2) \
+X(45,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_SIDEKICK_IDLE_DEPRECATED, "Pow: Sidekick ready to be powered down\n", 0) \
+X(46,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_POW_DUSTS_CHANGE_REQ_DEPRECATED, "Pow: Request to change num of dusts to %d (bPowRascalDust=%d)\n", 2) \
+X(47,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PARTIALRENDER_WITHOUT_ZSBUFFER_STORE, "No ZS Buffer used for partial render (store)\n", 0) \
+X(48,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PARTIALRENDER_WITHOUT_ZSBUFFER_LOAD, "No Depth/Stencil Buffer used for partial render (load)\n", 0) \
+X(49,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_SET_LOCKUP_DEPRECATED, "HWR: Lock-up DM%d FWCtx: %08.8X \n", 2) \
+X(50,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_REG_VALUE_DEPRECATED, "MLIST%d checker: CatBase TE=0x%08x (%d Pages), VCE=0x%08x (%d Pages), ALIST=0x%08x, IsTA=%d\n", 7) \
+X(51,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_MLIST_VALUE, "MLIST%d checker: MList[%d] = 0x%08x\n", 3) \
+X(52,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_OK, "MLIST%d OK\n", 1) \
+X(53,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_EMPTY, "MLIST%d is empty\n", 1) \
+X(54,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_MLIST_CHECKER_REG_VALUE, "MLIST%d checker: CatBase TE=0x%08X%08X, VCE=0x%08x%08X, ALIST=0x%08x%08X, IsTA=%d\n", 8) \
+X(55,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_40480KICK, "3D OQ flush kick\n", 0) \
+X(56,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWP_UNSUPPORTED_BLOCK, "HWPerf block ID (0x%x) unsupported by device\n", 1) \
+X(57,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BREAKPOINT_SET, "Setting breakpoint: Addr 0x%08.8X DM%u\n", 2) \
+X(58,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RTU_DEPRECATED, "Kick RTU: FWCtx 0x%08.8X @ %d, prio: %d\n", 3) \
+X(59,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTU_FINISHED, "RDM finished on context %u\n", 1) \
+X(60,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_SHG_DEPRECATED, "Kick SHG: FWCtx 0x%08.8X @ %d, prio: %d\n", 3) \
+X(61,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SHG_FINISHED, "SHG finished\n", 0) \
+X(62,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FBA_FINISHED, "FBA finished on context %u\n", 1) \
+X(63,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_CHECK_FAILED, "UFO Checks failed\n", 0) \
+X(64,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KILLDM_START, "Kill DM%d start\n", 1) \
+X(65,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KILLDM_COMPLETE, "Kill DM%d complete\n", 1) \
+X(66,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FC_CCB_UPDATE, "FC%u cCCB Woff update = %u\n", 2) \
+X(67,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RTU_DEPRECATED2, "Kick RTU: FWCtx 0x%08.8X @ %d, prio: %d, Frame Context: %d\n", 4) \
+X(68,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIDEKICK_INIT, "Sidekick init\n", 0) \
+X(69,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RD_INIT, "Rascal+Dusts init (# dusts mask: %X)\n", 1) \
+X(70,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_REGTIMES, "Register access cycles: read: %d cycles, write: %d cycles, iterations: %d\n", 3) \
+X(71,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_REGCONFIG_ADD, "Register configuration added. Address: 0x%x Value: 0x%x%x\n", 3) \
+X(72,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_REGCONFIG_SET, "Register configuration applied to type %d. (0:pow on, 1:Rascal/dust init, 2-5: TA,3D,CDM,TLA, 6:All)\n", 1) \
+X(73,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TPC_FLUSH, "Perform TPC flush.\n", 0) \
+X(74,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_HIT_LOCKUP, "GPU has locked up (see HWR logs for more info)\n", 0) \
+X(75,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_HIT_OUTOFTIME, "HWR has been triggered - GPU has overrun its deadline (see HWR logs)\n", 0) \
+X(76,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HWR_HIT_POLLFAILURE, "HWR has been triggered - GPU has failed a poll (see HWR logs)\n", 0) \
+X(77,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DOPPLER_OOM, "Doppler out of memory event for FC %u\n", 1) \
+X(78,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK1, "UFO SPM special PR-Check: [%08.8X] is %08.8X requires >= %08.8X\n", 3) \
+X(79,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_SPM_PR_CHECK2, "UFO SPM special PR-Check: [%08.8X] is %08.8X requires %08.8X\n", 3) \
+X(80,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TIMESTAMP, "TIMESTAMP -> [%08.8X]\n", 1) \
+X(81,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_RMW_UPDATE_START, "UFO RMW Updates for FWCtx %08.8X @ %d\n", 2) \
+X(82,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UFO_RMW_UPDATE, "UFO Update: [%08.8X] = %08.8X\n", 2) \
+X(83,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_NULLCMD, "Kick Null cmd: FWCtx 0x%08.8X @ %d\n", 2) \
+X(84,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RPM_OOM, "RPM Out of memory! Context 0x%08x, SH requestor %d\n", 2) \
+X(85,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RTU_ABORT_DISCARD, "Discard RTU due to RPM abort: FWCtx 0x%08.8X @ %d, prio: %d, Frame Context: %d\n", 4) \
+X(86,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEFERRED, "Deferring DM%u from running context 0x%08x @ %d (deferred DMs = 0x%08x)\n", 4) \
+X(87,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEFERRED_WAITING_TURN, "Deferring DM%u from running context 0x%08x @ %d to let other deferred DMs run (deferred DMs = 0x%08x)\n", 4) \
+X(88,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEFERRED_NO_LONGER, "No longer deferring DM%u from running context = 0x%08x @ %d (deferred DMs = 0x%08x)\n", 4) \
+X(89,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_WAITING_FOR_FWCCB_DEPRECATED, "FWCCB for DM%u is full, we will have to wait for space! (Roff = %u, Woff = %u)\n", 3) \
+X(90,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_WAITING_FOR_FWCCB, "FWCCB for OSid %u is full, we will have to wait for space! (Roff = %u, Woff = %u)\n", 3) \
+X(91,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SYNC_PART, "Host Sync Partition marker: %d\n", 1) \
+X(92,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SYNC_PART_RPT, "Host Sync Partition repeat: %d\n", 1) \
+X(93,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CLOCK_SPEED_CHANGE, "Core clock set to %d Hz\n", 1) \
+X(94,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_OFFSETS, "Compute Queue: FWCtx 0x%08.8X, prio: %d, queue: 0x%08X%08X (Roff = %u, Woff = %u, Size = %u)\n", 7) \
+X(95,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIGNAL_WAIT_FAILURE, "Signal check failed, Required Data: 0x%X, Address: 0x%08x%08x\n", 3) \
+X(96,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIGNAL_UPDATE, "Signal update, Snoop Filter: %u, MMU Ctx: %u, Signal Id: %u, Signals Base: 0x%08x%08x\n", 5) \
+X(97,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FWCONTEXT_SIGNALED, "Signalled the previously waiting FWCtx: 0x%08.8X, OSId: %u, Signal Address: 0x%08x%08x\n", 4) \
+X(98,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_STALLED_DEPRECATED, "Compute stalled\n", 0) \
+X(99,  RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_STALLED, "Compute stalled (Roff = %u, Woff = %u, Size = %u)\n", 3) \
+X(100, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_RESUMED_FROM_STALL, "Compute resumed (Roff = %u, Woff = %u, Size = %u)\n", 3) \
+X(101, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_NOTIFY_SIGNAL_UPDATE, "Signal update notification from the host, PC Physical Address: 0x%08x%08x, Signal Virtual Address: 0x%08x%08x\n", 4) \
+X(102, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIGNAL_UPDATE_OSID_DM, "Signal update from DM: %u, OSId: %u, PC Physical Address: 0x%08x%08x\n", 4) \
+X(103, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIGNAL_WAIT_FAILURE_DM, "DM: %u signal check failed\n", 1) \
+X(104, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TDM_DEPRECATED, "Kick TDM: FWCtx 0x%08.8X @ %d, prio:%d\n", 3) \
+X(105, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TDM_FINISHED, "TDM finished\n", 0) \
+X(106, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TE_PIPE_STATUS, "MMU_PM_CAT_BASE_TE[%d]_PIPE[%d]:  0x%08X 0x%08X)\n", 4) \
+X(107, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BRN_54141_HIT, "BRN 54141 HIT\n", 0) \
+X(108, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BRN_54141_APPLYING_DUMMY_TA, "BRN 54141 Dummy TA kicked\n", 0) \
+X(109, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BRN_54141_RESUME_TA, "BRN 54141 resume TA\n", 0) \
+X(110, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BRN_54141_DOUBLE_HIT, "BRN 54141 double hit after applying WA\n", 0) \
+X(111, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_BRN_54141_DUMMY_TA_VDM_BASE, "BRN 54141 Dummy TA VDM base address: 0x%08x%08x\n", 2) \
+X(112, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIGNAL_WAIT_FAILURE_WITH_CURRENT, "Signal check failed, Required Data: 0x%X, Current Data: 0x%X, Address: 0x%08x%08x\n", 4) \
+X(113, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TDM_BUFFER_STALL, "TDM stalled (Roff = %u, Woff = %u)\n", 2) \
+X(114, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_NOTIFY_WRITE_OFFSET_UPDATE, "Write Offset update notification for stalled FWCtx %08.8X\n", 1) \
+X(115, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OS_PRIORITY_CHANGE, "Changing OSid %d's priority from %u to %u \n", 3) \
+X(116, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_RESUMED, "Compute resumed\n", 0) \
+X(117, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TLA, "Kick TLA: FWCtx 0x%08.8X @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 7) \
+X(118, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TDM, "Kick TDM: FWCtx 0x%08.8X @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 7) \
+X(119, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TA, "Kick TA: FWCtx 0x%08.8X @ %d, RTD 0x%08x, First kick:%d, Last kick:%d, CSW resume:%d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 11) \
+X(120, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_3D, "Kick 3D: FWCtx 0x%08.8X @ %d, RTD 0x%08x, Partial render:%d, CSW resume:%d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 10) \
+X(121, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_3DTQ, "Kick 3D TQ: FWCtx 0x%08.8X @ %d, CSW resume:%d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 8) \
+X(122, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_COMPUTE, "Kick Compute: FWCtx 0x%08.8X @ %d. (PID:%d, prio:%d, ext:0x%08X, int:0x%08X)\n", 6) \
+X(123, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RTU, "Kick RTU: FWCtx 0x%08.8X @ %d, Frame Context:%d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 8) \
+X(124, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_SHG, "Kick SHG: FWCtx 0x%08.8X @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08X, int:0x%08X)\n", 7) \
+X(125, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CSRM_RECONFIG, "Reconfigure CSRM: special coeff support enable %d.\n", 1) \
+X(127, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_REQ_MAX_COEFFS, "TA requires max coeff mode, deferring: %d.\n", 1) \
+X(128, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_REQ_MAX_COEFFS, "3D requires max coeff mode, deferring: %d.\n", 1) \
+X(129, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KILLDM_FAILED, "Kill DM%d failed\n", 1) \
+X(130, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_WAITING_FOR_QUEUE, "Thread Queue is full, we will have to wait for space! (Roff = %u, Woff = %u)\n", 2) \
+X(131, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_WAITING_FOR_QUEUE_FENCE, "Thread Queue is fencing, we are waiting for Roff = %d (Roff = %u, Woff = %u)\n", 3) \
+X(132, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SET_HCS_TRIGGERED, "DM %d failed to Context Switch on time. Triggered HCS (see HWR logs).\n", 1) \
+X(133, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_HCS_SET, "HCS changed to %d ms\n", 1) \
+X(134, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UPDATE_TILES_IN_FLIGHT, "Updating Tiles In Flight (Dusts=%d, PartitionMask=0x%08x, ISPCtl=0x%08x%08x)\n", 4) \
+X(135, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SET_TILES_IN_FLIGHT, "  Phantom %d: USCTiles=%d\n", 2) \
+X(136, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ISOLATION_CONF_OFF, "Isolation grouping is disabled \n", 0) \
+X(137, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ISOLATION_CONF, "Isolation group configured with a priority threshold of %d\n", 1) \
+X(138, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OS_ONLINE, "OS %d has come online \n", 1) \
+X(139, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OS_OFFLINE, "OS %d has gone offline \n", 1) \
+X(140, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FWCONTEXT_SIGNAL_REKICK, "Signalled the previously stalled FWCtx: 0x%08.8X, OSId: %u, Signal Address: 0x%08x%08x\n", 4) \
+X(141, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TDM_OFFSETS, "TDM Queue: FWCtx 0x%08.8X, prio: %d, queue: 0x%08X%08X (Roff = %u, Woff = %u, Size = %u)\n", 7) \
+X(142, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TDM_OFFSET_READ_RESET, "Reset TDM Queue Read Offset: FWCtx 0x%08.8X, queue: 0x%08X%08X (Roff = %u becomes 0, Woff = %u, Size = %u)\n", 6) \
+X(143, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_UMQ_MISMATCHED_READ_OFFSET, "User Mode Queue mismatched stream start: FWCtx 0x%08.8X, queue: 0x%08X%08X (Roff = %u, StreamStartOffset = %u)\n", 5) \
+X(144, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIDEKICK_DEINIT, "Sidekick deinit\n", 0) \
+X(145, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RD_DEINIT, "Rascal+Dusts deinit\n", 0) \
+X(146, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OS_INIT_CONFIG, "Initialised OS %d with config flags 0x%08x\n", 2) \
+X(148, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_62850KICK, "3D Dummy stencil store\n", 0) \
 \
-X( 1, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_KICK, "Bg Task DM = %u, counted = %d\n", 2) \
-X( 2, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_COMPLETE, "Bg Task complete DM = %u\n", 1) \
+X( 1, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_KICK_DEPRECATED, "Bg Task DM = %u, counted = %d\n", 2) \
+X( 2, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_COMPLETE_DEPRECATED, "Bg Task complete DM = %u\n", 1) \
 X( 3, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_KICK, "Irq Task DM = %u, Breq = %d, SBIrq = 0x%X\n", 3) \
-X( 4, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_COMPLETE, "Irq Task complete DM = %u\n", 1) \
+X( 4, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_COMPLETE_DEPRECATED, "Irq Task complete DM = %u\n", 1) \
 X( 5, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KICK_MTS_BG_ALL, "Kick MTS Bg task DM=All\n", 0) \
 X( 6, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KICK_MTS_IRQ, "Kick MTS Irq task DM=%d \n", 1) \
 X( 7, RGXFW_GROUP_MTS, RGXFW_SF_MTS_READYCELLTYPE_DEPRECATED, "Ready queue debug DM = %u, celltype = %d\n", 2) \
@@ -198,6 +248,9 @@
 X( 9, RGXFW_GROUP_MTS, RGXFW_SF_MTS_CMDHEADER, "Client command header DM = %u, client CCB = %x, cmd = %x\n", 3) \
 X(10, RGXFW_GROUP_MTS, RGXFW_SF_MTS_READYTORUN, "Ready-to-run debug OSid = %u, DM = %u, item = 0x%x\n", 3) \
 X(11, RGXFW_GROUP_MTS, RGXFW_SF_MTS_READYCELLTYPE, "Ready queue debug DM = %u, celltype = %d, OSid = %u\n", 3) \
+X(12, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_KICK, "Bg Task DM = %u, counted = %d, OSid = %u\n", 3 ) \
+X(13, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_COMPLETE, "Bg Task complete DM Bitfield: %u\n", 1) \
+X(14, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_COMPLETE, "Irq Task complete.\n", 0) \
 \
 X( 1, RGXFW_GROUP_CLEANUP, RGXFW_SF_CLEANUP_FWCTX_CLEANUP, "FwCommonContext [0x%08x] cleaned\n", 1) \
 X( 2, RGXFW_GROUP_CLEANUP, RGXFW_SF_CLEANUP_FWCTX_BUSY, "FwCommonContext [0x%08x] is busy: ReadOffset = %d, WriteOffset = %d\n", 3) \
@@ -231,7 +284,7 @@
 X(15, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_SHARED, "TA context shared alloc size store 0x%X, load 0x%X\n", 2) \
 X(16, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_STORE_COMPLETE, "*** TA context store complete\n", 0) \
 X(17, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_STORE_START, "*** TA context store start\n", 0) \
-X(18, RGXFW_GROUP_CSW, RGXFW_SF_CSW_HIGHER_PRIORITY_SCHEDULED, "Higher priority context scheduled for DM %u, old prio:%d, new prio:%d\n", 3) \
+X(18, RGXFW_GROUP_CSW, RGXFW_SF_CSW_HIGHER_PRIORITY_SCHEDULED_DEPRECATED, "Higher priority context scheduled for DM %u, old prio:%d, new prio:%d\n", 3) \
 X(19, RGXFW_GROUP_CSW, RGXFW_SF_CSW_SET_CONTEXT_PRIORITY, "Set FWCtx 0x%x priority to %u\n", 2) \
 X(20, RGXFW_GROUP_CSW, RGXFW_SF_CSW_3D_STORE_PIPE_STATE, "3D context store pipe%d state: 0x%08.8X\n", 2) \
 X(21, RGXFW_GROUP_CSW, RGXFW_SF_CSW_3D_RESUME_PIPE_STATE, "3D context resume pipe%d state: 0x%08.8X\n", 2) \
@@ -241,11 +294,16 @@
 X(25, RGXFW_GROUP_CSW, RGXFW_SF_CSW_SHG_STORE_COMPLETE, "*** SHG context store complete\n", 0) \
 X(26, RGXFW_GROUP_CSW, RGXFW_SF_CSW_SHG_STORE_START, "*** SHG context store start\n", 0) \
 X(27, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_PIPE_INDIRECT, "Performing TA indirection, last used pipe %d\n", 1) \
-X(28, RGXFW_GROUP_CSW, RGXFW_SF_CSW_CDM_STORE_CTRL_STREAM_TERMINATE, "CDM context store hit ctrl stream terminate. Skip resume.", 0) \
+X(28, RGXFW_GROUP_CSW, RGXFW_SF_CSW_CDM_STORE_CTRL_STREAM_TERMINATE, "CDM context store hit ctrl stream terminate. Skip resume.\n", 0) \
 X(29, RGXFW_GROUP_CSW, RGXFW_SF_CSW_CDM_RESUME_AB_BUFFER, "*** CDM FWCtx 0x%08.8X resume from snapshot buffer 0x%08X%08X, shader state %u\n", 4) \
 X(30, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_STATE_BUFFER_FLIP, "TA PDS/USC state buffer flip (%d->%d)\n", 2) \
 X(31, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_STORE_52563_HIT, "TA context store hit BRN 52563: vertex store tasks outstanding\n", 0) \
 X(32, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_STORE_USC_POLL_FAILED, "TA USC poll failed (USC vertex task count: %d)\n", 1) \
+X(33, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TA_STORE_DEFERRED, "TA context store deferred due to BRN 54141.", 0) \
+X(34, RGXFW_GROUP_CSW, RGXFW_SF_CSW_HIGHER_PRIORITY_SCHEDULED, "Higher priority context scheduled for DM %u. Prios (OSid, OSid Prio, Context Prio): Current: %u, %u, %u New: %u, %u, %u\n", 7) \
+X(35, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TDM_STORE_START, "*** TDM context store start\n", 0) \
+X(36, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TDM_STORE_COMPLETE, "*** TDM context store complete\n", 0) \
+X(37, RGXFW_GROUP_CSW, RGXFW_SF_CSW_TDM_STORE_NEEDS_RESUME, "TDM context needs resume, header [%08.8X, %08.8X]\n", 2) \
 \
 X( 1, RGXFW_GROUP_BIF, RGXFW_SF_BIF_ACTIVATE, "Activate MemCtx=0x%08x BIFreq=%d secure=%d\n", 3) \
 X( 2, RGXFW_GROUP_BIF, RGXFW_SF_BIF_DEACTIVATE, "Deactivate MemCtx=0x%08x \n", 1) \
@@ -266,7 +324,7 @@
 X( 5, RGXFW_GROUP_PM, RGXFW_SF_PM_FL_GROW_COMPLETE, "Freelist grow completed [0x%08x]: added pages 0x%08x, total pages 0x%08x, new DevVirtAddr 0x%08x%08x\n", 5) \
 X( 6, RGXFW_GROUP_PM, RGXFW_SF_PM_FL_GROW_DENIED, "Grow for freelist ID=0x%08x denied by host\n", 1) \
 X( 7, RGXFW_GROUP_PM, RGXFW_SF_PM_FL_UPDATE_COMPLETE, "Freelist update completed [0x%08x]: old total pages 0x%08x, new total pages 0x%08x, new DevVirtAddr 0x%08x%08x\n", 5) \
-X( 8, RGXFW_GROUP_PM, RGXFW_SF_PM_FL_RECONSTRUCTION_FAILED, "Reconstruction of freelist ID=0x%08x failed\n", 1) \
+X( 8, RGXFW_GROUP_PM, RGXFW_SF_PM_FL_RECONSTRUCTION_FAILED_DEPRECATED, "Reconstruction of freelist ID=0x%08x failed\n", 1) \
 X( 9, RGXFW_GROUP_PM, RGXFW_SF_PM_DM_PAUSE_WARNING, "Ignored attempt to pause or unpause the DM while there is no relevant operation in progress (0-TA,1-3D): %d, operation(0-unpause, 1-pause): %d\n", 2) \
 X( 10, RGXFW_GROUP_PM, RGXFW_SF_PM_3D_TIMEOUT_STATUS, "Force free 3D Context memory, FWCtx: %08x, status(1:success, 0:fail): %d\n", 2)\
 X( 11, RGXFW_GROUP_PM, RGXFW_SF_PM_DM_PAUSE_ALLOC, "PM pause TA ALLOC: PM_PAGE_MANAGEOP set to 0x%x\n", 1) \
@@ -282,17 +340,24 @@
 X( 5, RGXFW_GROUP_RPM, RGXFW_SF_RPM_STATE_WAIT_FOR_PENDING_GROW, "RPM waiting for pending grow on freelist 0x%08x\n", 1) \
 X( 6, RGXFW_GROUP_RPM, RGXFW_SF_RPM_REQUEST_HOST_GROW, "Request freelist grow [0x%08x] current pages %d, grow size %d\n", 3) \
 X( 7, RGXFW_GROUP_RPM, RGXFW_SF_RPM_FREELIST_LOAD, "Freelist load: SHF = 0x%08x, SHG = 0x%08x\n", 2) \
-X( 8, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHF_FPL, "SHF FPL register: 0x%08X.%08X\n", 2) \
-X( 9, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHG_FPL, "SHG FPL register: 0x%08X.%08X\n", 2) \
+X( 8, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHF_FPL_DEPRECATED, "SHF FPL register: 0x%08X.%08X\n", 2) \
+X( 9, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHG_FPL_DEPRECATED, "SHG FPL register: 0x%08X.%08X\n", 2) \
 X(10, RGXFW_GROUP_RPM, RGXFW_SF_RPM_GROW_FREELIST, "Kernel requested RPM grow on freelist (type %d) at 0x%08x from current size %d to new size %d, RPM restart: %d (1=Yes)\n", 5) \
 X(11, RGXFW_GROUP_RPM, RGXFW_SF_RPM_GROW_RESTART, "Restarting SHG\n", 0) \
 X(12, RGXFW_GROUP_RPM, RGXFW_SF_RPM_GROW_ABORTED, "Grow failed, aborting the current frame.\n", 0) \
 X(13, RGXFW_GROUP_RPM, RGXFW_SF_RPM_ABORT_COMPLETE, "RPM abort complete on HWFrameData [0x%08x].\n", 1) \
 X(14, RGXFW_GROUP_RPM, RGXFW_SF_RPM_CLEANUP_NEEDS_ABORT, "RPM freelist cleanup [0x%08x] requires abort to proceed.\n", 1) \
 X(15, RGXFW_GROUP_RPM, RGXFW_SF_RPM_RPM_PT, "RPM page table base register: 0x%08X.%08X\n", 2) \
+X(16, RGXFW_GROUP_RPM, RGXFW_SF_RPM_OOM_ABORT, "Issuing RPM abort.\n", 0) \
+X(17, RGXFW_GROUP_RPM, RGXFW_SF_RPM_OOM_TOGGLE_CHECK_FULL, "RPM OOM received but toggle bits indicate free pages available\n", 0) \
+X(18, RGXFW_GROUP_RPM, RGXFW_SF_RPM_STATE_HW_TIMEOUT, "RPM hardware timeout. Unable to process OOM event.\n", 0) \
+X(19, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHF_FPL_LOAD, "SHF FL (0x%08x) load, FPL: 0x%08X.%08X, roff: 0x%08X, woff: 0x%08X\n", 5) \
+X(20, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHG_FPL_LOAD, "SHG FL (0x%08x) load, FPL: 0x%08X.%08X, roff: 0x%08X, woff: 0x%08X\n", 5) \
+X(21, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHF_FPL_STORE, "SHF FL (0x%08x) store, roff: 0x%08X, woff: 0x%08X\n", 3) \
+X(22, RGXFW_GROUP_RPM, RGXFW_SF_RPM_SHG_FPL_STORE, "SHG FL (0x%08x) store, roff: 0x%08X, woff: 0x%08X\n", 3) \
 \
-X( 1, RGXFW_GROUP_RTD, RGXFW_SF_RTD_RTDATA_FINISHED, "3D RTData 0x%08x finished on HW context %u\n", 2) \
-X( 2, RGXFW_GROUP_RTD, RGXFW_SF_RTD_RTDATA_READY, "3D RTData 0x%08x ready on HW context %u\n", 2) \
+X( 1, RGXFW_GROUP_RTD, RGXFW_SF_RTD_3D_RTDATA_FINISHED, "3D RTData 0x%08x finished on HW context %u\n", 2) \
+X( 2, RGXFW_GROUP_RTD, RGXFW_SF_RTD_3D_RTDATA_READY, "3D RTData 0x%08x ready on HW context %u\n", 2) \
 X( 3, RGXFW_GROUP_RTD, RGXFW_SF_RTD_PB_SET_TO, "CONTEXT_PB_BASE set to %X, FL different between TA/3D: local: %d, global: %d, mmu: %d\n", 4) \
 X( 4, RGXFW_GROUP_RTD, RGXFW_SF_RTD_LOADVFP_3D, "Loading VFP table 0x%08x%08x for 3D\n", 2) \
 X( 5, RGXFW_GROUP_RTD, RGXFW_SF_RTD_LOADVFP_TA, "Loading VFP table 0x%08x%08x for TA\n", 2) \
@@ -310,11 +375,15 @@
 X(17, RGXFW_GROUP_RTD, RGXFW_SF_RTD_LOAD_FL, "Load  Freelist 0x%X type: %d (0:local,1:global,2:mmu) for DM%d: FL Total Pages %u (max=%u,grow size=%u), FL-addr = 0x%08x%08x, stacktop = 0x%08x%08x, Alloc Page Count = %u, Alloc MMU Page Count = %u\n", 12) \
 X(18, RGXFW_GROUP_RTD, RGXFW_SF_RTD_DEBUG, "Freelist 0x%X RESET!!!!!!!!\n", 1) \
 X(19, RGXFW_GROUP_RTD, RGXFW_SF_RTD_DEBUG2, "Freelist 0x%X stacktop = 0x%08x%08x, Alloc Page Count = %u, Alloc MMU Page Count = %u\n", 5) \
-X(20, RGXFW_GROUP_RTD, RGXFW_SF_RTD_FL_RECON, "Request reconstruction of Freelist 0x%X type: %d (0:local,1:global,2:mmu) on HW context %u\n", 3) \
+X(20, RGXFW_GROUP_RTD, RGXFW_SF_RTD_FL_RECON_DEPRECATED, "Request reconstruction of Freelist 0x%X type: %d (0:local,1:global,2:mmu) on HW context %u\n", 3) \
 X(21, RGXFW_GROUP_RTD, RGXFW_SF_RTD_FL_RECON_ACK_DEPRECATED, "Freelist reconstruction ACK from host (HWR state :%u)\n", 1) \
-X(22, RGXFW_GROUP_RTD, RGXFW_SF_RTD_FL_RECON_ACK, "Freelist reconstruction completed\n", 0) \
+X(22, RGXFW_GROUP_RTD, RGXFW_SF_RTD_FL_RECON_ACK_DEPRECATED2, "Freelist reconstruction completed\n", 0) \
 X(23, RGXFW_GROUP_RTD, RGXFW_SF_RTD_TA_RTDATA_LOADED_DEPRECATED, "TA RTData 0x%08x loaded on HW context %u HWRTDataNeedsLoading=%d\n", 3) \
 X(24, RGXFW_GROUP_RTD, RGXFW_SF_RTD_TE_RGNHDR_INFO, "TE Region headers base 0x%08x%08x (RGNHDR Init: %d)\n", 3) \
+X(25, RGXFW_GROUP_RTD, RGXFW_SF_RTD_TA_RTDATA_BUFFER_ADDRS, "TA Buffers: FWCtx 0x%08x, RT 0x%08x, RTData 0x%08x, VHeap 0x%08x%08x, TPC 0x%08x%08x (MemCtx 0x%08x)\n", 8) \
+X(26, RGXFW_GROUP_RTD, RGXFW_SF_RTD_3D_RTDATA_LOADED, "3D RTData 0x%08x loaded on HW context %u\n", 2) \
+X(27, RGXFW_GROUP_RTD, RGXFW_SF_RTD_3D_RTDATA_BUFFER_ADDRS, "3D Buffers: FWCtx 0x%08x, RT 0x%08x, RTData 0x%08x (MemCtx 0x%08x)\n", 4) \
+X(28, RGXFW_GROUP_RTD, RGXFW_SF_RTD_TA_RESTART_AFTER_PR_EXECUTED, "Restarting TA after partial render, HWRTData0State=%d, HWRTData1State=%d\n", 2) \
 \
 X( 1, RGXFW_GROUP_SPM, RGXFW_SF_SPM_ZLOAD_DEPRECATED, "Force Z-Load for partial render\n", 0) \
 X( 2, RGXFW_GROUP_SPM, RGXFW_SF_SPM_ZSTORE_DEPRECATED, "Force Z-Store for partial render\n", 0) \
@@ -323,7 +392,7 @@
 X( 5, RGXFW_GROUP_SPM, RGXFW_SF_SPM_3DMEMFREE_GLOBAL, "3D MemFree: Global FL 0x%08x\n", 1) \
 X( 6, RGXFW_GROUP_SPM, RGXFW_SF_SPM_OOM_TACMD, "OOM TA/3D PR Check: [%08.8X] is %08.8X requires %08.8X, HardwareSync Fence [%08.8X] is %08.8X requires %08.8X\n", 6) \
 X( 7, RGXFW_GROUP_SPM, RGXFW_SF_SPM_OOM_TACMD_UN_FL, "OOM TA_cmd=0x%08x, U-FL 0x%08x, N-FL 0x%08x\n", 3) \
-X( 8, RGXFW_GROUP_SPM, RGXFW_SF_SPM_OOM_TACMD_UN_MMU_FL, "OOM TA_cmd=0x%08x, Oom MMU:%d, U-FL 0x%08x, N-FL 0x%08x, MMU-FL 0x%08x\n", 5) \
+X( 8, RGXFW_GROUP_SPM, RGXFW_SF_SPM_OOM_TACMD_UN_MMU_FL, "OOM TA_cmd=0x%08x, OOM MMU:%d, U-FL 0x%08x, N-FL 0x%08x, MMU-FL 0x%08x\n", 5) \
 X( 9, RGXFW_GROUP_SPM, RGXFW_SF_SPM_PRENDER_AVOIDED, "Partial render avoided\n", 0) \
 X(10, RGXFW_GROUP_SPM, RGXFW_SF_SPM_PRENDER_DISCARDED, "Partial render discarded\n", 0) \
 X(11, RGXFW_GROUP_SPM, RGXFW_SF_SPM_PRENDER_FINISHED, "Partial Render finished\n", 0) \
@@ -359,13 +428,13 @@
 X(41, RGXFW_GROUP_SPM, RGXFW_SF_SPM_STATE_WAIT_FOR_PENDING_GROW, "Wait for pending grow on Freelist 0x%08x\n", 1) \
 X(42, RGXFW_GROUP_SPM, RGXFW_SF_SPM_ZSBUFFER_BACKING_REQUEST_FAILED, "ZS Buffer failed to be populated (ID=0x%08x)\n", 1) \
 \
-X( 1, RGXFW_GROUP_POW, RGXFW_SF_POW_CHECK, "Check Pow state DM%d int: 0x%X, ext: 0x%X, pow flags: 0x%X\n", 4) \
+X( 1, RGXFW_GROUP_POW, RGXFW_SF_POW_CHECK_DEPRECATED, "Check Pow state DM%d int: 0x%X, ext: 0x%X, pow flags: 0x%X\n", 4) \
 X( 2, RGXFW_GROUP_POW, RGXFW_SF_POW_SIDEKICK_IDLE, "Sidekick idle (might be powered down). Pow state int: 0x%X, ext: 0x%X, flags: 0x%X\n", 3) \
 X( 3, RGXFW_GROUP_POW, RGXFW_SF_POW_OSREQ, "OS requested pow off (forced = %d), DM%d, pow flags: 0x%8.8X\n", 3) \
 X( 4, RGXFW_GROUP_POW, RGXFW_SF_POW_INIOFF_DEPRECATED, "Initiate powoff query. Inactive DMs: %d %d %d %d\n", 4) \
 X( 5, RGXFW_GROUP_POW, RGXFW_SF_POW_CHECKOFF_DEPRECATED, "Any RD-DM pending? %d, Any RD-DM Active? %d\n", 2) \
 X( 6, RGXFW_GROUP_POW, RGXFW_SF_POW_SIDEKICK_OFF, "Sidekick ready to be powered down. Pow state int: 0x%X, ext: 0x%X, flags: 0x%X\n", 3) \
-X( 7, RGXFW_GROUP_POW, RGXFW_SF_POW_HWREQ, "On(1)/Off(0): %d, Units: 0x%08.8X\n", 2) \
+X( 7, RGXFW_GROUP_POW, RGXFW_SF_POW_HWREQ, "HW Request On(1)/Off(0): %d, Units: 0x%08.8X\n", 2) \
 X( 8, RGXFW_GROUP_POW, RGXFW_SF_POW_DUSTS_CHANGE_REQ, "Request to change num of dusts to %d (Power flags=%d)\n", 2) \
 X( 9, RGXFW_GROUP_POW, RGXFW_SF_POW_DUSTS_CHANGE, "Changing number of dusts from %d to %d\n", 2) \
 X(11, RGXFW_GROUP_POW, RGXFW_SF_POW_SIDEKICK_INIT_DEPRECATED, "Sidekick init\n", 0) \
@@ -384,6 +453,25 @@
 X(24, RGXFW_GROUP_POW, RGXFW_SF_POW_CDM_CLUSTERS, "Compute cluster mask change to 0x%X, %d dusts powered.\n", 2) \
 X(25, RGXFW_GROUP_POW, RGXFW_SF_POW_NULL_CMD_INIOFF_RD, "Null command executed, repeating initiate powoff query for RD-DMs.\n", 0) \
 X(26, RGXFW_GROUP_POW, RGXFW_SF_POW_POWMON_ENERGY, "Power monitor: Estimate of dynamic energy %u\n", 1) \
+X(27, RGXFW_GROUP_POW, RGXFW_SF_POW_CHECK, "Check Pow state: Int: 0x%X, Ext: 0x%X, Pow flags: 0x%X\n", 3) \
+X(28, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_NEW_DEADLINE, "Proactive DVFS: New deadline, time = 0x%08x%08x\n", 2) \
+X(29, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_NEW_WORKLOAD, "Proactive DVFS: New workload, cycles = 0x%08x%08x\n", 2) \
+X(30, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_CALCULATE, "Proactive DVFS: Proactive frequency calculated = 0x%08x\n", 1) \
+X(31, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_UTILISATION, "Proactive DVFS: Reactive utilisation = 0x%08x\n", 1) \
+X(32, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_REACT, "Proactive DVFS: Reactive frequency calculated = 0x%08x%08x\n", 2) \
+X(33, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_GPIO_SEND, "Proactive DVFS: OPP Point Sent = 0x%x\n", 1) \
+X(34, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_DEADLINE_REMOVED, "Proactive DVFS: Deadline removed = 0x%08x%08x\n", 2) \
+X(35, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_WORKLOAD_REMOVED, "Proactive DVFS: Workload removed = 0x%08x%08x\n", 2) \
+X(36, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_THROTTLE, "Proactive DVFS: Throttle to a maximum = 0x%x\n", 1) \
+X(37, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_GPIO_FAILURE, "Proactive DVFS: Failed to pass OPP point via GPIO.\n", 0) \
+X(38, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_INVALID_NODE, "Proactive DVFS: Invalid node passed to function.\n", 0) \
+X(39, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_GUEST_BAD_ACCESS, "Proactive DVFS: Guest OS attempted to do a privileged action. OSid = %u\n", 1) \
+X(40, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_UNPROFILED_STARTED, "Proactive DVFS: Unprofiled work started. Total unprofiled work present: 0x%x\n", 1) \
+X(41, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_UNPROFILED_FINISHED, "Proactive DVFS: Unprofiled work finished. Total unprofiled work present: 0x%x\n", 1) \
+X(42, RGXFW_GROUP_POW, RGXFW_SF_POW_PDVFS_DISABLED, "Proactive DVFS: Disabled: Not enabled by host.\n", 0) \
+X(43, RGXFW_GROUP_POW, RGXFW_SF_POW_HWREQ_RESULT, "HW Request Completed(1)/Aborted(0): %d, Ticks: %d\n", 2) \
+X(44, RGXFW_GROUP_POW, RGXFW_SF_POW_DUSTS_CHANGE_FIX_59042, "Allowed number of dusts is %d due to BRN59042.\n", 1) \
+X(45, RGXFW_GROUP_POW, RGXFW_SF_POW_HOST_TIMEOUT_NOTIFICATION, "Host timed out while waiting for a forced idle state. Pow state int: 0x%X, ext: 0x%X, flags: 0x%X\n", 3) \
 \
 X(1, RGXFW_GROUP_HWR, RGXFW_SF_HWR_LOCKUP_DEPRECATED, "Lockup detected on DM%d, FWCtx: %08.8X\n", 2) \
 X(2, RGXFW_GROUP_HWR, RGXFW_SF_HWR_RESET_FW_DEPRECATED, "Reset fw state for DM%d, FWCtx: %08.8X, MemCtx: %08.8X\n", 3) \
@@ -403,7 +491,7 @@
 X(16, RGXFW_GROUP_HWR, RGXFW_SF_HWR_PM_FENCE, "PM fence WA could not be applied, Valid TA Setup: %d, RD powered off: %d\n", 2) \
 X(17, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_SNAPSHOT, "FL snapshot RTD 0x%08.8X - local (0x%08.8X): %d, global (0x%08.8X): %d\n", 5) \
 X(18, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_CHECK, "FL check RTD 0x%08.8X, discard: %d - local (0x%08.8X): s%d?=c%d, global (0x%08.8X): s%d?=c%d\n", 8) \
-X(19, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_RECON, "FL reconstruction 0x%08.8X c%d\n", 2) \
+X(19, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_RECON_DEPRECATED, "FL reconstruction 0x%08.8X c%d\n", 2) \
 X(20, RGXFW_GROUP_HWR, RGXFW_SF_HWR_3D_CHECK, "3D check: missing TA FWCtx 0x%08.8X @ %d, RTD 0x%08x.\n", 3) \
 X(21, RGXFW_GROUP_HWR, RGXFW_SF_HWR_RESET_HW_DEPRECATED2, "Reset HW (mmu:%d, extmem: %d)\n", 2) \
 X(22, RGXFW_GROUP_HWR, RGXFW_SF_HWR_ZERO_TA_CACHES, "Zero TA caches for FWCtx: %08.8X (TPC addr: %08X%08X, size: %d bytes)\n", 4) \
@@ -424,7 +512,7 @@
 X(37, RGXFW_GROUP_HWR, RGXFW_SF_HWR_DM_FALSE_LOCKUP, "DM%u lockup falsely detected, R-Flags=0x%08X\n", 2) \
 X(38, RGXFW_GROUP_HWR, RGXFW_SF_HWR_SET_OUTOFTIME, "GPU has overrun its deadline\n", 0) \
 X(39, RGXFW_GROUP_HWR, RGXFW_SF_HWR_SET_POLLFAILURE, "GPU has failed a poll\n", 0) \
-X(40, RGXFW_GROUP_HWR, RGXFW_SF_HWR_PERF_CYCLE_REG, "RGX DM%u cycle count=0x%08x\n", 2) \
+X(40, RGXFW_GROUP_HWR, RGXFW_SF_HWR_PERF_PHASE_REG, "RGX DM%u phase count=0x%08x\n", 2) \
 X(41, RGXFW_GROUP_HWR, RGXFW_SF_HWR_RESET_HW, "Reset HW (loop:%d, poll failures: 0x%08X)\n", 2) \
 X(42, RGXFW_GROUP_HWR, RGXFW_SF_HWR_MMU_FAULT_EVENT, "MMU fault event: 0x%08X\n", 1) \
 X(43, RGXFW_GROUP_HWR, RGXFW_SF_HWR_BIF1_FAULT, "BIF1 page fault detected (Bank1 MMU Status: 0x%08X)\n", 1) \
@@ -435,7 +523,22 @@
 X(48, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FINAL_RESULT, "Final result for DM%u is HWRNeeded=%u with HWRChecksToGo=%u\n", 3) \
 X(49, RGXFW_GROUP_HWR, RGXFW_SF_HWR_USC_SLOTS_CHECK, "USC Slots result for DM%u is HWRNeeded=%u USCSlotsUsedByDM=%d\n", 3) \
 X(50, RGXFW_GROUP_HWR, RGXFW_SF_HWR_DEADLINE_CHECK, "Deadline counter for DM%u is HWRDeadline=%u\n", 2) \
-X(51, RGXFW_GROUP_HWR, RGXFW_SF_HWR_COMPUTE_EXTRA_ACTIVITY, "Special compute/BIF checks (BIF0Idle=%u, OnlyCDMWasRunning=%u, OnlyCDMIsRunning=%u)\n", 3) \
+X(51, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HOLD_SCHEDULING_DUE_TO_FREELIST_DEPRECATED, "Holding Scheduling on OSid %u due to pending freelist reconstruction\n", 1) \
+X(52, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_RECON_REQUEST, "Requesting reconstruction for freelist 0x%X (ID=%d)\n", 2) \
+X(53, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_RECON_PASSED, "Reconstruction of freelist ID=%d complete\n", 1) \
+X(54, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_RECON_NEEDED, "Reconstruction needed for freelist 0x%X (ID=%d) type: %d (0:local,1:global,2:mmu) on HW context %u\n", 4) \
+X(55, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FL_RECON_FAILED, "Reconstruction of freelist ID=%d failed\n", 1) \
+X(56, RGXFW_GROUP_HWR, RGXFW_SF_HWR_RESTRICTING_PDS_TASKS, "Restricting PDS Tasks to help other stalling DMs (RunningMask=0x%02X, StallingMask=0x%02X, PDS_CTRL=0x%08X%08X)\n", 4) \
+X(57, RGXFW_GROUP_HWR, RGXFW_SF_HWR_UNRESTRICTING_PDS_TASKS, "Unrestricting PDS Tasks again (RunningMask=0x%02X, StallingMask=0x%02X, PDS_CTRL=0x%08X%08X)\n", 4) \
+X(58, RGXFW_GROUP_HWR, RGXFW_SF_HWR_USC_SLOTS_USED, "USC slots: %u used by DM%u\n", 2) \
+X(59, RGXFW_GROUP_HWR, RGXFW_SF_HWR_USC_SLOTS_EMPTY, "USC slots: %u empty\n", 1) \
+X(60, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HCS_FIRE, "HCS DM%d's Context Switch failed to meet deadline. Current time: %08x%08x, deadline: %08x%08x\n", 5) \
+X(61, RGXFW_GROUP_HWR, RGXFW_SF_HWR_START_HW_RESET, "Begin hardware reset (HWR Counter=%d)\n", 1) \
+X(62, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FINISH_HW_RESET, "Finished hardware reset (HWR Counter=%d)\n", 1) \
+X(63, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HOLD_SCHEDULING_DUE_TO_FREELIST, "Holding Scheduling on DM %u for OSid %u due to pending freelist reconstruction\n", 2) \
+X(64, RGXFW_GROUP_HWR, RGXFW_SF_HWR_RESET_UMQ_READ_OFFSET, "User Mode Queue ROff reset: FWCtx 0x%08.8X, queue: 0x%08X%08X (Roff = %u becomes StreamStartOffset = %u)\n", 5) \
+X(65, RGXFW_GROUP_HWR, RGXFW_SF_HWR_MIPS_FAULT, "Mips page fault detected (BadVAddr: 0x%08x, EntryLo0: 0x%08x, EntryLo1: 0x%08x)\n", 3) \
+X(67, RGXFW_GROUP_HWR, RGXFW_SF_HWR_ANOTHER_CHANCE, "At least one other DM is running okay so DM%u will get another chance\n", 1) \
 \
 X( 1, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CFGBLK, "Block 0x%x mapped to Config Idx %u\n", 2) \
 X( 2, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_OMTBLK, "Block 0x%x omitted from event - not enabled in HW\n", 1) \
@@ -443,7 +546,7 @@
 X( 4, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_SELREG, "Select register state hi_0x%x lo_0x%x\n", 2) \
 X( 5, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CSBHDR, "Counter stream block header word 0x%x\n", 1) \
 X( 6, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CTROFF, "Counter register offset 0x%x\n", 1) \
-X( 7, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CFGSKP, "Block 0x%x disabled, skipping configuration\n", 1) \
+X( 7, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CFGSKP, "Block 0x%x config unset, skipping\n", 1) \
 X( 8, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_INDBLK, "Accessing Indirect block 0x%x\n", 1) \
 X( 9, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_DIRBLK, "Accessing Direct block 0x%x\n", 1) \
 X(10, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CNTPRG, "Programmed counter select register at offset 0x%x\n", 1) \
@@ -461,12 +564,17 @@
 X(22, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CHECK_FILTER, "Check Filter %x is %x ?\n", 2) \
 X(23, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_RESET_CUSTOM_BLOCK, "The custom block %u is reset\n", 1) \
 X(24, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_INVALID_CMD, "Encountered an invalid command (%d)\n", 1) \
+X(25, RGXFW_GROUP_HWP, RGXFW_SF_HWP_WAITING_FOR_QUEUE_DEPRECATED, "HWPerf Queue is full, we will have to wait for space! (Roff = %u, Woff = %u)\n", 2) \
+X(26, RGXFW_GROUP_HWP, RGXFW_SF_HWP_WAITING_FOR_QUEUE_FENCE_DEPRECATED, "HWPerf Queue is fencing, we are waiting for Roff = %d (Roff = %u, Woff = %u)\n", 3) \
+X(27, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CUSTOM_BLOCK, "Custom Counter block: %d \n", 1) \
 \
 X( 1, RGXFW_GROUP_DMA, RGXFW_SF_DMA_TRANSFER_REQUEST, "Transfer 0x%02x request: 0x%02x%08x -> 0x%08x, size %u\n", 5) \
 X( 2, RGXFW_GROUP_DMA, RGXFW_SF_DMA_TRANSFER_COMPLETE, "Transfer of type 0x%02x expected on channel %u, 0x%02x found, status %u\n", 4) \
 X( 3, RGXFW_GROUP_DMA, RGXFW_SF_DMA_INT_REG, "DMA Interrupt register 0x%08x\n", 1) \
 X( 4, RGXFW_GROUP_DMA, RGXFW_SF_DMA_WAIT, "Waiting for transfer ID %u completion...\n", 1) \
 X( 5, RGXFW_GROUP_DMA, RGXFW_SF_DMA_CCB_LOADING_FAILED, "Loading of cCCB data from FW common context 0x%08x (offset: %u, size: %u) failed\n", 3) \
+X( 6, RGXFW_GROUP_DMA, RGXFW_SF_DMA_CCB_LOAD_INVALID, "Invalid load of cCCB data from FW common context 0x%08x (offset: %u, size: %u)\n", 3) \
+X( 7, RGXFW_GROUP_DMA, RGXFW_SF_DMA_POLL_FAILED, "Transfer 0x%02x request poll failure\n", 1) \
 \
 X(1, RGXFW_GROUP_DBG, RGXFW_SF_DBG_INTPAIR, "0x%8.8x 0x%8.8x\n", 2) \
 \
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_shared.h b/drivers/staging/imgtec/rogue/rgx_fwif_shared.h
index c1fe2e9..d3cdedc 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_shared.h
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_shared.h
@@ -45,10 +45,23 @@
 #if !defined (__RGX_FWIF_SHARED_H__)
 #define __RGX_FWIF_SHARED_H__
 
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
 #include "img_types.h"
 #include "rgx_common.h"
 #include "devicemem_typedefs.h"
 
+/*
+ * Firmware binary block unit in bytes.
+ * Raw data stored in FW binary will be aligned on this size.
+ */
+#define FW_BLOCK_SIZE 4096L
+
+/* Offset for BVNC struct from the end of the FW binary */
+#define FW_BVNC_BACKWARDS_OFFSET (FW_BLOCK_SIZE)
 
 /*!
  ******************************************************************************
@@ -60,7 +73,7 @@
 #define RGXKMIF_DEVICE_STATE_DUST_REQUEST_INJECT_EN (0x1 << 3)		/*!< Used for validation to inject dust requests every TA/3D kick */
 #define RGXKMIF_DEVICE_STATE_HWPERF_HOST_EN         (0x1 << 4)		/*!< Used to enable host-side-only HWPerf stream */
 
-/* Required memory alignment for 64-bit variables accessible by Meta 
+/* Required memory alignment for 64-bit variables accessible by Meta
   (the gcc meta aligns 64-bit vars to 64-bit; therefore, mem shared between
    the host and meta that contains 64-bit vars has to maintain this aligment)*/
 #define RGXFWIF_FWALLOC_ALIGN	sizeof(IMG_UINT64)
@@ -73,12 +86,7 @@
 typedef struct _RGXFWIF_DMA_ADDR_
 {
 	IMG_DEV_VIRTADDR        RGXFW_ALIGN psDevVirtAddr;
-
-#if defined(RGX_FIRMWARE)
-	IMG_PBYTE               pbyFWAddr;
-#else
 	RGXFWIF_DEV_VIRTADDR    pbyFWAddr;
-#endif
 } UNCACHED_ALIGN RGXFWIF_DMA_ADDR;
 
 typedef IMG_UINT8	RGXFWIF_CCCB;
@@ -94,7 +102,11 @@
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_UFO_ADDR;
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_CLEANUP_CTL;
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_TIMESTAMP_ADDR;
+typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_WORKLOAD_DATA;
+typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_DEADLINE_LIST_NODE;
+typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_WORKLOAD_LIST_NODE;
 
+/* FIXME PRGXFWIF_UFO_ADDR and RGXFWIF_UFO should move back into rgx_fwif_client.h */
 typedef struct _RGXFWIF_UFO_
 {
 	PRGXFWIF_UFO_ADDR	puiAddrUFO;
@@ -152,7 +164,7 @@
 	IMG_UINT32				ui32WrapMask;		/*!< Offset wrapping mask (Total capacity of the CCB - 1) */
 } UNCACHED_ALIGN RGXFWIF_CCCB_CTL;
 
-typedef enum 
+typedef enum
 {
 	RGXFW_LOCAL_FREELIST = 0,
 	RGXFW_GLOBAL_FREELIST = 1,
@@ -164,18 +176,13 @@
 
 typedef struct _RGXFWIF_RTA_CTL_
 {
-	IMG_UINT32				ui32RenderTargetIndex;		//Render number
-	IMG_UINT32				ui32CurrentRenderTarget;	//index in RTA
-	IMG_UINT32				ui32ActiveRenderTargets;	//total active RTs
-	IMG_UINT32				ui32CumulActiveRenderTargets;   //total active RTs from the first TA kick, for OOM
-#if defined(RGX_FIRMWARE)
-	IMG_UINT32				*paui32ValidRenderTargets;	//Array of valid RT indices
-	IMG_UINT32              		*paui32NumRenders;  //Array of number of occurred partial renders per render target
-#else
-	RGXFWIF_DEV_VIRTADDR			paui32ValidRenderTargets;  //Array of valid RT indices
-	RGXFWIF_DEV_VIRTADDR    		paui32NumRenders;  //Array of number of occurred partial renders per render target
-#endif
-	IMG_UINT16              		ui16MaxRTs;   //Number of render targets in the array
+	IMG_UINT32           ui32RenderTargetIndex;		//Render number
+	IMG_UINT32           ui32CurrentRenderTarget;	//index in RTA
+	IMG_UINT32           ui32ActiveRenderTargets;	//total active RTs
+	IMG_UINT32           ui32CumulActiveRenderTargets;   //total active RTs from the first TA kick, for OOM
+	RGXFWIF_DEV_VIRTADDR sValidRenderTargets;  //Array of valid RT indices
+	RGXFWIF_DEV_VIRTADDR sNumRenders;  //Array of number of occurred partial renders per render target
+	IMG_UINT16           ui16MaxRTs;   //Number of render targets in the array
 } UNCACHED_ALIGN RGXFWIF_RTA_CTL;
 
 typedef struct _RGXFWIF_FREELIST_
@@ -193,8 +200,7 @@
 	IMG_BOOL			bGrowPending;
 } UNCACHED_ALIGN RGXFWIF_FREELIST;
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-typedef enum 
+typedef enum
 {
 	RGXFW_RPM_SHF_FREELIST = 0,
 	RGXFW_RPM_SHG_FREELIST = 1,
@@ -205,7 +211,7 @@
 typedef struct _RGXFWIF_RPM_FREELIST_
 {
 	IMG_DEV_VIRTADDR	RGXFW_ALIGN sFreeListDevVAddr;		/*!< device base address */
-	IMG_DEV_VIRTADDR	RGXFW_ALIGN sRPMPageListDevVAddr;	/*!< device base address for RPM pages in-use */
+	//IMG_DEV_VIRTADDR	RGXFW_ALIGN sRPMPageListDevVAddr;	/*!< device base address for RPM pages in-use */
 	IMG_UINT32			sSyncAddr;				/*!< Free list sync object for OOM event */
 	IMG_UINT32			ui32MaxPages;			/*!< maximum size */
 	IMG_UINT32			ui32GrowPages;			/*!< grow size = maximum pages which may be added later */
@@ -214,7 +220,7 @@
 	IMG_UINT32			ui32WriteOffset;		/*!< tail: where to write de-alloc'd pages */
 	IMG_BOOL			bReadToggle;			/*!< toggle bit for circular buffer */
 	IMG_BOOL			bWriteToggle;
-	IMG_UINT32			ui32AllocatedPageCount;
+	IMG_UINT32			ui32AllocatedPageCount; /*!< TODO: not sure yet if this is useful */
 	IMG_UINT32			ui32HWRCounter;
 	IMG_UINT32			ui32FreeListID;			/*!< unique ID per device, e.g. rolling counter */
 	IMG_BOOL			bGrowPending;			/*!< FW is waiting for host to grow the freelist */
@@ -223,11 +229,12 @@
 typedef struct _RGXFWIF_RAY_FRAME_DATA_
 {
 	/* state manager for shared state between vertex and ray processing */
-	
+
+	/* TODO: not sure if this will be useful, link it here for now */
 	IMG_UINT32		sRPMFreeLists[RGXFW_MAX_RPM_FREELISTS];
-	
+
 	IMG_BOOL		bAbortOccurred;
-	
+
 	/* cleanup state.
 	 * Both the SHG and RTU must complete or discard any outstanding work
 	 * which references this frame data.
@@ -239,7 +246,7 @@
 #define HWFRAMEDATA_RTU_CLEAN	(1 << 1)
 
 } UNCACHED_ALIGN RGXFWIF_RAY_FRAME_DATA;
-#endif
+
 
 typedef struct _RGXFWIF_RENDER_TARGET_
 {
@@ -249,24 +256,17 @@
 } UNCACHED_ALIGN RGXFWIF_RENDER_TARGET;
 
 
-typedef struct _RGXFWIF_HWRTDATA_ 
+typedef struct _RGXFWIF_HWRTDATA_
 {
 	RGXFWIF_RTDATA_STATE	eState;
 
 	IMG_UINT32				ui32NumPartialRenders; /*!< Number of partial renders. Used to setup ZLS bits correctly */
 	IMG_DEV_VIRTADDR		RGXFW_ALIGN psPMMListDevVAddr; /*!< MList Data Store */
 
-#if defined(RGX_FEATURE_SCALABLE_TE_ARCH)
 	IMG_UINT64				RGXFW_ALIGN ui64VCECatBase[4];
 	IMG_UINT64				RGXFW_ALIGN ui64VCELastCatBase[4];
 	IMG_UINT64				RGXFW_ALIGN ui64TECatBase[4];
 	IMG_UINT64				RGXFW_ALIGN ui64TELastCatBase[4];
-#else
-	IMG_UINT64				RGXFW_ALIGN ui64VCECatBase;
-	IMG_UINT64				RGXFW_ALIGN ui64VCELastCatBase;
-	IMG_UINT64				RGXFW_ALIGN ui64TECatBase;
-	IMG_UINT64				RGXFW_ALIGN ui64TELastCatBase;
-#endif
 	IMG_UINT64				RGXFW_ALIGN ui64AlistCatBase;
 	IMG_UINT64				RGXFW_ALIGN ui64AlistLastCatBase;
 
@@ -276,9 +276,9 @@
 	IMG_UINT64				RGXFW_ALIGN ui64PMAListStackPointer;
 	IMG_UINT32				ui32PMMListStackPointer;
 
-	PRGXFWIF_FREELIST 		RGXFW_ALIGN apsFreeLists[RGXFW_MAX_FREELISTS]; 
+	PRGXFWIF_FREELIST 		RGXFW_ALIGN apsFreeLists[RGXFW_MAX_FREELISTS];
 	IMG_UINT32				aui32FreeListHWRSnapshot[RGXFW_MAX_FREELISTS];
-	
+
 	PRGXFWIF_RENDER_TARGET	psParentRenderTarget;
 
 	RGXFWIF_CLEANUP_CTL		sTACleanupState;
@@ -296,6 +296,7 @@
 	IMG_UINT32				ui32PPPGridOffset;
 	IMG_UINT64				RGXFW_ALIGN ui64PPPMultiSampleCtl;
 	IMG_UINT32				ui32TPCStride;
+	IMG_UINT32				bLastWasPartial; /*!< Whether the last render was a partial render */
 	IMG_DEV_VIRTADDR		RGXFW_ALIGN sTailPtrsDevVAddr;
 	IMG_UINT32				ui32TPCSize;
 	IMG_UINT32				ui32TEScreen;
@@ -309,6 +310,7 @@
 	IMG_UINT32				ui32ISPMergeUpperY;
 	IMG_UINT32				ui32ISPMergeScaleX;
 	IMG_UINT32				ui32ISPMergeScaleY;
+	IMG_BOOL				bDisableTileReordering;
 } UNCACHED_ALIGN RGXFWIF_HWRTDATA;
 
 typedef enum
@@ -336,19 +338,18 @@
  *****************************************************************************/
 /* WARNING: RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX can be increased only and
 		always equal to (N * sizeof(IMG_UINT32) - 1) */
-#define RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX 3 /* WARNING: Do not change this macro without changing 
-			accesses from dword to byte in function rgx_bvnc_packed() */
+#define RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX 7
 
 /* WARNING: Whenever the layout of RGXFWIF_COMPCHECKS_BVNC is a subject of change,
-	following define should be increased by 1 to indicate to compatibility logic, 
+	following define should be increased by 1 to indicate to compatibility logic,
 	that layout has changed */
-#define RGXFWIF_COMPCHECKS_LAYOUT_VERSION 1
+#define RGXFWIF_COMPCHECKS_LAYOUT_VERSION 2
 
 typedef struct _RGXFWIF_COMPCHECKS_BVNC_
 {
 	IMG_UINT32	ui32LayoutVersion; /* WARNING: This field must be defined as first one in this structure */
 	IMG_UINT32  ui32VLenMax;
-	IMG_UINT32	ui32BNC;
+	IMG_UINT64	RGXFW_ALIGN ui64BNC;
 	IMG_CHAR	aszV[RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX + 1];
 } UNCACHED_ALIGN RGXFWIF_COMPCHECKS_BVNC;
 
@@ -363,7 +364,7 @@
 	do { \
 		(name).ui32LayoutVersion = RGXFWIF_COMPCHECKS_LAYOUT_VERSION; \
 		(name).ui32VLenMax = RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX; \
-		(name).ui32BNC = 0; \
+		(name).ui64BNC = 0; \
 		(name).aszV[0] = 0; \
 	} while (0)
 
@@ -400,7 +401,7 @@
 #if defined(EMULATOR)
 
 /* On emulator platform, the sizes are kept as 64 KB for all contexts as the cCCBs
- * are expected to be almost always used upto their full sizes */
+ * are expected to be almost always used up to their full sizes */
 
 #define RGX_TQ3D_CCB_SIZE_LOG2	16	/* 64K */
 #define RGX_TQ2D_CCB_SIZE_LOG2	16
@@ -446,30 +447,92 @@
 	RGXFWIF_CCB_CMD_TYPE_RTU		= 209 | RGX_CCB_TYPE_TASK,
 	RGXFWIF_CCB_CMD_TYPE_RTU_FC		  = 210 | RGX_CCB_TYPE_TASK,
 	RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP = 211 | RGX_CCB_TYPE_TASK,
+	RGXFWIF_CCB_CMD_TYPE_TQ_TDM     = 212 | RGX_CCB_TYPE_TASK,
 
 /* Leave a gap between CCB specific commands and generic commands */
-	RGXFWIF_CCB_CMD_TYPE_FENCE          = 212,
-	RGXFWIF_CCB_CMD_TYPE_UPDATE         = 213,
-	RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE     = 214,
-	RGXFWIF_CCB_CMD_TYPE_FENCE_PR       = 215,
-	RGXFWIF_CCB_CMD_TYPE_PRIORITY       = 216,
+	RGXFWIF_CCB_CMD_TYPE_FENCE          = 213,
+	RGXFWIF_CCB_CMD_TYPE_UPDATE         = 214,
+	RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE     = 215,
+	RGXFWIF_CCB_CMD_TYPE_FENCE_PR       = 216,
+	RGXFWIF_CCB_CMD_TYPE_PRIORITY       = 217,
 /* Pre and Post timestamp commands are supposed to sandwich the DM cmd. The
    padding code with the CCB wrap upsets the FW if we don't have the task type
    bit cleared for POST_TIMESTAMPs. That's why we have 2 different cmd types.
 */
-	RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP = 217,
-	RGXFWIF_CCB_CMD_TYPE_UNFENCED_UPDATE = 218,
-	RGXFWIF_CCB_CMD_TYPE_UNFENCED_RMW_UPDATE = 219,
-	
-	RGXFWIF_CCB_CMD_TYPE_PADDING	= 220,
+	RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP = 218,
+	RGXFWIF_CCB_CMD_TYPE_UNFENCED_UPDATE = 219,
+	RGXFWIF_CCB_CMD_TYPE_UNFENCED_RMW_UPDATE = 220,
+
+	RGXFWIF_CCB_CMD_TYPE_PADDING	= 221,
 } RGXFWIF_CCB_CMD_TYPE;
 
+typedef struct _RGXFWIF_WORKLOAD_DATA_
+{
+	/* Workload characteristics data*/
+	IMG_UINT64 RGXFW_ALIGN                    ui64WorkloadCharacteristics;
+	/* Deadline for the workload */
+	IMG_UINT64 RGXFW_ALIGN                    ui64DeadlineInus;
+	/* Bool for whether the workload was completed */
+	IMG_BOOL                                  bComplete;
+	/* Predicted time taken to do the work in cycles */
+	IMG_UINT64 RGXFW_ALIGN                    ui64CyclesPrediction;
+	/* The actual time taken in cycles */
+	IMG_UINT64 RGXFW_ALIGN                    ui64CyclesTaken;
+	/* The memory descriptor for this workload */
+	IMG_UINT64 RGXFW_ALIGN                    ui64SelfMemDesc;
+	/* Memory descriptor to be able to chain workload data */
+	IMG_UINT64 RGXFW_ALIGN                    ui64NextNodeMemdesc;
+	/* Reference to Host side data */
+	IMG_UINT64 RGXFW_ALIGN                    ui64WorkloadHostData;
+	/* Reference to Specific Hash table */
+	IMG_UINT64 RGXFW_ALIGN                    ui64WorkloadMatchingData;
+	/* The following are for the memory management of the PDVFS workload
+	 * tree in the firmware */
+	PRGXFWIF_DEADLINE_LIST_NODE RGXFW_ALIGN  sDeadlineNodeFWAddress;
+	PRGXFWIF_WORKLOAD_LIST_NODE RGXFW_ALIGN  sWorkloadNodeFWAddress;
+	IMG_UINT64 RGXFW_ALIGN                    ui64DeadlineNodeMemDesc;
+	IMG_UINT64 RGXFW_ALIGN                    ui64WorkloadNodeMemDesc;
+} RGXFWIF_WORKLOAD_DATA;
+
+typedef struct _RGXFWIF_WORKEST_KICK_DATA_
+{
+	/* Index for the KM Workload estimation return data array */
+	IMG_UINT64 RGXFW_ALIGN                    ui64ReturnDataIndex;
+	/* Deadline for the workload */
+	IMG_UINT64 RGXFW_ALIGN                    ui64DeadlineInus;
+	/* Predicted time taken to do the work in cycles */
+	IMG_UINT64 RGXFW_ALIGN                    ui64CyclesPrediction;
+} RGXFWIF_WORKEST_KICK_DATA;
+
+typedef struct _RGXFWIF_WORKLOAD_LIST_NODE_ RGXFWIF_WORKLOAD_LIST_NODE;
+typedef struct _RGXFWIF_DEADLINE_LIST_NODE_ RGXFWIF_DEADLINE_LIST_NODE;
+
+struct _RGXFWIF_WORKLOAD_LIST_NODE_
+{
+	IMG_UINT64 RGXFW_ALIGN ui64Cycles;
+	IMG_UINT64 RGXFW_ALIGN ui64SelfMemDesc;
+	IMG_UINT64 RGXFW_ALIGN ui64WorkloadDataMemDesc;
+	IMG_BOOL					bReleased;
+	RGXFWIF_WORKLOAD_LIST_NODE *psNextNode;
+};
+
+struct _RGXFWIF_DEADLINE_LIST_NODE_
+{
+	IMG_UINT64 RGXFW_ALIGN ui64DeadlineInus;
+	RGXFWIF_WORKLOAD_LIST_NODE *psWorkloadList;
+	IMG_UINT64 RGXFW_ALIGN ui64SelfMemDesc;
+	IMG_UINT64 RGXFW_ALIGN ui64WorkloadDataMemDesc;
+	IMG_BOOL					bReleased;
+	RGXFWIF_DEADLINE_LIST_NODE *psNextNode;
+};
 typedef struct _RGXFWIF_CCB_CMD_HEADER_
 {
-	RGXFWIF_CCB_CMD_TYPE	eCmdType;
-	IMG_UINT32				ui32CmdSize;
-	IMG_UINT32				ui32ExtJobRef; /*!< external job reference - provided by client and used in debug for tracking submitted work */
-	IMG_UINT32				ui32IntJobRef; /*!< internal job reference - generated by services and used in debug for tracking submitted work */
+	RGXFWIF_CCB_CMD_TYPE				eCmdType;
+	IMG_UINT32							ui32CmdSize;
+	IMG_UINT32							ui32ExtJobRef; /*!< external job reference - provided by client and used in debug for tracking submitted work */
+	IMG_UINT32							ui32IntJobRef; /*!< internal job reference - generated by services and used in debug for tracking submitted work */
+	PRGXFWIF_WORKLOAD_DATA RGXFW_ALIGN	sWorkloadDataFWAddr;
+	RGXFWIF_WORKEST_KICK_DATA			sWorkEstKickData; /*!< Workload Estimation - Workload Estimation Data */
 } RGXFWIF_CCB_CMD_HEADER;
 
 typedef enum _RGXFWIF_REG_CFG_TYPE_
@@ -480,6 +543,7 @@
 	RGXFWIF_REG_CFG_TYPE_3D,	         /* 3D kick */
 	RGXFWIF_REG_CFG_TYPE_CDM,	         /* Compute kick */
 	RGXFWIF_REG_CFG_TYPE_TLA,	         /* TLA kick */
+	RGXFWIF_REG_CFG_TYPE_TDM,	         /* TDM kick */
 	RGXFWIF_REG_CFG_TYPE_ALL             /* Applies to all types. Keep as last element */
 } RGXFWIF_REG_CFG_TYPE;
 
@@ -494,6 +558,7 @@
 typedef struct _RGXFWIF_TIME_CORR_
 {
 	IMG_UINT64 RGXFW_ALIGN ui64OSTimeStamp;
+	IMG_UINT64 RGXFW_ALIGN ui64OSMonoTimeStamp;
 	IMG_UINT64 RGXFW_ALIGN ui64CRTimeStamp;
 	IMG_UINT32             ui32CoreClockSpeed;
 
@@ -535,8 +600,8 @@
 
 #define RGXFWIF_GET_CRDELTA_TO_OSDELTA_K_NS(clockfreq, remainder) \
 	OSDivide64((256000000ULL << RGXFWIF_CRDELTA_TO_OSDELTA_ACCURACY_SHIFT), \
-	           ((clockfreq) + 500) / 1000, \
-	           &(remainder))
+			   ((clockfreq) + 500) / 1000, \
+			   &(remainder))
 
 #define RGXFWIF_GET_DELTA_OSTIME_NS(deltaCR, K) \
 	( ((deltaCR) * (K)) >> RGXFWIF_CRDELTA_TO_OSDELTA_ACCURACY_SHIFT)
@@ -549,7 +614,16 @@
  * calibration)
  */
 #define RGXFWIF_GET_GPU_CLOCK_FREQUENCY_HZ(deltacr_us, deltaos_us, remainder) \
-	OSDivide64((deltacr_us) * 256000000, (deltaos_us), &(remainder))
+    OSDivide64((deltacr_us) * 256000000, (deltaos_us), &(remainder))
+
+/* 
+	The maximum configurable size via RGX_FW_HEAP_SHIFT is
+	32MiB (1<<25) and the minimum is 4MiB (1<<22); the
+	default firmware heap size is set to maximum 32MiB.
+*/
+#if (RGX_FW_HEAP_SHIFT < 22 || RGX_FW_HEAP_SHIFT > 25)
+#error "RGX_FW_HEAP_SHIFT is outside valid range [22, 25]"
+#endif
 
 #endif /*  __RGX_FWIF_SHARED_H__ */
 
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_sig.h b/drivers/staging/imgtec/rogue/rgx_fwif_sig.h
new file mode 100644
index 0000000..77c5f7e
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgx_fwif_sig.h
@@ -0,0 +1,147 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX firmware signature checks
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX firmware interface structures used by srvinit and server
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__RGX_FWIF_SIG_H__)
+#define __RGX_FWIF_SIG_H__
+
+#include "rgxdefs_km.h"
+
+/************************************************************************
+* RGX FW signature checks
+************************************************************************/
+
+#if defined(PDUMP) && defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__)
+
+#define SIG_REG_TA_MAX_COUNT	(12)
+static RGXFW_REGISTER_LIST asTASigRegList[SIG_REG_TA_MAX_COUNT];
+static IMG_UINT32 gui32TASigRegCount = 0;
+
+#define SIG_REG_3D_MAX_COUNT	(6)
+static RGXFW_REGISTER_LIST as3DSigRegList[SIG_REG_3D_MAX_COUNT];
+static IMG_UINT32	gui323DSigRegCount = 0;
+
+#else
+
+/* List of TA signature and checksum register addresses */
+static const RGXFW_REGISTER_LIST asTASigRegList[] =
+{	/* Register */						/* Indirect_Reg */			/* Start, End */
+#if defined(RGX_FEATURE_SCALABLE_VDM_GPP)
+	{RGX_CR_USC_UVB_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+#else
+	{RGX_CR_USC_UVS0_CHECKSUM,			0,							0, 0},
+	{RGX_CR_USC_UVS1_CHECKSUM,			0,							0, 0},
+	{RGX_CR_USC_UVS2_CHECKSUM,			0,							0, 0},
+	{RGX_CR_USC_UVS3_CHECKSUM,			0,							0, 0},
+	{RGX_CR_USC_UVS4_CHECKSUM,			0,							0, 0},
+	{RGX_CR_USC_UVS5_CHECKSUM,			0,							0, 0},
+#endif
+#if defined(RGX_FEATURE_SCALABLE_TE_ARCH)
+#if defined(RGX_FEATURE_SCALABLE_VDM_GPP)
+	{RGX_CR_PPP_CLIP_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+#else
+	{RGX_CR_PPP,						0,							0, 0},
+#endif
+	{RGX_CR_TE_CHECKSUM,				0,							0, 0},
+#else
+	{RGX_CR_PPP_SIGNATURE,				0,							0, 0},
+	{RGX_CR_TE_SIGNATURE,				0,							0, 0},
+#endif
+	{RGX_CR_VCE_CHECKSUM,				0,							0, 0},
+#if !defined(RGX_FEATURE_PDS_PER_DUST)
+	{RGX_CR_PDS_DOUTM_STM_SIGNATURE,	0,							0, 0},
+#endif
+};
+
+
+/* List of 3D signature and checksum register addresses */
+static const RGXFW_REGISTER_LIST as3DSigRegList[] =
+{	/* Register */						/* Indirect_Reg */			/* Start, End */
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+	{RGX_CR_ISP_PDS_CHECKSUM,			0,							0, 0},
+	{RGX_CR_ISP_TPF_CHECKSUM,			0,							0, 0},
+	{RGX_CR_TFPU_PLANE0_CHECKSUM,		0,							0, 0},
+	{RGX_CR_TFPU_PLANE1_CHECKSUM,		0,							0, 0},
+	{RGX_CR_PBE_CHECKSUM,				0,							0, 0},
+	{RGX_CR_IFPU_ISP_CHECKSUM,			0,							0, 0},
+#else
+	{RGX_CR_ISP_PDS_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+	{RGX_CR_ISP_TPF_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+	{RGX_CR_TFPU_PLANE0_CHECKSUM,		RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+	{RGX_CR_TFPU_PLANE1_CHECKSUM,		RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+	{RGX_CR_PBE_CHECKSUM,				RGX_CR_PBE_INDIRECT,		0, RGX_FEATURE_NUM_CLUSTERS-1},
+	{RGX_CR_IFPU_ISP_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, RGX_NUM_PHANTOMS-1},
+#endif
+};
+#endif
+
+#if defined (RGX_FEATURE_RAY_TRACING) || defined(__KERNEL__)
+/* List of SHG signature and checksum register addresses */
+static const RGXFW_REGISTER_LIST asRTUSigRegList[] =
+{	/* Register */						/* Indirect_Reg */			/* Start, End */
+	{DPX_CR_RS_PDS_RR_CHECKSUM,				0,							0, 0},
+	{RGX_CR_FBA_FC0_CHECKSUM,				0,							0, 0},
+	{RGX_CR_FBA_FC1_CHECKSUM,				0,							0, 0},
+	{RGX_CR_FBA_FC2_CHECKSUM,				0,							0, 0},
+	{RGX_CR_FBA_FC3_CHECKSUM,				0,							0, 0},
+	{DPX_CR_RQ_USC_DEBUG,					0,							0, 0},
+};
+
+/* List of SHG signature and checksum register addresses */
+static const RGXFW_REGISTER_LIST asSHGSigRegList[] =
+{	/* Register */						/* Indirect_Reg */			/* Start, End */
+	{RGX_CR_SHF_SHG_CHECKSUM,			0,							0, 0},
+	{RGX_CR_SHF_VERTEX_BIF_CHECKSUM,	0,							0, 0},
+	{RGX_CR_SHF_VARY_BIF_CHECKSUM,		0,							0, 0},
+	{RGX_CR_RPM_BIF_CHECKSUM,			0,							0, 0},
+	{RGX_CR_SHG_BIF_CHECKSUM,			0,							0, 0},
+	{RGX_CR_SHG_FE_BE_CHECKSUM,			0,							0, 0},
+};
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+#endif /*  __RGX_FWIF_SIG_H__ */
+
+/******************************************************************************
+ End of file (rgx_fwif_sig.h)
+******************************************************************************/
+
+
diff --git a/drivers/staging/imgtec/rogue/rgx_heaps.h b/drivers/staging/imgtec/rogue/rgx_heaps.h
index 1772d11..6a9b7bf 100644
--- a/drivers/staging/imgtec/rogue/rgx_heaps.h
+++ b/drivers/staging/imgtec/rogue/rgx_heaps.h
@@ -44,35 +44,41 @@
 #define __RGX_HEAPS_H__
 
 #include "km/rgxdefs_km.h"
+#include "log2.h"
+#include "pvr_debug.h"
 
 /* RGX Heap IDs, note: not all heaps are available to clients */
 /* N.B.  Old heap identifiers are deprecated now that the old memory
    management is. New heap identifiers should be suitably renamed */
-#define RGX_UNDEFINED_HEAP_ID					(~0LU)          /*!< RGX Undefined Heap ID */
-#define RGX_GENERAL_HEAP_ID						0               /*!< RGX General Heap ID */
-#define RGX_PDSCODEDATA_HEAP_ID					1               /*!< RGX PDS Code/Data Heap ID */
-//#define RGX_3DPARAMETERS_HEAP_ID				2               /*!< RGX 3D Parameters Heap ID */
-#define RGX_USCCODE_HEAP_ID						2               /*!< RGX USC Code Heap ID */
-#define RGX_FIRMWARE_HEAP_ID					3               /*!< RGX Firmware Heap ID */
-#define RGX_TQ3DPARAMETERS_HEAP_ID				4               /*!< RGX Firmware Heap ID */
-#define RGX_BIF_TILING_HEAP_1_ID				5 				/*!< RGX BIF Tiling Heap 1 ID */
-#define RGX_BIF_TILING_HEAP_2_ID				6 				/*!< RGX BIF Tiling Heap 2 ID */
-#define RGX_BIF_TILING_HEAP_3_ID				7 				/*!< RGX BIF Tiling Heap 3 ID */
-#define RGX_BIF_TILING_HEAP_4_ID				8 				/*!< RGX BIF Tiling Heap 4 ID */
-#define RGX_HWBRN37200_HEAP_ID					9				/*!< RGX HWBRN37200 */
-#define RGX_DOPPLER_HEAP_ID						10				/*!< Doppler Heap ID */
-#define RGX_DOPPLER_OVERFLOW_HEAP_ID			11				/*!< Doppler Overflow Heap ID */
-#define RGX_SIGNALS_HEAP_ID	                                12              /*!< Signals Heap ID */
-#if (RGXFW_NUM_OS  == 1)
-#define RGX_MAX_HEAP_ID     	(RGX_SIGNALS_HEAP_ID + 1)		/*!< Max Valid Heap ID */
-#else
-#define RGX_GUEST_FIRMWARE_HEAP_ID				13				/*!< Additional OSIDs Firmware */
+#define RGX_UNDEFINED_HEAP_ID					(~0LU)			/*!< RGX Undefined Heap ID */
+#define RGX_GENERAL_SVM_HEAP_ID					0				/*!< RGX General SVM (shared virtual memory) Heap ID */
+#define RGX_GENERAL_HEAP_ID						1				/*!< RGX General Heap ID */
+#define RGX_GENERAL_NON4K_HEAP_ID				2				/*!< RGX General none-4K Heap ID */
+#define RGX_RGNHDR_BRN_63142__ID				3				/*!< RGX General Heap ID */
+#define RGX_PDSCODEDATA_HEAP_ID					4				/*!< RGX PDS Code/Data Heap ID */
+#define RGX_USCCODE_HEAP_ID						5				/*!< RGX USC Code Heap ID */
+#define RGX_FIRMWARE_HEAP_ID					6				/*!< RGX Firmware Heap ID */
+#define RGX_TQ3DPARAMETERS_HEAP_ID				7				/*!< RGX Firmware Heap ID */
+#define RGX_BIF_TILING_HEAP_1_ID				8				/*!< RGX BIF Tiling Heap 1 ID */
+#define RGX_BIF_TILING_HEAP_2_ID				9				/*!< RGX BIF Tiling Heap 2 ID */
+#define RGX_BIF_TILING_HEAP_3_ID				10				/*!< RGX BIF Tiling Heap 3 ID */
+#define RGX_BIF_TILING_HEAP_4_ID				11				/*!< RGX BIF Tiling Heap 4 ID */
+#define RGX_HWBRN37200_HEAP_ID					12				/*!< RGX HWBRN37200 */
+#define RGX_DOPPLER_HEAP_ID						13				/*!< Doppler Heap ID */
+#define RGX_DOPPLER_OVERFLOW_HEAP_ID			14				/*!< Doppler Overflow Heap ID */
+#define RGX_SERVICES_SIGNALS_HEAP_ID			15				/*!< Services Signals Heap ID */
+#define RGX_SIGNALS_HEAP_ID						16				/*!< Signals Heap ID */
+#define RGX_TDM_TPU_YUV_COEFFS_HEAP_ID          17
+#define RGX_GUEST_FIRMWARE_HEAP_ID				18				/*!< Additional OSIDs Firmware */
 #define RGX_MAX_HEAP_ID     	(RGX_GUEST_FIRMWARE_HEAP_ID + RGXFW_NUM_OS)	/*!< Max Valid Heap ID */
-#endif
+
 /*
   Identify heaps by their names
 */
+#define RGX_GENERAL_SVM_HEAP_IDENT		"General SVM"			/*!< RGX General SVM (shared virtual memory) Heap Identifier */
 #define RGX_GENERAL_HEAP_IDENT 			"General"               /*!< RGX General Heap Identifier */
+#define RGX_GENERAL_NON4K_HEAP_IDENT	"General NON-4K"        /*!< RGX General non-4K Heap Identifier */
+#define RGX_RGNHDR_BRN_63142_HEAP_IDENT "RgnHdr BRN63142"       /*!< RGX RgnHdr BRN63142 Heap Identifier */
 #define RGX_PDSCODEDATA_HEAP_IDENT 		"PDS Code and Data"     /*!< RGX PDS Code/Data Heap Identifier */
 #define RGX_USCCODE_HEAP_IDENT			"USC Code"              /*!< RGX USC Code Heap Identifier */
 #define RGX_TQ3DPARAMETERS_HEAP_IDENT	"TQ3DParameters"        /*!< RGX TQ 3D Parameters Heap Identifier */
@@ -82,20 +88,91 @@
 #define RGX_BIF_TILING_HEAP_4_IDENT	    "BIF Tiling Heap 4"	    /*!< RGX BIF Tiling Heap 4 identifier */
 #define RGX_DOPPLER_HEAP_IDENT			"Doppler"				/*!< Doppler Heap Identifier */
 #define RGX_DOPPLER_OVERFLOW_HEAP_IDENT	"Doppler Overflow"		/*!< Doppler Heap Identifier */
+#define RGX_SERVICES_SIGNALS_HEAP_IDENT	"Services Signals"		/*!< Services Signals Heap Identifier */
 #define RGX_SIGNALS_HEAP_IDENT	        "Signals"		        /*!< Signals Heap Identifier */
 #define RGX_VISTEST_HEAP_IDENT			"VisTest"				/*!< VisTest heap */
+#define RGX_TDM_TPU_YUV_COEFFS_HEAP_IDENT "TDM TPU YUV Coeffs"
 
 /* BIF tiling heaps have specific buffer requirements based on their XStride
  * configuration. This is detailed in the BIF tiling documentation and ensures
  * that the bits swapped by the BIF tiling algorithm do not result in addresses
  * outside the allocated buffer. The representation here reflects the diagram
- * in the BIF tiling documentation.
- * XStride is defined for a platform in sysconfig.h, but the resulting alignment
- * can be queried through the PVRSRVGetHeapLog2ImportAlignment() API.
+ * in the BIF tiling documentation for tiling mode '0'.
+ *
+ * For tiling mode '1', the overall tile size does not change, width increases
+ * to 2^9 but the height drops to 2^3.
+ * This means the RGX_BIF_TILING_HEAP_ALIGN_LOG2_FROM_XSTRIDE macro can be
+ * used for both modes.
+ *
+ * Previous TILING_HEAP_STRIDE macros are retired in preference to storing an
+ * alignment to stride factor, derived from the tiling mode, with the tiling
+ * heap configuration data.
+ *
+ * XStride is defined for a platform in sysconfig.h, but the resulting
+ * alignment and stride factor can be queried through the
+ * PVRSRVGetHeapLog2ImportAlignmentAndTilingStrideFactor() API.
+ * For reference:
+ *   Log2BufferStride = Log2Alignment - Log2AlignmentToTilingStrideFactor
  */
-#define RGX_BIF_TILING_HEAP_STRIDE_LOG2_FROM_XSTRIDE(X)        (X+1+8)
 #define RGX_BIF_TILING_HEAP_ALIGN_LOG2_FROM_XSTRIDE(X)       (4+X+1+8)
-#define RGX_BIF_TILING_HEAP_STRIDE_LOG2_FROM_ALIGN_LOG2(A)       (A-4)
+#define RGX_BIF_TILING_HEAP_LOG2_ALIGN_TO_STRIDE_BASE              (4)
+
+/*
+ *  Supported log2 page size values for RGX_GENERAL_NON_4K_HEAP_ID
+ */
+#define RGX_HEAP_4KB_PAGE_SHIFT					(12)
+#define RGX_HEAP_16KB_PAGE_SHIFT				(14)
+#define RGX_HEAP_64KB_PAGE_SHIFT				(16)
+#define RGX_HEAP_256KB_PAGE_SHIFT				(18)
+#define RGX_HEAP_1MB_PAGE_SHIFT					(20)
+#define RGX_HEAP_2MB_PAGE_SHIFT					(21)
+
+/* Takes a log2 page size parameter and calculates a suitable page size
+ * for the RGX heaps. Returns 0 if parameter is wrong.*/
+static INLINE IMG_UINT32 RGXHeapDerivePageSize(IMG_UINT32 uiLog2PageSize)
+{
+	IMG_BOOL bFound = IMG_FALSE;
+
+	/* OS page shift must be at least RGX_HEAP_4KB_PAGE_SHIFT,
+	 * max RGX_HEAP_2MB_PAGE_SHIFT, non-zero and a power of two*/
+	if ( uiLog2PageSize == 0 ||
+		(uiLog2PageSize < RGX_HEAP_4KB_PAGE_SHIFT) ||
+		(uiLog2PageSize > RGX_HEAP_2MB_PAGE_SHIFT))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: Provided incompatible log2 page size %u",
+				__FUNCTION__,
+				uiLog2PageSize));
+		PVR_ASSERT(0);
+		return 0;
+	}
+
+	do
+	{
+		switch (uiLog2PageSize)
+		{
+			case RGX_HEAP_4KB_PAGE_SHIFT:
+			case RGX_HEAP_16KB_PAGE_SHIFT:
+			case RGX_HEAP_64KB_PAGE_SHIFT:
+			case RGX_HEAP_256KB_PAGE_SHIFT:
+			case RGX_HEAP_1MB_PAGE_SHIFT:
+			case RGX_HEAP_2MB_PAGE_SHIFT:
+				/* All good, RGX page size equals given page size
+				 * => use it as default for heaps */
+				bFound = IMG_TRUE;
+				break;
+			default:
+				/* We have to fall back to a smaller device
+				 * page size than given page size because there
+				 * is no exact match for any supported size. */
+				uiLog2PageSize -= 1;
+				break;
+		}
+	} while (!bFound);
+
+	return uiLog2PageSize;
+}
+
 
 #endif /* __RGX_HEAPS_H__ */
 
diff --git a/drivers/staging/imgtec/rogue/rgx_hwperf_km.h b/drivers/staging/imgtec/rogue/rgx_hwperf_km.h
index 397cac4..8dd8668 100644
--- a/drivers/staging/imgtec/rogue/rgx_hwperf_km.h
+++ b/drivers/staging/imgtec/rogue/rgx_hwperf_km.h
@@ -2,7 +2,7 @@
 @File
 @Title          RGX HWPerf Types and Defines Header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description	Common data types definitions for hardware performance API
+@Description    Common data types definitions for hardware performance API
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -50,7 +50,7 @@
  * The definitions within are common and may be used in user-mode, kernel-mode
  * and firmware compilation units.
  */
- 
+
 #if defined (__cplusplus)
 extern "C" {
 #endif
@@ -58,7 +58,13 @@
 #define RGX_HWPERF_V2_FORMAT 2
 
 #include "rgx_common.h"
+#include "pvrsrv_tlcommon.h"
+#include <powervr/sync_external.h>
 
+/* HWPerf host buffer size constraints in KBs */
+#define HWPERF_HOST_TL_STREAM_SIZE_DEFAULT (128U)
+#define HWPERF_HOST_TL_STREAM_SIZE_MIN     (32U)
+#define HWPERF_HOST_TL_STREAM_SIZE_MAX     (1024U)
 
 /*! The number of indirectly addressable TPU_MSC blocks in the GPU */
 #define RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST MAX((RGX_FEATURE_NUM_CLUSTERS>>1),1)
@@ -75,43 +81,52 @@
  #define RGX_HWPERF_PHANTOM_NONDUST_BLKS 1 /* BLACKPEARL */
  #define RGX_HWPERF_PHANTOM_DUST_BLKS 2 /* TPU, TEXAS */
  #define RGX_HWPERF_PHANTOM_DUST_CLUSTER_BLKS 2 /* USC, PBE */
+ #define RGX_HWPERF_DOPPLER_BX_TU_BLKS	0 /* No doppler unit */
+ #define RGX_HWPERF_MAX_OTHER_INDIRECT_BLKS 0 /* some indirect blocks have fixed instances in a core */
 
 #elif defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
 
  #if defined(RGX_FEATURE_RAY_TRACING)
   /*! Defines the number of performance counter blocks that are directly
    * addressable in the RGX register map. */
-  #define RGX_HWPERF_MAX_DIRECT_ADDR_BLKS 7 /* TORNADO, TA, BF, BT, RT, BX_TU, SH */
+  #define RGX_HWPERF_MAX_DIRECT_ADDR_BLKS 6 /* TORNADO, TA, BF, BT, RT, SH */
+  #define RGX_HWPERF_DOPPLER_BX_TU_BLKS	4 /* Doppler unit unconditionally has 4 instances of BX_TU */
+  #define RGX_HWPERF_MAX_OTHER_INDIRECT_BLKS RGX_HWPERF_DOPPLER_BX_TU_BLKS
  #else /*#if defined(RAY_TRACING) */
   /*! Defines the number of performance counter blocks that are directly
    * addressable in the RGX register map. */
   #define RGX_HWPERF_MAX_DIRECT_ADDR_BLKS 2 /* TORNADO, TA */
+  #define RGX_HWPERF_DOPPLER_BX_TU_BLKS	0 /* No doppler unit */
+  #define RGX_HWPERF_MAX_OTHER_INDIRECT_BLKS 0
  #endif /*#if defined(RAY_TRACING) */
 
- #define	RGX_HWPERF_INDIRECT_BY_PHANTOM (RGX_NUM_PHANTOMS)
+ #define RGX_HWPERF_INDIRECT_BY_PHANTOM (RGX_NUM_PHANTOMS)
  #define RGX_HWPERF_PHANTOM_NONDUST_BLKS 2 /* RASTER, TEXAS */
- #define	RGX_HWPERF_PHANTOM_DUST_BLKS 1 /* TPU */
- #define	RGX_HWPERF_PHANTOM_DUST_CLUSTER_BLKS 1 /* USC */
+ #define RGX_HWPERF_PHANTOM_DUST_BLKS 1 /* TPU */
+ #define RGX_HWPERF_PHANTOM_DUST_CLUSTER_BLKS 1 /* USC */
 
 #else	/* if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
 
  /*! Defines the number of performance counter blocks that are directly
   * addressable in the RGX register map. */
  #define RGX_HWPERF_MAX_DIRECT_ADDR_BLKS 3 /* TA, RASTER, HUB */
- #define	RGX_HWPERF_INDIRECT_BY_PHANTOM 0  /* PHANTOM is not there is Rogue1. Just using it to keep nameing same as later series (RogueXT n Rogue XT+) */
- #define	RGX_HWPERF_PHANTOM_NONDUST_BLKS 0
+ #define RGX_HWPERF_INDIRECT_BY_PHANTOM 0  /* PHANTOM is not there is Rogue1. Just using it to keep naming same as later series (RogueXT n Rogue XT+) */
+ #define RGX_HWPERF_PHANTOM_NONDUST_BLKS 0
  #define RGX_HWPERF_PHANTOM_DUST_BLKS 1 /* TPU */
  #define RGX_HWPERF_PHANTOM_DUST_CLUSTER_BLKS 1 /* USC */
+#define RGX_HWPERF_DOPPLER_BX_TU_BLKS	0 /* No doppler unit */
+ #define RGX_HWPERF_MAX_OTHER_INDIRECT_BLKS 0
 
 #endif
 
 /*! The number of indirect addressable layout blocks in the GPU with performance counters */
 #define RGX_HWPERF_MAX_INDIRECT_ADDR_BLKS 	(RGX_HWPERF_PHANTOM_DUST_BLKS * RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST +\
 											RGX_HWPERF_PHANTOM_DUST_CLUSTER_BLKS * RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER +\
-											RGX_HWPERF_PHANTOM_NONDUST_BLKS      * RGX_HWPERF_INDIRECT_BY_PHANTOM)
+											RGX_HWPERF_PHANTOM_NONDUST_BLKS      * RGX_HWPERF_INDIRECT_BY_PHANTOM +\
+											RGX_HWPERF_MAX_OTHER_INDIRECT_BLKS)
 
 /*! The number of custom non-mux counter blocks supported */
-#define RGX_HWPERF_MAX_CUSTOM_BLKS 4
+#define RGX_HWPERF_MAX_CUSTOM_BLKS 5
 
 /*! The number of counters supported in each non-mux counter block */
 #define RGX_HWPERF_MAX_CUSTOM_CNTRS 8
@@ -127,14 +142,16 @@
  
 /*! Type used to encode the event that generated the HW performance packet.
  * NOTE: When this type is updated the corresponding hwperfbin2json tool source
- * needs to be updated as well. Also need to update the table in rgxhwperf.c.
- * The RGX_HWPERF_EVENT_MASK_* macros will also need updating when adding new
- * types.
+ * needs to be updated as well. The RGX_HWPERF_EVENT_MASK_* macros will also need
+ * updating when adding new types.
  */
 typedef enum
 {
 	RGX_HWPERF_INVALID				= 0x00,
-	/* FW types 0x01..0x07 */
+
+	/* FW types 0x01..0x06 */
+	RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE	= 0x01,
+
 	RGX_HWPERF_FW_BGSTART			= 0x01,
 	RGX_HWPERF_FW_BGEND				= 0x02,
 	RGX_HWPERF_FW_IRQSTART			= 0x03,
@@ -143,48 +160,67 @@
 	RGX_HWPERF_FW_DBGSTART			= 0x05,
 	RGX_HWPERF_FW_DBGEND			= 0x06,
 
-	/* HW types 0x08..0x18 */
+	RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE		= 0x06,
+
+	/* HW types 0x07..0x19 */
+	RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE	= 0x07,
+
+	RGX_HWPERF_HW_PMOOM_TAPAUSE		= 0x07,
 	RGX_HWPERF_HW_TAKICK			= 0x08,
+/*	RGX_HWPERF_HW_PMOOM_TAPAUSE		= 0x07, */
+/*	RGX_HWPERF_HW_PMOOM_TARESUME	= 0x19, */
 	RGX_HWPERF_HW_TAFINISHED		= 0x09,
 	RGX_HWPERF_HW_3DTQKICK			= 0x0A,
 /*	RGX_HWPERF_HW_3DTQFINISHED		= 0x17, */
 /*	RGX_HWPERF_HW_3DSPMKICK			= 0x11, */
 /*	RGX_HWPERF_HW_3DSPMFINISHED		= 0x18, */
 	RGX_HWPERF_HW_3DKICK			= 0x0B,
-
 	RGX_HWPERF_HW_3DFINISHED		= 0x0C,
 	RGX_HWPERF_HW_CDMKICK			= 0x0D,
 	RGX_HWPERF_HW_CDMFINISHED		= 0x0E,
 	RGX_HWPERF_HW_TLAKICK			= 0x0F,
-
 	RGX_HWPERF_HW_TLAFINISHED		= 0x10,
 	RGX_HWPERF_HW_3DSPMKICK			= 0x11,
 	RGX_HWPERF_HW_PERIODIC			= 0x12,
 	RGX_HWPERF_HW_RTUKICK			= 0x13,
-	
 	RGX_HWPERF_HW_RTUFINISHED		= 0x14,
 	RGX_HWPERF_HW_SHGKICK			= 0x15,
 	RGX_HWPERF_HW_SHGFINISHED		= 0x16,
 	RGX_HWPERF_HW_3DTQFINISHED		= 0x17,
-
 	RGX_HWPERF_HW_3DSPMFINISHED		= 0x18,
+	RGX_HWPERF_HW_PMOOM_TARESUME	= 0x19,
+
+	/* HW_EVENT_RANGE0 used up. Use next empty range below to add new hardware events */
+	RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE	= 0x19,
 
 	/* other types 0x1A..0x1F */
 	RGX_HWPERF_CLKS_CHG				= 0x1A,
 	RGX_HWPERF_GPU_STATE_CHG		= 0x1B,
 
 	/* power types 0x20..0x27 */
+	RGX_HWPERF_PWR_EST_RANGE_FIRST_TYPE	= 0x20,
 	RGX_HWPERF_PWR_EST_REQUEST		= 0x20,
 	RGX_HWPERF_PWR_EST_READY		= 0x21,
 	RGX_HWPERF_PWR_EST_RESULT		= 0x22,
+	RGX_HWPERF_PWR_EST_RANGE_LAST_TYPE	= 0x22,
+
 	RGX_HWPERF_PWR_CHG				= 0x23,
 
+	/* HW_EVENT_RANGE1 0x28..0x2F, for accommodating new hardware events */
+	RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE	= 0x28,
+
+	RGX_HWPERF_HW_TDMKICK			= 0x28,
+	RGX_HWPERF_HW_TDMFINISHED		= 0x29,
+
+	RGX_HWPERF_HW_EVENT_RANGE1_LAST_TYPE = 0x29,
+
 	/* context switch types 0x30..0x31 */
 	RGX_HWPERF_CSW_START			= 0x30,
 	RGX_HWPERF_CSW_FINISHED			= 0x31,
 
-	/* ufo types 0x38 */
+	/* firmware misc 0x38..0x39 */
 	RGX_HWPERF_UFO					= 0x38,
+	RGX_HWPERF_FWACT				= 0x39,
 
 	/* last */
 	RGX_HWPERF_LAST_TYPE,
@@ -195,15 +231,28 @@
 	RGX_HWPERF_MAX_TYPE				= 0x40
 } RGX_HWPERF_EVENT_TYPE;
 
+/* Macro used to check if an event type ID is present in the known set of hardware type events */
+#define HWPERF_PACKET_IS_HW_TYPE(_etype)	(((_etype) >= RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE && (_etype) <= RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE) || \
+											 ((_etype) >= RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE && (_etype) <= RGX_HWPERF_HW_EVENT_RANGE1_LAST_TYPE))
+
+#define HWPERF_PACKET_IS_FW_TYPE(_etype)					\
+	((_etype) >= RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE &&	\
+	 (_etype) <= RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE)
+
 typedef enum {
 	RGX_HWPERF_HOST_INVALID        = 0x00,
 	RGX_HWPERF_HOST_ENQ            = 0x01,
 	RGX_HWPERF_HOST_UFO            = 0x02,
+	RGX_HWPERF_HOST_ALLOC          = 0x03,
 	RGX_HWPERF_HOST_CLK_SYNC       = 0x04,
+	RGX_HWPERF_HOST_FREE           = 0x05,
 
 	/* last */
 	RGX_HWPERF_HOST_LAST_TYPE,
 
+	/* event used as a control layer for HWPerf */
+	RGX_HWPERF_HOST_CTRL           = 0x1f,
+
 	/* This enumeration must have a value that is a power of two as it is
 	 * used in masks and a filter bit field (currently 32 bits long).
 	 */
@@ -216,18 +265,6 @@
  */
 static_assert(RGX_HWPERF_LAST_TYPE < RGX_HWPERF_MAX_TYPE, "Too many HWPerf event types");
 
-/*! Type obsolete and will be removed in a later release, use RGXFWIF_DM */
-typedef RGXFWIF_DM RGX_HWPERF_DM;
-#define RGX_HWPERF_DM_GP	RGXFWIF_DM_GP
-#define RGX_HWPERF_DM_2D	RGXFWIF_DM_2D
-#define RGX_HWPERF_DM_TA	RGXFWIF_DM_TA
-#define RGX_HWPERF_DM_3D	RGXFWIF_DM_3D
-#define RGX_HWPERF_DM_CDM	RGXFWIF_DM_CDM
-#define RGX_HWPERF_DM_RTU	RGXFWIF_DM_RTU
-#define RGX_HWPERF_DM_SHG   RGXFWIF_DM_SHG
-#define RGX_HWPERF_DM_LAST	RGXFWIF_DM_LAST
-
-
 /******************************************************************************
  * 	Packet Format Version 2 Types
  *****************************************************************************/
@@ -263,21 +300,27 @@
 	                             * Use RGX_HWPERF_MAKE_SIZE_* and RGX_HWPERF_GET_SIZE
 	                             * macros to set/get, never write directly. */
 
-	IMG_UINT32  eTypeId;        /*!< Includes event type and META thread ID in
-	                             * the 19 LSb. 13 MSb reserved.
+	IMG_UINT32  eTypeId;        /*!< Fields layout as shown: 
+								 * |<--------------------------32-bits----------------------------->|
+								 * |<---8---->|<----5----->|<----3----->|<---1---->|<------15------>|
+								 * |   OSID   |  RESERVED  |  STREAM-ID | META TID |    EventType   |
+								 *
+								 * NOTE- It seems 3-bits (total 8 OSIDs) are enough for OSID field above?
+								 * In case some bits are in future, perhaps 5 MS bits can be borrowed.
+								 *
 	                             * Use RGX_HWPERF_MAKE_TYPEID and RGX_HWPERF_GET_*
 	                             * macros to set/get, never write directly. */
 
 	IMG_UINT32  ui32Ordinal;    /*!< Sequential number of the packet */
-	IMG_UINT64  ui64Timestamp;   /*!< Depending on the side that packet oridinated
+	IMG_UINT64  ui64Timestamp;   /*!< Depending on the side that packet originated
 	                              * may be either CPU timestamp or value of RGX_CR_TIMER
 	                              * at event. */
 
 	/* PAYLOAD - bytes from this point on in the buffer are from the
-	 * RGX_HWPERF_V2_PACKET_DATA union which encodes the payload data specific
+	 * RGX_PHWPERF_V2_PACKET_DATA union which encodes the payload data specific
 	 * to the event type set in the header. When the structure in the union
-	 * has a variable length member e.g. HW packets the payload length
-	 * varies.
+	 * has a variable length member e.g. HW packets, the payload length
+	 * varies and ui32Size in the header defines the end of the payload data.
 	 */
 } RGX_HWPERF_V2_PACKET_HDR, *RGX_PHWPERF_V2_PACKET_HDR;
 
@@ -287,29 +330,45 @@
 
 
 /*! Mask for use with the IMG_UINT32 ui32Size header field */
-#define RGX_HWPERF_SIZE_MASK			0xFFFFU
+#define RGX_HWPERF_SIZE_MASK         0xFFFFU
+
+/*! This macro defines an upper limit to which the size of the largest variable
+ * length HWPerf packet must fall within, currently 3KB. This constant may be
+ * used to allocate a buffer to hold one packet.
+ * This upper limit is policed by packet producing code.
+ */
+#define RGX_HWPERF_MAX_PACKET_SIZE   0xC00U
+
+/*! Defines an upper limit to the size of a variable length packet payload.
+ */
+#define RGX_HWPERF_MAX_PAYLOAD_SIZE	 ((IMG_UINT32)(RGX_HWPERF_MAX_PACKET_SIZE-\
+	sizeof(RGX_HWPERF_V2_PACKET_HDR)))
+
 
 /*! Macro which takes a structure name and provides the packet size for
- * a fixed size payload packet for assignment to the ui16Size field. */
-#define RGX_HWPERF_MAKE_SIZE_FIXED(_struct)       ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+sizeof(_struct))))
+ * a fixed size payload packet, rounded up to 8 bytes to align packets
+ * for 64 bit architectures. */
+#define RGX_HWPERF_MAKE_SIZE_FIXED(_struct)       ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN(sizeof(_struct), PVRSRVTL_PACKET_ALIGNMENT))))
 
 /*! Macro which takes the number of bytes written in the data payload of a
- * packet for a variable size payload packet, rounds it up to 8 bytes where
- * it may be assigned to the ui16Size field. */
-#define RGX_HWPERF_MAKE_SIZE_VARIABLE(_size)       ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN(_size, 8))))
+ * packet for a variable size payload packet, rounded up to 8 bytes to 
+ * align packets for 64 bit architectures. */
+#define RGX_HWPERF_MAKE_SIZE_VARIABLE(_size)      ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN(_size, PVRSRVTL_PACKET_ALIGNMENT))))
 
 /*! Macro to obtain the size of the packet */
-#define RGX_HWPERF_GET_SIZE(_packet_addr)    ((IMG_UINT16)(((_packet_addr)->ui32Size) & RGX_HWPERF_SIZE_MASK))
+#define RGX_HWPERF_GET_SIZE(_packet_addr)         ((IMG_UINT16)(((_packet_addr)->ui32Size) & RGX_HWPERF_SIZE_MASK))
 
 /*! Macro to obtain the size of the packet data */
-#define RGX_HWPERF_GET_DATA_SIZE(_packet_addr)   (RGX_HWPERF_GET_SIZE(_packet_addr) - sizeof(RGX_HWPERF_V2_PACKET_HDR))
+#define RGX_HWPERF_GET_DATA_SIZE(_packet_addr)    (RGX_HWPERF_GET_SIZE(_packet_addr) - sizeof(RGX_HWPERF_V2_PACKET_HDR))
+
 
 
 /*! Masks for use with the IMG_UINT32 eTypeId header field */
 #define RGX_HWPERF_TYPEID_MASK			0x7FFFFU
+#define RGX_HWPERF_TYPEID_EVENT_MASK	0x07FFFU
 #define RGX_HWPERF_TYPEID_THREAD_MASK	0x08000U
 #define RGX_HWPERF_TYPEID_STREAM_MASK	0x70000U
-#define RGX_HWPERF_TYPEID_EVENT_MASK	(RGX_HWPERF_MAX_TYPE-1)
+#define RGX_HWPERF_TYPEID_OSID_MASK		0xFF000000U
 
 /*! Meta thread macros for encoding the ID into the type field of a packet */
 #define RGX_HWPERF_META_THREAD_SHIFT	15U
@@ -319,9 +378,12 @@
 #define RGX_HWPERF_META_THREAD_MASK		0x1U
 /*! Stream ID macros for encoding the ID into the type field of a packet */
 #define RGX_HWPERF_STREAM_SHIFT			16U
+/*! OSID bit-shift macro used for encoding OSID into type field of a packet */
+#define RGX_HWPERF_OSID_SHIFT			24U
 typedef enum {
-	RGX_HWPERF_STREAM_ID0_FW,
-	RGX_HWPERF_STREAM_ID1_HOST,
+	RGX_HWPERF_STREAM_ID0_FW,     /*!< Events from the Firmware/GPU */
+	RGX_HWPERF_STREAM_ID1_HOST,   /*!< Events from the Server host driver component */
+	RGX_HWPERF_STREAM_ID2_CLIENT, /*!< Events from the Client host driver component */
 	RGX_HWPERF_STREAM_ID_LAST,
 } RGX_HWPERF_STREAM_ID;
 
@@ -329,11 +391,12 @@
 static_assert((RGX_HWPERF_STREAM_ID_LAST - 1) < (RGX_HWPERF_TYPEID_STREAM_MASK >> RGX_HWPERF_STREAM_SHIFT),
 		"To many HWPerf stream IDs.");
 
-/*! Macros used to set the packet type and encode meta thread ID (0|1) within */
-#define RGX_HWPERF_MAKE_TYPEID(_stream,_type,_thread)\
+/*! Macros used to set the packet type and encode meta thread ID (0|1), hwperf stream ID, and OSID within */
+#define RGX_HWPERF_MAKE_TYPEID(_stream,_type,_thread,_osid)\
 		((IMG_UINT32) ((RGX_HWPERF_TYPEID_STREAM_MASK&((_stream)<<RGX_HWPERF_STREAM_SHIFT)) | \
 		(RGX_HWPERF_TYPEID_THREAD_MASK&((_thread)<<RGX_HWPERF_META_THREAD_SHIFT)) | \
-		(RGX_HWPERF_TYPEID_EVENT_MASK&(_type))))
+		(RGX_HWPERF_TYPEID_EVENT_MASK&(_type)) | \
+		(RGX_HWPERF_TYPEID_OSID_MASK & ((_osid) << RGX_HWPERF_OSID_SHIFT))))
 
 /*! Obtains the event type that generated the packet */
 #define RGX_HWPERF_GET_TYPE(_packet_addr)            (((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_EVENT_MASK)
@@ -341,6 +404,9 @@
 /*! Obtains the META Thread number that generated the packet */
 #define RGX_HWPERF_GET_THREAD_ID(_packet_addr)       (((((_packet_addr)->eTypeId)&RGX_HWPERF_TYPEID_THREAD_MASK) >> RGX_HWPERF_META_THREAD_SHIFT))
 
+/*! Obtains the guest OSID which resulted in packet generation */
+#define RGX_HWPERF_GET_OSID(_packet_addr)            (((_packet_addr)->eTypeId & RGX_HWPERF_TYPEID_OSID_MASK) >> RGX_HWPERF_OSID_SHIFT)
+
 /*! Obtain stream id */
 #define RGX_HWPERF_GET_STREAM_ID(_packet_addr)       (((((_packet_addr)->eTypeId)&RGX_HWPERF_TYPEID_STREAM_MASK) >> RGX_HWPERF_STREAM_SHIFT))
 
@@ -352,6 +418,17 @@
 /*! Obtains a typed pointer to a packet header given the packed data address */
 #define RGX_HWPERF_GET_PACKET_HEADER(_packet_addr)     ((RGX_HWPERF_V2_PACKET_HDR*)  ( ((IMG_BYTE*)(_packet_addr)) - sizeof(RGX_HWPERF_V2_PACKET_HDR) ))
 
+/* This macro is not a real array size, but indicates the array has a
+ * variable length only known at run-time but always contains at least 1 element.
+ * The final size of the array is deduced from the size field of a packet
+ * header. */
+#define RGX_HWPERF_ONE_OR_MORE_ELEMENTS  1U
+
+/* This macro is not a real array size, but indicates the array is optional
+ * and if present has a variable length only known at run-time. The final 
+ * size of the array is deduced from the size field of a packet header. */
+#define RGX_HWPERF_ZERO_OR_MORE_ELEMENTS 1U
+
 
 /*! Masks for use with the IMG_UINT32 ui32BlkInfo field */
 #define RGX_HWPERF_BLKINFO_BLKCOUNT_MASK	0xFFFF0000U
@@ -415,8 +492,7 @@
 	RGX_CNTBLK_ID_BF			= 0x0005, /* Doppler unit */
 	RGX_CNTBLK_ID_BT			= 0x0006, /* Doppler unit */
 	RGX_CNTBLK_ID_RT			= 0x0007, /* Doppler unit */
-	RGX_CNTBLK_ID_BX_TU			= 0x0008, /* Doppler unit */
-	RGX_CNTBLK_ID_SH			= 0x0009, /* Ray tracing unit */
+	RGX_CNTBLK_ID_SH			= 0x0008, /* Ray tracing unit */
 
 	RGX_CNTBLK_ID_DIRECT_LAST,
 
@@ -489,12 +565,19 @@
 	RGX_CNTBLK_ID_PBE15			= 0x006F,
 	RGX_CNTBLK_ID_PBE_ALL		= 0x4060,
 
-	RGX_CNTBLK_ID_LAST			= 0x0070,
+	RGX_CNTBLK_ID_BX_TU0		= 0x0070, /* Doppler unit, XT only */
+	RGX_CNTBLK_ID_BX_TU1		= 0x0071,
+	RGX_CNTBLK_ID_BX_TU2		= 0x0072,
+	RGX_CNTBLK_ID_BX_TU3		= 0x0073,
+	RGX_CNTBLK_ID_BX_TU_ALL		= 0x4070,
 
-	RGX_CNTBLK_ID_CUSTOM0       = 0x7FF0,
-	RGX_CNTBLK_ID_CUSTOM1       = 0x7FF1,
-	RGX_CNTBLK_ID_CUSTOM2       = 0x7FF2,
-	RGX_CNTBLK_ID_CUSTOM3       = 0x7FF3,
+	RGX_CNTBLK_ID_LAST			= 0x0074,
+
+	RGX_CNTBLK_ID_CUSTOM0		= 0x7FF0,
+	RGX_CNTBLK_ID_CUSTOM1		= 0x7FF1,
+	RGX_CNTBLK_ID_CUSTOM2		= 0x7FF2,
+	RGX_CNTBLK_ID_CUSTOM3		= 0x7FF3,
+	RGX_CNTBLK_ID_CUSTOM4_FW	= 0x7FF4	/* Custom block used for getting statistics held in the FW */
 
 } RGX_HWPERF_CNTBLK_ID;
 
@@ -504,6 +587,48 @@
 #define RGX_CNTBLK_ID_UNIT_ALL_MASK  (0x4000U)
 #define RGX_CNTBLK_ID_UNIT_MASK		 (0xf)
 
+#define RGX_CNTBLK_INDIRECT_COUNT(_class, _n) ((RGX_CNTBLK_ID_ ## _class ## _n) - (RGX_CNTBLK_ID_ ## _class ## 0) +1)
+
+/*! The number of layout blocks defined with configurable multiplexed
+ * performance counters, hence excludes custom counter blocks.
+ */
+#define RGX_HWPERF_MAX_DEFINED_BLKS  (\
+	RGX_CNTBLK_ID_DIRECT_LAST               +\
+	RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU,     7)+\
+	RGX_CNTBLK_INDIRECT_COUNT(USC,        15)+\
+	RGX_CNTBLK_INDIRECT_COUNT(TEXAS,       7)+\
+	RGX_CNTBLK_INDIRECT_COUNT(RASTER,      3)+\
+	RGX_CNTBLK_INDIRECT_COUNT(BLACKPEARL,  3)+\
+	RGX_CNTBLK_INDIRECT_COUNT(PBE,        15)+\
+	RGX_CNTBLK_INDIRECT_COUNT(BX_TU,       3) )
+
+#define RGX_HWPERF_EVENT_MASK_VALUE(e)      (((IMG_UINT64)1)<<(e))
+
+#define RGX_CUSTOM_FW_CNTRS	\
+		X(TA_LOCAL_FL_SIZE,		0x0,	RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_TAKICK) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_PMOOM_TAPAUSE) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_PMOOM_TARESUME) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_TAFINISHED))	\
+		X(TA_GLOBAL_FL_SIZE,	0x1,	RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_TAKICK) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_PMOOM_TAPAUSE) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_PMOOM_TARESUME) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_TAFINISHED))	\
+		X(3D_LOCAL_FL_SIZE,		0x2,	RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_3DKICK) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_3DFINISHED))	\
+		X(3D_GLOBAL_FL_SIZE,	0x3,	RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_3DKICK) | \
+										RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_3DFINISHED))
+
+/*! Counter IDs for the firmware held stats */
+typedef enum
+{
+#define X(ctr, id, allow_mask)	RGX_CUSTOM_FW_CNTR_##ctr = id,
+	RGX_CUSTOM_FW_CNTRS
+#undef X
+
+	/* always the last entry in the list */
+	RGX_CUSTOM_FW_CNTR_LAST
+} RGX_HWPERF_CUSTOM_FW_CNTR_ID;
+
 /*! Identifier for each counter in a performance counting module */
 typedef enum
 {
@@ -512,24 +637,54 @@
 	RGX_CNTBLK_COUNTER2_ID	  = 2,
 	RGX_CNTBLK_COUNTER3_ID	  = 3,
 	RGX_CNTBLK_COUNTER4_ID	  = 4,
-	RGX_CNTBLK_COUNTER5_ID	  = 5
-	/* RGX_HWPERF_CNTRS_IN_BLK has the maximum number of counters per block*/
-
+	RGX_CNTBLK_COUNTER5_ID	  = 5,
+	/* MAX value used in server handling of counter config arrays */
+	RGX_CNTBLK_COUNTERS_MAX 
 } RGX_HWPERF_CNTBLK_COUNTER_ID;
 
+/* sets all the bits from bit _b1 to _b2, in a IMG_UINT64 type */
+#define _MASK_RANGE(_b1, _b2)	(((IMG_UINT64_C(1) << ((_b2)-(_b1)+1)) - 1) << _b1)
+#define MASK_RANGE(R)			_MASK_RANGE(R##_FIRST_TYPE, R##_LAST_TYPE)
+#define RGX_HWPERF_HOST_EVENT_MASK_VALUE(e) ((IMG_UINT32)(1<<(e)))
+
 /*! Mask macros for use with RGXCtrlHWPerf() API.
- * RGX_HWPERF_EVENT_ALL is obsolete, use RGX_HWPERF_EVENT_MASK_ALL
  */
 #define RGX_HWPERF_EVENT_MASK_NONE          (IMG_UINT64_C(0x0000000000000000))
 #define RGX_HWPERF_EVENT_MASK_ALL           (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
-#define RGX_HWPERF_EVENT_MASK_ALL_FW        (IMG_UINT64_C(0x000000000000007E))
-#define RGX_HWPERF_EVENT_MASK_HW_KICKFINISH (IMG_UINT64_C(0x0000000001FBFF00))
-#define RGX_HWPERF_EVENT_MASK_HW_PERIODIC   (IMG_UINT64_C(0x0000000000040000))
-#define RGX_HWPERF_EVENT_MASK_ALL_HW        (RGX_HWPERF_EVENT_MASK_HW_KICKFINISH \
-                                            | RGX_HWPERF_EVENT_MASK_HW_PERIODIC)
-#define RGX_HWPERF_EVENT_MASK_ALL_PWR_EST   (IMG_UINT64_C(0X0000000700000000))
-#define RGX_HWPERF_EVENT_MASK_ALL_PWR       (IMG_UINT64_C(0X0000000800000000))
-#define RGX_HWPERF_EVENT_MASK_VALUE(e)      (((IMG_UINT64)1)<<(e))
+
+/*! HWPerf Firmware event masks
+ * Next macro covers all FW Start/End/Debug (SED) events.
+ */
+#define RGX_HWPERF_EVENT_MASK_FW_SED    (MASK_RANGE(RGX_HWPERF_FW_EVENT_RANGE))
+
+#define RGX_HWPERF_EVENT_MASK_FW_UFO    (RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_UFO))
+#define RGX_HWPERF_EVENT_MASK_FW_CSW    (RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_CSW_START) |\
+                                          RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_CSW_FINISHED))
+#define RGX_HWPERF_EVENT_MASK_ALL_FW    (RGX_HWPERF_EVENT_MASK_FW_SED |\
+                                          RGX_HWPERF_EVENT_MASK_FW_UFO |\
+                                          RGX_HWPERF_EVENT_MASK_FW_CSW)
+
+#define RGX_HWPERF_EVENT_MASK_HW_PERIODIC   (RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_PERIODIC))
+#define RGX_HWPERF_EVENT_MASK_HW_KICKFINISH ((MASK_RANGE(RGX_HWPERF_HW_EVENT_RANGE0) |\
+                                               MASK_RANGE(RGX_HWPERF_HW_EVENT_RANGE1)) &\
+                                              ~(RGX_HWPERF_EVENT_MASK_HW_PERIODIC))
+
+#define RGX_HWPERF_EVENT_MASK_ALL_HW        (RGX_HWPERF_EVENT_MASK_HW_KICKFINISH |\
+                                              RGX_HWPERF_EVENT_MASK_HW_PERIODIC)
+
+#define RGX_HWPERF_EVENT_MASK_ALL_PWR_EST   (MASK_RANGE(RGX_HWPERF_PWR_EST_RANGE))
+
+#define RGX_HWPERF_EVENT_MASK_ALL_PWR       (RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_CLKS_CHG) |\
+                                              RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_GPU_STATE_CHG) |\
+                                              RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_PWR_CHG))
+
+/*! HWPerf Host event masks
+ */
+#define RGX_HWPERF_EVENT_MASK_HOST_WORK_ENQ  (RGX_HWPERF_HOST_EVENT_MASK_VALUE(RGX_HWPERF_HOST_ENQ))
+#define RGX_HWPERF_EVENT_MASK_HOST_ALL_UFO   (RGX_HWPERF_HOST_EVENT_MASK_VALUE(RGX_HWPERF_HOST_UFO))
+#define RGX_HWPERF_EVENT_MASK_HOST_ALL_PWR   (RGX_HWPERF_HOST_EVENT_MASK_VALUE(RGX_HWPERF_HOST_CLK_SYNC))
+
+
 
 /*! Type used in the RGX API RGXConfigureAndEnableHWPerfCounters()
  * It is used to configure the performance counter module in a layout
@@ -539,14 +694,14 @@
  * also encodes which values in the arrays are valid, for example, if bit 1 set
  * then aui8Mode[1], aui16GroupSelect[1], aui16BitSelect[1], aui32BatchMax[1],
  * and aui32BatchMin[1] must be set. If these array elements are all set to 
- * 0 then the counter will not count and will not be in the HW event, 
- * effectively disabling the counter from the callers point of view. 
+ * 0 then the counter will not count and will not be in the HW event,
+ * effectively disabling the counter from the callers point of view.
  * If any are non zero then the counter will be included in the HW event.
  *
  * Each layout block has 4 or 6 counters that can be programmed independently to
  * profile the performance of a HW block. Each counter can be configured to
  * accumulate statistics from 1 of 32 counter groups defined for that block.
- * Each counter group can have up to 16	signals/bits defined that can be
+ * Each counter group can have up to 16 signals/bits defined that can be
  * selected. Each counter may accumulate in one of two modes.
  * See hwdefs/regapiperf.h for block/group/signal definitions.
  */
@@ -567,19 +722,19 @@
 
 	/*! 5 or 6 LSBs used as the GROUP_SELECT field in the RGX_CR_<N>_PERF_SELECTm
 	 * register. Array index 0 is counter 0, index 1 is counter 1 and so on. */
-	IMG_UINT8	aui8GroupSelect[RGX_HWPERF_CNTRS_IN_BLK];
+	IMG_UINT8	aui8GroupSelect[RGX_CNTBLK_COUNTERS_MAX];
 
 	/*! 16 LSBs used as the BIT_SELECT field in the RGX_CR_<N>_PERF_SELECTm
 	 * register. Array indexes relate to counters as above. */
-	IMG_UINT16  aui16BitSelect[RGX_HWPERF_CNTRS_IN_BLK];
+	IMG_UINT16  aui16BitSelect[RGX_CNTBLK_COUNTERS_MAX];
 
 	/*! 14 LSBs used as the BATCH_MAX field in the RGX_CR_<N>_PERF_SELECTm
 	 * register. Array indexes relate to counters as above. */
-	IMG_UINT32  aui32BatchMax[RGX_HWPERF_CNTRS_IN_BLK];
+	IMG_UINT32  aui32BatchMax[RGX_CNTBLK_COUNTERS_MAX];
 
 	/*! 14 LSBs used as the BATCH_MIN field in the RGX_CR_<N>_PERF_SELECTm
 	 * register. Array indexes relate to counters as above. */
-	IMG_UINT32  aui32BatchMin[RGX_HWPERF_CNTRS_IN_BLK];
+	IMG_UINT32  aui32BatchMin[RGX_CNTBLK_COUNTERS_MAX];
 } UNCACHED_ALIGN RGX_HWPERF_CONFIG_CNTBLK;
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_CONFIG_CNTBLK);
@@ -588,24 +743,45 @@
  * 	Data Stream Common Types
  *****************************************************************************/
 
+/* All the Data Masters HWPerf is aware of. When a new DM is added to this list,
+ * it should be appended at the end to maintain backward compatibility of HWPerf data */
+typedef enum _RGX_HWPERF_DM {
+
+	RGX_HWPERF_DM_GP,
+	RGX_HWPERF_DM_2D,
+	RGX_HWPERF_DM_TA,
+	RGX_HWPERF_DM_3D,
+	RGX_HWPERF_DM_CDM,
+	RGX_HWPERF_DM_RTU,
+	RGX_HWPERF_DM_SHG,
+	RGX_HWPERF_DM_TDM,
+
+	RGX_HWPERF_DM_LAST,
+
+	RGX_HWPERF_DM_INVALID = 0x1FFFFFFF
+} RGX_HWPERF_DM;
+
 /* These structures are used on both GPU and CPU and must be a size that is a
  * multiple of 64 bits, 8 bytes to allow the FW to write 8 byte quantities
  * at 8 byte aligned addresses.  RGX_FW_STRUCT_*_ASSERT() is used to check this.
  */
 
+
 /*! This structure holds the field data of a Hardware packet.
  */
 #define RGX_HWPERF_HW_DATA_FIELDS_LIST \
 IMG_UINT32 ui32DMCyc;         /*!< DataMaster cycle count register, 0 if none */\
-IMG_UINT32 ui32FrameNum;      /*!< Frame number */\
+IMG_UINT32 ui32FrameNum;      /*!< Frame number, undefined on some DataMasters */\
 IMG_UINT32 ui32PID;           /*!< Process identifier */\
-IMG_UINT32 ui32DMContext;     /*!< RenderContext for a TA,3D, Compute context for CDM, etc. */\
-IMG_UINT32 ui32RenderTarget;  /*!< RenderTarget for a TA,3D, 0x0 otherwise */\
+IMG_UINT32 ui32DMContext;     /*!< GPU Data Master (FW) Context */\
+IMG_UINT32 ui32WorkTarget;    /*!< RenderTarget for a TA,3D; Frame context for RTU, 0x0 otherwise */\
 IMG_UINT32 ui32ExtJobRef;     /*!< Externally provided job reference used to track work for debugging purposes */\
 IMG_UINT32 ui32IntJobRef;     /*!< Internally provided job reference used to track work for debugging purposes */\
 IMG_UINT32 ui32TimeCorrIndex; /*!< Index to the time correlation at the time the packet was generated */\
 IMG_UINT32 ui32BlkInfo;       /*!< <31..16> NumBlocks <15..0> Counterblock stream offset */\
-IMG_UINT32 ui32WorkContext;   /*!< Work context number. Frame number for RTU DM, 0x0 otherwise */
+IMG_UINT32 ui32WorkCtx;       /*!< Work context: Render Context for TA/3D; RayTracing Context for RTU/SHG; 0x0 otherwise */\
+IMG_UINT32 ui32CtxPriority;   /*!< Context priority */\
+IMG_UINT32 ui32Padding1;      /* To ensure correct alignment */
 
 typedef struct
 {
@@ -654,12 +830,12 @@
 	IMG_UINT32 ui32PID;
 	IMG_UINT32 ui32ExtJobRef;
 	IMG_UINT32 ui32IntJobRef;
-	IMG_UINT32 ui32FWCtx;
+	IMG_UINT32 ui32DMContext;      /*!< GPU Data Master (FW) Context */
 	IMG_UINT32 ui32StreamInfo;
-	IMG_UINT32 ui32DM;
+	RGX_HWPERF_DM eDM;
 	IMG_UINT32 ui32Padding;
 
-	IMG_UINT32 aui32StreamData[sizeof(RGX_HWPERF_UFO_DATA_ELEMENT) / sizeof(IMG_UINT32)];
+	IMG_UINT32 aui32StreamData[RGX_HWPERF_ONE_OR_MORE_ELEMENTS];
 	/*!< Data stream contains UFO objects for specific command.
 	 *
 	 * Data stream consists of tuples containing UFO related data. Depending
@@ -688,13 +864,46 @@
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_UFO_DATA);
 
-typedef enum {
+/*! This structure holds the data of a firmware packet. */
+typedef struct
+{
+	RGX_HWPERF_DM eDM;				/*!< DataMaster identifier, see RGX_HWPERF_DM */
+	IMG_UINT32 ui32TxtActCyc;		/*!< Meta TXTACTCYC register value */
+	IMG_UINT32 ui32FWPerfCount0;	/*!< Meta/MIPS PERF_COUNT0 register */
+	IMG_UINT32 ui32FWPerfCount1;	/*!< Meta/MIPS PERF_COUNT1 register */
+	IMG_UINT32 ui32TimeCorrIndex;
+	IMG_UINT32 ui32Padding;
+} RGX_HWPERF_FW_DATA;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_FW_DATA);
+
+typedef enum
+{
+	RGX_HWPERF_CTRL_TYPE_INVALID,
+	RGX_HWPERF_CTRL_TYPE_CLIENT_STREAM_OPEN,
+	RGX_HWPERF_CTRL_TYPE_CLIENT_STREAM_CLOSE,
+	RGX_HWPERF_CTRL_TYPE_LAST
+} RGX_HWPERF_HOST_CTRL_TYPE;
+
+typedef struct
+{
+	RGX_HWPERF_HOST_CTRL_TYPE eEvType;
+	union
+	{
+		IMG_UINT32 ui32Pid;
+	} uData;
+} RGX_HWPERF_HOST_CTRL_DATA;
+
+typedef enum
+{
 	RGX_HWPERF_KICK_TYPE_TA3D,
 	RGX_HWPERF_KICK_TYPE_TQ2D,
 	RGX_HWPERF_KICK_TYPE_TQ3D,
 	RGX_HWPERF_KICK_TYPE_CDM,
 	RGX_HWPERF_KICK_TYPE_RS,
 	RGX_HWPERF_KICK_TYPE_VRDM,
+	RGX_HWPERF_KICK_TYPE_TQTDM,
+	RGX_HWPERF_KICK_TYPE_SYNC,
 	RGX_HWPERF_KICK_TYPE_LAST
 } RGX_HWPERF_KICK_TYPE;
 
@@ -704,28 +913,82 @@
 	IMG_UINT32 ui32PID;
 	IMG_UINT32 ui32ExtJobRef;
 	IMG_UINT32 ui32IntJobRef;
-	IMG_UINT32 ui32FWCtx;
+	IMG_UINT32 ui32DMContext;      /*!< GPU Data Master (FW) Context */
+	IMG_UINT32 ui32Padding;        /* Align structure size to 8 bytes */
 } RGX_HWPERF_HOST_ENQ_DATA;
 
-/* This macro is not a real size of the array. The size is dynamic and
- * calculated in runtime. The final size of the array is reflected in the
- * size field of a packet header. */
-#define RGX_HWPERF_ONE_OR_MORE_ELEMENTS \
-    (sizeof(RGX_HWPERF_UFO_DATA_ELEMENT) / sizeof(IMG_UINT32))
+/* Payload size must be multiple of 8 bytes to align start of next packet. */
+static_assert((sizeof(RGX_HWPERF_HOST_ENQ_DATA) & (PVRSRVTL_PACKET_ALIGNMENT-1)) == 0,
+			  "sizeof(RGX_HWPERF_HOST_ENQ_DATA) must be a multiple PVRSRVTL_PACKET_ALIGNMENT");
 
 typedef struct
 {
 	RGX_HWPERF_UFO_EV eEvType;
 	IMG_UINT32 ui32StreamInfo;
 	IMG_UINT32 aui32StreamData[RGX_HWPERF_ONE_OR_MORE_ELEMENTS];
+	IMG_UINT32 ui32Padding;      /* Align structure size to 8 bytes */
 } RGX_HWPERF_HOST_UFO_DATA;
 
-typedef struct {
+/* Payload size must be multiple of 8 bytes to align start of next packet. */
+static_assert((sizeof(RGX_HWPERF_HOST_UFO_DATA) & (PVRSRVTL_PACKET_ALIGNMENT-1)) == 0,
+			  "sizeof(RGX_HWPERF_HOST_UFO_DATA) must be a multiple PVRSRVTL_PACKET_ALIGNMENT");
+
+typedef enum
+{
+	RGX_HWPERF_HOST_RESOURCE_TYPE_INVALID,
+	RGX_HWPERF_HOST_RESOURCE_TYPE_SYNC,
+	RGX_HWPERF_HOST_RESOURCE_TYPE_LAST
+} RGX_HWPERF_HOST_RESOURCE_TYPE;
+
+typedef union
+{
+	struct
+	{
+		IMG_UINT32 ui32FWAddr;
+		IMG_CHAR acName[SYNC_MAX_CLASS_NAME_LEN];
+	} sSyncAlloc;
+} RGX_HWPERF_HOST_ALLOC_DETAIL;
+
+typedef struct
+{
+	RGX_HWPERF_HOST_RESOURCE_TYPE ui32AllocType;
+	RGX_HWPERF_HOST_ALLOC_DETAIL uAllocDetail;
+} RGX_HWPERF_HOST_ALLOC_DATA;
+
+/* Payload size must be multiple of 8 bytes to align start of next packet. */
+static_assert((sizeof(RGX_HWPERF_HOST_ALLOC_DATA) & (PVRSRVTL_PACKET_ALIGNMENT-1)) == 0,
+			  "sizeof(RGX_HWPERF_HOST_ALLOC_DATA) must be a multiple PVRSRVTL_PACKET_ALIGNMENT");
+
+typedef union
+{
+	struct
+	{
+		IMG_UINT32 ui32FWAddr;
+	} sSyncFree;
+} RGX_HWPERF_HOST_FREE_DETAIL;
+
+typedef struct
+{
+	RGX_HWPERF_HOST_RESOURCE_TYPE ui32FreeType;
+	RGX_HWPERF_HOST_FREE_DETAIL uFreeDetail;
+} RGX_HWPERF_HOST_FREE_DATA;
+
+/* Payload size must be multiple of 8 bytes to align start of next packet. */
+static_assert((sizeof(RGX_HWPERF_HOST_FREE_DATA) & (PVRSRVTL_PACKET_ALIGNMENT-1)) == 0,
+			  "sizeof(RGX_HWPERF_HOST_FREE_DATA) must be a multiple PVRSRVTL_PACKET_ALIGNMENT");
+
+typedef struct
+{
 	IMG_UINT64 ui64CRTimestamp;
 	IMG_UINT64 ui64OSTimestamp;
 	IMG_UINT32 ui32ClockSpeed;
+	IMG_UINT32 ui32Padding;       /* Align structure size to 8 bytes */
 } RGX_HWPERF_HOST_CLK_SYNC_DATA;
 
+/* Payload size must be multiple of 8 bytes to align start of next packet. */
+static_assert((sizeof(RGX_HWPERF_HOST_CLK_SYNC_DATA) & (PVRSRVTL_PACKET_ALIGNMENT-1)) == 0,
+			  "sizeof(RGX_HWPERF_HOST_CLK_SYNC_DATA) must be a multiple PVRSRVTL_PACKET_ALIGNMENT");
+
 #if defined (__cplusplus)
 }
 #endif
diff --git a/drivers/staging/imgtec/rogue/rgx_hwperf_table.c b/drivers/staging/imgtec/rogue/rgx_hwperf_table.c
index a379866..c596666 100644
--- a/drivers/staging/imgtec/rogue/rgx_hwperf_table.c
+++ b/drivers/staging/imgtec/rogue/rgx_hwperf_table.c
@@ -40,43 +40,57 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
+
 #include "rgx_fwif_hwperf.h"
 #include "rgxdefs_km.h"
 #include "rgx_hwperf_table.h"
 
-/* Used for counter blocks that are always powered when FW is running */
-static IMG_BOOL rgxfw_hwperf_pow_st_true(RGX_HWPERF_CNTBLK_ID eBlkType, IMG_UINT8 ui8UnitId)
-{
-	PVR_UNREFERENCED_PARAMETER(eBlkType);
-	PVR_UNREFERENCED_PARAMETER(ui8UnitId);
+/* Includes needed for PVRSRVKM (Server) context */
+#if defined(SUPPORT_KERNEL_SRVINIT)
+#	include "rgx_bvnc_defs_km.h"
+#	if defined(__KERNEL__)
+#		include "rgxdevice.h"
+#	endif
+#endif
 
-	return IMG_TRUE;
-}
-
+/* Shared compile-time context ASSERT macro */
 #if defined(RGX_FIRMWARE)
+#	include "rgxfw_utils.h"
+/*  firmware context */
+#	define DBG_ASSERT(_c) RGXFW_ASSERT((_c))
+#else
+#	include "pvr_debug.h"
+/*  host client/server context */
+#	define DBG_ASSERT(_c) PVR_ASSERT((_c))
+#endif
 
+/*****************************************************************************
+ RGXFW_HWPERF_CNTBLK_TYPE_MODEL struct PFNs pfnIsBlkPowered()
+
+ Referenced in gasCntBlkTypeModel[] table below and only called from
+ RGX_FIRMWARE run-time context. Therefore compile time configuration is used.
+ *****************************************************************************/
+
+#if defined(RGX_FIRMWARE) && defined(RGX_FEATURE_PERFBUS)
 #	include "rgxfw_pow.h"
 #	include "rgxfw_utils.h"
 
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 static IMG_BOOL rgxfw_hwperf_pow_st_direct(RGX_HWPERF_CNTBLK_ID eBlkType, IMG_UINT8 ui8UnitId)
 {
 	PVR_UNREFERENCED_PARAMETER(eBlkType);
 	PVR_UNREFERENCED_PARAMETER(ui8UnitId);
-	
-	/* Avoid unused function warning for S6 BVNCs */	
-	PVR_UNREFERENCED_PARAMETER(rgxfw_hwperf_pow_st_true);
 
-#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+	/* S7XT: JONES */
+	return (eBlkType == RGX_CNTBLK_ID_JONES) ? IMG_TRUE : IMG_FALSE;
+#elif defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
 	/* S6XT: TA, TORNADO */
 	return IMG_TRUE;
 #else
 	/* S6  : TA, HUB, RASTER (RASCAL) */
-	return (RGXFW_POWCTL_CACHED_GET()->ePowState & RGXFW_POW_ST_RD_ON) ? IMG_TRUE : IMG_FALSE;
+	return (gsPowCtl.ePowState & RGXFW_POW_ST_RD_ON) ? IMG_TRUE : IMG_FALSE;
 #endif
 }
-#endif /* !RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
-
 
 /* Only use conditional compilation when counter blocks appear in different
  * islands for different Rogue families.
@@ -85,7 +99,7 @@
 {
 	IMG_UINT32 ui32NumDustsEnabled = rgxfw_pow_get_enabled_dusts_num();
 
-	if ((RGXFW_POWCTL_CACHED_GET()->ePowState & RGXFW_POW_ST_RD_ON) &&
+	if ((gsPowCtl.ePowState & RGXFW_POW_ST_RD_ON) &&
 			(ui32NumDustsEnabled > 0))
 	{
 #if defined(RGX_FEATURE_DYNAMIC_DUST_POWER)
@@ -137,128 +151,522 @@
 	return IMG_TRUE;
 }
 
-#else
-#  define rgxfw_hwperf_pow_st_direct   rgxfw_hwperf_pow_st_true
-#  define rgxfw_hwperf_pow_st_indirect rgxfw_hwperf_pow_st_true
-#endif /* RGX_FIRMWARE */
+#else /* !defined(RGX_FIRMWARE) || !defined(RGX_FEATURE_PERFBUS) */
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-/* Currently there is no power island control in the firmware so 
- * we currently assume these blocks are always powered. */
-#  define rgxfw_hwperf_pow_st_gandalf        rgxfw_hwperf_pow_st_true
-#endif /* RGX_FEATURE_RAY_TRACING */
+# define rgxfw_hwperf_pow_st_direct   ((void*)NULL)
+# define rgxfw_hwperf_pow_st_indirect ((void*)NULL)
+# define rgxfw_hwperf_pow_st_gandalf  ((void*)NULL)
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-/* A direct block only in S7, always powered as it contains Garten like
- * Sidekick (S6) and Tornado (S6XT). 
- */
-#	define rgxfw_hwperf_pow_st_jones          rgxfw_hwperf_pow_st_true
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+#endif /* !defined(RGX_FIRMWARE) || !defined(RGX_FEATURE_PERFBUS) */
 
-/* This tables holds the entries for the performance counter block type model 
- * Where the block is not present for a given feature then a NULL block must
- * be included to ensure index hash from a RGX_HWPERF_CNTBLK_ID remains valid */
-IMG_INTERNAL const RGXFW_HWPERF_CNTBLK_TYPE_MODEL gasCntBlkTypeModel[] = {
-/*   uiCntBlkIdBase,         iIndirectReg,                  uiPerfReg,                  uiSelect0BaseReg,                    uiBitSelectPreserveMask,                       uiNumCounters,  uiNumUnits,                    uiSelectRegModeShift, uiSelectRegOffsetShift,            pfnIsBlkPowered
- *                                                                                                                                    uiCounter0BaseReg                                                                                              pszBlockNameComment,  */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_TA,       0, /* direct */                RGX_CR_TA_PERF,             RGX_CR_TA_PERF_SELECT0,              0x0000,  RGX_CR_TA_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_TA_PERF",              rgxfw_hwperf_pow_st_direct },
+#if defined(RGX_FIRMWARE) && defined(RGX_FEATURE_RAY_TRACING)
+
+/* Currently there is no power island control in the firmware for ray tracing
+ * so we currently assume these blocks are always powered. */
+static IMG_BOOL rgxfw_hwperf_pow_st_gandalf(RGX_HWPERF_CNTBLK_ID eBlkType, IMG_UINT8 ui8UnitId)
+{
+	PVR_UNREFERENCED_PARAMETER(eBlkType);
+	PVR_UNREFERENCED_PARAMETER(ui8UnitId);
+
+	return IMG_TRUE;
+}
+
+#else /* !defined(RGX_FIRMWARE) || !defined(RGX_FEATURE_RAY_TRACING) */
+
+# define rgxfw_hwperf_pow_st_gandalf  ((void*)NULL)
+
+#endif /* !defined(RGX_FIRMWARE) || !defined(RGX_FEATURE_RAY_TRACING) */
+
+/*****************************************************************************
+ RGXFW_HWPERF_CNTBLK_TYPE_MODEL struct PFNs pfnIsBlkPowered() end
+ *****************************************************************************/
+
+/*****************************************************************************
+ RGXFW_HWPERF_CNTBLK_TYPE_MODEL struct PFNs pfnIsBlkPresent() start
+
+ Referenced in gasCntBlkTypeModel[] table below and called from all build
+ contexts:
+ RGX_FIRMWARE, PVRSRVCTL (UM) and PVRSRVKM (Server).
+
+ Therefore each function has two implementations, one for compile time and one
+ run time configuration depending on the context. The functions will inform the
+ caller whether this block is valid for this particular RGX device. Other
+ run-time dependent data is returned in psRtInfo for the caller to use.
+ *****************************************************************************/
+
+/* Used for block types: USC */
+static IMG_BOOL rgx_hwperf_blk_present_perfbus(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	DBG_ASSERT(psBlkTypeDesc != NULL);
+	DBG_ASSERT(psRtInfo != NULL);
+	DBG_ASSERT(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_USC0);
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+	PVR_ASSERT(pvDev_km != NULL);
+	{
+		PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDev_km;
+		if ((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_PERFBUS_BIT_MASK) != 0)
+		{
+			psRtInfo->uiBitSelectPreserveMask = 0x0000;
+			psRtInfo->uiNumUnits = psDevInfo->sDevFeatureCfg.ui32NumClusters;
+			return IMG_TRUE;
+		}
+	}
+    PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+#else /* FW or Client context */
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+# if defined(RGX_FEATURE_PERFBUS)
+	psRtInfo->uiBitSelectPreserveMask = 0x0000;
+	psRtInfo->uiNumUnits = psBlkTypeDesc->uiNumUnits;
+	return IMG_TRUE;
+# else
+    PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+    PVR_UNREFERENCED_PARAMETER(psRtInfo);
+# endif
+#endif
+	return IMG_FALSE;
+}
+
+/* Used for block types: Direct RASTERISATION, HUB */
+static IMG_BOOL rgx_hwperf_blk_present_not_clustergrouping(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	DBG_ASSERT(psBlkTypeDesc != NULL);
+	DBG_ASSERT(psRtInfo != NULL);
+	DBG_ASSERT((psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_RASTER) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_HUB));
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+	PVR_ASSERT(pvDev_km != NULL);
+	{
+		PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDev_km;
+		if (((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK) == 0) &&
+				((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_PERFBUS_BIT_MASK) != 0))
+		{
+			psRtInfo->uiNumUnits = 1;
+			if (((psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_44885_BIT_MASK) != 0) &&
+				(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_RASTER))
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0X7c00;
+			}
+			else
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0x0000;
+			}
+			return IMG_TRUE;
+		}
+	}
+#else /* FW or Client context */
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+# if !defined(RGX_FEATURE_CLUSTER_GROUPING) && defined(RGX_FEATURE_PERFBUS)
+	psRtInfo->uiNumUnits = 1;
+#  if defined(HW_ERN_44885)
+	if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_RASTER)
+	{
+		psRtInfo->uiBitSelectPreserveMask = 0x7C00;
+	}
+	else
+#  endif
+	{
+		psRtInfo->uiBitSelectPreserveMask = 0x0000;
+	}
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	return IMG_TRUE;
+# else
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	PVR_UNREFERENCED_PARAMETER(psRtInfo);
+# endif
+#endif
+	return IMG_FALSE;
+}
+
+/* Used for block types: BF, BT, RT, SH, BX_TU */
+static IMG_BOOL rgx_hwperf_blk_present_raytracing(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	DBG_ASSERT(psBlkTypeDesc != NULL);
+	DBG_ASSERT(psRtInfo != NULL);
+	DBG_ASSERT((psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_BF) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_BT) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_RT) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_SH) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_BX_TU0));
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+	PVR_ASSERT(pvDev_km != NULL);
+	{
+		PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDev_km;
+		if ((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK) != 0)
+		{
+			psRtInfo->uiBitSelectPreserveMask = 0x0000;
+			psRtInfo->uiNumUnits = psBlkTypeDesc->uiNumUnits;
+			return IMG_TRUE;
+		}
+	}
+#else /* FW or Client context */
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+# if defined(RGX_FEATURE_RAY_TRACING)
+	psRtInfo->uiBitSelectPreserveMask = 0x0000;
+	psRtInfo->uiNumUnits = psBlkTypeDesc->uiNumUnits;
+	DBG_ASSERT(psBlkTypeDesc->uiPerfReg != 0); /* Check for broken config */
+	return IMG_TRUE;
+# else
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	PVR_UNREFERENCED_PARAMETER(psRtInfo);
+# endif
+#endif
+	return IMG_FALSE;
+}
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+static INLINE IMG_UINT32 rgx_units_indirect_by_phantom(PVRSRV_DEVICE_FEATURE_CONFIG *psFeatCfg)
+{
+	/* Run-time math for RGX_HWPERF_INDIRECT_BY_PHANTOM */
+	return ((psFeatCfg->ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK) == 0) ? 1
+		: (psFeatCfg->ui32NumClusters+3)/4;
+}
+
+static INLINE IMG_UINT32 rgx_units_phantom_indirect_by_dust(PVRSRV_DEVICE_FEATURE_CONFIG *psFeatCfg)
+{
+	/* Run-time math for RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST */
+	return MAX((psFeatCfg->ui32NumClusters>>1),1);
+}
+
+static INLINE IMG_UINT32 rgx_units_phantom_indirect_by_cluster(PVRSRV_DEVICE_FEATURE_CONFIG *psFeatCfg)
+{
+	/* Run-time math for RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER */
+	return psFeatCfg->ui32NumClusters;
+}
+#endif /* defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) */
+
+/* Used for block types: TORNADO, TEXAS, Indirect RASTERISATION */
+static IMG_BOOL rgx_hwperf_blk_present_xttop(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	DBG_ASSERT(psBlkTypeDesc != NULL);
+	DBG_ASSERT(psRtInfo != NULL);
+	DBG_ASSERT((psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TORNADO) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TEXAS0) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_RASTER0));
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+	PVR_ASSERT(pvDev_km != NULL);
+	{
+		PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDev_km;
+		if ((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK) != 0)
+		{
+			psRtInfo->uiBitSelectPreserveMask = 0x0000;
+			psRtInfo->uiNumUnits =
+				(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TORNADO) ? 1
+					: rgx_units_indirect_by_phantom(&psDevInfo->sDevFeatureCfg); // Texas, Ind. Raster
+			return IMG_TRUE;
+		}
+	}
+#else /* FW or Client context */
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+# if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE) && defined(RGX_FEATURE_PERFBUS)
+	psRtInfo->uiBitSelectPreserveMask = 0x0000;
+	psRtInfo->uiNumUnits = psBlkTypeDesc->uiNumUnits;
+	return IMG_TRUE;
+# else
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	PVR_UNREFERENCED_PARAMETER(psRtInfo);
+# endif
+#endif
+	return IMG_FALSE;
+}
+
+/* Used for block types: JONES, TPU_MCU, TEXAS, BLACKPERL, PBE */
+static IMG_BOOL rgx_hwperf_blk_present_s7top(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	DBG_ASSERT(psBlkTypeDesc != NULL);
+	DBG_ASSERT(psRtInfo != NULL);
+	DBG_ASSERT((psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_JONES) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TPU_MCU0) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TEXAS0) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_BLACKPEARL0) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_PBE0));
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+	PVR_ASSERT(pvDev_km != NULL);
+	{
+		PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDev_km;
+		if ((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK) != 0)
+		{
+			if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TPU_MCU0)
+			{
+				psRtInfo->uiBitSelectPreserveMask =
+						((psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_41805_BIT_MASK) != 0)
+						? 0x8000 : 0x0000;
+				psRtInfo->uiNumUnits = rgx_units_phantom_indirect_by_dust(&psDevInfo->sDevFeatureCfg);
+				return IMG_TRUE;
+			}
+			else if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TEXAS0)
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0x0000;
+				psRtInfo->uiNumUnits = rgx_units_phantom_indirect_by_dust(&psDevInfo->sDevFeatureCfg);
+				return IMG_TRUE;
+			}
+			else if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_BLACKPEARL0)
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0x0000;
+				psRtInfo->uiNumUnits = rgx_units_indirect_by_phantom(&psDevInfo->sDevFeatureCfg);
+				return IMG_TRUE;
+			}
+			else if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_PBE0)
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0x0000;
+				psRtInfo->uiNumUnits = rgx_units_phantom_indirect_by_cluster(&psDevInfo->sDevFeatureCfg);
+				return IMG_TRUE;
+			}
+			else if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_JONES)
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0x0000;
+				psRtInfo->uiNumUnits = 1;
+				return IMG_TRUE;
+			}
+		}
+	}
+#else /* FW or Client context */
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+# if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+	psRtInfo->uiNumUnits = psBlkTypeDesc->uiNumUnits;
+#  if defined(HW_ERN_41805)
+	if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TPU_MCU0)
+	{
+		psRtInfo->uiBitSelectPreserveMask = 0x8000;
+	}
+	else
+#  endif
+	{
+		psRtInfo->uiBitSelectPreserveMask = 0x0000;
+	}
+	return IMG_TRUE;
+# else
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	PVR_UNREFERENCED_PARAMETER(psRtInfo);
+# endif
+#endif
+	return IMG_FALSE;
+}
+
+/* Used for block types: TA, TPU_MCU */
+static IMG_BOOL rgx_hwperf_blk_present_not_s7top(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	DBG_ASSERT(psBlkTypeDesc != NULL);
+	DBG_ASSERT(psRtInfo != NULL);
+	DBG_ASSERT((psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TA) ||
+		(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TPU_MCU0));
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__) /* Server context */
+	PVR_ASSERT(pvDev_km != NULL);
+	{
+		PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDev_km;
+		if (((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK) == 0) &&
+				((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_PERFBUS_BIT_MASK) != 0))
+		{
+			if (((psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_41805_BIT_MASK) != 0) &&
+				(psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TPU_MCU0))
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0X8000;
+			}
+			else
+			{
+				psRtInfo->uiBitSelectPreserveMask = 0x0000;
+			}
+			psRtInfo->uiNumUnits = (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TA) ? 1
+				: rgx_units_phantom_indirect_by_dust(&psDevInfo->sDevFeatureCfg); // TPU_MCU0
+			return IMG_TRUE;
+		}
+	}
+#else /* FW or Client context */
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+# if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) && defined(RGX_FEATURE_PERFBUS)
+	psRtInfo->uiNumUnits = psBlkTypeDesc->uiNumUnits;
+#  if defined(HW_ERN_41805)
+	if (psBlkTypeDesc->uiCntBlkIdBase == RGX_CNTBLK_ID_TPU_MCU0)
+	{
+		psRtInfo->uiBitSelectPreserveMask = 0x8000;
+	}
+	else
+#  endif
+	{
+		psRtInfo->uiBitSelectPreserveMask = 0x0000;
+	}
+	return IMG_TRUE;
+# else
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	PVR_UNREFERENCED_PARAMETER(psRtInfo);
+# endif
+#endif
+	return IMG_FALSE;
+}
+
+#if !defined(__KERNEL__) /* Firmware or User-mode context */
+static IMG_BOOL rgx_hwperf_blk_present_false(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc, void *pvDev_km, RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psBlkTypeDesc);
+	PVR_UNREFERENCED_PARAMETER(pvDev_km);
+	PVR_UNREFERENCED_PARAMETER(psRtInfo);
+
+	/* Some functions not used on some BVNCs, silence compiler warnings */
+	PVR_UNREFERENCED_PARAMETER(rgx_hwperf_blk_present_perfbus);
+	PVR_UNREFERENCED_PARAMETER(rgx_hwperf_blk_present_not_clustergrouping);
+	PVR_UNREFERENCED_PARAMETER(rgx_hwperf_blk_present_raytracing);
+	PVR_UNREFERENCED_PARAMETER(rgx_hwperf_blk_present_xttop);
+	PVR_UNREFERENCED_PARAMETER(rgx_hwperf_blk_present_s7top);
+	PVR_UNREFERENCED_PARAMETER(rgx_hwperf_blk_present_not_s7top);
+
+	return IMG_FALSE;
+}
+
+/* Used to instantiate a null row in the block type model table below where the
+ * block is not supported for a given build BVNC in firmware/user mode context.
+ * This is needed as the blockid to block type lookup uses the table as well
+ * and clients may try to access blocks not in the hardware. */
+#define RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(_blkid) {_blkid, 0, 0, 0, 0, 0, 0, 0, 0, #_blkid, NULL, rgx_hwperf_blk_present_false}
+
+#endif
+
+
+/*****************************************************************************
+ RGXFW_HWPERF_CNTBLK_TYPE_MODEL struct PFNs pfnIsBlkPresent() end
+ *****************************************************************************/
+
+/*****************************************************************************
+ RGXFW_HWPERF_CNTBLK_TYPE_MODEL gasCntBlkTypeModel[] table
+
+ This table holds the entries for the performance counter block type model.
+ Where the block is not present on an RGX device in question the ()
+ pfnIsBlkPresent() returns false, if valid and present it returns true.
+ Columns in the table with a ** indicate the value is a default and the
+ value returned in RGX_HWPERF_CNTBLK_RT_INFO when calling pfnIsBlkPresent()
+ should be used at runtime by the caller. These columns are only valid for
+ compile time BVNC configured contexts.
+
+ Order of table rows must match order of counter block IDs in the enumeration
+ RGX_HWPERF_CNTBLK_ID.
+*****************************************************************************/
+
+static const RGXFW_HWPERF_CNTBLK_TYPE_MODEL gasCntBlkTypeModel[] =
+{
+/*   uiCntBlkIdBase,         iIndirectReg,                  uiPerfReg,                  uiSelect0BaseReg,                    uiCounter0BaseReg                   uiNumCounters,  uiNumUnits**,                  uiSelectRegModeShift, uiSelectRegOffsetShift,            pfnIsBlkPowered               pfnIsBlkPresent
+ *                                                                                                                                                                                                                                                   pszBlockNameComment,  */
+    /*RGX_CNTBLK_ID_TA*/
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) && defined(RGX_FEATURE_PERFBUS) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_TA,       0, /* direct */                RGX_CR_TA_PERF,             RGX_CR_TA_PERF_SELECT0,              RGX_CR_TA_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_TA_PERF",              rgxfw_hwperf_pow_st_direct,   rgx_hwperf_blk_present_not_s7top },
 #else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TA),
 #endif
 
-#if !defined(RGX_FEATURE_CLUSTER_GROUPING)
-    {RGX_CNTBLK_ID_RASTER,   0, /* direct */                RGX_CR_RASTERISATION_PERF,  RGX_CR_RASTERISATION_PERF_SELECT0,
-#if defined(HW_ERN_44885)
-                                                                                                                             0x7C00,
-#else
-                                                                                                                             0x0000,
-#endif
-                                                                                                                                      RGX_CR_RASTERISATION_PERF_COUNTER_0,  4,              1,                              21,                  3,  "RGX_CR_RASTERISATION_PERF",   rgxfw_hwperf_pow_st_direct },
-    
-	{RGX_CNTBLK_ID_HUB,      0, /* direct */                RGX_CR_HUB_BIFPMCACHE_PERF, RGX_CR_HUB_BIFPMCACHE_PERF_SELECT0,  0x0000,  RGX_CR_HUB_BIFPMCACHE_PERF_COUNTER_0, 4,              1,                              21,                  3,  "RGX_CR_HUB_BIFPMCACHE_PERF",  rgxfw_hwperf_pow_st_direct},
+    /*RGX_CNTBLK_ID_RASTER*/
+#if !defined(RGX_FEATURE_CLUSTER_GROUPING) && defined(RGX_FEATURE_PERFBUS) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_RASTER,   0, /* direct */                RGX_CR_RASTERISATION_PERF,  RGX_CR_RASTERISATION_PERF_SELECT0,   RGX_CR_RASTERISATION_PERF_COUNTER_0,  4,              1,                              21,                  3,  "RGX_CR_RASTERISATION_PERF",   rgxfw_hwperf_pow_st_direct,   rgx_hwperf_blk_present_not_clustergrouping },
 #else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_RASTER),
+#endif
+
+    /*RGX_CNTBLK_ID_HUB*/
+#if !defined(RGX_FEATURE_CLUSTER_GROUPING) && defined(RGX_FEATURE_PERFBUS) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_HUB,      0, /* direct */                RGX_CR_HUB_BIFPMCACHE_PERF, RGX_CR_HUB_BIFPMCACHE_PERF_SELECT0,  RGX_CR_HUB_BIFPMCACHE_PERF_COUNTER_0, 4,              1,                              21,                  3,  "RGX_CR_HUB_BIFPMCACHE_PERF",  rgxfw_hwperf_pow_st_direct,   rgx_hwperf_blk_present_not_clustergrouping },
+#else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_HUB),
 #endif
 
-#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_TORNADO,  0, /* direct */                RGX_CR_TORNADO_PERF,        RGX_CR_TORNADO_PERF_SELECT0,         0x0000,  RGX_CR_TORNADO_PERF_COUNTER_0,        4,              1,                              21,                  4,  "RGX_CR_TORNADO_PERF",         rgxfw_hwperf_pow_st_direct },
+    /*RGX_CNTBLK_ID_TORNADO*/
+#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_TORNADO,  0, /* direct */                RGX_CR_TORNADO_PERF,        RGX_CR_TORNADO_PERF_SELECT0,         RGX_CR_TORNADO_PERF_COUNTER_0,        4,              1,                              21,                  4,  "RGX_CR_TORNADO_PERF",         rgxfw_hwperf_pow_st_direct,   rgx_hwperf_blk_present_xttop },
 #else
-    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TORNADO),
+	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TORNADO),
 #endif
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_JONES,   0, /* direct */                 RGX_CR_JONES_PERF,          RGX_CR_JONES_PERF_SELECT0,           0x0000,  RGX_CR_JONES_PERF_COUNTER_0,          4,              1,                              21,                  3,  "RGX_CR_JONES_PERF",           rgxfw_hwperf_pow_st_jones },
+    /*RGX_CNTBLK_ID_JONES*/
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_JONES,   0, /* direct */                 RGX_CR_JONES_PERF,          RGX_CR_JONES_PERF_SELECT0,           RGX_CR_JONES_PERF_COUNTER_0,          4,              1,                              21,                  3,  "RGX_CR_JONES_PERF",           rgxfw_hwperf_pow_st_direct,    rgx_hwperf_blk_present_s7top },
 #else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_JONES),
 #endif
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-
-    {RGX_CNTBLK_ID_BF,      0, /* direct */                 DPX_CR_BF_PERF,             DPX_CR_BF_PERF_SELECT0,              0x0000,  DPX_CR_BF_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_BF_PERF",              rgxfw_hwperf_pow_st_gandalf },
-
-    {RGX_CNTBLK_ID_BT,      0, /* direct */                 DPX_CR_BT_PERF,             DPX_CR_BT_PERF_SELECT0,              0x0000,  DPX_CR_BT_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_BT_PERF",              rgxfw_hwperf_pow_st_gandalf },
-
-    {RGX_CNTBLK_ID_RT,      0, /* direct */                 DPX_CR_RT_PERF,             DPX_CR_RT_PERF_SELECT0,              0x0000,  DPX_CR_RT_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_RT_PERF",              rgxfw_hwperf_pow_st_gandalf },
-
-    {RGX_CNTBLK_ID_BX_TU,   0, /* direct */                 DPX_CR_BX_TU_PERF,          DPX_CR_BX_TU_PERF_SELECT0,           0x0000,  DPX_CR_BX_TU_PERF_COUNTER_0,          4,              1,                              21,                  3,  "RGX_CR_BX_TU_PERF",           rgxfw_hwperf_pow_st_gandalf },
-
-    {RGX_CNTBLK_ID_SH,      0, /* direct */                 RGX_CR_SH_PERF,             RGX_CR_SH_PERF_SELECT0,              0x0000,  RGX_CR_SH_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_SH_PERF",              rgxfw_hwperf_pow_st_gandalf },
+	/*RGX_CNTBLK_ID_BF RGX_CNTBLK_ID_BT RGX_CNTBLK_ID_RT RGX_CNTBLK_ID_SH*/
+	/* Conditional for rgxsrvinit.c UM build where CR defs not unconditional in any context and multi BVNC is not operational */
+#if defined(RGX_FEATURE_RAY_TRACING ) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_BF,      0, /* direct */                 DPX_CR_BF_PERF,             DPX_CR_BF_PERF_SELECT0,              DPX_CR_BF_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_BF_PERF",              rgxfw_hwperf_pow_st_gandalf, rgx_hwperf_blk_present_raytracing },
+    {RGX_CNTBLK_ID_BT,      0, /* direct */                 DPX_CR_BT_PERF,             DPX_CR_BT_PERF_SELECT0,              DPX_CR_BT_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_BT_PERF",              rgxfw_hwperf_pow_st_gandalf, rgx_hwperf_blk_present_raytracing },
+    {RGX_CNTBLK_ID_RT,      0, /* direct */                 DPX_CR_RT_PERF,             DPX_CR_RT_PERF_SELECT0,              DPX_CR_RT_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_RT_PERF",              rgxfw_hwperf_pow_st_gandalf, rgx_hwperf_blk_present_raytracing },
+    {RGX_CNTBLK_ID_SH,      0, /* direct */                 RGX_CR_SH_PERF,             RGX_CR_SH_PERF_SELECT0,              RGX_CR_SH_PERF_COUNTER_0,             4,              1,                              21,                  3,  "RGX_CR_SH_PERF",              rgxfw_hwperf_pow_st_gandalf, rgx_hwperf_blk_present_raytracing },
 #else
-    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BF),
-	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BT),
-	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_RT),
-	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BX_TU),
-	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_SH),
+	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BF),
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BT),
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_RT),
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_SH),
 #endif
-    
-	{RGX_CNTBLK_ID_TPU_MCU0,
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) 
-                            RGX_CR_TPU_PERF_INDIRECT,
-#else
-                            RGX_CR_TPU_MCU_L0_PERF_INDIRECT,
-#endif
-                                                            RGX_CR_TPU_MCU_L0_PERF,     RGX_CR_TPU_MCU_L0_PERF_SELECT0,
-#if defined(HW_ERN_41805)
-                                                                                                                            0x8000,
-#else
-                                                                                                                            0x0000,
-#endif
-                                                                                                                                      RGX_CR_TPU_MCU_L0_PERF_COUNTER_0,     4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST, 21,             3,  "RGX_CR_TPU_MCU_L0_PERF",      rgxfw_hwperf_pow_st_indirect },
 
-    {RGX_CNTBLK_ID_USC0,    RGX_CR_USC_PERF_INDIRECT,       RGX_CR_USC_PERF,            RGX_CR_USC_PERF_SELECT0,            0x0000,   RGX_CR_USC_PERF_COUNTER_0,            4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER, 21,          3,  "RGX_CR_USC_PERF",             rgxfw_hwperf_pow_st_indirect },
+    /*RGX_CNTBLK_ID_TPU_MCU0*/
+#if defined(RGX_FEATURE_PERFBUS) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) && defined(RGX_FEATURE_PERFBUS) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_TPU_MCU0, RGX_CR_TPU_MCU_L0_PERF_INDIRECT, RGX_CR_TPU_MCU_L0_PERF,   RGX_CR_TPU_MCU_L0_PERF_SELECT0,     RGX_CR_TPU_MCU_L0_PERF_COUNTER_0,     4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST,    21,          3,  "RGX_CR_TPU_MCU_L0_PERF",      rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_not_s7top },
+#else
+	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TPU_MCU0),
+#endif
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_TPU_MCU0, RGX_CR_TPU_PERF_INDIRECT,      RGX_CR_TPU_MCU_L0_PERF,     RGX_CR_TPU_MCU_L0_PERF_SELECT0,     RGX_CR_TPU_MCU_L0_PERF_COUNTER_0,     4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST,    21,          3,  "RGX_CR_TPU_MCU_L0_PERF",      rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_s7top },
+#else
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TPU_MCU0),
+#endif
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_TEXAS0,  RGX_CR_TEXAS3_PERF_INDIRECT,    RGX_CR_TEXAS_PERF,          RGX_CR_TEXAS_PERF_SELECT0,          0x0000,   RGX_CR_TEXAS_PERF_COUNTER_0,          6,              RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST, 31,             3,  "RGX_CR_TEXAS_PERF",           rgxfw_hwperf_pow_st_indirect },
-#elif defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_TEXAS0,  RGX_CR_TEXAS_PERF_INDIRECT,     RGX_CR_TEXAS_PERF,          RGX_CR_TEXAS_PERF_SELECT0,          0x0000,   RGX_CR_TEXAS_PERF_COUNTER_0,          6,              RGX_HWPERF_INDIRECT_BY_PHANTOM, 31,                  3,  "RGX_CR_TEXAS_PERF",           rgxfw_hwperf_pow_st_indirect },
+    /*RGX_CNTBLK_ID_USC0*/
+#if defined(RGX_FEATURE_PERFBUS) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_USC0,    RGX_CR_USC_PERF_INDIRECT,       RGX_CR_USC_PERF,            RGX_CR_USC_PERF_SELECT0,            RGX_CR_USC_PERF_COUNTER_0,            4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER, 21,          3,  "RGX_CR_USC_PERF",             rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_perfbus },
+#else
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_USC0),
+#endif
+
+    /*RGX_CNTBLK_ID_TEXAS0*/
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_TEXAS0,  RGX_CR_TEXAS3_PERF_INDIRECT,    RGX_CR_TEXAS_PERF,          RGX_CR_TEXAS_PERF_SELECT0,          RGX_CR_TEXAS_PERF_COUNTER_0,          6,              RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST,    31,          3,  "RGX_CR_TEXAS_PERF",           rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_s7top },
+#else
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TEXAS0),
+#endif
+#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_TEXAS0,  RGX_CR_TEXAS_PERF_INDIRECT,     RGX_CR_TEXAS_PERF,          RGX_CR_TEXAS_PERF_SELECT0,          RGX_CR_TEXAS_PERF_COUNTER_0,          6,              RGX_HWPERF_INDIRECT_BY_PHANTOM,         31,          3,  "RGX_CR_TEXAS_PERF",           rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_xttop },
 #else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_TEXAS0),
 #endif
 
-#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_RASTER0, RGX_CR_RASTERISATION_PERF_INDIRECT, RGX_CR_RASTERISATION_PERF, RGX_CR_RASTERISATION_PERF_SELECT0, 0x0000, RGX_CR_RASTERISATION_PERF_COUNTER_0,  4,              RGX_HWPERF_INDIRECT_BY_PHANTOM, 21,                  3,  "RGX_CR_RASTERISATION_PERF",   rgxfw_hwperf_pow_st_indirect },
+    /*RGX_CNTBLK_ID_RASTER0*/
+#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_RASTER0, RGX_CR_RASTERISATION_PERF_INDIRECT, RGX_CR_RASTERISATION_PERF, RGX_CR_RASTERISATION_PERF_SELECT0, RGX_CR_RASTERISATION_PERF_COUNTER_0,  4,            RGX_HWPERF_INDIRECT_BY_PHANTOM,         21,          3,  "RGX_CR_RASTERISATION_PERF",   rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_xttop },
 #else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_RASTER0),
 #endif
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-    {RGX_CNTBLK_ID_BLACKPEARL0, RGX_CR_BLACKPEARL_PERF_INDIRECT, RGX_CR_BLACKPEARL_PERF, RGX_CR_BLACKPEARL_PERF_SELECT0,    0x0000,   RGX_CR_BLACKPEARL_PERF_COUNTER_0,     6,              RGX_HWPERF_INDIRECT_BY_PHANTOM, 21,                  3,  "RGX_CR_BLACKPEARL_PERF",      rgxfw_hwperf_pow_st_indirect },
-    {RGX_CNTBLK_ID_PBE0,    RGX_CR_PBE_PERF_INDIRECT, RGX_CR_PBE_PERF,                  RGX_CR_PBE_PERF_SELECT0,            0x0000,   RGX_CR_PBE_PERF_COUNTER_0,            4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER, 21,          3,  "RGX_CR_PBE_PERF",             rgxfw_hwperf_pow_st_indirect },
+    /*RGX_CNTBLK_ID_BLACKPEARL0*/
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_BLACKPEARL0, RGX_CR_BLACKPEARL_PERF_INDIRECT, RGX_CR_BLACKPEARL_PERF, RGX_CR_BLACKPEARL_PERF_SELECT0,    RGX_CR_BLACKPEARL_PERF_COUNTER_0,     6,              RGX_HWPERF_INDIRECT_BY_PHANTOM,         21,          3,  "RGX_CR_BLACKPEARL_PERF",      rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_s7top },
 #else
-	RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BLACKPEARL0),
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BLACKPEARL0),
+#endif
+
+    /*RGX_CNTBLK_ID_PBE0*/
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_PBE0,    RGX_CR_PBE_PERF_INDIRECT, RGX_CR_PBE_PERF,                  RGX_CR_PBE_PERF_SELECT0,            RGX_CR_PBE_PERF_COUNTER_0,            4,              RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER, 21,          3,  "RGX_CR_PBE_PERF",             rgxfw_hwperf_pow_st_indirect, rgx_hwperf_blk_present_s7top },
+#else
     RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_PBE0),
 #endif
-};
 
-/* Length of the array used to hold the block type model table */
-IMG_INTERNAL const IMG_UINT32 gasCntBlkModelLen = sizeof(gasCntBlkTypeModel)/sizeof(gasCntBlkTypeModel[0]);
+    /*RGX_CNTBLK_ID_BX_TU0*/
+    /* Conditional for rgxsrvinit.c UM build where CR defs not unconditional in any context and multi BVNC is not operational */
+#if defined (RGX_FEATURE_RAY_TRACING) || defined(__KERNEL__)
+    {RGX_CNTBLK_ID_BX_TU0, RGX_CR_BX_TU_PERF_INDIRECT,       DPX_CR_BX_TU_PERF,           DPX_CR_BX_TU_PERF_SELECT0,        DPX_CR_BX_TU_PERF_COUNTER_0,          4,              RGX_HWPERF_DOPPLER_BX_TU_BLKS,          21,          3,  "RGX_CR_BX_TU_PERF",           rgxfw_hwperf_pow_st_gandalf,  rgx_hwperf_blk_present_raytracing },
+#else
+    RGXFW_HWPERF_CNTBLK_TYPE_UNSUPPORTED(RGX_CNTBLK_ID_BX_TU0),
+#endif
+	};
+
 
 IMG_INTERNAL IMG_UINT32
 RGXGetHWPerfBlockConfig(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL **ppsModel)
 {
 	*ppsModel = gasCntBlkTypeModel;
-	return gasCntBlkModelLen;
+	return IMG_ARR_NUM_ELEMS(gasCntBlkTypeModel);
 }
 
+/******************************************************************************
+ End of file (rgx_hwperf_table.c)
+******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgx_hwperf_table.h b/drivers/staging/imgtec/rogue/rgx_hwperf_table.h
index 6f28cf1..167349b 100644
--- a/drivers/staging/imgtec/rogue/rgx_hwperf_table.h
+++ b/drivers/staging/imgtec/rogue/rgx_hwperf_table.h
@@ -48,6 +48,60 @@
 #include "img_types.h"
 #include "rgx_fwif_hwperf.h"
 
+
+/*****************************************************************************/
+
+/* Forward declaration */
+typedef struct _RGXFW_HWPERF_CNTBLK_TYPE_MODEL_ RGXFW_HWPERF_CNTBLK_TYPE_MODEL;
+
+/* Function pointer type for functions to check dynamic power state of
+ * counter block instance. Used only in firmware. */
+typedef IMG_BOOL (*PFN_RGXFW_HWPERF_CNTBLK_POWERED)(
+		RGX_HWPERF_CNTBLK_ID eBlkType,
+		IMG_UINT8 ui8UnitId);
+
+/* Counter block run-time info */
+typedef struct _RGX_HWPERF_CNTBLK_RT_INFO_
+{
+	IMG_UINT32 uiBitSelectPreserveMask; /* Select register bits to preserve on programming, HW_ERN_41805 */
+	IMG_UINT32 uiNumUnits;              /* Number of instances of this block type in the core */
+} RGX_HWPERF_CNTBLK_RT_INFO;
+
+/* Function pointer type for functions to check block is valid and present
+ * on that RGX Device at runtime. It may have compile logic or run-time
+ * logic depending on where the code executes: server, srvinit or firmware.
+ * Values in the psRtInfo output parameter are only valid if true returned. */
+typedef IMG_BOOL (*PFN_RGXFW_HWPERF_CNTBLK_PRESENT)(
+		const struct _RGXFW_HWPERF_CNTBLK_TYPE_MODEL_* psBlkTypeDesc,
+		void *pvDev_km,
+		RGX_HWPERF_CNTBLK_RT_INFO *psRtInfo);
+
+/* This structure encodes properties of a type of performance counter block.
+ * The structure is sometimes referred to as a block type descriptor. These
+ * properties contained in this structure represent the columns in the
+ * block type model table variable below. There values vary depending on
+ * the build BVNC and core type.
+ * Each direct block has a unique type descriptor and each indirect group has
+ * a type descriptor. */
+struct _RGXFW_HWPERF_CNTBLK_TYPE_MODEL_
+{
+	/* Could use RGXFW_ALIGN_DCACHEL here but then we would waste 40% of the cache line? */
+	IMG_UINT32 uiCntBlkIdBase;         /* The starting block id for this block type */
+	IMG_UINT32 uiIndirectReg;          /* 0 if direct type otherwise the indirect control register to select indirect unit */
+	IMG_UINT32 uiPerfReg;              /* RGX_CR_*_PERF register for this block type */
+	IMG_UINT32 uiSelect0BaseReg;       /* RGX_CR_*_PERF_SELECT0 register for this block type */
+	IMG_UINT32 uiCounter0BaseReg;      /* RGX_CR_*_PERF_COUNTER_0 register for this block type */
+	IMG_UINT8  uiNumCounters;          /* Number of counters in this block type */
+	IMG_UINT8  uiNumUnits;             /* Number of instances of this block type in the core */
+	IMG_UINT8  uiSelectRegModeShift;   /* Mode field shift value of select registers */
+	IMG_UINT8  uiSelectRegOffsetShift; /* Interval between select registers, either 8 bytes or 16, hence << 3 or << 4 */
+	IMG_CHAR   pszBlockNameComment[30];              /* Name of the PERF register. Used while dumping the perf counters to pdumps */
+	PFN_RGXFW_HWPERF_CNTBLK_POWERED pfnIsBlkPowered; /* A function to determine dynamic power state for the block type */
+	PFN_RGXFW_HWPERF_CNTBLK_PRESENT pfnIsBlkPresent; /* A function to determine presence on RGX Device at run-time */
+};
+
+/*****************************************************************************/
+
 IMG_INTERNAL IMG_UINT32 RGXGetHWPerfBlockConfig(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL **ppsModel);
 
 
@@ -56,4 +110,3 @@
 /******************************************************************************
  End of file (rgx_hwperf_table.h)
 ******************************************************************************/
-
diff --git a/drivers/staging/imgtec/rogue/rgx_meta.h b/drivers/staging/imgtec/rogue/rgx_meta.h
index 0abefb1..a092449 100644
--- a/drivers/staging/imgtec/rogue/rgx_meta.h
+++ b/drivers/staging/imgtec/rogue/rgx_meta.h
@@ -214,62 +214,67 @@
 #define RGX_META_LDR_CFG_MEMSET			(0x0003)
 #define RGX_META_LDR_CFG_MEMCHECK		(0x0004)
 
+
 /************************************************************************
 * RGX FW segmented MMU definitions
 ************************************************************************/
 /* All threads can access the segment */
 #define RGXFW_SEGMMU_ALLTHRS	(0xf << 8)
-/* Writeable */
+/* Writable */
 #define RGXFW_SEGMMU_WRITEABLE	(0x1 << 1)
-/* All threads can access and writeable */
+/* All threads can access and writable */
 #define RGXFW_SEGMMU_ALLTHRS_WRITEABLE	(RGXFW_SEGMMU_ALLTHRS | RGXFW_SEGMMU_WRITEABLE)
 
-/* Direct map regions mapping (8-10) */
-#define RGXFW_SEGMMU_DMAP_ID_START			(8)
-#define RGXFW_SEGMMU_DMAP_ADDR_START		(0x06000000U)
-#define RGXFW_SEGMMU_DMAP_ADDR_META			(0x06000000U)
-#define RGXFW_SEGMMU_DMAP_SIZE				(8*1024*1024) /* 8 MB */
-
 /* Direct map region 11 used for mapping GPU memory */
 #define RGXFW_SEGMMU_DMAP_GPU_ID			(11)
-#define RGXFW_SEGMMU_DMAP_GPU_ADDR_START	(RGXFW_SEGMMU_DMAP_ADDR_START + 3*RGXFW_SEGMMU_DMAP_SIZE)
+#define RGXFW_SEGMMU_DMAP_GPU_ADDR_START	(0x07800000U)
 
 /* Segment IDs */
-#define RGXFW_SEGMMU_TEXT_ID			(0)
-#define RGXFW_SEGMMU_SHARED_ID			(1)
+#define RGXFW_SEGMMU_DATA_ID			(1)
 #define RGXFW_SEGMMU_BOOTLDR_ID			(2)
-#define RGXFW_SEGMMU_DATA_ID			(3)
+#define RGXFW_SEGMMU_TEXT_ID			(RGXFW_SEGMMU_BOOTLDR_ID)
 
 #define RGXFW_SEGMMU_META_DM_ID			(0x7)
 
-#if defined(HW_ERN_45914)
-/* SLC caching strategy is emitted through the segment MMU. All the segments configured 
-   through this macro are CACHED in the SLC. The interface has been kept the same to 
-   simplify the code changes. The bifdm argument is ignored (no longer relevant). */
-#if defined(HW_ERN_49144)
-#define RGXFW_SEGMMU_OUTADDR_TOP_S7(pers, coheren, mmu_ctx)     ( (((IMG_UINT64) ((pers)    & 0x3))  << 50) | \
-                                                                  (((IMG_UINT64) ((mmu_ctx) & 0xFF)) << 42) | \
-                                                                  (((IMG_UINT64) ((coheren) & 0x1))  << 40) )
-#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED(mmu_ctx)         RGXFW_SEGMMU_OUTADDR_TOP_S7(0x3, 0x0, mmu_ctx)
-#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED(mmu_ctx)       RGXFW_SEGMMU_OUTADDR_TOP_S7(0x0, 0x1, mmu_ctx)
 
+/*
+ * SLC caching strategy in S7 is emitted through the segment MMU. All the segments
+ * configured through the macro RGXFW_SEGMMU_OUTADDR_TOP are CACHED in the SLC.
+ * The interface has been kept the same to simplify the code changes.
+ * The bifdm argument is ignored (no longer relevant) in S7.
+ */
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_ERN_49144(pers, coheren, mmu_ctx)  ( (((IMG_UINT64) ((pers)    & 0x3))  << 50) | \
+                                                                         (((IMG_UINT64) ((mmu_ctx) & 0xFF)) << 42) | \
+                                                                         (((IMG_UINT64) ((coheren) & 0x1))  << 40) )
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED_ERN_49144(mmu_ctx)      RGXFW_SEGMMU_OUTADDR_TOP_S7_ERN_49144(0x3, 0x0, mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED_ERN_49144(mmu_ctx)    RGXFW_SEGMMU_OUTADDR_TOP_S7_ERN_49144(0x0, 0x1, mmu_ctx)
 /* Set FW code/data cached in the SLC as default */
-#define RGXFW_SEGMMU_OUTADDR_TOP(mmu_ctx, bifdm)                RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED(mmu_ctx | (bifdm&0x0))
-#else
-#define RGXFW_SEGMMU_OUTADDR_TOP_S7(pers, coheren, mmu_ctx)     ( (((IMG_UINT64) ((pers)    & 0x3))  << 52) | \
-                                                                  (((IMG_UINT64) ((mmu_ctx) & 0xFF)) << 44) | \
-                                                                  (((IMG_UINT64) ((coheren) & 0x1))  << 40) )
-#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED(mmu_ctx)         RGXFW_SEGMMU_OUTADDR_TOP_S7(0x3, 0x0, mmu_ctx)
-#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED(mmu_ctx)       RGXFW_SEGMMU_OUTADDR_TOP_S7(0x0, 0x1, mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP_ERN_49144(mmu_ctx, bifdm)             RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED_ERN_49144(mmu_ctx | (bifdm&0x0))
 
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_ERN_45914(pers, coheren, mmu_ctx)  ( (((IMG_UINT64) ((pers)    & 0x3))  << 52) | \
+                                                                         (((IMG_UINT64) ((mmu_ctx) & 0xFF)) << 44) | \
+                                                                         (((IMG_UINT64) ((coheren) & 0x1))  << 40) )
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED_ERN_45914(mmu_ctx)      RGXFW_SEGMMU_OUTADDR_TOP_S7_ERN_45914(0x3, 0x0, mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED_ERN_45914(mmu_ctx)    RGXFW_SEGMMU_OUTADDR_TOP_S7_ERN_45914(0x0, 0x1, mmu_ctx)
 /* Set FW code/data cached in the SLC as default */
-#define RGXFW_SEGMMU_OUTADDR_TOP(mmu_ctx, bifdm)                RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED(mmu_ctx | (bifdm&0x0))
-#endif
-#else
+#define RGXFW_SEGMMU_OUTADDR_TOP_ERN_45914(mmu_ctx, bifdm)             RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED_ERN_45914(mmu_ctx | (bifdm&0x0))
+
 /* To configure the Page Catalog and BIF-DM fed into the BIF for Garten accesses through this segment */
-#define RGXFW_SEGMMU_OUTADDR_TOP(pc, bifdm)			            ( (((IMG_UINT64) ((pc)    & 0xF)) << 44) | \
+#define RGXFW_SEGMMU_OUTADDR_TOP_PRE_S7(pc, bifdm)              ( (((IMG_UINT64) ((pc)    & 0xF)) << 44) | \
                                                                   (((IMG_UINT64) ((bifdm) & 0xF)) << 40) )
+
+#if !defined(__KERNEL__) && defined(RGX_FEATURE_META)
+#if defined(HW_ERN_49144)
+#define RGXFW_SEGMMU_OUTADDR_TOP                  RGXFW_SEGMMU_OUTADDR_TOP_ERN_49144
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED  RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED_ERN_49144
+#elif defined(HW_ERN_45914)
+#define RGXFW_SEGMMU_OUTADDR_TOP                  RGXFW_SEGMMU_OUTADDR_TOP_ERN_45914
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED  RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED_ERN_45914
+#else
+#define RGXFW_SEGMMU_OUTADDR_TOP                  RGXFW_SEGMMU_OUTADDR_TOP_PRE_S7
 #endif
+#endif
+
 
 /* META segments have 4kB minimum size */
 #define RGXFW_SEGMMU_ALIGN			(0x1000) 
@@ -280,9 +285,39 @@
 #define META_CR_MMCU_SEGMENTn_OUTA0(n)			(0x04850008 + (n)*0x10)
 #define META_CR_MMCU_SEGMENTn_OUTA1(n)			(0x0485000C + (n)*0x10)
 
-/* Win mode for data cache */
-#define RGXFW__SEGMMU_DMAP_DC_WIN (0x3)
-#define RGXFW__SEGMMU_DMAP_DC_SHIFT (0x6)
+/* The following defines must be recalculated if the Meta MMU segments
+ * used to access Host-FW data are changed
+ * Current combinations are:
+ * - SLC uncached, META cached,   FW base address 0x70000000
+ * - SLC uncached, META uncached, FW base address 0xF0000000
+ * - SLC cached,   META cached,   FW base address 0x10000000
+ * - SLC cached,   META uncached, FW base address 0x90000000
+ */
+#define RGXFW_SEGMMU_DATA_BASE_ADDRESS        (0x10000000)
+#define RGXFW_SEGMMU_DATA_META_CACHED         (0x0)
+#define RGXFW_SEGMMU_DATA_META_UNCACHED       (META_MEM_GLOBAL_RANGE_BIT) // 0x80000000
+#define RGXFW_SEGMMU_DATA_META_CACHE_MASK     (META_MEM_GLOBAL_RANGE_BIT)
+/* For non-VIVT SLCs the cacheability of the FW data in the SLC is selected
+ * in the PTEs for the FW data, not in the Meta Segment MMU,
+ * which means these defines have no real effect in those cases */
+#define RGXFW_SEGMMU_DATA_VIVT_SLC_CACHED     (0x0)
+#define RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED   (0x60000000)
+#define RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK (0x60000000)
+
+
+/************************************************************************
+* RGX FW RGX MMU definitions
+************************************************************************/
+#if defined(RGX_FEATURE_SLC_VIVT) && defined(SUPPORT_TRUSTED_DEVICE)
+
+#define META_MMU_CONTEXT_MAPPING        (0x1) /* fw data */
+#define META_MMU_CONTEXT_MAPPING_CODE   (0x0) /* fw code */
+
+#else 
+
+#define META_MMU_CONTEXT_MAPPING       (0x0)
+
+#endif 
 
 /************************************************************************
 * RGX FW Bootloader defaults
@@ -297,13 +332,6 @@
 #define RGXFW_BOOTLDR_CONF_OFFSET	(0x80)
 
 
-/* Firmware to host interrupts defines */
-#define RGXFW_CR_IRQ_STATUS           RGX_CR_META_SP_MSLVIRQSTATUS
-#define RGXFW_CR_IRQ_STATUS_EVENT_EN  RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN
-#define RGXFW_CR_IRQ_CLEAR            RGX_CR_META_SP_MSLVIRQSTATUS
-#define RGXFW_CR_IRQ_CLEAR_MASK       RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK
-
-
 /************************************************************************
 * RGX META Stack
 ************************************************************************/
@@ -312,16 +340,29 @@
 /************************************************************************
 * RGX META Core memory
 ************************************************************************/
-#define RGX_META_COREMEM_BSS_SIZE    (0xA00)
-
-#if defined(RGX_FEATURE_META_DMA)
-	#define RGX_META_COREMEM_CCBBUF_SIZE (0x2A0)
-	#define RGX_META_COREMEM_DATA_SIZE   (RGX_META_COREMEM_CCBBUF_SIZE + RGX_META_COREMEM_BSS_SIZE + RGX_META_STACK_SIZE)
+#if defined(RGXFW_META_SUPPORT_2ND_THREAD)
+	#define RGX_META_COREMEM_STACK_SIZE  (RGX_META_STACK_SIZE*2)
+	#define RGX_META_COREMEM_BSS_SIZE    (0xF40)
+	#if defined(RGX_FEATURE_META_DMA)
+		#define RGX_META_COREMEM_CCBBUF_SIZE (0x3C0)
+		#define RGX_META_COREMEM_DATA_SIZE   (RGX_META_COREMEM_CCBBUF_SIZE + RGX_META_COREMEM_BSS_SIZE + RGX_META_COREMEM_STACK_SIZE)
+	#else
+		#define RGX_META_COREMEM_DATA_SIZE   (RGX_META_COREMEM_BSS_SIZE + RGX_META_COREMEM_STACK_SIZE)
+	#endif
 #else
-	#define RGX_META_COREMEM_DATA_SIZE   (RGX_META_COREMEM_BSS_SIZE + RGX_META_STACK_SIZE)
+	#define RGX_META_COREMEM_STACK_SIZE  (RGX_META_STACK_SIZE)
+	#define RGX_META_COREMEM_BSS_SIZE    (0xB00)
+	#if defined(RGX_FEATURE_META_DMA)
+		#define RGX_META_COREMEM_CCBBUF_SIZE (0x3C0)
+		#define RGX_META_COREMEM_DATA_SIZE   (RGX_META_COREMEM_CCBBUF_SIZE + RGX_META_COREMEM_BSS_SIZE + RGX_META_COREMEM_STACK_SIZE)
+	#else
+		#define RGX_META_COREMEM_DATA_SIZE   (RGX_META_COREMEM_BSS_SIZE + RGX_META_COREMEM_STACK_SIZE)
+	#endif
 #endif
 
+#if defined (RGX_META_COREMEM_CODE)
 #define RGX_META_COREMEM_CODE_SIZE   (RGX_META_COREMEM_SIZE - RGX_META_COREMEM_DATA_SIZE)
+#endif
 
 /* code and data both map to the same physical memory */
 #define RGX_META_COREMEM_CODE_ADDR   (0x80000000)
@@ -329,16 +370,21 @@
 /* because data and code share the same memory, base address for code is offset by the data */
 #define RGX_META_COREMEM_CODE_BADDR  (RGX_META_COREMEM_CODE_ADDR + RGX_META_COREMEM_DATA_SIZE)
 
-#define RGX_META_COREMEM_STACK_ADDR  (RGX_META_COREMEM_DATA_ADDR)
-#define RGX_META_COREMEM_BSS_ADDR    (RGX_META_COREMEM_STACK_ADDR + RGX_META_STACK_SIZE)
+#if defined(RGXFW_META_SUPPORT_2ND_THREAD)
+	#define RGX_META_COREMEM_STACK_ADDR      (RGX_META_COREMEM_DATA_ADDR)
+	#define RGX_META_COREMEM_2ND_STACK_ADDR  (RGX_META_COREMEM_DATA_ADDR + RGX_META_STACK_SIZE)
+	#define RGX_META_COREMEM_BSS_ADDR        (RGX_META_COREMEM_2ND_STACK_ADDR + RGX_META_STACK_SIZE)
+#else
+	#define RGX_META_COREMEM_STACK_ADDR      (RGX_META_COREMEM_DATA_ADDR)
+	#define RGX_META_COREMEM_BSS_ADDR        (RGX_META_COREMEM_STACK_ADDR + RGX_META_STACK_SIZE)
+#endif
 
 #if defined(RGX_FEATURE_META_DMA)
 	#define RGX_META_COREMEM_CCBBUF_ADDR (RGX_META_COREMEM_BSS_ADDR + RGX_META_COREMEM_BSS_SIZE)
 #endif
 
-#define RGX_META_IS_COREMEM_CODE(A)  (((A) >= RGX_META_COREMEM_CODE_BADDR) && ((A) < (RGX_META_COREMEM_CODE_ADDR + RGX_META_COREMEM_SIZE)))
-#define RGX_META_IS_COREMEM_DATA(A)  (((A) >= RGX_META_COREMEM_DATA_ADDR) && ((A) < (RGX_META_COREMEM_DATA_ADDR + RGX_META_COREMEM_DATA_SIZE)))
-
+#define RGX_META_IS_COREMEM_CODE(A, B)  (((A) >= RGX_META_COREMEM_CODE_ADDR) && ((A) < (RGX_META_COREMEM_CODE_ADDR + (B))))
+#define RGX_META_IS_COREMEM_DATA(A, B)  (((A) >= RGX_META_COREMEM_DATA_ADDR) && ((A) < (RGX_META_COREMEM_DATA_ADDR + (B))))
 
 /************************************************************************
 * 2nd thread
@@ -354,30 +400,28 @@
 #define META_CR_CORE_ID_VER_SHIFT	(16U)
 #define META_CR_CORE_ID_VER_CLRMSK	(0XFF00FFFFU)
 
-#if (RGX_FEATURE_META == MTP218)
-#define RGX_CR_META_CORE_ID_VALUE 0x19
-#elif (RGX_FEATURE_META == MTP219)
-#define RGX_CR_META_CORE_ID_VALUE 0x1E
-#elif (RGX_FEATURE_META == LTP218)
-#define RGX_CR_META_CORE_ID_VALUE 0x1C
-#elif (RGX_FEATURE_META == LTP217)
-#define RGX_CR_META_CORE_ID_VALUE 0x1F
+#if !defined(__KERNEL__) && defined(RGX_FEATURE_META)
+
+	#if (RGX_FEATURE_META == MTP218)
+	#define RGX_CR_META_CORE_ID_VALUE 0x19
+	#elif (RGX_FEATURE_META == MTP219)
+	#define RGX_CR_META_CORE_ID_VALUE 0x1E
+	#elif (RGX_FEATURE_META == LTP218)
+	#define RGX_CR_META_CORE_ID_VALUE 0x1C
+	#elif (RGX_FEATURE_META == LTP217)
+	#define RGX_CR_META_CORE_ID_VALUE 0x1F
+	#else
+	#error "Unknown META ID"
+	#endif
 #else
-#error "Unknown META ID"
+
+	#define RGX_CR_META_MTP218_CORE_ID_VALUE 0x19
+	#define RGX_CR_META_MTP219_CORE_ID_VALUE 0x1E
+	#define RGX_CR_META_LTP218_CORE_ID_VALUE 0x1C
+	#define RGX_CR_META_LTP217_CORE_ID_VALUE 0x1F
+
 #endif
-
-#define FW_CORE_ID_VALUE	    RGX_CR_META_CORE_ID_VALUE
-#define RGXFW_PROCESSOR             "META"
-
-
-typedef enum
-{
-	FW_PERF_CONF_NONE = 0,
-	FW_PERF_CONF_ICACHE = 1,
-	FW_PERF_CONF_DCACHE = 2,
-	FW_PERF_CONF_POLLS = 3,
-	FW_PERF_CONF_CUSTOM_TIMER = 4
-} FW_PERF_CONF;
+#define RGXFW_PROCESSOR_META        "META"
 
 
 #endif /*  __RGX_META_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgx_mips.h b/drivers/staging/imgtec/rogue/rgx_mips.h
new file mode 100644
index 0000000..7548d58
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgx_mips.h
@@ -0,0 +1,398 @@
+/*************************************************************************/ /*!
+@File           rgx_mips.h
+@Title
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Platform       RGX
+@Description    RGX MIPS definitions, user space
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__RGX_MIPS_H__)
+#define __RGX_MIPS_H__
+
+/*
+ * Utility defines for memory management
+ */
+#define RGXMIPSFW_LOG2_PAGE_SIZE                 (12)
+#define RGXMIPSFW_LOG2_PAGE_SIZE_64K             (16)
+/* Page size */
+#define RGXMIPSFW_PAGE_SIZE                      (0x1 << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_PAGE_MASK                      (RGXMIPSFW_PAGE_SIZE - 1)
+#define RGXMIPSFW_LOG2_PAGETABLE_PAGE_SIZE       (15)
+#define RGXMIPSFW_LOG2_PTE_ENTRY_SIZE            (2)
+/* Page mask MIPS register setting for bigger pages */
+#define RGXMIPSFW_PAGE_MASK_16K                  (0x00007800)
+#define RGXMIPSFW_PAGE_MASK_64K                  (0x0001F800)
+/* Page Frame Number of the entry lo */
+#define RGXMIPSFW_ENTRYLO_PFN_MASK               (0x03FFFFC0)
+#define RGXMIPSFW_ENTRYLO_PFN_SHIFT              (6)
+/* Dirty Valid And Global bits in entry lo */
+#define RGXMIPSFW_ENTRYLO_DVG_MASK               (0x00000007)
+/* Dirty Valid And Global bits + caching policy in entry lo */
+#define RGXMIPSFW_ENTRYLO_DVGC_MASK              (0x0000003F)
+/* Total number of TLB entries */
+#define RGXMIPSFW_NUMBER_OF_TLB_ENTRIES          (16)
+
+
+/*
+ * Firmware physical layout
+ */
+#define RGXMIPSFW_CODE_BASE_PAGE                 (0x0)
+#define RGXMIPSFW_CODE_OFFSET                    (RGXMIPSFW_CODE_BASE_PAGE << RGXMIPSFW_LOG2_PAGE_SIZE)
+#if defined(SUPPORT_TRUSTED_DEVICE)
+/* Clean way of getting a 256K allocation (62 + 1 + 1 pages) without using too many ifdefs */
+/* This will need to be changed if the non-secure builds reach this amount of pages */
+#define RGXMIPSFW_CODE_NUMPAGES                  (62)
+#else
+#define RGXMIPSFW_CODE_NUMPAGES                  (40)
+#endif
+#define RGXMIPSFW_CODE_SIZE                      (RGXMIPSFW_CODE_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+
+#define RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE    (RGXMIPSFW_CODE_BASE_PAGE + RGXMIPSFW_CODE_NUMPAGES)
+#define RGXMIPSFW_EXCEPTIONSVECTORS_OFFSET       (RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_EXCEPTIONSVECTORS_NUMPAGES     (1)
+#define RGXMIPSFW_EXCEPTIONSVECTORS_SIZE         (RGXMIPSFW_EXCEPTIONSVECTORS_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+
+#define RGXMIPSFW_BOOT_NMI_CODE_BASE_PAGE        (RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE + RGXMIPSFW_EXCEPTIONSVECTORS_NUMPAGES)
+#define RGXMIPSFW_BOOT_NMI_CODE_OFFSET           (RGXMIPSFW_BOOT_NMI_CODE_BASE_PAGE << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_BOOT_NMI_CODE_NUMPAGES         (1)
+#define RGXMIPSFW_BOOT_NMI_CODE_SIZE             (RGXMIPSFW_BOOT_NMI_CODE_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+
+
+#define RGXMIPSFW_DATA_BASE_PAGE                 (0x0)
+#define RGXMIPSFW_DATA_OFFSET                    (RGXMIPSFW_DATA_BASE_PAGE << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_DATA_NUMPAGES                  (22)
+#define RGXMIPSFW_DATA_SIZE                      (RGXMIPSFW_DATA_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+
+#define RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE        (RGXMIPSFW_DATA_BASE_PAGE + RGXMIPSFW_DATA_NUMPAGES)
+#define RGXMIPSFW_BOOT_NMI_DATA_OFFSET           (RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_BOOT_NMI_DATA_NUMPAGES         (1)
+#define RGXMIPSFW_BOOT_NMI_DATA_SIZE             (RGXMIPSFW_BOOT_NMI_DATA_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+
+#define RGXMIPSFW_STACK_BASE_PAGE                (RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE + RGXMIPSFW_BOOT_NMI_DATA_NUMPAGES)
+#define RGXMIPSFW_STACK_OFFSET                   (RGXMIPSFW_STACK_BASE_PAGE << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_STACK_NUMPAGES                 (1)
+#define RGXMIPSFW_STACK_SIZE                     (RGXMIPSFW_STACK_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+
+/*
+ * Pages to trampoline problematic physical addresses:
+ *   - RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN : 0x1FC0_0000
+ *   - RGXMIPSFW_DATA_REMAP_PHYS_ADDR_IN : 0x1FC0_1000
+ *   - RGXMIPSFW_CODE_REMAP_PHYS_ADDR_IN : 0x1FC0_2000
+ *   - (benign trampoline)               : 0x1FC0_3000
+ * that would otherwise be erroneously remapped by the MIPS wrapper
+ * (see "Firmware virtual layout and remap configuration" section below)
+ */
+
+#define RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES       (2)
+#define RGXMIPSFW_TRAMPOLINE_NUMPAGES            (1 << RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
+#define RGXMIPSFW_TRAMPOLINE_SIZE                (RGXMIPSFW_TRAMPOLINE_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE)
+#define RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE   (RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES + RGXMIPSFW_LOG2_PAGE_SIZE)
+
+#define RGXMIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR    (RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
+#define RGXMIPSFW_TRAMPOLINE_OFFSET(a)           (a - RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
+
+#define RGXMIPSFW_SENSITIVE_ADDR(a)              (RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN == (~((1<<RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE)-1) & a))
+
+/*
+ * Firmware virtual layout and remap configuration
+ */
+/*
+ * For each remap region we define:
+ * - the virtual base used by the Firmware to access code/data through that region
+ * - the microAptivAP physical address correspondent to the virtual base address,
+ *   used as input address and remapped to the actual physical address
+ * - log2 of size of the region remapped by the MIPS wrapper, i.e. number of bits from
+ *   the bottom of the base input address that survive onto the output address
+ *   (this defines both the alignment and the maximum size of the remapped region)
+ * - one or more code/data segments within the remapped region
+ */
+
+/* Boot remap setup */
+#define RGXMIPSFW_BOOT_REMAP_VIRTUAL_BASE        (0xBFC00000)
+#define RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN        (0x1FC00000)
+#define RGXMIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE   (12)
+#define RGXMIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE     (RGXMIPSFW_BOOT_REMAP_VIRTUAL_BASE)
+
+/* Data remap setup */
+#define RGXMIPSFW_DATA_REMAP_VIRTUAL_BASE        (0xBFC01000)
+#define RGXMIPSFW_DATA_REMAP_PHYS_ADDR_IN        (0x1FC01000)
+#define RGXMIPSFW_DATA_REMAP_LOG2_SEGMENT_SIZE   (12)
+#define RGXMIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE     (RGXMIPSFW_DATA_REMAP_VIRTUAL_BASE)
+
+/* Code remap setup */
+#define RGXMIPSFW_CODE_REMAP_VIRTUAL_BASE        (0x9FC02000)
+#define RGXMIPSFW_CODE_REMAP_PHYS_ADDR_IN        (0x1FC02000)
+#define RGXMIPSFW_CODE_REMAP_LOG2_SEGMENT_SIZE   (12)
+#define RGXMIPSFW_EXCEPTIONS_VIRTUAL_BASE        (RGXMIPSFW_CODE_REMAP_VIRTUAL_BASE)
+
+/* Fixed TLB setup */
+#define RGXMIPSFW_PT_VIRTUAL_BASE                (0xCF000000)
+#define RGXMIPSFW_REGISTERS_VIRTUAL_BASE         (0xCF400000)
+#define RGXMIPSFW_STACK_VIRTUAL_BASE             (0xCF600000)
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+/* The extra fixed TLB entries are used in security builds for the FW code */
+#define RGXMIPSFW_NUMBER_OF_RESERVED_TLB         (5)
+#else
+#define RGXMIPSFW_NUMBER_OF_RESERVED_TLB         (3)
+#endif
+
+/* Firmware heap setup */
+#define RGXMIPSFW_FIRMWARE_HEAP_BASE             (0xC0000000)
+#define RGXMIPSFW_CODE_VIRTUAL_BASE              (RGXMIPSFW_FIRMWARE_HEAP_BASE)
+/* The data virtual base takes into account the exception vectors page
+ * and the boot code page mapped in the FW heap together with the FW code
+ * (we can only map Firmware code allocation as a whole) */
+#define RGXMIPSFW_DATA_VIRTUAL_BASE              (RGXMIPSFW_CODE_VIRTUAL_BASE + RGXMIPSFW_CODE_SIZE + \
+                                                  RGXMIPSFW_EXCEPTIONSVECTORS_SIZE + RGXMIPSFW_BOOT_NMI_CODE_SIZE)
+
+
+/*
+ * Bootloader configuration data
+ */
+/* Bootloader configuration offset within the bootloader/NMI data page */
+#define RGXMIPSFW_BOOTLDR_CONF_OFFSET                         (0x0)
+/* Offsets of bootloader configuration parameters in 64-bit words */
+#define RGXMIPSFW_ROGUE_REGS_BASE_PHYADDR_OFFSET              (0x0)
+#define RGXMIPSFW_PAGE_TABLE_BASE_PHYADDR_OFFSET              (0x1)
+#define RGXMIPSFW_STACKPOINTER_PHYADDR_OFFSET                 (0x2)
+#define RGXMIPSFW_RESERVED_FUTURE_OFFSET                      (0x3)
+#define RGXMIPSFW_FWINIT_VIRTADDR_OFFSET                      (0x4)
+
+/*
+ * MIPS Fence offset in the bootloader/NMI data page
+ */
+#define RGXMIPSFW_FENCE_OFFSET                                (0x80)
+
+/*
+ * NMI shared data
+ */
+/* Base address of the shared data within the bootloader/NMI data page */
+#define RGXMIPSFW_NMI_SHARED_DATA_BASE                        (0x100)
+/* Size used by Debug dump data */
+#define RGXMIPSFW_NMI_SHARED_SIZE                             (0x128)
+/* Offsets in the NMI shared area in 32-bit words */
+#define RGXMIPSFW_NMI_SYNC_FLAG_OFFSET                        (0x0)
+#define RGXMIPSFW_NMI_STATE_OFFSET                            (0x1)
+
+/*
+ * MIPS fault data
+ */
+/* Base address of the fault data within the bootloader/NMI data page */
+#define RGXMIPSFW_FAULT_DATA_BASE                             (0x280)
+
+/* The things that follow are excluded when compiling assembly sources*/
+#if !defined (RGXMIPSFW_ASSEMBLY_CODE)
+#include "img_types.h"
+#include "km/rgxdefs_km.h"
+
+#define RGXMIPSFW_GET_OFFSET_IN_DWORDS(offset)                (offset / sizeof(IMG_UINT32))
+#define RGXMIPSFW_GET_OFFSET_IN_QWORDS(offset)                (offset / sizeof(IMG_UINT64))
+
+/* Used for compatibility checks */
+#define RGXMIPSFW_ARCHTYPE_VER_CLRMSK                         (0xFFFFE3FFU)
+#define RGXMIPSFW_ARCHTYPE_VER_SHIFT                          (10U)
+#define RGXMIPSFW_CORE_ID_VALUE                               (0x001U)
+#define RGXFW_PROCESSOR_MIPS		                          "MIPS"
+
+/* microAptivAP cache line size */
+#define RGXMIPSFW_MICROAPTIVEAP_CACHELINE_SIZE                (16U)
+
+/* The SOCIF transactions are identified with the top 16 bits of the physical address emitted by the MIPS */
+#define RGXMIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN           (16U)
+
+/* Values to put in the MIPS selectors for performance counters*/
+#define RGXMIPSFW_PERF_COUNT_CTRL_ICACHE_ACCESSES_C0          (9U)   /* Icache accesses in COUNTER0 */
+#define RGXMIPSFW_PERF_COUNT_CTRL_ICACHE_MISSES_C1            (9U)   /* Icache misses in COUNTER1 */
+
+#define RGXMIPSFW_PERF_COUNT_CTRL_DCACHE_ACCESSES_C0          (10U)  /* Dcache accesses in COUNTER0 */
+#define RGXMIPSFW_PERF_COUNT_CTRL_DCACHE_MISSES_C1            (11U) /* Dcache misses in COUNTER1 */
+
+#define RGXMIPSFW_PERF_COUNT_CTRL_ITLB_INSTR_ACCESSES_C0      (5U)  /* ITLB instruction accesses in COUNTER0 */
+#define RGXMIPSFW_PERF_COUNT_CTRL_JTLB_INSTR_MISSES_C1        (7U)  /* JTLB instruction accesses misses in COUNTER1 */
+
+#define RGXMIPSFW_PERF_COUNT_CTRL_INSTR_COMPLETED_C0          (1U)  /* Instructions completed in COUNTER0 */
+#define RGXMIPSFW_PERF_COUNT_CTRL_JTLB_DATA_MISSES_C1         (8U)  /* JTLB data misses in COUNTER1 */
+
+#define RGXMIPSFW_PERF_COUNT_CTRL_EVENT_SHIFT                 (5U)  /* Shift for the Event field in the MIPS perf ctrl registers */
+/* Additional flags for performance counters. See MIPS manual for further reference*/
+#define RGXMIPSFW_PERF_COUNT_CTRL_COUNT_USER_MODE             (8U)
+#define RGXMIPSFW_PERF_COUNT_CTRL_COUNT_KERNEL_MODE           (2U)
+#define RGXMIPSFW_PERF_COUNT_CTRL_COUNT_EXL                   (1U)
+
+
+#define RGXMIPSFW_C0_NBHWIRQ	8
+
+/* Macros to decode C0_Cause register */
+#define RGXMIPSFW_C0_CAUSE_EXCCODE(CAUSE)       (((CAUSE) & 0x7c) >> 2)
+/* Use only when Coprocessor Unusable exception */
+#define RGXMIPSFW_C0_CAUSE_UNUSABLE_UNIT(CAUSE) (((CAUSE) >> 28) & 0x3)
+#define RGXMIPSFW_C0_CAUSE_PENDING_HWIRQ(CAUSE) (((CAUSE) & 0x3fc00) >> 10)
+#define RGXMIPSFW_C0_CAUSE_FDCIPENDING          (1 << 21)
+#define RGXMIPSFW_C0_CAUSE_IV                   (1 << 23)
+#define RGXMIPSFW_C0_CAUSE_IC                   (1 << 25)
+#define RGXMIPSFW_C0_CAUSE_PCIPENDING           (1 << 26)
+#define RGXMIPSFW_C0_CAUSE_TIPENDING            (1 << 30)
+
+/* Macros to decode C0_Debug register */
+#define RGXMIPSFW_C0_DEBUG_EXCCODE(DEBUG) (((DEBUG) >> 10) & 0x1f)
+#define RGXMIPSFW_C0_DEBUG_DSS            (1 << 0)
+#define RGXMIPSFW_C0_DEBUG_DBP            (1 << 1)
+#define RGXMIPSFW_C0_DEBUG_DDBL           (1 << 2)
+#define RGXMIPSFW_C0_DEBUG_DDBS           (1 << 3)
+#define RGXMIPSFW_C0_DEBUG_DIB            (1 << 4)
+#define RGXMIPSFW_C0_DEBUG_DINT           (1 << 5)
+#define RGXMIPSFW_C0_DEBUG_DIBIMPR        (1 << 6)
+#define RGXMIPSFW_C0_DEBUG_DDBLIMPR       (1 << 18)
+#define RGXMIPSFW_C0_DEBUG_DDBSIMPR       (1 << 19)
+#define RGXMIPSFW_C0_DEBUG_IEXI           (1 << 20)
+#define RGXMIPSFW_C0_DEBUG_DBUSEP         (1 << 21)
+#define RGXMIPSFW_C0_DEBUG_CACHEEP        (1 << 22)
+#define RGXMIPSFW_C0_DEBUG_MCHECKP        (1 << 23)
+#define RGXMIPSFW_C0_DEBUG_IBUSEP         (1 << 24)
+#define RGXMIPSFW_C0_DEBUG_DM             (1 << 30)
+#define RGXMIPSFW_C0_DEBUG_DBD            (1 << 31)
+
+/* ELF format defines */
+#define ELF_PT_LOAD     (0x1U)   /* Program header identifier as Load */
+#define ELF_SHT_SYMTAB  (0x2U)   /* Section identifier as Symbol Table */
+#define ELF_SHT_STRTAB  (0x3U)   /* Section identifier as String Table */
+#define MAX_STRTAB_NUM  (0x8U)   /* Maximum number of string table in the firmware ELF file */
+
+
+/* Redefined structs of ELF format */
+typedef struct
+{
+	IMG_UINT8    ui32Eident[16];
+	IMG_UINT16   ui32Etype;
+	IMG_UINT16   ui32Emachine;
+	IMG_UINT32   ui32Eversion;
+	IMG_UINT32   ui32Eentry;
+	IMG_UINT32   ui32Ephoff;
+	IMG_UINT32   ui32Eshoff;
+	IMG_UINT32   ui32Eflags;
+	IMG_UINT16   ui32Eehsize;
+	IMG_UINT16   ui32Ephentsize;
+	IMG_UINT16   ui32Ephnum;
+	IMG_UINT16   ui32Eshentsize;
+	IMG_UINT16   ui32Eshnum;
+	IMG_UINT16   ui32Eshtrndx;
+} RGX_MIPS_ELF_HDR;
+
+
+typedef struct
+{
+	IMG_UINT32   ui32Stname;
+	IMG_UINT32   ui32Stvalue;
+	IMG_UINT32   ui32Stsize;
+	IMG_UINT8    ui32Stinfo;
+	IMG_UINT8    ui32Stother;
+	IMG_UINT16   ui32Stshndx;
+} RGX_MIPS_ELF_SYM;
+
+
+typedef struct
+{
+	IMG_UINT32   ui32Shname;
+	IMG_UINT32   ui32Shtype;
+	IMG_UINT32   ui32Shflags;
+	IMG_UINT32   ui32Shaddr;
+	IMG_UINT32   ui32Shoffset;
+	IMG_UINT32   ui32Shsize;
+	IMG_UINT32   ui32Shlink;
+	IMG_UINT32   ui32Shinfo;
+	IMG_UINT32   ui32Shaddralign;
+	IMG_UINT32   ui32Shentsize;
+} RGX_MIPS_ELF_SHDR;
+
+typedef struct
+{
+	IMG_UINT32   ui32Ptype;
+	IMG_UINT32   ui32Poffset;
+	IMG_UINT32   ui32Pvaddr;
+	IMG_UINT32   ui32Ppaddr;
+	IMG_UINT32   ui32Pfilesz;
+	IMG_UINT32   ui32Pmemsz;
+	IMG_UINT32   ui32Pflags;
+	IMG_UINT32   ui32Palign;
+ } RGX_MIPS_ELF_PROGRAM_HDR;
+
+#define RGXMIPSFW_TLB_GET_MASK(ENTRY_PAGE_MASK) (((ENTRY_PAGE_MASK) >> 13) & 0xffffU)
+#define RGXMIPSFW_TLB_GET_VPN2(ENTRY_HI)        ((ENTRY_HI) >> 13)
+#define RGXMIPSFW_TLB_GET_COHERENCY(ENTRY_LO)   (((ENTRY_LO) >> 3) & 0x7U)
+#define RGXMIPSFW_TLB_GET_PFN(ENTRY_LO)         (((ENTRY_LO) >> 6) & 0xfffffU)
+#define RGXMIPSFW_TLB_GET_INHIBIT(ENTRY_LO)     (((ENTRY_LO) >> 30) & 0x3U)
+#define RGXMIPSFW_TLB_GET_DGV(ENTRY_LO)         ((ENTRY_LO) & 0x7U)
+#define RGXMIPSFW_TLB_GLOBAL                    (1U)
+#define RGXMIPSFW_TLB_VALID                     (1U << 1)
+#define RGXMIPSFW_TLB_DIRTY                     (1U << 2)
+#define RGXMIPSFW_TLB_XI                        (1U << 30)
+#define RGXMIPSFW_TLB_RI                        (1U << 31)
+
+typedef struct {
+	IMG_UINT32 ui32TLBPageMask;
+	IMG_UINT32 ui32TLBHi;
+	IMG_UINT32 ui32TLBLo0;
+	IMG_UINT32 ui32TLBLo1;
+} RGX_MIPS_TLB_ENTRY;
+
+typedef struct {
+	IMG_UINT32 ui32ErrorEPC;
+	IMG_UINT32 ui32StatusRegister;
+	IMG_UINT32 ui32CauseRegister;
+	IMG_UINT32 ui32BadRegister;
+	IMG_UINT32 ui32EPC;
+	IMG_UINT32 ui32SP;
+	IMG_UINT32 ui32Debug;
+	IMG_UINT32 ui32DEPC;
+	IMG_UINT32 ui32BadInstr;
+	RGX_MIPS_TLB_ENTRY asTLB[RGXMIPSFW_NUMBER_OF_TLB_ENTRIES];
+} RGX_MIPS_STATE;
+
+typedef struct {
+	IMG_UINT32 ui32FaultPageEntryLo;
+	IMG_UINT32 ui32BadVAddr;
+	IMG_UINT32 ui32EntryLo0;
+	IMG_UINT32 ui32EntryLo1;
+} RGX_MIPS_FAULT_DATA;
+
+#endif  /* RGXMIPSFW_ASSEMBLY_CODE */
+
+
+#endif /*__RGX_MIPS_H__*/
diff --git a/drivers/staging/imgtec/rogue/rgx_options.h b/drivers/staging/imgtec/rogue/rgx_options.h
index e6f146d..d2708c2 100644
--- a/drivers/staging/imgtec/rogue/rgx_options.h
+++ b/drivers/staging/imgtec/rogue/rgx_options.h
@@ -41,21 +41,137 @@
 */ /**************************************************************************/
 
 /* Each build option listed here is packed into a dword which
- * provides up to (32 - log2(RGX_BUILD_OPTIONS_MASK_KM + 1)) flags.
- * The corresponding bit is set if the build option 
+ * provides up to log2(RGX_BUILD_OPTIONS_MASK_KM + 1) flags for KM 
+ * and (32 - log2(RGX_BUILD_OPTIONS_MASK_KM + 1)) flags for UM.
+ * The corresponding bit is set if the build option
  * was enabled at compile time.
  *
  * In order to extract the enabled build flags the INTERNAL_TEST
  * switch should be enabled in a client program which includes this
  * header. Then the client can test specific build flags by reading
- * the bit value at ##OPTIONNAME##_SET_OFFSET in RGX_BUILD_OPTIONS.
+ * the bit value at ##OPTIONNAME##_SET_OFFSET in RGX_BUILD_OPTIONS_KM 
+ * RGX_BUILD_OPTIONS.
  *
  * IMPORTANT: add new options to unused bits or define a new dword
- * (e.g. RGX_BUILD_OPTIONS2) so that the bitfield remains backwards
+ * (e.g. RGX_BUILD_OPTIONS_KM2 or RGX_BUILD_OPTIONS2) so that the bitfield 
+ * remains backwards
  * compatible.
  */
 
-#include "rgx_options_km.h"
+#define RGX_BUILD_OPTIONS_MASK_KM 0x0000FFFFUL
+
+#if defined(NO_HARDWARE) || defined (INTERNAL_TEST)
+	#define NO_HARDWARE_SET_OFFSET	OPTIONS_BIT0
+	#define OPTIONS_BIT0		(0x1ul << 0)
+	#if OPTIONS_BIT0 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT0		0x0
+#endif /* NO_HARDWARE */
+
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+	#define PDUMP_SET_OFFSET	OPTIONS_BIT1
+	#define OPTIONS_BIT1		(0x1ul << 1)
+	#if OPTIONS_BIT1 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT1		0x0
+#endif /* PDUMP */
+
+
+#if defined (INTERNAL_TEST)
+	#define UNUSED_SET_OFFSET	OPTIONS_BIT2
+	#define OPTIONS_BIT2		(0x1ul << 2)
+	#if OPTIONS_BIT2 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT2		0x0
+#endif /* SUPPORT_META_SLAVE_BOOT */
+
+
+#if defined(SUPPORT_MMU_FREELIST) || defined (INTERNAL_TEST)
+	#define SUPPORT_MMU_FREELIST_SET_OFFSET	OPTIONS_BIT3
+	#define OPTIONS_BIT3		(0x1ul << 3)
+	#if OPTIONS_BIT3 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT3		0x0
+#endif /* SUPPORT_MMU_FREELIST */
+
+
+#if defined(SUPPORT_RGX) || defined (INTERNAL_TEST)
+	#define SUPPORT_RGX_SET_OFFSET	OPTIONS_BIT4
+	#define OPTIONS_BIT4		(0x1ul << 4)
+	#if OPTIONS_BIT4 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT4		0x0
+#endif /* SUPPORT_RGX */
+
+
+#if defined(SUPPORT_SECURE_EXPORT) || defined (INTERNAL_TEST)
+	#define SUPPORT_SECURE_EXPORT_SET_OFFSET	OPTIONS_BIT5
+	#define OPTIONS_BIT5		(0x1ul << 5)
+	#if OPTIONS_BIT5 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT5		0x0
+#endif /* SUPPORT_SECURE_EXPORT */
+
+
+#if defined(SUPPORT_INSECURE_EXPORT) || defined (INTERNAL_TEST)
+	#define SUPPORT_INSECURE_EXPORT_SET_OFFSET	OPTIONS_BIT6
+	#define OPTIONS_BIT6		(0x1ul << 6)
+	#if OPTIONS_BIT6 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT6	0x0
+#endif /* SUPPORT_INSECURE_EXPORT */
+
+
+#if defined(SUPPORT_VFP) || defined (INTERNAL_TEST)
+	#define SUPPORT_VFP_SET_OFFSET	OPTIONS_BIT7
+	#define OPTIONS_BIT7		(0x1ul << 7)
+	#if OPTIONS_BIT7 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT7		0x0
+#endif /* SUPPORT_VFP */
+
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+	#define DEBUG_SET_OFFSET	OPTIONS_BIT10
+	#define OPTIONS_BIT10		(0x1ul << 10)
+	#if OPTIONS_BIT10 > RGX_BUILD_OPTIONS_MASK_KM
+	#error "Bit exceeds reserved range"
+	#endif
+#else
+	#define OPTIONS_BIT10		0x0
+#endif /* DEBUG */
+/* The bit position of this should be the
+ * same as DEBUG_SET_OFFSET option when
+ * defined */
+#define OPTIONS_DEBUG_MASK	(0x1ul << 10)
+
+#define RGX_BUILD_OPTIONS_KM	\
+	OPTIONS_BIT0  |\
+	OPTIONS_BIT1  |\
+	OPTIONS_BIT2  |\
+	OPTIONS_BIT3  |\
+	OPTIONS_BIT4  |\
+	OPTIONS_BIT6  |\
+	OPTIONS_BIT7  |\
+	OPTIONS_BIT10
+
 
 #if defined(SUPPORT_PERCONTEXT_FREELIST) || defined (INTERNAL_TEST)
 	#define OPTIONS_BIT31		(0x1ul << 31)
diff --git a/drivers/staging/imgtec/rogue/rgx_options_km.h b/drivers/staging/imgtec/rogue/rgx_options_km.h
deleted file mode 100644
index e73b3e9..0000000
--- a/drivers/staging/imgtec/rogue/rgx_options_km.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX KM build options
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-/* Each build option listed here is packed into a dword which
- * provides up to log2(RGX_BUILD_OPTIONS_MASK_KM + 1) flags.
- * The corresponding bit is set if the build option 
- * was enabled at compile time.
- *
- * In order to extract the enabled build flags the INTERNAL_TEST
- * switch should be enabled in a client program which includes this
- * header. Then the client can test specific build flags by reading
- * the bit value at ##OPTIONNAME##_SET_OFFSET in RGX_BUILD_OPTIONS_KM.
- *
- * IMPORTANT: add new options to unused bits or define a new dword
- * (e.g. RGX_BUILD_OPTIONS_KM2) so that the bitfield remains backwards
- * compatible.
- */
-
-#define RGX_BUILD_OPTIONS_MASK_KM 0x0000FFFFUL
-
-#if defined(NO_HARDWARE) || defined (INTERNAL_TEST)
-	#define NO_HARDWARE_SET_OFFSET	OPTIONS_BIT0
-	#define OPTIONS_BIT0		(0x1ul << 0)
-	#if OPTIONS_BIT0 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT0		0x0
-#endif /* NO_HARDWARE */
-
-
-#if defined(PDUMP) || defined (INTERNAL_TEST)
-	#define PDUMP_SET_OFFSET	OPTIONS_BIT1
-	#define OPTIONS_BIT1		(0x1ul << 1)
-	#if OPTIONS_BIT1 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT1		0x0
-#endif /* PDUMP */
-
-
-#if defined (INTERNAL_TEST)
-	#define UNUSED_SET_OFFSET	OPTIONS_BIT2
-	#define OPTIONS_BIT2		(0x1ul << 2)
-	#if OPTIONS_BIT2 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT2		0x0
-#endif /* SUPPORT_META_SLAVE_BOOT */
-
-
-#if defined(SUPPORT_MMU_FREELIST) || defined (INTERNAL_TEST)
-	#define SUPPORT_MMU_FREELIST_SET_OFFSET	OPTIONS_BIT3
-	#define OPTIONS_BIT3		(0x1ul << 3)
-	#if OPTIONS_BIT3 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT3		0x0
-#endif /* SUPPORT_MMU_FREELIST */
-
-
-#if defined(SUPPORT_RGX) || defined (INTERNAL_TEST)
-	#define SUPPORT_RGX_SET_OFFSET	OPTIONS_BIT4
-	#define OPTIONS_BIT4		(0x1ul << 4)
-	#if OPTIONS_BIT4 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT4		0x0
-#endif /* SUPPORT_RGX */
-
-
-#if defined(SUPPORT_SECURE_EXPORT) || defined (INTERNAL_TEST)
-	#define SUPPORT_SECURE_EXPORT_SET_OFFSET	OPTIONS_BIT5
-	#define OPTIONS_BIT5		(0x1ul << 5)
-	#if OPTIONS_BIT5 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT5		0x0
-#endif /* SUPPORT_SECURE_EXPORT */
-
-
-#if defined(SUPPORT_INSECURE_EXPORT) || defined (INTERNAL_TEST)
-	#define SUPPORT_INSECURE_EXPORT_SET_OFFSET	OPTIONS_BIT6
-	#define OPTIONS_BIT6		(0x1ul << 6)
-	#if OPTIONS_BIT6 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT6	0x0
-#endif /* SUPPORT_INSECURE_EXPORT */
-
-
-#if defined(SUPPORT_VFP) || defined (INTERNAL_TEST)
-	#define SUPPORT_VFP_SET_OFFSET	OPTIONS_BIT7
-	#define OPTIONS_BIT7		(0x1ul << 7)
-	#if OPTIONS_BIT7 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT7		0x0
-#endif /* SUPPORT_VFP */
-
-
-#if defined(SUPPORT_DRM) || defined (INTERNAL_TEST)
-	#define SUPPORT_DRM_SET_OFFSET	OPTIONS_BIT8
-	#define OPTIONS_BIT8		(0x1ul << 8)
-	#if OPTIONS_BIT8 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT8		0x0
-#endif /* SUPPORT_DRM */
-
-
-#if defined(DEBUG) || defined (INTERNAL_TEST)
-	#define DEBUG_SET_OFFSET	OPTIONS_BIT10
-	#define OPTIONS_BIT10		(0x1ul << 10)
-	#if OPTIONS_BIT10 > RGX_BUILD_OPTIONS_MASK_KM
-	#error "Bit exceeds reserved range"
-	#endif
-#else
-	#define OPTIONS_BIT10		0x0
-#endif /* DEBUG */
-/* The bit position of this should be the
- * same as DEBUG_SET_OFFSET option when
- * defined */
-#define OPTIONS_DEBUG_MASK	(0x1ul << 10)
-
-#define RGX_BUILD_OPTIONS_KM	\
-	OPTIONS_BIT0  |\
-	OPTIONS_BIT1  |\
-	OPTIONS_BIT2  |\
-	OPTIONS_BIT3  |\
-	OPTIONS_BIT4  |\
-	OPTIONS_BIT6  |\
-	OPTIONS_BIT7  |\
-	OPTIONS_BIT8  |\
-	OPTIONS_BIT10
-
-
diff --git a/drivers/staging/imgtec/rogue/rgxapi_km.h b/drivers/staging/imgtec/rogue/rgxapi_km.h
index 59da68e..0730f1a 100644
--- a/drivers/staging/imgtec/rogue/rgxapi_km.h
+++ b/drivers/staging/imgtec/rogue/rgxapi_km.h
@@ -86,7 +86,7 @@
 			   connection object has to be provided which means the this
 			   function needs to be preceded by the call to
 			   RGXHWPerfLazyConnect() function.
-@Output        phDevData      handle to a connection object
+@Input        phDevData      handle to a connection object
 @Return        PVRSRV_ERROR:  for system error codes
 */ /***************************************************************************/
 PVRSRV_ERROR RGXHWPerfOpen(
@@ -99,6 +99,8 @@
 			   connection object references opened connection.
 			   Calling this function is an equivalent of calling
 			   RGXHWPerfLazyConnect and RGXHWPerfOpen.
+			   This connect should be used when the caller will be retrieving
+			   event data.
 @Output        phDevData      Address of a handle to a connection object
 @Return        PVRSRV_ERROR:  for system error codes
 */ /***************************************************************************/
@@ -109,7 +111,7 @@
 /**************************************************************************/ /*!
 @Function       RGXHWPerfFreeConnection
 @Description    Frees the handle to RGX device
-@Input          hSrvHandle    Handle to connection object as returned from
+@Input          hDevData      Handle to connection object as returned from
                               RGXHWPerfLazyConnect()
 @Return         PVRSRV_ERROR: for system error codes
 */ /***************************************************************************/
@@ -120,7 +122,7 @@
 /**************************************************************************/ /*!
 @Function       RGXHWPerfClose
 @Description    Disconnect from the RGX device
-@Input          hSrvHandle    Handle to connection object as returned from
+@Input          hDevData      Handle to connection object as returned from
                               RGXHWPerfConnect() or RGXHWPerfOpen()
 @Return         PVRSRV_ERROR: for system error codes
 */ /***************************************************************************/
@@ -131,7 +133,7 @@
 /**************************************************************************/ /*!
 @Function       RGXHWPerfDisconnect
 @Description    Disconnect from the RGX device
-@Input          hSrvHandle    Handle to connection object as returned from
+@Input          hDevData      Handle to connection object as returned from
                               RGXHWPerfConnect() or RGXHWPerfOpen().
                               Calling this function is an equivalent of calling
 			                  RGXHWPerfClose and RGXHWPerfFreeConnection.
@@ -146,6 +148,7 @@
 @Description    Enable or disable the generation of RGX HWPerf event packets.
                  See RGXCtrlHWPerf().
 @Input          hDevData         Handle to connection object
+@Input			eStreamId		 ID of the HWPerf stream
 @Input          bToggle          Switch to toggle or apply mask.
 @Input          ui64Mask         Mask of events to control.
 @Return         PVRSRV_ERROR:    for system error codes
@@ -158,6 +161,22 @@
 
 
 /**************************************************************************/ /*!
+@Function       RGXHWPerfGetFilter
+@Description    Reads HWPerf stream filter where stream is identified by
+                the given stream ID.
+@Input          hDevData        Handle to connection/device object
+@Input          eStreamId       ID of the HWPerf stream
+@Output         IMG_UINT64      HWPerf filter value
+@Return         PVRSRV_ERROR:   for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR RGXHWPerfGetFilter(
+		IMG_HANDLE  hDevData,
+		RGX_HWPERF_STREAM_ID eStreamId,
+		IMG_UINT64 *ui64Filter
+);
+
+
+/**************************************************************************/ /*!
 @Function       RGXHWPerfConfigureAndEnableCounters
 @Description    Enable and configure the performance counter block for
                  one or more device layout modules.
@@ -188,6 +207,20 @@
 		IMG_UINT32   ui32NumBlocks,
 		IMG_UINT16*   aeBlockIDs);
 
+/**************************************************************************/ /*!
+@Function       RGXEnableHWPerfCounters
+@Description    Enable the performance counter block for one or more
+                 device layout modules. See RGXEnableHWPerfCounters().
+@Input          hDevData        Handle to connection/device object
+@Input          ui32NumBlocks   Number of elements in the array
+@Input          aeBlockIDs      An array of bytes with values taken from
+                                 the RGX_HWPERF_CNTBLK_ID enumeration.
+@Return         PVRSRV_ERROR:   for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV RGXHWPerfEnableCounters(
+		IMG_HANDLE   hDevData,
+		IMG_UINT32   ui32NumBlocks,
+		IMG_UINT16*   aeBlockIDs);
 
 /******************************************************************************
  * RGX HW Performance Profiling Retrieval API(s)
@@ -200,22 +233,23 @@
  *****************************************************************************/
 
 /**************************************************************************/ /*!
-@Function       RGXHWPerfAcquireData
-@Description    When there is data available to read this call returns with
-                 the address and length of the data buffer the
+@Function       RGXHWPerfAcquireEvents
+@Description    When there is data available to read this call returns with OK
+                 and the address and length of the data buffer the
                  client can safely read. This buffer may contain one or more
-                 event packets. If no data is available then this call 
-				 returns OK and sets *puiBufLen to 0 on exit.
-				 Clients must pair this call with a ReleaseData call.
+                 event packets.
+                 When there is no data to read, this call returns with OK
+                 and sets *puiBufLen to 0 on exit.
+				 Clients must pair this call with a ReleaseEvents call.
 @Input          hDevData        Handle to connection/device object
 @Input          eStreamId       ID of the HWPerf stream
 @Output         ppBuf           Address of a pointer to a byte buffer. On exit
-                                 it contains the address of buffer to read from
-@Output         puiBufLen       Pointer to an integer. On exit it is the size
-                                 of the data to read from the buffer
+                                it contains the address of buffer to read from
+@Output         pui32BufLen     Pointer to an integer. On exit it is the size
+                                of the data to read from the buffer
 @Return         PVRSRV_ERROR:   for system error codes
 */ /***************************************************************************/
-PVRSRV_ERROR RGXHWPerfAcquireData(
+PVRSRV_ERROR RGXHWPerfAcquireEvents(
 		IMG_HANDLE  hDevData,
 		RGX_HWPERF_STREAM_ID eStreamId,
 		IMG_PBYTE*  ppBuf,
@@ -223,34 +257,38 @@
 
 
 /**************************************************************************/ /*!
-@Function       RGXHWPerfGetFilter
-@Description    Reads HWPerf stream filter where stream is identified by
-                the given stream ID.
+@Function       RGXHWPerfReleaseEvents
+@Description    Called after client has read the event data out of the buffer
+                 retrieved from the Acquire Events call to release resources.
 @Input          hDevData        Handle to connection/device object
 @Input          eStreamId       ID of the HWPerf stream
-@Output         IMG_UINT64      HWPerf filter value
-@Return         PVRSRV_ERROR:   for system error codes
-*/ /***************************************************************************/
-PVRSRV_ERROR RGXHWPerfGetFilter(
-		IMG_HANDLE  hDevData,
-		RGX_HWPERF_STREAM_ID eStreamId,
-		IMG_UINT64 *ui64Filter
-);
-
-
-/**************************************************************************/ /*!
-@Function       RGXHWPerfReleaseData
-@Description    Called after client has read the event data out of the buffer
-                 retrieved from the Acquire Data call to release resources.
-@Input          hDevData        Handle to connection/device object
 @Return         PVRSRV_ERROR:   for system error codes
 */ /***************************************************************************/
 IMG_INTERNAL
-PVRSRV_ERROR RGXHWPerfReleaseData(
+PVRSRV_ERROR RGXHWPerfReleaseEvents(
 		IMG_HANDLE hDevData,
 		RGX_HWPERF_STREAM_ID eStreamId);
 
 
+/**************************************************************************/ /*!
+@Function       RGXHWPerfConvertCRTimeStamp
+@Description    Converts the timestamp given by FW events to the common OS
+                timestamp. The first three inputs are obtained via
+                a CLK_SYNC event, ui64CRTimeStamp is the CR timestamp
+                from the FW event to be converted.
+@Input          ui32ClkSpeed            Clock speed given by sync event
+@Input          ui64CorrCRTimeStamp     CR Timestamp given by sync event
+@Input          ui64CorrOSTimeStamp     Correlating OS Timestamp given by sync
+                                        event
+@Input          ui64CRTimeStamp         CR Timestamp to convert
+@Return         IMG_UINT64:             Calculated OS Timestamp
+ */ /**************************************************************************/
+IMG_UINT64 RGXHWPerfConvertCRTimeStamp(
+		IMG_UINT32 ui32ClkSpeed,
+		IMG_UINT64 ui64CorrCRTimeStamp,
+		IMG_UINT64 ui64CorrOSTimeStamp,
+		IMG_UINT64 ui64CRTimeStamp);
+
 #endif /* __RGXAPI_KM_H__ */
 
 /******************************************************************************
diff --git a/drivers/staging/imgtec/rogue/rgxbreakpoint.c b/drivers/staging/imgtec/rogue/rgxbreakpoint.c
index cd8f1b3..7183c314 100644
--- a/drivers/staging/imgtec/rogue/rgxbreakpoint.c
+++ b/drivers/staging/imgtec/rogue/rgxbreakpoint.c
@@ -59,13 +59,14 @@
                                       IMG_UINT32           ui32HandlerAddr,
                                       IMG_UINT32           ui32DataMaster)
 {
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
 	DEVMEM_MEMDESC		*psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
 	PVRSRV_ERROR 		eError = PVRSRV_OK;
 	RGXFWIF_KCCB_CMD 	sBPCmd;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	
-	if (psDeviceNode->psDevConfig->bBPSet == IMG_TRUE)
+	if (psDevInfo->bBPSet == IMG_TRUE)
 		return PVRSRV_ERROR_BP_ALREADY_SET;
 	
 	sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
@@ -80,11 +81,12 @@
 				0 , 
 				RFW_FWADDR_NOREF_FLAG);
 		
-	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+	eError = RGXScheduleCommand(psDevInfo,
 				eFWDataMaster,
 				&sBPCmd,
 				sizeof(sBPCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -92,15 +94,15 @@
 	}
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eFWDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDevInfo, eFWDataMaster, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXSetBreakpointKM: Wait for completion aborted with error (%u)", eError));
 		return eError;
 	}
 
-	psDeviceNode->psDevConfig->eBPDM = eFWDataMaster;
-	psDeviceNode->psDevConfig->bBPSet = IMG_TRUE;
+	psDevInfo->eBPDM = eFWDataMaster;
+	psDevInfo->bBPSet = IMG_TRUE;
 	
 	return eError;
 }
@@ -109,10 +111,10 @@
                                         PVRSRV_DEVICE_NODE * psDeviceNode,
                                         IMG_HANDLE           hMemCtxPrivData)
 {
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
 	DEVMEM_MEMDESC		*psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
 	PVRSRV_ERROR 		eError = PVRSRV_OK;
 	RGXFWIF_KCCB_CMD 	sBPCmd;
-	RGXFWIF_DM			eDataMaster = psDeviceNode->psDevConfig->eBPDM;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	
@@ -127,11 +129,12 @@
 				0 , 
 				RFW_FWADDR_NOREF_FLAG);
 
-	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
-				eDataMaster,
+	eError = RGXScheduleCommand(psDevInfo,
+				psDevInfo->eBPDM,
 				&sBPCmd,
 				sizeof(sBPCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXClearBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -139,14 +142,14 @@
 	}
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDevInfo, psDevInfo->eBPDM, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXClearBreakpointKM: Wait for completion aborted with error (%u)", eError));
 		return eError;
 	}
 
-	psDeviceNode->psDevConfig->bBPSet = IMG_FALSE;
+	psDevInfo->bBPSet = IMG_FALSE;
 	
 	return eError;
 }
@@ -155,14 +158,14 @@
                                          PVRSRV_DEVICE_NODE * psDeviceNode,
                                          IMG_HANDLE           hMemCtxPrivData)
 {
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
 	DEVMEM_MEMDESC		*psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
 	PVRSRV_ERROR 		eError = PVRSRV_OK;
 	RGXFWIF_KCCB_CMD 	sBPCmd;
-	RGXFWIF_DM			eDataMaster = psDeviceNode->psDevConfig->eBPDM;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
-	if (psDeviceNode->psDevConfig->bBPSet == IMG_FALSE)
+	if (psDevInfo->bBPSet == IMG_FALSE)
 		return PVRSRV_ERROR_BP_NOT_SET;
 	
 	sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
@@ -174,11 +177,12 @@
 				0 , 
 				RFW_FWADDR_NOREF_FLAG);
 
-	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
-				eDataMaster,
+	eError = RGXScheduleCommand(psDevInfo,
+				psDevInfo->eBPDM,
 				&sBPCmd,
 				sizeof(sBPCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXEnableBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -186,7 +190,7 @@
 	}
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDevInfo, psDevInfo->eBPDM, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXEnableBreakpointKM: Wait for completion aborted with error (%u)", eError));
@@ -200,14 +204,14 @@
                                           PVRSRV_DEVICE_NODE * psDeviceNode,
                                           IMG_HANDLE           hMemCtxPrivData)
 {
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
 	DEVMEM_MEMDESC		*psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
 	PVRSRV_ERROR 		eError = PVRSRV_OK;
 	RGXFWIF_KCCB_CMD 	sBPCmd;
-	RGXFWIF_DM			eDataMaster = psDeviceNode->psDevConfig->eBPDM;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	
-	if (psDeviceNode->psDevConfig->bBPSet == IMG_FALSE)
+	if (psDevInfo->bBPSet == IMG_FALSE)
 		return PVRSRV_ERROR_BP_NOT_SET;
 	
 	sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
@@ -219,11 +223,12 @@
 				0 , 
 				RFW_FWADDR_NOREF_FLAG);
 	
-	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
-				eDataMaster,
+	eError = RGXScheduleCommand(psDevInfo,
+				psDevInfo->eBPDM,
 				&sBPCmd,
 				sizeof(sBPCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDisableBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -231,7 +236,7 @@
 	}
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDevInfo, psDevInfo->eBPDM, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDisableBreakpointKM: Wait for completion aborted with error (%u)", eError));
@@ -260,7 +265,8 @@
 				RGXFWIF_DM_GP,
 				&sBPCmd,
 				sizeof(sBPCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXOverallocateBPRegistersKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -268,7 +274,7 @@
 	}
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXOverallocateBPRegistersKM: Wait for completion aborted with error (%u)", eError));
diff --git a/drivers/staging/imgtec/rogue/rgxccb.c b/drivers/staging/imgtec/rogue/rgxccb.c
index 720157e..88ee534 100644
--- a/drivers/staging/imgtec/rogue/rgxccb.c
+++ b/drivers/staging/imgtec/rogue/rgxccb.c
@@ -57,6 +57,7 @@
 #if defined(LINUX)
 #include "trace_events.h"
 #endif
+#include "rgxutils.h"
 
 /*
 *  Defines the number of fence updates to record so that future fences in the CCB
@@ -64,6 +65,27 @@
 */
 #define RGX_CCCB_FENCE_UPDATE_LIST_SIZE  (32)
 
+#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_INFO)
+
+#define PVRSRV_CLIENT_CCCB_UTILISATION_WARNING_THRESHOLD 0x1
+#define PVRSRV_CLIENT_CCCB_UTILISATION_WARNING_ACQUIRE_FAILED 0x2
+
+typedef struct _RGX_CLIENT_CCB_UTILISATION_
+{
+	/* the threshold in bytes.
+	 * when the CCB utilisation hits the threshold then we will print
+	 * a warning message.
+	 */
+	IMG_UINT32 ui32ThresholdBytes;
+	/* Maximum cCCB usage at some point in time */
+	IMG_UINT32 ui32HighWaterMark;
+	/* keep track of the warnings already printed.
+	 * bit mask of PVRSRV_CLIENT_CCCB_UTILISATION_WARNING_xyz
+	 */
+	IMG_UINT32 ui32Warnings;
+} RGX_CLIENT_CCB_UTILISATION;
+
+#endif /* PVRSRV_ENABLE_CCCB_UTILISATION_INFO */
 
 struct _RGX_CLIENT_CCB_ {
 	volatile RGXFWIF_CCCB_CTL	*psClientCCBCtrl;				/*!< CPU mapping of the CCB control structure used by the fw */
@@ -82,8 +104,9 @@
 	void						*hTransition;					/*!< Handle for Transition callback */
 	IMG_CHAR					szName[MAX_CLIENT_CCB_NAME];	/*!< Name of this client CCB */
 	RGX_SERVER_COMMON_CONTEXT   *psServerCommonContext;     	/*!< Parent server common context that this CCB belongs to */
-#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_DEBUG)
-	IMG_UINT32					ui32HighWaterMark;		/* Maximum cCCB usage at some point in time */
+#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_INFO)
+	RGX_CCB_REQUESTOR_TYPE				eRGXCCBRequestor;
+	RGX_CLIENT_CCB_UTILISATION		sUtilisation;				/*!< CCB utilisation data */
 #endif
 #if defined(DEBUG)
 	IMG_UINT32					ui32UpdateEntries;				/*!< Number of Fence Updates in asFenceUpdateList */
@@ -98,7 +121,7 @@
    The first string being used as comment when allocating ClientCCB for the given requestor, the second for CCBControl
    structure, and the 3rd one for use in PDUMP comments. The number of tuples in the table must adhere to the following
    build assert. */
-IMG_PCHAR aszCCBRequestors[][3] =
+IMG_CHAR *const aszCCBRequestors[][3] =
 {
 #define REQUESTOR_STRING(prefix,req) #prefix ":" #req
 #define FORM_REQUESTOR_TUPLE(req) { REQUESTOR_STRING(FwClientCCB,req), REQUESTOR_STRING(FwClientCCBControl,req), #req },
@@ -106,17 +129,14 @@
 #undef FORM_REQUESTOR_TUPLE
 };
 /* The number of tuples in the above table is always equal to those provided in the RGX_CCB_REQUESTORS X macro list.
-   In an event of change in value of DPX_MAX_RAY_CONTEXTS to say 'n', appropriate entry/entries upto FC[n-1] must be added to
+   In an event of change in value of DPX_MAX_RAY_CONTEXTS to say 'n', appropriate entry/entries up to FC[n-1] must be added to
    the RGX_CCB_REQUESTORS list. */
 static_assert((sizeof(aszCCBRequestors)/(3*sizeof(aszCCBRequestors[0][0]))) == (REQ_TYPE_FIXED_COUNT + DPX_MAX_RAY_CONTEXTS + 1),
 			  "Mismatch between aszCCBRequestors table and DPX_MAX_RAY_CONTEXTS");
 
 IMG_EXPORT PVRSRV_ERROR RGXCCBPDumpDrainCCB(RGX_CLIENT_CCB *psClientCCB,
-						IMG_BOOL bPDumpContinuous)
+						IMG_UINT32 ui32PDumpFlags)
 {
-	IMG_UINT32 ui32PDumpFlags;
-
-	ui32PDumpFlags = bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0;
 
 	PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
 						  "cCCB(%s@%p): Draining CCB rgxfw_roff == woff (%d)",
@@ -132,12 +152,10 @@
 									ui32PDumpFlags);
 }
 
-static PVRSRV_ERROR _RGXCCBPDumpTransition(void **pvData, IMG_BOOL bInto, IMG_BOOL bContinuous)
+static PVRSRV_ERROR _RGXCCBPDumpTransition(void **pvData, IMG_BOOL bInto, IMG_UINT32 ui32PDumpFlags)
 {
 	RGX_CLIENT_CCB *psClientCCB = (RGX_CLIENT_CCB *) pvData;
 	
-	IMG_UINT32 ui32PDumpFlags = bContinuous ? PDUMP_FLAGS_CONTINUOUS:0;
-
 	/*
 		We're about to Transition into capture range and we've submitted
 		new commands since the last time we entered capture range so drain
@@ -172,7 +190,7 @@
 			prim dump or not.
 		*/
 
-		eError = RGXCCBPDumpDrainCCB(psClientCCB, bContinuous);
+		eError = RGXCCBPDumpDrainCCB(psClientCCB, ui32PDumpFlags);
 
 		if (eError != PVRSRV_OK)
 		{
@@ -207,7 +225,7 @@
 							   0,
 							   sizeof(RGXFWIF_CCCB_CTL),
 							   ui32PDumpFlags);
-							   
+			
 			/*
 				Although we've entered capture range we might not do any work
 				on this CCB so update the ui32LastPDumpWriteOffset to reflect
@@ -220,6 +238,101 @@
 	return PVRSRV_OK;
 }
 
+#if defined (PVRSRV_ENABLE_CCCB_UTILISATION_INFO)
+
+static INLINE void _RGXInitCCBUtilisation(RGX_CLIENT_CCB *psClientCCB)
+{
+	psClientCCB->sUtilisation.ui32HighWaterMark = 0; /* initialize ui32HighWaterMark level to zero */
+	psClientCCB->sUtilisation.ui32ThresholdBytes = (psClientCCB->ui32Size *
+							PVRSRV_ENABLE_CCCB_UTILISATION_INFO_THRESHOLD)	/ 100;
+	psClientCCB->sUtilisation.ui32Warnings = 0;
+}
+
+static INLINE void _RGXPrintCCBUtilisationWarning(RGX_CLIENT_CCB *psClientCCB,
+									IMG_UINT32 ui32WarningType,
+									IMG_UINT32 ui32CmdSize)
+{
+#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_INFO_VERBOSE)
+	if(ui32WarningType == PVRSRV_CLIENT_CCCB_UTILISATION_WARNING_ACQUIRE_FAILED)
+	{
+		PVR_LOG(("Failed to acquire CCB space for %u byte command:", ui32CmdSize));
+	}
+
+	PVR_LOG(("%s: Client CCB (%s) watermark (%u) hit %d%% of its allocation size (%u)",
+								__FUNCTION__,
+								psClientCCB->szName,
+								psClientCCB->sUtilisation.ui32HighWaterMark,
+								psClientCCB->sUtilisation.ui32HighWaterMark * 100 / psClientCCB->ui32Size,
+								psClientCCB->ui32Size));
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32WarningType);
+	PVR_UNREFERENCED_PARAMETER(ui32CmdSize);
+
+	PVR_LOG(("GPU %s command buffer usage high (%u). This is not an error but the application may not run optimally.",
+							aszCCBRequestors[psClientCCB->eRGXCCBRequestor][REQ_PDUMP_COMMENT],
+							psClientCCB->sUtilisation.ui32HighWaterMark * 100 / psClientCCB->ui32Size));
+#endif
+}
+
+static INLINE void _RGXCCBUtilisationEvent(RGX_CLIENT_CCB *psClientCCB,
+						IMG_UINT32 ui32WarningType,
+						IMG_UINT32 ui32CmdSize)
+{
+	/* in VERBOSE mode we will print a message for each different
+	 * event type as they happen.
+	 * but by default we will only issue one message
+	 */
+#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_INFO_VERBOSE)
+	if(!(psClientCCB->sUtilisation.ui32Warnings & ui32WarningType))
+#else
+	if(!psClientCCB->sUtilisation.ui32Warnings)
+#endif
+	{
+		_RGXPrintCCBUtilisationWarning(psClientCCB,
+						ui32WarningType,
+						ui32CmdSize);
+		/* record that we have issued a warning of this type */
+		psClientCCB->sUtilisation.ui32Warnings |= ui32WarningType;
+	}
+}
+
+/* Check the current CCB utilisation. Print a one-time warning message if it is above the
+ * specified threshold
+ */
+static INLINE void _RGXCheckCCBUtilisation(RGX_CLIENT_CCB *psClientCCB)
+{
+	/* Print a warning message if the cCCB watermark is above the threshold value */
+	if(psClientCCB->sUtilisation.ui32HighWaterMark >= psClientCCB->sUtilisation.ui32ThresholdBytes)
+	{
+		_RGXCCBUtilisationEvent(psClientCCB,
+					PVRSRV_CLIENT_CCCB_UTILISATION_WARNING_THRESHOLD,
+					0);
+	}
+}
+
+/* Update the cCCB high watermark level if necessary */
+static void _RGXUpdateCCBUtilisation(RGX_CLIENT_CCB *psClientCCB)
+{
+	IMG_UINT32 ui32FreeSpace, ui32MemCurrentUsage;
+
+	ui32FreeSpace = GET_CCB_SPACE(psClientCCB->ui32HostWriteOffset,
+									  psClientCCB->psClientCCBCtrl->ui32ReadOffset,
+									  psClientCCB->ui32Size);
+	ui32MemCurrentUsage = psClientCCB->ui32Size - ui32FreeSpace;
+
+	if (ui32MemCurrentUsage > psClientCCB->sUtilisation.ui32HighWaterMark)
+	{
+		psClientCCB->sUtilisation.ui32HighWaterMark = ui32MemCurrentUsage;
+
+		/* The high water mark has increased. Check if it is above the
+		 * threshold so we can print a warning if necessary.
+		 */
+		_RGXCheckCCBUtilisation(psClientCCB);
+	}
+}
+
+#endif /* PVRSRV_ENABLE_CCCB_UTILISATION_INFO */
+
 PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO	*psDevInfo,
 						  IMG_UINT32			ui32CCBSizeLog2,
 						  CONNECTION_DATA		*psConnectionData,
@@ -249,7 +362,7 @@
 								PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
 								PVRSRV_MEMALLOCFLAG_GPU_READABLE |
 								PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-								PVRSRV_MEMALLOCFLAG_UNCACHED |
+								PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
 								PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
 								PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
 
@@ -336,8 +449,9 @@
 	psClientCCB->ui32UpdateEntries = 0;
 #endif
 
-#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_DEBUG)
-	psClientCCB->ui32HighWaterMark = 0; /* initialize ui32HighWaterMark level to zero */
+#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_INFO)
+	_RGXInitCCBUtilisation(psClientCCB);
+	psClientCCB->eRGXCCBRequestor = eRGXCCBRequestor;
 #endif
 	eError = PDumpRegisterTransitionCallback(psConnectionData->psPDumpConnectionData,
 											  _RGXCCBPDumpTransition,
@@ -366,11 +480,11 @@
 fail_pdumpreg:
 	DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc);
 fail_map_ccbctrl:
-	DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc);
+	DevmemFwFree(psDevInfo, psClientCCB->psClientCCBCtrlMemDesc);
 fail_alloc_ccbctrl:
 	DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc);
 fail_map_ccb:
-	DevmemFwFree(psClientCCB->psClientCCBMemDesc);
+	DevmemFwFree(psDevInfo, psClientCCB->psClientCCBMemDesc);
 fail_alloc_ccb:
 	OSFreeMem(psClientCCB);
 fail_alloc:
@@ -378,25 +492,13 @@
 	return eError;
 }
 
-void RGXDestroyCCB(RGX_CLIENT_CCB *psClientCCB)
+void RGXDestroyCCB(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_CLIENT_CCB *psClientCCB)
 {
-#if defined (PVRSRV_ENABLE_CCCB_UTILISATION_DEBUG)
-	/* Print a warning message if the cCCB watermarks touched 90% of the threshold value */
-	if (psClientCCB->ui32HighWaterMark > psClientCCB->ui32Size * 90/100)
-	{
-		PVR_LOG(("%s: Client CCB (%s) watermark (%u) hit %d%% of its allocation size (%u)",
-										__FUNCTION__,
-										psClientCCB->szName,
-										psClientCCB->ui32HighWaterMark,
-										psClientCCB->ui32HighWaterMark * 100 / psClientCCB->ui32Size,
-										psClientCCB->ui32Size));
-	}
-#endif
 	PDumpUnregisterTransitionCallback(psClientCCB->hTransition);
 	DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc);
-	DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc);
+	DevmemFwFree(psDevInfo, psClientCCB->psClientCCBCtrlMemDesc);
 	DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc);
-	DevmemFwFree(psClientCCB->psClientCCBMemDesc);
+	DevmemFwFree(psDevInfo, psClientCCB->psClientCCBMemDesc);
 	OSFreeMem(psClientCCB);
 }
 
@@ -409,31 +511,30 @@
  PARAMETERS	: psClientCCB		- The client CCB
 			  ui32CmdSize		- How much space is required
 			  ppvBufferSpace	- Pointer to space in the buffer
-			  bPDumpContinuous  - Should this be PDump continuous?
+			  ui32PDumpFlags - Should this be PDump continuous?
 
  RETURNS	: PVRSRV_ERROR
 ******************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
 										IMG_UINT32		ui32CmdSize,
 										void			**ppvBufferSpace,
-										IMG_BOOL		bPDumpContinuous)
+										IMG_UINT32		ui32PDumpFlags)
 {
 	PVRSRV_ERROR eError;
-	IMG_UINT32	ui32PDumpFlags	= bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0;
 	IMG_BOOL	bInCaptureRange;
 	IMG_BOOL	bPdumpEnabled;
 
 	PDumpIsCaptureFrameKM(&bInCaptureRange);
-	bPdumpEnabled = (bInCaptureRange || bPDumpContinuous);
+	bPdumpEnabled = (bInCaptureRange || PDUMP_IS_CONTINUOUS(ui32PDumpFlags));
 
 	/*
 		PDumpSetFrame will detect as we Transition into capture range for
 		frame based data but if we are PDumping continuous data then we
 		need to inform the PDump layer ourselves
 	*/
-	if (bPDumpContinuous && !bInCaptureRange)
+	if (PDUMP_IS_CONTINUOUS(ui32PDumpFlags) && !bInCaptureRange)
 	{
-		eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_TRUE, IMG_TRUE);
+		eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_TRUE, PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			return eError;
@@ -485,11 +586,11 @@
 			return PVRSRV_OK;
 		}
 
-		return PVRSRV_ERROR_RETRY;
+		goto e_retry;
 	}
 	else
 	{
-		/* 
+		/*
 			We're at the end of the buffer without enough contiguous space.
 			The command cannot fit without wrapping, we need to insert a
 			padding command and wrap. We need to do this in one go otherwise
@@ -540,14 +641,21 @@
 								   ui32Remain,
 								   ui32PDumpFlags);
 			}
-					
+			
 			*ppvBufferSpace = (void *) (psClientCCB->pui8ClientCCB +
 										0 /*ui32HostWriteOffset after wrap */);
 			return PVRSRV_OK;
 		}
 
-		return PVRSRV_ERROR_RETRY;
+		goto e_retry;
 	}
+e_retry:
+#if defined(PVRSRV_ENABLE_CCCB_UTILISATION_INFO)
+	_RGXCCBUtilisationEvent(psClientCCB,
+				PVRSRV_CLIENT_CCCB_UTILISATION_WARNING_ACQUIRE_FAILED,
+				ui32CmdSize);
+#endif  /* PVRSRV_ENABLE_CCCB_UTILISATION_INFO */
+	return PVRSRV_ERROR_RETRY;
 }
 
 /******************************************************************************
@@ -562,16 +670,15 @@
 ******************************************************************************/
 IMG_INTERNAL void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
 								IMG_UINT32		ui32CmdSize,
-								IMG_BOOL		bPDumpContinuous)
+								IMG_UINT32		ui32PDumpFlags)
 {
-	IMG_UINT32	ui32PDumpFlags	= bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0;
 	IMG_BOOL	bInCaptureRange;
 	IMG_BOOL	bPdumpEnabled;
 
 	PDumpIsCaptureFrameKM(&bInCaptureRange);
-	bPdumpEnabled = (bInCaptureRange || bPDumpContinuous);
+	bPdumpEnabled = (bInCaptureRange || PDUMP_IS_CONTINUOUS(ui32PDumpFlags));
 	
-	/* 
+	/*
 	 *  If a padding command was needed then we should now move ui32HostWriteOffset
 	 *  forward. The command has already be dumped (if bPdumpEnabled).
 	 */
@@ -687,33 +794,20 @@
 					  psClientCCB->ui32Size);
 	psClientCCB->ui32ByteCount += ui32CmdSize;
 
-#if defined (PVRSRV_ENABLE_CCCB_UTILISATION_DEBUG)
-/* update the cCCB high watermark level if necessary */
-	{
-		IMG_UINT32	ui32FreeSpace, ui32MemCurrentUsage;
-
-		ui32FreeSpace = GET_CCB_SPACE(psClientCCB->ui32HostWriteOffset,
-									  psClientCCB->psClientCCBCtrl->ui32ReadOffset,
-									  psClientCCB->ui32Size);
-		ui32MemCurrentUsage = psClientCCB->ui32Size - ui32FreeSpace;
-
-		if (ui32MemCurrentUsage > psClientCCB->ui32HighWaterMark)
-		{
-			psClientCCB->ui32HighWaterMark = ui32MemCurrentUsage;
-		}
-	}
+#if defined (PVRSRV_ENABLE_CCCB_UTILISATION_INFO)
+	_RGXUpdateCCBUtilisation(psClientCCB);
 #endif
 	/*
 		PDumpSetFrame will detect as we Transition out of capture range for
 		frame based data but if we are PDumping continuous data then we
 		need to inform the PDump layer ourselves
 	*/
-	if (bPDumpContinuous && !bInCaptureRange)
+	if (PDUMP_IS_CONTINUOUS(ui32PDumpFlags)&& !bInCaptureRange)
 	{
 		PVRSRV_ERROR eError;
 
 		/* Only Transitioning into capture range can cause an error */
-		eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_FALSE, IMG_TRUE);
+		eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_FALSE, PDUMP_FLAGS_CONTINUOUS);
 		PVR_ASSERT(eError == PVRSRV_OK);
 	}
 
@@ -843,27 +937,29 @@
 /*
 	Workout how much space this command will require
 */
-PVRSRV_ERROR RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB 			*psClientCCB,
-                                    IMG_UINT32				ui32ClientFenceCount,
-                                    PRGXFWIF_UFO_ADDR		*pauiFenceUFOAddress,
-                                    IMG_UINT32				*paui32FenceValue,
-                                    IMG_UINT32				ui32ClientUpdateCount,
-                                    PRGXFWIF_UFO_ADDR		*pauiUpdateUFOAddress,
-                                    IMG_UINT32				*paui32UpdateValue,
-                                    IMG_UINT32				ui32ServerSyncCount,
-                                    IMG_UINT32				*paui32ServerSyncFlags,
-                                    SERVER_SYNC_PRIMITIVE	**papsServerSyncs,
-                                    IMG_UINT32				ui32CmdSize,
-                                    IMG_PBYTE				pui8DMCmd,
-                                    PRGXFWIF_TIMESTAMP_ADDR *ppPreAddr,
-                                    PRGXFWIF_TIMESTAMP_ADDR *ppPostAddr,
-                                    PRGXFWIF_UFO_ADDR       *ppRMWUFOAddr,
-                                    RGXFWIF_CCB_CMD_TYPE	eType,
-                                    IMG_UINT32              ui32ExtJobRef,
-                                    IMG_UINT32              ui32IntJobRef,
-                                    IMG_BOOL				bPDumpContinuous,
-                                    IMG_CHAR				*pszCommandName,
-                                    RGX_CCB_CMD_HELPER_DATA	*psCmdHelperData)
+PVRSRV_ERROR RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB            *psClientCCB,
+                                    IMG_UINT32                ui32ClientFenceCount,
+                                    PRGXFWIF_UFO_ADDR         *pauiFenceUFOAddress,
+                                    IMG_UINT32                *paui32FenceValue,
+                                    IMG_UINT32                ui32ClientUpdateCount,
+                                    PRGXFWIF_UFO_ADDR         *pauiUpdateUFOAddress,
+                                    IMG_UINT32                *paui32UpdateValue,
+                                    IMG_UINT32                ui32ServerSyncCount,
+                                    IMG_UINT32                *paui32ServerSyncFlags,
+                                    IMG_UINT32                ui32ServerSyncFlagMask,
+                                    SERVER_SYNC_PRIMITIVE     **papsServerSyncs,
+                                    IMG_UINT32                ui32CmdSize,
+                                    IMG_PBYTE                 pui8DMCmd,
+                                    PRGXFWIF_TIMESTAMP_ADDR   *ppPreAddr,
+                                    PRGXFWIF_TIMESTAMP_ADDR   *ppPostAddr,
+                                    PRGXFWIF_UFO_ADDR         *ppRMWUFOAddr,
+                                    RGXFWIF_CCB_CMD_TYPE      eType,
+                                    IMG_UINT32                ui32ExtJobRef,
+                                    IMG_UINT32                ui32IntJobRef,
+                                    IMG_UINT32                ui32PDumpFlags,
+                                    RGXFWIF_WORKEST_KICK_DATA *psWorkEstKickData,
+                                    IMG_CHAR                  *pszCommandName,
+                                    RGX_CCB_CMD_HELPER_DATA   *psCmdHelperData)
 {
 	IMG_UINT32 ui32FenceCount;
 	IMG_UINT32 ui32UpdateCount;
@@ -875,7 +971,7 @@
 
 	/* Save the data we require in the submit call */
 	psCmdHelperData->psClientCCB = psClientCCB;
-	psCmdHelperData->bPDumpContinuous = bPDumpContinuous;
+	psCmdHelperData->ui32PDumpFlags = ui32PDumpFlags;
 	psCmdHelperData->pszCommandName = pszCommandName;
 
 	/* Client sync data */
@@ -889,6 +985,7 @@
 	/* Server sync data */
 	psCmdHelperData->ui32ServerSyncCount = ui32ServerSyncCount;
 	psCmdHelperData->paui32ServerSyncFlags = paui32ServerSyncFlags;
+	psCmdHelperData->ui32ServerSyncFlagMask = ui32ServerSyncFlagMask;
 	psCmdHelperData->papsServerSyncs = papsServerSyncs;
 
 	/* Command data */
@@ -896,7 +993,7 @@
 	psCmdHelperData->pui8DMCmd = pui8DMCmd;
 	psCmdHelperData->eType = eType;
 
-	PDUMPCOMMENTWITHFLAGS((bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0,
+	PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
 			"%s Command Server Init on FWCtx %08x", pszCommandName,
 			FWCommonContextGetFWAddress(psClientCCB->psServerCommonContext).ui32Addr);
 
@@ -908,6 +1005,10 @@
 	psCmdHelperData->ui32PostTimeStampCmdSize = 0;
 	psCmdHelperData->ui32RMWUFOCmdSize = 0;
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	/* Workload Data added */
+	psCmdHelperData->psWorkEstKickData = psWorkEstKickData;
+#endif
 
 	if (ppPreAddr && (ppPreAddr->ui32Addr != 0))
 	{
@@ -934,17 +1035,19 @@
 	/* Workout how many fences and updates this command will have */
 	for (i = 0; i < ui32ServerSyncCount; i++)
 	{
-		if (paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)
+		IMG_UINT32 ui32Flag = paui32ServerSyncFlags[i] & ui32ServerSyncFlagMask;
+
+		if (ui32Flag & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)
 		{
 			/* Server syncs must fence */
 			psCmdHelperData->ui32ServerFenceCount++;
 		}
 
 		/* If it is an update */
-		if (paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
+		if (ui32Flag & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
 		{
 			/* is it a fenced update or a progress update (a.k.a unfenced update) ?*/
-			if ((paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE) == PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE)
+			if ((ui32Flag & PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE) == PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE)
 			{
 				/* it is a progress update */
 				psCmdHelperData->ui32ServerUnfencedUpdateCount++;
@@ -986,7 +1089,7 @@
 		psCmdHelperData->ui32UpdateCmdSize = 0;
 	}
 
-	/* Total unfenced update command size (header plus command data) */ 
+	/* Total unfenced update command size (header plus command data) */
 	if (psCmdHelperData->ui32ServerUnfencedUpdateCount != 0)
 	{
 		psCmdHelperData->ui32UnfencedUpdateCmdSize = RGX_CCB_FWALLOC_ALIGN((psCmdHelperData->ui32ServerUnfencedUpdateCount * sizeof(RGXFWIF_UFO)) +
@@ -1020,12 +1123,12 @@
 
 	for (i = 0; i < ui32CmdCount; i++)
 	{
-		if (asCmdHelperData[0].bPDumpContinuous != asCmdHelperData[i].bPDumpContinuous)
+		if ((asCmdHelperData[0].ui32PDumpFlags ^ asCmdHelperData[i].ui32PDumpFlags) & PDUMP_FLAGS_CONTINUOUS)
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: PDump continuous is not consistent (%s != %s) for command %d",
 					 __FUNCTION__,
-					 asCmdHelperData[0].bPDumpContinuous?"IMG_TRUE":"IMG_FALSE",
-					 asCmdHelperData[i].bPDumpContinuous?"IMG_TRUE":"IMG_FALSE",
+					 PDUMP_IS_CONTINUOUS(asCmdHelperData[0].ui32PDumpFlags)?"IMG_TRUE":"IMG_FALSE",
+					 PDUMP_IS_CONTINUOUS(asCmdHelperData[i].ui32PDumpFlags)?"IMG_TRUE":"IMG_FALSE",
 					 ui32CmdCount));
 			return PVRSRV_ERROR_INVALID_PARAMS;
 		}
@@ -1037,7 +1140,7 @@
 	eError = RGXAcquireCCB(asCmdHelperData[0].psClientCCB,
 						   ui32AllocSize,
 						   (void **)&pui8StartPtr,
-						   asCmdHelperData[0].bPDumpContinuous);	
+						   asCmdHelperData[0].ui32PDumpFlags);
 	if (eError != PVRSRV_OK)
 	{
 		return eError;
@@ -1087,6 +1190,13 @@
 			psHeader->ui32CmdSize = psCmdHelperData->ui32FenceCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
 			psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
 			psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+			psHeader->sWorkloadDataFWAddr.ui32Addr = 0;
+			psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+			psHeader->sWorkEstKickData.ui64DeadlineInus = 0;
+			psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+#endif
+
 			pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
 
 			/* Fill in the client fences */
@@ -1138,17 +1248,29 @@
 			psHeader->ui32CmdSize = psCmdHelperData->ui32DMCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
 			psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
 			psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+			psHeader->sWorkloadDataFWAddr.ui32Addr = 0;
 
-
+			if(psCmdHelperData->psWorkEstKickData != NULL)
+			{
+				PVR_ASSERT(psCmdHelperData->eType == RGXFWIF_CCB_CMD_TYPE_TA ||
+				           psCmdHelperData->eType == RGXFWIF_CCB_CMD_TYPE_3D);
+				psHeader->sWorkEstKickData = *psCmdHelperData->psWorkEstKickData;
+			}
+			else
+			{
+				psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+				psHeader->sWorkEstKickData.ui64DeadlineInus = 0;
+				psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+			}
+#endif
 			pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
 
-
-			OSMemCopy(pui8CmdPtr, psCmdHelperData->pui8DMCmd, psCmdHelperData->ui32CmdSize);
+			/* The buffer is write-combine, so no special device memory treatment required. */
+			OSCachedMemCopy(pui8CmdPtr, psCmdHelperData->pui8DMCmd, psCmdHelperData->ui32CmdSize);
 			pui8CmdPtr += psCmdHelperData->ui32CmdSize;
 		}
 
-
-
 		if (psCmdHelperData->ui32PostTimeStampCmdSize != 0)
 		{
 			RGXWriteTimestampCommand(& pui8CmdPtr,
@@ -1167,6 +1289,13 @@
 			psHeader->ui32CmdSize = psCmdHelperData->ui32RMWUFOCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
 			psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
 			psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+
+			psHeader->sWorkloadDataFWAddr.ui32Addr = 0;
+			psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+			psHeader->sWorkEstKickData.ui64DeadlineInus = 0;
+			psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+#endif
 			pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
 
 			psUFO = (RGXFWIF_UFO *) pui8CmdPtr;
@@ -1193,6 +1322,12 @@
 			psHeader->ui32CmdSize = psCmdHelperData->ui32UpdateCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
 			psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
 			psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+			psHeader->sWorkloadDataFWAddr.ui32Addr = 0;
+			psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+			psHeader->sWorkEstKickData.ui64DeadlineInus = 0;
+			psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+#endif
 			pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
 
 			/* Fill in the client updates */
@@ -1229,7 +1364,13 @@
 			psHeader->ui32CmdSize = psCmdHelperData->ui32UnfencedUpdateCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
 			psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
 			psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
-		
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+			psHeader->sWorkloadDataFWAddr.ui32Addr = 0;
+			psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+			psHeader->sWorkEstKickData.ui64DeadlineInus = 0;
+			psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+#endif
+
 			/* jump over the header */
 			psCmdHelperData->pui8ServerUnfencedUpdateStart = ((IMG_UINT8*) psHeader) + sizeof(RGXFWIF_CCB_CMD_HEADER);
 		}
@@ -1247,7 +1388,7 @@
 			psCmdHelperData->ui32PreTimeStampCmdSize  +
 			psCmdHelperData->ui32DMCmdSize            +
 			psCmdHelperData->ui32PostTimeStampCmdSize +
-			psCmdHelperData->ui32RMWUFOCmdSize        + 
+			psCmdHelperData->ui32RMWUFOCmdSize        +
 			psCmdHelperData->ui32UpdateCmdSize        +
 			psCmdHelperData->ui32UnfencedUpdateCmdSize;
 
@@ -1276,6 +1417,10 @@
 {
 	IMG_UINT32 ui32AllocSize = 0;
 	IMG_UINT32 i;
+#if defined(LINUX)
+	IMG_BOOL bTraceChecks = trace_rogue_are_fence_checks_traced();
+	IMG_BOOL bTraceUpdates = trace_rogue_are_fence_updates_traced();
+#endif
 
 	/*
 		Workout how much space we need for all the command(s)
@@ -1290,7 +1435,7 @@
 		RGX_CCB_CMD_HELPER_DATA *psCmdHelperData = &asCmdHelperData[i];
 		IMG_UINT8 *pui8ServerFenceStart = psCmdHelperData->pui8ServerFenceStart;
 		IMG_UINT8 *pui8ServerUpdateStart = psCmdHelperData->pui8ServerUpdateStart;
-		IMG_UINT8 *pui8ServerUnfencedUpdateStart = psCmdHelperData->pui8ServerUnfencedUpdateStart;		
+		IMG_UINT8 *pui8ServerUnfencedUpdateStart = psCmdHelperData->pui8ServerUnfencedUpdateStart;
 		IMG_UINT32 j;
 
 		/* Now fill in the server fence and updates together */
@@ -1299,10 +1444,12 @@
 			RGXFWIF_UFO *psUFOPtr;
 			IMG_UINT32 ui32UpdateValue;
 			IMG_UINT32 ui32FenceValue;
+			IMG_UINT32 ui32SyncAddr;
 			PVRSRV_ERROR eError;
-			IMG_BOOL bFence = ((psCmdHelperData->paui32ServerSyncFlags[j] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)!=0)?IMG_TRUE:IMG_FALSE;
-			IMG_BOOL bUpdate = ((psCmdHelperData->paui32ServerSyncFlags[j] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)!=0)?IMG_TRUE:IMG_FALSE;
-			const IMG_BOOL bUnfencedUpdate = ((psCmdHelperData->paui32ServerSyncFlags[j] & PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE) == PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE)
+			IMG_UINT32 ui32Flag = psCmdHelperData->paui32ServerSyncFlags[j] & psCmdHelperData->ui32ServerSyncFlagMask;
+			IMG_BOOL bFence = ((ui32Flag & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)!=0)?IMG_TRUE:IMG_FALSE;
+			IMG_BOOL bUpdate = ((ui32Flag & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)!=0)?IMG_TRUE:IMG_FALSE;
+			const IMG_BOOL bUnfencedUpdate = ((ui32Flag & PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE) == PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE)
 				? IMG_TRUE
 				: IMG_FALSE;
 
@@ -1318,23 +1465,34 @@
 				which ensures the client is playing ball) the filling in of the fence
 				is unconditional.
 			*/
+			eError = ServerSyncGetFWAddr(psCmdHelperData->papsServerSyncs[j], &ui32SyncAddr);
+			if (PVRSRV_OK != eError)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+					"%s: Failed to read Server Sync FW address (%d)",
+					__FUNCTION__, eError));
+				PVR_ASSERT(eError == PVRSRV_OK);
+			}
 			if (bFence)
 			{
 				PVR_ASSERT(pui8ServerFenceStart != 0);
 
 				psUFOPtr = (RGXFWIF_UFO *) pui8ServerFenceStart;
-				psUFOPtr->puiAddrUFO.ui32Addr = ServerSyncGetFWAddr(psCmdHelperData->papsServerSyncs[j]);
+				psUFOPtr->puiAddrUFO.ui32Addr = ui32SyncAddr;
 				psUFOPtr->ui32Value = ui32FenceValue;
 				pui8ServerFenceStart += sizeof(RGXFWIF_UFO);
 
 #if defined(LINUX)
-				trace_rogue_fence_checks(psCmdHelperData->pszCommandName,
-										 pcszDMName,
-										 ui32CtxAddr,
-										 psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
-										 1,
-										 &psUFOPtr->puiAddrUFO,
-										 &psUFOPtr->ui32Value);
+				if (bTraceChecks)
+				{
+					trace_rogue_fence_checks(psCmdHelperData->pszCommandName,
+											 pcszDMName,
+											 ui32CtxAddr,
+											 psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+											 1,
+											 &psUFOPtr->puiAddrUFO,
+											 &psUFOPtr->ui32Value);
+				}
 #endif
 			}
 	
@@ -1346,7 +1504,7 @@
 					PVR_ASSERT(pui8ServerUnfencedUpdateStart != 0);
 
 					psUFOPtr = (RGXFWIF_UFO *) pui8ServerUnfencedUpdateStart;
-					psUFOPtr->puiAddrUFO.ui32Addr = ServerSyncGetFWAddr(psCmdHelperData->papsServerSyncs[j]);
+					psUFOPtr->puiAddrUFO.ui32Addr = ui32SyncAddr;
 					psUFOPtr->ui32Value = ui32UpdateValue;
 					pui8ServerUnfencedUpdateStart += sizeof(RGXFWIF_UFO);
 				}
@@ -1356,18 +1514,21 @@
 					PVR_ASSERT(pui8ServerUpdateStart != 0);
 
 					psUFOPtr = (RGXFWIF_UFO *) pui8ServerUpdateStart;
-					psUFOPtr->puiAddrUFO.ui32Addr = ServerSyncGetFWAddr(psCmdHelperData->papsServerSyncs[j]);
+					psUFOPtr->puiAddrUFO.ui32Addr = ui32SyncAddr;
 					psUFOPtr->ui32Value = ui32UpdateValue;
 					pui8ServerUpdateStart += sizeof(RGXFWIF_UFO);
 				}
 #if defined(LINUX)
-				trace_rogue_fence_updates(psCmdHelperData->pszCommandName,
-										  pcszDMName,
-										  ui32CtxAddr,
-										  psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
-										  1,
-										  &psUFOPtr->puiAddrUFO,
-										  &psUFOPtr->ui32Value);
+				if (bTraceUpdates)
+				{
+					trace_rogue_fence_updates(psCmdHelperData->pszCommandName,
+											  pcszDMName,
+											  ui32CtxAddr,
+											  psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+											  1,
+											  &psUFOPtr->puiAddrUFO,
+											  &psUFOPtr->ui32Value);
+				}
 #endif
 				
 #if defined(NO_HARDWARE)
@@ -1381,20 +1542,26 @@
 		}
 
 #if defined(LINUX)
-		trace_rogue_fence_checks(psCmdHelperData->pszCommandName,
-								 pcszDMName,
-								 ui32CtxAddr,
-								 psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
-								 psCmdHelperData->ui32ClientFenceCount,
-								 psCmdHelperData->pauiFenceUFOAddress,
-								 psCmdHelperData->paui32FenceValue);
-		trace_rogue_fence_updates(psCmdHelperData->pszCommandName,
-								  pcszDMName,
-								  ui32CtxAddr,
-								  psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
-								  psCmdHelperData->ui32ClientUpdateCount,
-								  psCmdHelperData->pauiUpdateUFOAddress,
-								  psCmdHelperData->paui32UpdateValue);
+		if (bTraceChecks)
+		{
+			trace_rogue_fence_checks(psCmdHelperData->pszCommandName,
+									 pcszDMName,
+									 ui32CtxAddr,
+									 psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+									 psCmdHelperData->ui32ClientFenceCount,
+									 psCmdHelperData->pauiFenceUFOAddress,
+									 psCmdHelperData->paui32FenceValue);
+		}
+		if (bTraceUpdates)
+		{
+			trace_rogue_fence_updates(psCmdHelperData->pszCommandName,
+									  pcszDMName,
+									  ui32CtxAddr,
+									  psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+									  psCmdHelperData->ui32ClientUpdateCount,
+									  psCmdHelperData->pauiUpdateUFOAddress,
+									  psCmdHelperData->paui32UpdateValue);
+		}
 #endif
 
 		if (psCmdHelperData->ui32ServerSyncCount)
@@ -1432,14 +1599,14 @@
 				           psCmdHelperData->ui32PostTimeStampCmdSize +
 				           psCmdHelperData->ui32UpdateCmdSize        +
 				           psCmdHelperData->ui32UnfencedUpdateCmdSize);
-			}			
+			}
 		}
 	
 		/*
 			All the commands have been filled in so release the CCB space.
 			The FW still won't run this command until we kick it
 		*/
-		PDUMPCOMMENTWITHFLAGS((psCmdHelperData->bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0,
+		PDUMPCOMMENTWITHFLAGS(psCmdHelperData->ui32PDumpFlags,
 				"%s Command Server Release on FWCtx %08x",
 				psCmdHelperData->pszCommandName, ui32CtxAddr);
 	}
@@ -1448,9 +1615,9 @@
 							  asCmdHelperData[0].psClientCCB->ui32HostWriteOffset,
 							  ui32AllocSize);
 
-	RGXReleaseCCB(asCmdHelperData[0].psClientCCB, 
+	RGXReleaseCCB(asCmdHelperData[0].psClientCCB,
 				  ui32AllocSize,
-				  asCmdHelperData[0].bPDumpContinuous);
+				  asCmdHelperData[0].ui32PDumpFlags);
 }
 
 
@@ -1469,7 +1636,7 @@
 			asCmdHelperData[i].ui32FenceCmdSize          +
 			asCmdHelperData[i].ui32DMCmdSize             +
 			asCmdHelperData[i].ui32UpdateCmdSize         +
-			asCmdHelperData[i].ui32UnfencedUpdateCmdSize +			
+			asCmdHelperData[i].ui32UnfencedUpdateCmdSize +
 			asCmdHelperData[i].ui32PreTimeStampCmdSize   +
 			asCmdHelperData[i].ui32PostTimeStampCmdSize  +
 			asCmdHelperData[i].ui32RMWUFOCmdSize;
@@ -1478,48 +1645,73 @@
 	return ui32AllocSize;
 }
 
+/* Work out how much of an offset there is to a specific command. */
+IMG_UINT32 RGXCmdHelperGetCommandOffset(RGX_CCB_CMD_HELPER_DATA *asCmdHelperData,
+                                        IMG_UINT32              ui32Cmdindex)
+{
+	IMG_UINT32 ui32Offset = 0;
+	IMG_UINT32 i;
+
+	for (i = 0; i < ui32Cmdindex; i++)
+	{
+		ui32Offset +=
+			asCmdHelperData[i].ui32FenceCmdSize          +
+			asCmdHelperData[i].ui32DMCmdSize             +
+			asCmdHelperData[i].ui32UpdateCmdSize         +
+			asCmdHelperData[i].ui32UnfencedUpdateCmdSize +
+			asCmdHelperData[i].ui32PreTimeStampCmdSize   +
+			asCmdHelperData[i].ui32PostTimeStampCmdSize  +
+			asCmdHelperData[i].ui32RMWUFOCmdSize;
+	}
+
+	return ui32Offset;
+}
+
+/* Returns the offset of the data master command from a write offset */
+IMG_UINT32 RGXCmdHelperGetDMCommandHeaderOffset(RGX_CCB_CMD_HELPER_DATA *psCmdHelperData)
+{
+	return psCmdHelperData->ui32FenceCmdSize + psCmdHelperData->ui32PreTimeStampCmdSize;
+}
+
 
 static const char *_CCBCmdTypename(RGXFWIF_CCB_CMD_TYPE cmdType)
 {
-	static const char *aCCBCmdName[20] = { "TA", "3D", "CDM", "TQ_3D", "TQ_2D",
-										   "3D_PR", "NULL", "SHG", "RTU", "RTU_FC",
-										   "PRE_TIMESTAMP",
-										   "FENCE", "UPDATE", "RMW_UPDATE",
-										   "FENCE_PR", "PRIORITY",
-										   "POST_TIMESTAMP", "UNFENCED_UPDATE",
-										   "UNFENCED_RMW_UPDATE", "PADDING"};
-	IMG_UINT32	cmdStrIdx = 19;
-
-	PVR_ASSERT( (cmdType == RGXFWIF_CCB_CMD_TYPE_TA)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_3D)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_CDM)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_TQ_3D)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_TQ_2D)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_3D_PR)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_NULL)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_SHG)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_RTU)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_RTU_FC)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_FENCE)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_UPDATE)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_FENCE_PR)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_PRIORITY)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_UNFENCED_UPDATE)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_UNFENCED_RMW_UPDATE)
-	            || (cmdType == RGXFWIF_CCB_CMD_TYPE_PADDING));
-
-	if( cmdType !=  RGXFWIF_CCB_CMD_TYPE_PADDING)
+	switch (cmdType)
 	{
-		cmdStrIdx = ((IMG_UINT32)cmdType & ~RGX_CCB_TYPE_TASK) - (RGXFWIF_CCB_CMD_TYPE_TA & ~RGX_CCB_TYPE_TASK);
-	}
+		case RGXFWIF_CCB_CMD_TYPE_TA: return "TA";
+		case RGXFWIF_CCB_CMD_TYPE_3D: return "3D";
+		case RGXFWIF_CCB_CMD_TYPE_CDM: return "CDM";
+		case RGXFWIF_CCB_CMD_TYPE_TQ_3D: return "TQ_3D";
+		case RGXFWIF_CCB_CMD_TYPE_TQ_2D: return "TQ_2D";
+		case RGXFWIF_CCB_CMD_TYPE_3D_PR: return "3D_PR";
+		case RGXFWIF_CCB_CMD_TYPE_NULL: return "NULL";
+		case RGXFWIF_CCB_CMD_TYPE_SHG: return "SHG";
+		case RGXFWIF_CCB_CMD_TYPE_RTU: return "RTU";
+		case RGXFWIF_CCB_CMD_TYPE_RTU_FC: return "RTU_FC";
+		case RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP: return "PRE_TIMESTAMP";
+		case RGXFWIF_CCB_CMD_TYPE_TQ_TDM: return "TQ_TDM";
 
-	return aCCBCmdName[cmdStrIdx];
+		case RGXFWIF_CCB_CMD_TYPE_FENCE: return "FENCE";
+		case RGXFWIF_CCB_CMD_TYPE_UPDATE: return "UPDATE";
+		case RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE: return "RMW_UPDATE";
+		case RGXFWIF_CCB_CMD_TYPE_FENCE_PR: return "FENCE_PR";
+		case RGXFWIF_CCB_CMD_TYPE_PRIORITY: return "PRIORITY";
+
+		case RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP: return "POST_TIMESTAMP";
+		case RGXFWIF_CCB_CMD_TYPE_UNFENCED_UPDATE: return "UNFENCED_UPDATE";
+		case RGXFWIF_CCB_CMD_TYPE_UNFENCED_RMW_UPDATE: return "UNFENCED_RMW_UPDATE";
+
+		case RGXFWIF_CCB_CMD_TYPE_PADDING: return "PADDING";
+
+		default:
+			PVR_ASSERT(IMG_FALSE);
+		break;
+	}
+	
+	return "INVALID";
 }
 
-PVRSRV_ERROR CheckForStalledCCB(RGX_CLIENT_CCB  *psCurrentClientCCB)
+PVRSRV_ERROR CheckForStalledCCB(RGX_CLIENT_CCB  *psCurrentClientCCB, RGX_KICK_TYPE_DM eKickTypeDM)
 {
 	volatile RGXFWIF_CCCB_CTL	*psClientCCBCtrl;
 	IMG_UINT32 					ui32SampledRdOff, ui32SampledWrOff;
@@ -1555,8 +1747,8 @@
 		 * function will log the stalled condition. Helps avoid double
 		 *  messages in the log.
 		 */
-		PVR_DPF((PVR_DBG_MESSAGE, "CheckForStalledCCB: CCCB has not progressed (ROFF=%d WOFF=%d)",
-				ui32SampledRdOff, ui32SampledWrOff));
+		PVR_DPF((PVR_DBG_WARNING, "CheckForStalledCCB: CCCB has not progressed (ROFF=%d WOFF=%d) for DM: %s",
+				ui32SampledRdOff, ui32SampledWrOff, RGXStringifyKickTypeDM(eKickTypeDM)));
 		eError =  PVRSRV_ERROR_CCCB_STALLED;
 	}
 
@@ -1568,12 +1760,15 @@
 }
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) || defined(PVRSRV_ENABLE_FULL_CCB_DUMP)
-void DumpCCB(
-	PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
-	RGX_CLIENT_CCB  *psCurrentClientCCB,
-	DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-	void *pvDumpDebugFile)
+void DumpCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+			PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
+			RGX_CLIENT_CCB  *psCurrentClientCCB,
+			DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+			void *pvDumpDebugFile)
 {
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+#endif
 	volatile RGXFWIF_CCCB_CTL *psClientCCBCtrl = psCurrentClientCCB->psClientCCBCtrl;
 	IMG_UINT8 *pui8ClientCCBBuff = psCurrentClientCCB->pui8ClientCCB;
 	IMG_UINT32 ui32Offset = psClientCCBCtrl->ui32ReadOffset;
@@ -1627,7 +1822,8 @@
 				{
 					bLastUFO = (ui32NoOfUpdates-1 == i)? IMG_TRUE: IMG_FALSE;
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
-					SyncRecordLookup(psUFOPtr->puiAddrUFO.ui32Addr, pszSyncInfo, CCB_SYNC_INFO_LEN);
+					SyncRecordLookup(psDeviceNode, psUFOPtr->puiAddrUFO.ui32Addr,
+									 pszSyncInfo, CCB_SYNC_INFO_LEN);
 #endif
 					PVR_DUMPDEBUG_LOG("  %s  %s--Addr:0x%08x Val=0x%08x %s",
 						bLastCommand? " ": "|",
@@ -1646,7 +1842,8 @@
 				{
 					bLastUFO = (ui32NoOfUpdates-1 == i)? IMG_TRUE: IMG_FALSE;
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
-					SyncRecordLookup(psUFOPtr->puiAddrUFO.ui32Addr, pszSyncInfo, CCB_SYNC_INFO_LEN);
+					SyncRecordLookup(psDeviceNode, psUFOPtr->puiAddrUFO.ui32Addr,
+									 pszSyncInfo, CCB_SYNC_INFO_LEN);
 #endif
 					PVR_DUMPDEBUG_LOG("  %s  %s--Addr:0x%08x Val++ %s",
 						bLastCommand? " ": "|",
diff --git a/drivers/staging/imgtec/rogue/rgxccb.h b/drivers/staging/imgtec/rogue/rgxccb.h
index 3f06058..bc1667f 100644
--- a/drivers/staging/imgtec/rogue/rgxccb.h
+++ b/drivers/staging/imgtec/rogue/rgxccb.h
@@ -52,8 +52,10 @@
 #include "rgx_fwif_shared.h"
 #include "rgxdebug.h"
 #include "rgxdefs_km.h"
+#include "pvr_notifier.h"
 
 #define MAX_CLIENT_CCB_NAME	30
+#define SYNC_FLAG_MASK_ALL  IMG_UINT32_MAX
 
 typedef struct _RGX_CLIENT_CCB_ RGX_CLIENT_CCB;
 
@@ -64,55 +66,57 @@
 
 typedef struct _RGX_CCB_CMD_HELPER_DATA_ {
 	/* Data setup at command init time */
-	RGX_CLIENT_CCB  		*psClientCCB;
-	IMG_CHAR 				*pszCommandName;
-	IMG_BOOL 				bPDumpContinuous;
+	RGX_CLIENT_CCB  			*psClientCCB;
+	IMG_CHAR 					*pszCommandName;
+	IMG_UINT32 					ui32PDumpFlags;
 	
-	IMG_UINT32				ui32ClientFenceCount;
-	PRGXFWIF_UFO_ADDR		*pauiFenceUFOAddress;
-	IMG_UINT32				*paui32FenceValue;
-	IMG_UINT32				ui32ClientUpdateCount;
-	PRGXFWIF_UFO_ADDR		*pauiUpdateUFOAddress;
-	IMG_UINT32				*paui32UpdateValue;
+	IMG_UINT32					ui32ClientFenceCount;
+	PRGXFWIF_UFO_ADDR			*pauiFenceUFOAddress;
+	IMG_UINT32					*paui32FenceValue;
+	IMG_UINT32					ui32ClientUpdateCount;
+	PRGXFWIF_UFO_ADDR			*pauiUpdateUFOAddress;
+	IMG_UINT32					*paui32UpdateValue;
 
-	IMG_UINT32				ui32ServerSyncCount;
-	IMG_UINT32				*paui32ServerSyncFlags;
-	SERVER_SYNC_PRIMITIVE	**papsServerSyncs;
-
-	RGXFWIF_CCB_CMD_TYPE	eType;
-	IMG_UINT32				ui32CmdSize;
-	IMG_UINT8				*pui8DMCmd;
-	IMG_UINT32				ui32FenceCmdSize;
-	IMG_UINT32				ui32DMCmdSize;
-	IMG_UINT32				ui32UpdateCmdSize;
-	IMG_UINT32				ui32UnfencedUpdateCmdSize;
+	IMG_UINT32					ui32ServerSyncCount;
+	IMG_UINT32					*paui32ServerSyncFlags;
+	IMG_UINT32					ui32ServerSyncFlagMask;
+	SERVER_SYNC_PRIMITIVE		**papsServerSyncs;
+	
+	RGXFWIF_CCB_CMD_TYPE		eType;
+	IMG_UINT32					ui32CmdSize;
+	IMG_UINT8					*pui8DMCmd;
+	IMG_UINT32					ui32FenceCmdSize;
+	IMG_UINT32					ui32DMCmdSize;
+	IMG_UINT32					ui32UpdateCmdSize;
+	IMG_UINT32					ui32UnfencedUpdateCmdSize;
 
 	/* timestamp commands */
-	PRGXFWIF_TIMESTAMP_ADDR pPreTimestampAddr;
-	IMG_UINT32              ui32PreTimeStampCmdSize;
-	PRGXFWIF_TIMESTAMP_ADDR pPostTimestampAddr;
-	IMG_UINT32              ui32PostTimeStampCmdSize;
-	PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
-	IMG_UINT32              ui32RMWUFOCmdSize;
+	PRGXFWIF_TIMESTAMP_ADDR     pPreTimestampAddr;
+	IMG_UINT32                  ui32PreTimeStampCmdSize;
+	PRGXFWIF_TIMESTAMP_ADDR     pPostTimestampAddr;
+	IMG_UINT32                  ui32PostTimeStampCmdSize;
+	PRGXFWIF_UFO_ADDR           pRMWUFOAddr;
+	IMG_UINT32                  ui32RMWUFOCmdSize;
 
 	/* Data setup at command acquire time */
-	IMG_UINT8				*pui8StartPtr;
-	IMG_UINT8				*pui8ServerUpdateStart;
-	IMG_UINT8				*pui8ServerUnfencedUpdateStart;
-	IMG_UINT8				*pui8ServerFenceStart;
-	IMG_UINT32				ui32ServerFenceCount;
-	IMG_UINT32				ui32ServerUpdateCount;
-	IMG_UINT32				ui32ServerUnfencedUpdateCount;
+	IMG_UINT8					*pui8StartPtr;
+	IMG_UINT8					*pui8ServerUpdateStart;
+	IMG_UINT8					*pui8ServerUnfencedUpdateStart;
+	IMG_UINT8					*pui8ServerFenceStart;
+	IMG_UINT32					ui32ServerFenceCount;
+	IMG_UINT32					ui32ServerUpdateCount;
+	IMG_UINT32					ui32ServerUnfencedUpdateCount;
 
 	/* Job reference fields */
-	IMG_UINT32				ui32ExtJobRef;
-	IMG_UINT32				ui32IntJobRef;
+	IMG_UINT32					ui32ExtJobRef;
+	IMG_UINT32					ui32IntJobRef;
+
+	/* Workload kick information */
+	RGXFWIF_WORKEST_KICK_DATA	*psWorkEstKickData;
 } RGX_CCB_CMD_HELPER_DATA;
 
 #define PADDING_COMMAND_SIZE	(sizeof(RGXFWIF_CCB_CMD_HEADER))
 
-PVRSRV_ERROR RGXCCBPDumpDrainCCB(RGX_CLIENT_CCB *psClientCCB,
-					IMG_UINT32 ui32PDumpContinuous);
 
 #define RGX_CCB_REQUESTORS(TYPE) \
 	/* for debugging purposes */ TYPE(UNDEF)	\
@@ -123,6 +127,7 @@
 	TYPE(RS)	\
 	TYPE(TQ_3D)	\
 	TYPE(TQ_2D)	\
+	TYPE(TQ_TDM)    \
 	TYPE(KICKSYNC)	\
 	/* Only used for validating the number of entries in this list */ TYPE(FIXED_COUNT)	\
 	TYPE(FC0)	\
@@ -145,7 +150,7 @@
 } RGX_CCB_REQUESTOR_TYPE;
 
 /*	The number of enum constants in the above table is always equal to those provided in the RGX_CCB_REQUESTORS X macro list.
-	In an event of change in value of DPX_MAX_RAY_CONTEXTS to say 'n', appropriate entry/entries upto FC[n-1] must be added to
+	In an event of change in value of DPX_MAX_RAY_CONTEXTS to say 'n', appropriate entry/entries up to FC[n-1] must be added to
 	the RGX_CCB_REQUESTORS list.
 */
 static_assert(REQ_TYPE_TOTAL_COUNT == REQ_TYPE_FIXED_COUNT + DPX_MAX_RAY_CONTEXTS + 1,
@@ -162,11 +167,14 @@
 	REQ_TUPLE_CARDINALITY,
 } RGX_CCB_REQUESTOR_TUPLE;
 
-/*	Table containing an array of strings for each requestor type in the list of RGX_CCB_REQUESTORS.	In addition to its use in
+/*	Table containing an array of strings for each requestor type in the list of RGX_CCB_REQUESTORS. In addition to its use in
 	this module (rgxccb.c), this table is also used to access string to be dumped in PDUMP comments, hence, marking it extern for
 	use in other modules.
 */
-extern IMG_PCHAR aszCCBRequestors[][REQ_TUPLE_CARDINALITY]; 
+extern IMG_CHAR *const aszCCBRequestors[][REQ_TUPLE_CARDINALITY];
+
+PVRSRV_ERROR RGXCCBPDumpDrainCCB(RGX_CLIENT_CCB *psClientCCB,
+					IMG_UINT32 ui32PDumpFlags);
 
 PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO	*psDevInfo,
 						  IMG_UINT32			ui32CCBSizeLog2,
@@ -177,40 +185,42 @@
 						  DEVMEM_MEMDESC 		**ppsClientCCBMemDesc,
 						  DEVMEM_MEMDESC 		**ppsClientCCBCtlMemDesc);
 
-void RGXDestroyCCB(RGX_CLIENT_CCB *psClientCCB);
+void RGXDestroyCCB(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_CLIENT_CCB *psClientCCB);
 
 PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
 										IMG_UINT32		ui32CmdSize,
 										void			**ppvBufferSpace,
-										IMG_BOOL		bPDumpContinuous);
+										IMG_UINT32		ui32PDumpFlags);
 
 IMG_INTERNAL void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
 								IMG_UINT32		ui32CmdSize,
-								IMG_BOOL		bPDumpContinuous);
+								IMG_UINT32		ui32PDumpFlags);
 
 IMG_UINT32 RGXGetHostWriteOffsetCCB(RGX_CLIENT_CCB *psClientCCB);
 
-PVRSRV_ERROR RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB          *psClientCCB,
-                                    IMG_UINT32              ui32ClientFenceCount,
-                                    PRGXFWIF_UFO_ADDR       *pauiFenceUFOAddress,
-                                    IMG_UINT32              *paui32FenceValue,
-                                    IMG_UINT32              ui32ClientUpdateCount,
-                                    PRGXFWIF_UFO_ADDR       *pauiUpdateUFOAddress,
-                                    IMG_UINT32              *paui32UpdateValue,
-                                    IMG_UINT32              ui32ServerSyncCount,
-                                    IMG_UINT32              *paui32ServerSyncFlags,
-                                    SERVER_SYNC_PRIMITIVE   **pasServerSyncs,
-                                    IMG_UINT32              ui32CmdSize,
-                                    IMG_UINT8               *pui8DMCmd,
-                                    PRGXFWIF_TIMESTAMP_ADDR *ppPreAddr,
-                                    PRGXFWIF_TIMESTAMP_ADDR *ppPostAddr,
-                                    RGXFWIF_DEV_VIRTADDR    *ppRMWUFOAddr,
-                                    RGXFWIF_CCB_CMD_TYPE    eType,
-                                    IMG_UINT32              ui32ExtJobRef,
-                                    IMG_UINT32              ui32IntJobRef,
-                                    IMG_BOOL                bPDumpContinuous,
-                                    IMG_CHAR                *pszCommandName,
-                                    RGX_CCB_CMD_HELPER_DATA *psCmdHelperData);
+PVRSRV_ERROR RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB            *psClientCCB,
+                                    IMG_UINT32                ui32ClientFenceCount,
+                                    PRGXFWIF_UFO_ADDR         *pauiFenceUFOAddress,
+                                    IMG_UINT32                *paui32FenceValue,
+                                    IMG_UINT32                ui32ClientUpdateCount,
+                                    PRGXFWIF_UFO_ADDR         *pauiUpdateUFOAddress,
+                                    IMG_UINT32                *paui32UpdateValue,
+                                    IMG_UINT32                ui32ServerSyncCount,
+                                    IMG_UINT32                *paui32ServerSyncFlags,
+                                    IMG_UINT32                ui32ServerSyncFlagMask,
+                                    SERVER_SYNC_PRIMITIVE     **papsServerSyncs,
+                                    IMG_UINT32                ui32CmdSize,
+                                    IMG_PBYTE                 pui8DMCmd,
+                                    PRGXFWIF_TIMESTAMP_ADDR   *ppPreAddr,
+                                    PRGXFWIF_TIMESTAMP_ADDR   *ppPostAddr,
+                                    PRGXFWIF_UFO_ADDR         *ppRMWUFOAddr,
+                                    RGXFWIF_CCB_CMD_TYPE      eType,
+                                    IMG_UINT32                ui32ExtJobRef,
+                                    IMG_UINT32                ui32IntJobRef,
+                                    IMG_UINT32                ui32PDumpFlags,
+                                    RGXFWIF_WORKEST_KICK_DATA *psWorkEstKickData,
+                                    IMG_CHAR                  *pszCommandName,
+                                    RGX_CCB_CMD_HELPER_DATA   *psCmdHelperData);
 
 PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
 									   RGX_CCB_CMD_HELPER_DATA *asCmdHelperData);
@@ -223,13 +233,22 @@
 IMG_UINT32 RGXCmdHelperGetCommandSize(IMG_UINT32 ui32CmdCount,
 								   RGX_CCB_CMD_HELPER_DATA *asCmdHelperData);
 
+IMG_UINT32 RGXCmdHelperGetCommandOffset(RGX_CCB_CMD_HELPER_DATA *asCmdHelperData,
+                                        IMG_UINT32              ui32Cmdindex);
+
+IMG_UINT32 RGXCmdHelperGetDMCommandHeaderOffset(RGX_CCB_CMD_HELPER_DATA *psCmdHelperData);
+
 void DumpStalledCCBCommand(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
 				RGX_CLIENT_CCB  *psCurrentClientCCB,
 				DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 				void *pvDumpDebugFile);
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) || defined(PVRSRV_ENABLE_FULL_CCB_DUMP)
-void DumpCCB(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext, RGX_CLIENT_CCB  *psCurrentClientCCB, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile);
+void DumpCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+			PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
+			RGX_CLIENT_CCB *psCurrentClientCCB,
+			DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+			void *pvDumpDebugFile);
 #endif
 
-PVRSRV_ERROR CheckForStalledCCB(RGX_CLIENT_CCB  *psCurrentClientCCB);
+PVRSRV_ERROR CheckForStalledCCB(RGX_CLIENT_CCB  *psCurrentClientCCB, RGX_KICK_TYPE_DM eKickTypeDM);
 #endif /* __RGXCCB_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxcompute.c b/drivers/staging/imgtec/rogue/rgxcompute.c
index c45faf3..25c269c 100644
--- a/drivers/staging/imgtec/rogue/rgxcompute.c
+++ b/drivers/staging/imgtec/rogue/rgxcompute.c
@@ -47,6 +47,7 @@
 #include "rgxutils.h"
 #include "rgxfwutils.h"
 #include "rgxcompute.h"
+#include "rgx_bvnc_defs_km.h"
 #include "rgxmem.h"
 #include "allocmem.h"
 #include "devicemem.h"
@@ -59,8 +60,12 @@
 
 #include "sync_server.h"
 #include "sync_internal.h"
+#include "sync.h"
 #include "rgx_memallocflags.h"
-#include "rgxsync.h"
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+#include "pvr_sync.h"
+#endif
 
 struct _RGX_SERVER_COMPUTE_CONTEXT_ {
 	PVRSRV_DEVICE_NODE			*psDeviceNode;
@@ -82,6 +87,7 @@
 											 IMG_UINT32					ui32FrameworkCommandSize,
 											 IMG_PBYTE					pbyFrameworkCommand,
 											 IMG_HANDLE					hMemCtxPrivData,
+											 IMG_DEV_VIRTADDR			sServicesSignalAddr,
 											 RGX_SERVER_COMPUTE_CONTEXT	**ppsComputeContext)
 {
 	PVRSRV_RGXDEV_INFO 			*psDevInfo = psDeviceNode->pvDevice;
@@ -92,14 +98,12 @@
 
 	/* Prepare cleanup struct */
 	*ppsComputeContext = NULL;
-	psComputeContext = OSAllocMem(sizeof(*psComputeContext));
+	psComputeContext = OSAllocZMem(sizeof(*psComputeContext));
 	if (psComputeContext == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	OSMemSet(psComputeContext, 0, sizeof(*psComputeContext));
-
 	psComputeContext->psDeviceNode = psDeviceNode;
 
 	/* Allocate cleanup sync */
@@ -159,6 +163,15 @@
 	sInfo.psFWFrameworkMemDesc = psComputeContext->psFWFrameworkMemDesc;
 	sInfo.psMCUFenceAddr = &sMCUFenceAddr;
 
+	if((psDevInfo->sDevFeatureCfg.ui32CtrlStreamFormat == 2) && \
+			(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK))
+	{
+		sInfo.psResumeSignalAddr = &sServicesSignalAddr;
+	}else
+	{
+		PVR_UNREFERENCED_PARAMETER(sServicesSignalAddr);
+	}
+
 	eError = FWCommonContextAllocate(psConnection,
 									 psDeviceNode,
 									 REQ_TYPE_CDM,
@@ -192,9 +205,9 @@
 
 fail_contextalloc:
 fail_frameworkcopy:
-	DevmemFwFree(psComputeContext->psFWFrameworkMemDesc);
+	DevmemFwFree(psDevInfo, psComputeContext->psFWFrameworkMemDesc);
 fail_frameworkcreate:
-	DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc);
+	DevmemFwFree(psDevInfo, psComputeContext->psFWComputeContextStateMemDesc);
 fail_contextsuspendalloc:
 	SyncPrimFree(psComputeContext->psSync);
 fail_syncalloc:
@@ -212,7 +225,8 @@
 	eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode,
 											  psComputeContext->psServerCommonContext,
 											  psComputeContext->psSync,
-											  RGXFWIF_DM_CDM);
+											  RGXFWIF_DM_CDM,
+											  PDUMP_FLAGS_NONE);
 
 	if (eError == PVRSRV_ERROR_RETRY)
 	{
@@ -233,8 +247,8 @@
 	OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock);
 
 	FWCommonContextFree(psComputeContext->psServerCommonContext);
-	DevmemFwFree(psComputeContext->psFWFrameworkMemDesc);
-	DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc);
+	DevmemFwFree(psDevInfo, psComputeContext->psFWFrameworkMemDesc);
+	DevmemFwFree(psDevInfo, psComputeContext->psFWComputeContextStateMemDesc);
 	SyncPrimFree(psComputeContext->psSync);
 	OSFreeMem(psComputeContext);
 
@@ -244,6 +258,7 @@
 
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT	*psComputeContext,
+								IMG_UINT32					ui32ClientCacheOpSeqNum,
 								IMG_UINT32					ui32ClientFenceCount,
 								SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
 								IMG_UINT32					*paui32ClientFenceSyncOffset,
@@ -255,11 +270,14 @@
 								IMG_UINT32					ui32ServerSyncPrims,
 								IMG_UINT32					*paui32ServerSyncFlags,
 								SERVER_SYNC_PRIMITIVE		**pasServerSyncs,
+								IMG_INT32					i32CheckFenceFD,
+								IMG_INT32					i32UpdateTimelineFD,
+								IMG_INT32					*pi32UpdateFenceFD,
+								IMG_CHAR					pszUpdateFenceName[32],
 								IMG_UINT32					ui32CmdSize,
 								IMG_PBYTE					pui8DMCmd,
-								IMG_BOOL					bPDumpContinuous,
-							    IMG_UINT32					ui32ExtJobRef,
-								IMG_UINT32					ui32IntJobRef)
+								IMG_UINT32					ui32PDumpFlags,
+							    IMG_UINT32					ui32ExtJobRef)
 {
 	RGXFWIF_KCCB_CMD		sCmpKCCBCmd;
 	RGX_CCB_CMD_HELPER_DATA	asCmdHelperData[1];
@@ -273,7 +291,32 @@
 	PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
 	PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
 	PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
-	PVR_UNREFERENCED_PARAMETER(ui32IntJobRef);
+
+	PRGXFWIF_UFO_ADDR		*pauiClientFenceUFOAddress;
+	PRGXFWIF_UFO_ADDR		*pauiClientUpdateUFOAddress;
+	IMG_INT32				i32UpdateFenceFD = -1;
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	/* Android fd sync update info */
+	struct pvr_sync_append_data *psFDData = NULL;
+	if (i32UpdateTimelineFD >= 0 && !pi32UpdateFenceFD)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+#else
+	if (i32UpdateTimelineFD >= 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "%s: Providing native sync timeline (%d) in non native sync enabled driver",
+			__func__, i32UpdateTimelineFD));
+	}
+	if (i32CheckFenceFD >= 0)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "%s: Providing native check sync (%d) in non native sync enabled driver",
+			__func__, i32CheckFenceFD));
+	}
+#endif
+	/* Ensure the string is null-terminated (Required for safety) */
+	pszUpdateFenceName[31] = '\0';
 
 	ui32JobId = OSAtomicIncrement(&psComputeContext->hJobId);
 
@@ -286,6 +329,8 @@
 		goto err_populate_sync_addr_list;
 	}
 
+	pauiClientFenceUFOAddress = psComputeContext->sSyncAddrListFence.pasFWAddrs;
+
 	eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListUpdate,
 									ui32ClientUpdateCount,
 									pauiClientUpdateUFOSyncPrimBlock,
@@ -295,6 +340,8 @@
 		goto err_populate_sync_addr_list;
 	}
 
+	pauiClientUpdateUFOAddress = psComputeContext->sSyncAddrListUpdate.pasFWAddrs;
+
 
 	/* Sanity check the server fences */
 	for (i=0;i<ui32ServerSyncPrims;i++)
@@ -302,7 +349,8 @@
 		if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
 		{
 			PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on CDM) must fence", __FUNCTION__));
-			return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+			eError = PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+			goto err_populate_sync_addr_list;
 		}
 	}
 
@@ -310,16 +358,43 @@
 	                          & pPreAddr,
 	                          & pPostAddr,
 	                          & pRMWUFOAddr);
+	
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	if (i32CheckFenceFD >= 0 || i32UpdateTimelineFD >= 0)
+	{
+		eError =
+			pvr_sync_append_fences(pszUpdateFenceName,
+								   i32CheckFenceFD,
+								   i32UpdateTimelineFD,
+								   ui32ClientUpdateCount,
+								   pauiClientUpdateUFOAddress,
+								   paui32ClientUpdateValue,
+								   ui32ClientFenceCount,
+								   pauiClientFenceUFOAddress,
+								   paui32ClientFenceValue,
+								   &psFDData);
+		if (eError != PVRSRV_OK)
+		{
+			goto fail_fdsync;
+		}
+		pvr_sync_get_updates(psFDData, &ui32ClientUpdateCount,
+			&pauiClientUpdateUFOAddress, &paui32ClientUpdateValue);
+
+		pvr_sync_get_checks(psFDData, &ui32ClientFenceCount,
+			&pauiClientFenceUFOAddress, &paui32ClientFenceValue);
+	}
+#endif /* SUPPORT_NATIVE_FENCE_SYNC */
 
 	eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext),
 	                                ui32ClientFenceCount,
-	                                psComputeContext->sSyncAddrListFence.pasFWAddrs,
+	                                pauiClientFenceUFOAddress,
 	                                paui32ClientFenceValue,
 	                                ui32ClientUpdateCount,
-	                                psComputeContext->sSyncAddrListUpdate.pasFWAddrs,
+	                                pauiClientUpdateUFOAddress,
 	                                paui32ClientUpdateValue,
 	                                ui32ServerSyncPrims,
 	                                paui32ServerSyncFlags,
+	                                SYNC_FLAG_MASK_ALL,
 	                                pasServerSyncs,
 	                                ui32CmdSize,
 	                                pui8DMCmd,
@@ -329,7 +404,8 @@
 	                                RGXFWIF_CCB_CMD_TYPE_CDM,
 	                                ui32ExtJobRef,
 	                                ui32JobId,
-	                                bPDumpContinuous,
+	                                ui32PDumpFlags,
+	                                NULL,
 	                                "Compute",
 	                                asCmdHelperData);
 	if (eError != PVRSRV_OK)
@@ -341,7 +417,6 @@
 	                                   asCmdHelperData);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXKickCDM: Failed to acquire space for client CCB command"));
 		goto fail_cmdaquire;
 	}
 
@@ -393,7 +468,8 @@
 									RGXFWIF_DM_CDM,
 									&sCmpKCCBCmd,
 									sizeof(sCmpKCCBCmd),
-									bPDumpContinuous);
+									ui32ClientCacheOpSeqNum,
+									ui32PDumpFlags);
 		if (eError2 != PVRSRV_ERROR_RETRY)
 		{
 			break;
@@ -421,11 +497,42 @@
 	{
 		goto fail_cmdaquire;
 	}
+	
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	if (i32UpdateTimelineFD >= 0)
+	{
+		/* If we get here, this should never fail. Hitting that likely implies
+		 * a code error above */
+		i32UpdateFenceFD = pvr_sync_get_update_fd(psFDData);
+		if (i32UpdateFenceFD < 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get install update sync fd",
+				__FUNCTION__));
+			/* If we fail here, we cannot rollback the syncs as the hw already
+			 * has references to resources they may be protecting in the kick
+			 * so fallthrough */
+	
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto fail_cmdaquire;
+		}
+	}
+#if defined(NO_HARDWARE)
+	pvr_sync_nohw_complete_fences(psFDData);
+#endif
+	pvr_sync_free_append_fences_data(psFDData);
+#endif
+
+	*pi32UpdateFenceFD = i32UpdateFenceFD;
 
 	return PVRSRV_OK;
 
 fail_cmdaquire:
 fail_cmdinit:
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	pvr_sync_rollback_append_fences(psFDData);
+	pvr_sync_free_append_fences_data(psFDData);
+fail_fdsync:
+#endif
 err_populate_sync_addr_list:
 	return eError;
 }
@@ -450,7 +557,8 @@
 									RGXFWIF_DM_GP,
 									&sFlushCmd,
 									sizeof(sFlushCmd),
-									IMG_TRUE);
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_ERROR_RETRY)
 		{
 			break;
@@ -468,7 +576,7 @@
 		eError = RGXWaitForFWOp(psComputeContext->psDeviceNode->pvDevice,
 								RGXFWIF_DM_GP,
 								psComputeContext->psSync,
-								IMG_TRUE);
+								PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXFlushComputeDataKM: Compute flush aborted with error (%u)", eError));
@@ -477,6 +585,50 @@
 	return eError;
 }
 
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXNotifyComputeWriteOffsetUpdateKM(RGX_SERVER_COMPUTE_CONTEXT  *psComputeContext)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;
+	if (2 == psDevInfo->sDevFeatureCfg.ui32CtrlStreamFormat)
+	{
+
+		RGXFWIF_KCCB_CMD  sKCCBCmd;
+		PVRSRV_ERROR      eError;
+
+		/* Schedule the firmware command */
+		sKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE;
+		sKCCBCmd.uCmdData.sWriteOffsetUpdateData.psContext = FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext);
+
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			eError = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
+										RGXFWIF_DM_CDM,
+										&sKCCBCmd,
+										sizeof(sKCCBCmd),
+										0,
+										PDUMP_FLAGS_NONE);
+			if (eError != PVRSRV_ERROR_RETRY)
+			{
+				break;
+			}
+			OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+		} END_LOOP_UNTIL_TIMEOUT();
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXNotifyWriteOffsetUpdateKM: Failed to schedule the FW command %d (%s)",
+					eError, PVRSRVGETERRORSTRING(eError)));
+		}
+
+		return eError;
+	}else
+	{
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+}
+
+
 PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
                                                   PVRSRV_DEVICE_NODE * psDeviceNode,
 												  RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
@@ -531,9 +683,9 @@
 	OSWRLockReleaseRead(psDevInfo->hComputeCtxListLock);
 }
 
-IMG_BOOL CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+IMG_UINT32 CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_UINT32 ui32ContextBitMask = 0;
 	DLLIST_NODE *psNode, *psNext;
 	OSWRLockAcquireRead(psDevInfo->hComputeCtxListLock);
 	dllist_foreach_node(&psDevInfo->sComputeCtxtListHead, psNode, psNext)
@@ -541,14 +693,14 @@
 		RGX_SERVER_COMPUTE_CONTEXT *psCurrentServerComputeCtx =
 			IMG_CONTAINER_OF(psNode, RGX_SERVER_COMPUTE_CONTEXT, sListNode);
 
-		if (CheckStalledClientCommonContext(psCurrentServerComputeCtx->psServerCommonContext)
+		if (CheckStalledClientCommonContext(psCurrentServerComputeCtx->psServerCommonContext, RGX_KICK_TYPE_DM_CDM)
 			== PVRSRV_ERROR_CCCB_STALLED)
 		{
-			eError = PVRSRV_ERROR_CCCB_STALLED;
+			ui32ContextBitMask |= RGX_KICK_TYPE_DM_CDM;
 		}
 	}
 	OSWRLockReleaseRead(psDevInfo->hComputeCtxListLock);
-	return (PVRSRV_ERROR_CCCB_STALLED == eError)? IMG_TRUE: IMG_FALSE;
+	return ui32ContextBitMask;
 }
 
 /******************************************************************************
diff --git a/drivers/staging/imgtec/rogue/rgxcompute.h b/drivers/staging/imgtec/rogue/rgxcompute.h
index 28a9ae5..2a43c33 100644
--- a/drivers/staging/imgtec/rogue/rgxcompute.h
+++ b/drivers/staging/imgtec/rogue/rgxcompute.h
@@ -49,6 +49,7 @@
 #include "rgxfwutils.h"
 #include "rgx_fwif_resetframework.h"
 #include "rgxdebug.h"
+#include "pvr_notifier.h"
 
 #include "sync_server.h"
 #include "sync_internal.h"
@@ -62,12 +63,12 @@
  @Function	PVRSRVRGXCreateComputeContextKM
 
  @Description
-	
 
- @Input pvDeviceNode 
- @Input psCmpCCBMemDesc - 
- @Input psCmpCCBCtlMemDesc - 
- @Output ppsFWComputeContextMemDesc - 
+
+ @Input pvDeviceNode
+ @Input psCmpCCBMemDesc -
+ @Input psCmpCCBCtlMemDesc -
+ @Output ppsFWComputeContextMemDesc -
 
  @Return   PVRSRV_ERROR
 ******************************************************************************/
@@ -79,16 +80,17 @@
 											 IMG_UINT32					ui32FrameworkRegisterSize,
 											 IMG_PBYTE					pbyFrameworkRegisters,
 											 IMG_HANDLE					hMemCtxPrivData,
+											 IMG_DEV_VIRTADDR			sServicesSignalAddr,
 											 RGX_SERVER_COMPUTE_CONTEXT	**ppsComputeContext);
 
-/*! 
+/*!
 *******************************************************************************
  @Function	PVRSRVRGXDestroyComputeContextKM
 
  @Description
 	Server-side implementation of RGXDestroyComputeContext
 
- @Input psCleanupData - 
+ @Input psCleanupData -
 
  @Return   PVRSRV_ERROR
 ******************************************************************************/
@@ -111,6 +113,7 @@
 ******************************************************************************/
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT	*psComputeContext,
+								IMG_UINT32					ui32ClientCacheOpSeqNum,
 								IMG_UINT32					ui32ClientFenceCount,
 								SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
 								IMG_UINT32					*paui32ClientFenceSyncOffset,
@@ -121,12 +124,15 @@
 								IMG_UINT32					*paui32ClientUpdateValue,
 								IMG_UINT32					ui32ServerSyncPrims,
 								IMG_UINT32					*paui32ServerSyncFlags,
-								SERVER_SYNC_PRIMITIVE 		**pasServerSyncs,
+								SERVER_SYNC_PRIMITIVE		**pasServerSyncs,
+								IMG_INT32					i32CheckFenceFd,
+								IMG_INT32					i32UpdateTimelineFd,
+								IMG_INT32					*pi32UpdateFenceFd,
+								IMG_CHAR					pcszUpdateFenceName[32],
 								IMG_UINT32					ui32CmdSize,
 								IMG_PBYTE					pui8DMCmd,
-								IMG_BOOL					bPDumpContinuous,
-								IMG_UINT32					ui32ExtJobRef,
-								IMG_UINT32					ui32IntJobRef);
+								IMG_UINT32					ui32PDumpFlags,
+								IMG_UINT32					ui32ExtJobRef);
 
 /*!
 *******************************************************************************
@@ -142,8 +148,23 @@
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
 
+/*!
+*******************************************************************************
+
+ @Function	    PVRSRVRGXNotifyComputeWriteOffsetUpdateKM
+ @Description   Server-side implementation of RGXNotifyComputeWriteOffsetUpdate
+
+ @Input         psDeviceNode - RGX Device node
+ @Input         psComputeContext - Compute context to flush
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXNotifyComputeWriteOffsetUpdateKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
+
 PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
-                                                  PVRSRV_DEVICE_NODE * psDeviceNode,
+												  PVRSRV_DEVICE_NODE *psDeviceNode,
 												  RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
 												  IMG_UINT32 ui32Priority);
 
@@ -157,6 +178,6 @@
 					void *pvDumpDebugFile);
 
 /* Debug/Watchdog - check if client compute contexts are stalled */
-IMG_BOOL CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+IMG_UINT32 CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
 
 #endif /* __RGXCOMPUTE_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxdebug.c b/drivers/staging/imgtec/rogue/rgxdebug.c
index c34e031..3018aec 100644
--- a/drivers/staging/imgtec/rogue/rgxdebug.c
+++ b/drivers/staging/imgtec/rogue/rgxdebug.c
@@ -61,20 +61,35 @@
 #include "pvrsrv.h"
 #include "services_km.h"
 
+#include "devicemem.h"
 #include "devicemem_pdump.h"
+#include "devicemem_utils.h"
 #include "rgx_fwif.h"
 #include "rgx_fwif_sf.h"
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 #include "rgxfw_log_helper.h"
+#endif
 
 #include "rgxta3d.h"
 #include "rgxcompute.h"
 #include "rgxtransfer.h"
-#if defined(RGX_FEATURE_RAY_TRACING)
 #include "rgxray.h"
-#endif
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
 #include "devicemem_history_server.h"
 #endif
+#include "rgx_bvnc_defs_km.h"
+#define PVR_DUMP_DRIVER_INFO(x, y)										\
+	PVR_DUMPDEBUG_LOG("%s info: "										\
+					   "BuildOptions: 0x%08x "							\
+					   "BuildVersion: %d.%d "							\
+					   "BuildRevision: %8d "							\
+					   "BuildType: %s",									\
+					   (x),												\
+					   (y).ui32BuildOptions,							\
+					   PVRVERSION_UNPACK_MAJ((y).ui32BuildVersion),		\
+					   PVRVERSION_UNPACK_MIN((y).ui32BuildVersion),		\
+					   (y).ui32BuildRevision,							\
+					   (BUILD_TYPE_DEBUG == (y).ui32BuildType) ? "debug" : "release")
 
 
 #define RGX_DEBUG_STR_SIZE	(150)
@@ -87,18 +102,11 @@
 	((RGX_CR_BIF_CAT_BASE1 - RGX_CR_BIF_CAT_BASE0) * n)
 
 
-#if defined(RGX_FEATURE_RAY_TRACING)
 #define RGXDBG_BIF_IDS \
 	X(BIF0)\
 	X(BIF1)\
 	X(TEXAS_BIF)\
 	X(DPX_BIF)
-#else
-#define RGXDBG_BIF_IDS \
-	X(BIF0)\
-	X(BIF1)\
-	X(TEXAS_BIF)
-#endif
 
 #define RGXDBG_SIDEBAND_TYPES \
 	X(META)\
@@ -137,36 +145,93 @@
 #undef X
 } RGXDBG_SIDEBAND_TYPE;
 
-
-IMG_CHAR* pszPowStateName [] = {
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+static const IMG_CHAR *const pszPowStateName[] =
+{
 #define X(NAME)	#NAME,
 	RGXFWIF_POW_STATES
 #undef X
 };
 
-IMG_CHAR* pszBIFNames [] = {
+static const IMG_CHAR *const pszBIFNames[] =
+{
 #define X(NAME)	#NAME,
 	RGXDBG_BIF_IDS
 #undef X
 };
-
-#if defined(RGX_FEATURE_MIPS)
-typedef struct {
-	IMG_UINT32 ui32ErrorEPC;
-	IMG_UINT32 ui32StatusRegister;
-	IMG_UINT32 ui32CauseRegister;
-	IMG_UINT32 ui32BadRegister;
-	IMG_UINT32 ui32EPC;
-	IMG_UINT32 ui32UserLocalRegister;
-} RGX_MIPS_STATE;
 #endif
 
-extern IMG_UINT32 g_ui32HostSampleIRQCount;
+#if !defined(NO_HARDWARE)
+/* Translation of MIPS exception encoding */
+static const IMG_CHAR * const apszMIPSExcCodes[32] =
+{
+	"Interrupt",
+	"TLB modified exception",
+	"TLB exception (load/instruction fetch)",
+	"TLB exception (store)",
+	"Address error exception (load/instruction fetch)",
+	"Address error exception (store)",
+	"Bus error exception (instruction fetch)",
+	"Bus error exception (load/store)",
+	"Syscall exception",
+	"Breakpoint exception",
+	"Reserved instruction exception",
+	"Coprocessor Unusable exception",
+	"Arithmetic Overflow exception",
+	"Trap exception",
+	NULL,
+	NULL,
+	"Implementation-Specific Exception 1 (COP2)",
+	"CorExtend Unusable",
+	"Coprocessor 2 exceptions",
+	"TLB Read-Inhibit",
+	"TLB Execute-Inhibit",
+	NULL,
+	NULL,
+	"Reference to WatchHi/WatchLo address",
+	"Machine check",
+	NULL,
+	"DSP Module State Disabled exception",
+	NULL,
+	NULL,
+	NULL,
+	/* Can only happen in MIPS debug mode */
+	"Parity error",
+	NULL
+};
+#endif
+
+typedef struct _RGXMIPSFW_C0_DEBUG_TBL_ENTRY_
+{
+    IMG_UINT32 ui32Mask;
+    const IMG_CHAR * pszExplanation;
+} RGXMIPSFW_C0_DEBUG_TBL_ENTRY;
+
+#if !defined(NO_HARDWARE)
+static const RGXMIPSFW_C0_DEBUG_TBL_ENTRY sMIPS_C0_DebugTable[] =
+{
+    { RGXMIPSFW_C0_DEBUG_DSS,      "Debug single-step exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DBP,      "Debug software breakpoint exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DDBL,     "Debug data break exception occurred on a load" },
+    { RGXMIPSFW_C0_DEBUG_DDBS,     "Debug data break exception occurred on a store" },
+    { RGXMIPSFW_C0_DEBUG_DIB,      "Debug instruction break exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DINT,     "Debug interrupt exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DIBIMPR,  "Imprecise debug instruction break exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DDBLIMPR, "Imprecise debug data break load exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DDBSIMPR, "Imprecise debug data break store exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_IEXI,     "Imprecise error exception inhibit controls exception occurred" },
+    { RGXMIPSFW_C0_DEBUG_DBUSEP,   "Data access Bus Error exception pending" },
+    { RGXMIPSFW_C0_DEBUG_CACHEEP,  "Imprecise Cache Error pending" },
+    { RGXMIPSFW_C0_DEBUG_MCHECKP,  "Imprecise Machine Check exception pending" },
+    { RGXMIPSFW_C0_DEBUG_IBUSEP,   "Instruction fetch Bus Error exception pending" },
+    { RGXMIPSFW_C0_DEBUG_DBD,      "Debug exception occurred in branch delay slot" }
+};
+#endif
 
 IMG_UINT32 RGXReadWithSP(IMG_UINT32 ui32FWAddr)
 {
 	PVRSRV_DATA        *psPVRSRVData = PVRSRVGetPVRSRVData();
-	PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[0];
+	PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->psDeviceNodeList;
 	PVRSRV_RGXDEV_INFO *psDevInfo    = psDeviceNode->pvDevice;
 	IMG_UINT32         ui32Value     = 0;
 	PVRSRV_ERROR       eError;
@@ -289,20 +354,19 @@
 	                                "FW code");
 	if (eError != PVRSRV_OK) return eError;
 
-#if defined(RGX_META_COREMEM_CODE)
-	RGXSetFirmwareAddress(&sFWAddr,
-	                      psDevInfo->psRGXFWCorememMemDesc,
-	                      0, RFW_FWADDR_NOREF_FLAG);
-#if defined(HW_ERN_45914)
-	/* temporarily make sure the coremem is init using the SLC */
-	sFWAddr.ui32Addr &= ~RGXFW_SEGMMU_DMAP_ADDR_START;
-	sFWAddr.ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
-#endif
-	eError = _ValidateFWImageWithSP(psDevInfo,
+#if !defined(SUPPORT_TRUSTED_DEVICE)
+	if (0 != psDevInfo->sDevFeatureCfg.ui32MCMS)
+	{
+		RGXSetFirmwareAddress(&sFWAddr,
+							  psDevInfo->psRGXFWCorememMemDesc,
+							  0, RFW_FWADDR_NOREF_FLAG);
+
+		eError = _ValidateFWImageWithSP(psDevInfo,
 	                                psDevInfo->psRGXFWCorememMemDesc,
 	                                &sFWAddr,
 	                                "FW coremem code");
-	if (eError != PVRSRV_OK) return eError;
+		if (eError != PVRSRV_OK) return eError;
+	}
 #endif
 
 #else
@@ -314,14 +378,34 @@
 #endif /* defined(SUPPORT_EXTRA_METASP_DEBUG) */
 
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+
 /*
  	 Guest drivers have the following limitations:
 	 	 - Cannot perform general device management (including debug)
 	 	 - Cannot touch the hardware except OSID kick registers
+	 	 - Guest driver do not support Firmware Trace log
 */
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile,
+					PVRSRV_RGXDEV_INFO *psDevInfo,
+					IMG_UINT32 ui32VerbLevel)
+{
+	PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
+	PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(ui32VerbLevel);
+}
+
+void RGXDumpDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile,
+					PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
+	PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
+}
 #else
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 /*!
 *******************************************************************************
 
@@ -355,7 +439,6 @@
 	return pszPMPC;
 }
 
-#if defined(RGX_FEATURE_RAY_TRACING)
 /*!
 *******************************************************************************
 
@@ -427,7 +510,7 @@
 	*ppszTagID = pszTagID;
 	*ppszTagSB = pszTagSB;
 }
-#endif
+
 
 /*!
 *******************************************************************************
@@ -449,7 +532,8 @@
  @Return   void
 
 ******************************************************************************/
-static void _RGXDecodeBIFReqTags(RGXDBG_BIF_ID	eBankID,
+static void _RGXDecodeBIFReqTags(PVRSRV_RGXDEV_INFO	*psDevInfo,
+								 RGXDBG_BIF_ID	eBankID,
 								 IMG_UINT32		ui32TagID,
 								 IMG_UINT32		ui32TagSB,
 								 IMG_CHAR		**ppszTagID,
@@ -464,24 +548,41 @@
 	PVR_ASSERT(ppszTagID != NULL);
 	PVR_ASSERT(ppszTagSB != NULL);
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	if (eBankID == RGXDBG_DPX_BIF)
+	if ((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK) && (eBankID == RGXDBG_DPX_BIF))
 	{
 		_DPXDecodeBIFReqTags(eBankID, ui32TagID, ui32TagSB, ppszTagID, ppszTagSB, pszScratchBuf, ui32ScratchBufSize);
 		return;
 	}
-#endif
-	
+
 	switch (ui32TagID)
 	{
 		case 0x0:
 		{
-#if defined(RGX_FEATURE_RAY_TRACING)
-			if (eBankID == RGXDBG_BIF0)
+			if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
 			{
-				pszTagID = "VRDM";				
-			}
-			else
+				if (eBankID == RGXDBG_BIF0)
+				{
+					pszTagID = "VRDM";
+					switch (ui32TagSB)
+					{
+					case 0x0: pszTagSB = "Control Stream"; break;
+					case 0x1: pszTagSB = "SHF State"; break;
+					case 0x2: pszTagSB = "Index Data"; break;
+					case 0x4: pszTagSB = "Call Stack"; break;
+					case 0x8: pszTagSB = "Context State"; break;
+					}
+				}
+				else
+				{
+					pszTagID = "MMU";
+					switch (ui32TagSB)
+					{
+						case 0x0: pszTagSB = "Table"; break;
+						case 0x1: pszTagSB = "Directory"; break;
+						case 0x2: pszTagSB = "Catalogue"; break;
+					}
+				}
+			}else
 			{
 				pszTagID = "MMU";
 				switch (ui32TagSB)
@@ -491,15 +592,6 @@
 					case 0x2: pszTagSB = "Catalogue"; break;
 				}
 			}
-#else
-			pszTagID = "MMU";
-			switch (ui32TagSB)
-			{
-				case 0x0: pszTagSB = "Table"; break;
-				case 0x1: pszTagSB = "Directory"; break;
-				case 0x2: pszTagSB = "Catalogue"; break;
-			}
-#endif
 			break;
 		}
 		case 0x1:
@@ -515,56 +607,48 @@
 		}
 		case 0x2:
 		{
-#if defined(RGX_FEATURE_RAY_TRACING)
-			if (eBankID == RGXDBG_BIF0)
+			if ((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK) && (eBankID == RGXDBG_BIF0))
 			{
-				pszTagID = "SHF";				
-			}
-			else
+				pszTagID = "SHF";
+			}else
 			{
 				pszTagID = "HOST";
 			}
-#else
-			pszTagID = "HOST";
-#endif
 			break;
 		}
 		case 0x3:
 		{
-#if defined(RGX_FEATURE_RAY_TRACING)
-			if (eBankID == RGXDBG_BIF0)
+			if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
 			{
-				pszTagID = "SHG";				
+				if (eBankID == RGXDBG_BIF0)
+				{
+					pszTagID = "SHG";
+				}
+			}
+			else if (0 == (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK))
+			{
+					pszTagID = "META";
+					switch (ui32TagSB)
+					{
+						case 0x0: pszTagSB = "DCache - Thread 0"; break;
+						case 0x1: pszTagSB = "ICache - Thread 0"; break;
+						case 0x2: pszTagSB = "JTag - Thread 0"; break;
+						case 0x3: pszTagSB = "Slave bus - Thread 0"; break;
+						case 0x4: pszTagSB = "DCache - Thread "; break;
+						case 0x5: pszTagSB = "ICache - Thread 1"; break;
+						case 0x6: pszTagSB = "JTag - Thread 1"; break;
+						case 0x7: pszTagSB = "Slave bus - Thread 1"; break;
+					}
+			}
+			else if (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_57596_BIT_MASK)
+			{
+				pszTagID="TCU";
 			}
 			else
 			{
-				pszTagID = "META";
-				switch (ui32TagSB)
-				{
-					case 0x0: pszTagSB = "DCache - Thread 0"; break;
-					case 0x1: pszTagSB = "ICache - Thread 0"; break;
-					case 0x2: pszTagSB = "JTag - Thread 0"; break;
-					case 0x3: pszTagSB = "Slave bus - Thread 0"; break;
-					case 0x4: pszTagSB = "DCache - Thread "; break;
-					case 0x5: pszTagSB = "ICache - Thread 1"; break;
-					case 0x6: pszTagSB = "JTag - Thread 1"; break;
-					case 0x7: pszTagSB = "Slave bus - Thread 1"; break;
-				}
+				/* Unreachable code */
+				PVR_ASSERT(IMG_FALSE);
 			}
-#else
-			pszTagID = "META";
-			switch (ui32TagSB)
-			{
-				case 0x0: pszTagSB = "DCache - Thread 0"; break;
-				case 0x1: pszTagSB = "ICache - Thread 0"; break;
-				case 0x2: pszTagSB = "JTag - Thread 0"; break;
-				case 0x3: pszTagSB = "Slave bus - Thread 0"; break;
-				case 0x4: pszTagSB = "DCache - Thread "; break;
-				case 0x5: pszTagSB = "ICache - Thread 1"; break;
-				case 0x6: pszTagSB = "JTag - Thread 1"; break;
-				case 0x7: pszTagSB = "Slave bus - Thread 1"; break;
-			}
-#endif
 			break;
 		}
 		case 0x4:
@@ -575,27 +659,58 @@
 			pszTagSB = pszScratchBuf;
 			break;
 		}
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 		case 0x5:
 		{
-#if defined(RGX_FEATURE_RAY_TRACING)
-			if (eBankID == RGXDBG_TEXAS_BIF)
+			if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK)
+			{
+				if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+				{
+					if (eBankID == RGXDBG_TEXAS_BIF)
+					{
+						pszTagID = "PBE";
+					}
+					else
+					{
+						pszTagID = "RPM";
+					}
+				}else{
+					pszTagID = "PBE";
+				}
+			}else
 			{
 				pszTagID = "PBE";
+				break;
 			}
-			else
-			{
-				pszTagID = "RPM";
-			}
-#else
-			pszTagID = "PBE";
-#endif
 			break;
 		}
 		case 0x6:
 		{
-#if defined(RGX_FEATURE_RAY_TRACING)
-			if (eBankID == RGXDBG_TEXAS_BIF)
+			if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK)
+			{
+				if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+				{
+					if (eBankID == RGXDBG_TEXAS_BIF)
+					{
+						pszTagID = "ISP";
+						switch (ui32TagSB)
+						{
+							case 0x00: pszTagSB = "ZLS"; break;
+							case 0x20: pszTagSB = "Occlusion Query"; break;
+						}
+					}else
+					{
+						pszTagID = "FBA";
+					}
+				}else
+				{
+					pszTagID = "ISP";
+					switch (ui32TagSB)
+					{
+						case 0x00: pszTagSB = "ZLS"; break;
+						case 0x20: pszTagSB = "Occlusion Query"; break;
+					}
+				}
+			}else
 			{
 				pszTagID = "ISP";
 				switch (ui32TagSB)
@@ -604,85 +719,58 @@
 					case 0x20: pszTagSB = "Occlusion Query"; break;
 				}
 			}
-			else
-			{
-				pszTagID = "FBA";				
-			}
-#else
-			pszTagID = "ISP";
-			switch (ui32TagSB)
-			{
-				case 0x00: pszTagSB = "ZLS"; break;
-				case 0x20: pszTagSB = "Occlusion Query"; break;
-			}
-#endif
 			break;
 		}
 		case 0x7:
 		{
-			if (eBankID == RGXDBG_TEXAS_BIF)
+			if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK)
+			{
+
+				if (eBankID == RGXDBG_TEXAS_BIF)
+				{
+					pszTagID = "IPF";
+					switch (ui32TagSB)
+					{
+						case 0x0: pszTagSB = "CPF"; break;
+						case 0x1: pszTagSB = "DBSC"; break;
+						case 0x2:
+						case 0x4:
+						case 0x6:
+						case 0x8: pszTagSB = "Control Stream"; break;
+						case 0x3:
+						case 0x5:
+						case 0x7:
+						case 0x9: pszTagSB = "Primitive Block"; break;
+					}
+				}
+				else
+				{
+					pszTagID = "IPP";
+					switch (ui32TagSB)
+					{
+						case 0x0: pszTagSB = "Macrotile Header"; break;
+						case 0x1: pszTagSB = "Region Header"; break;
+					}
+				}
+			}else
 			{
 				pszTagID = "IPF";
 				switch (ui32TagSB)
 				{
-					case 0x0: pszTagSB = "CPF"; break;
-					case 0x1: pszTagSB = "DBSC"; break;
-					case 0x2:
+					case 0x0: pszTagSB = "Macrotile Header"; break;
+					case 0x1: pszTagSB = "Region Header"; break;
+					case 0x2: pszTagSB = "DBSC"; break;
+					case 0x3: pszTagSB = "CPF"; break;
 					case 0x4:
 					case 0x6:
 					case 0x8: pszTagSB = "Control Stream"; break;
-					case 0x3:
 					case 0x5:
 					case 0x7:
 					case 0x9: pszTagSB = "Primitive Block"; break;
 				}
 			}
-			else
-			{
-				pszTagID = "IPP";
-				switch (ui32TagSB)
-				{
-					case 0x0: pszTagSB = "Macrotile Header"; break;
-					case 0x1: pszTagSB = "Region Header"; break;
-				}
-			}
 			break;
 		}
-#else /* RGX_FEATURE_CLUSTER_GROUPING */
-		case 0x5:
-		{
-			pszTagID = "PBE";
-			break;
-		}
-		case 0x6:
-		{
-			pszTagID = "ISP";
-			switch (ui32TagSB)
-			{
-				case 0x00: pszTagSB = "ZLS"; break;
-				case 0x20: pszTagSB = "Occlusion Query"; break;
-			}
-			break;
-		}
-		case 0x7:
-		{
-			pszTagID = "IPF";
-			switch (ui32TagSB)
-			{
-				case 0x0: pszTagSB = "Macrotile Header"; break;
-				case 0x1: pszTagSB = "Region Header"; break;
-				case 0x2: pszTagSB = "DBSC"; break;
-				case 0x3: pszTagSB = "CPF"; break;
-				case 0x4: 
-				case 0x6:
-				case 0x8: pszTagSB = "Control Stream"; break;
-				case 0x5: 
-				case 0x7:
-				case 0x9: pszTagSB = "Primitive Block"; break;
-			}
-			break;
-		}
-#endif /* RGX_FEATURE_CLUSTER_GROUPING */
 		case 0x8:
 		{
 			pszTagID = "CDM";
@@ -816,13 +904,24 @@
 					case 0x2: pszGroupEnc = "USCA_USC"; break;
 					case 0x3: pszGroupEnc = "USCB_USC"; break;
 					case 0x4: pszGroupEnc = "PDS_USC"; break;
-#if (RGX_FEATURE_NUM_CLUSTERS < 6)
-					case 0x5: pszGroupEnc = "PDSRW"; break;
-#elif (RGX_FEATURE_NUM_CLUSTERS == 6)
-					case 0x5: pszGroupEnc = "UPUC_USC"; break;
-					case 0x6: pszGroupEnc = "TPUC_USC"; break;
-					case 0x7: pszGroupEnc = "PDSRW"; break;
-#endif
+					case 0x5:
+						if(6 > psDevInfo->sDevFeatureCfg.ui32NumClusters)
+						{
+							pszGroupEnc = "PDSRW"; break;
+						}else if(6 == psDevInfo->sDevFeatureCfg.ui32NumClusters)
+						{
+							pszGroupEnc = "UPUC_USC"; break;
+						}
+					case 0x6:
+						if(6 == psDevInfo->sDevFeatureCfg.ui32NumClusters)
+						{
+							pszGroupEnc = "TPUC_USC"; break;
+						}
+					case 0x7:
+						if(6 == psDevInfo->sDevFeatureCfg.ui32NumClusters)
+						{
+							pszGroupEnc = "PDSRW"; break;
+						}
 				}
 				switch (ui32Group)
 				{
@@ -841,7 +940,8 @@
 		case 0xF:
 		{
 			pszTagID = "FB_CDC";
-#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
+
+			if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK)
 			{
 				IMG_UINT32 ui32Req   = (ui32TagSB >> 0) & 0xf;
 				IMG_UINT32 ui32MCUSB = (ui32TagSB >> 4) & 0x3;
@@ -870,7 +970,7 @@
 				           "%s, MCU sideband 0x%X", pszReqOrig, ui32MCUSB);
 				pszTagSB = pszScratchBuf;
 			}
-#else
+			else
 			{
 				IMG_UINT32 ui32Req   = (ui32TagSB >> 2) & 0x7;
 				IMG_UINT32 ui32MCUSB = (ui32TagSB >> 0) & 0x3;
@@ -891,7 +991,6 @@
 				           "%s, MCU sideband 0x%X", pszReqOrig, ui32MCUSB);
 				pszTagSB = pszScratchBuf;
 			}
-#endif
 			break;
 		}
 	} /* switch(TagID) */
@@ -899,10 +998,9 @@
 	*ppszTagID = pszTagID;
 	*ppszTagSB = pszTagSB;
 }
-#endif
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+
 /*!
 *******************************************************************************
 
@@ -954,7 +1052,8 @@
  @Return   void
 
 ******************************************************************************/
-static void _RGXDecodeMMUReqTags(IMG_UINT32  ui32TagID,
+static void _RGXDecodeMMUReqTags(PVRSRV_RGXDEV_INFO    *psDevInfo,
+								IMG_UINT32  ui32TagID,
 								 IMG_UINT32  ui32TagSB,
 								 IMG_BOOL    bRead,
 								 IMG_CHAR    **ppszTagID,
@@ -969,184 +1068,168 @@
 	PVR_ASSERT(ppszTagID != NULL);
 	PVR_ASSERT(ppszTagSB != NULL);
 
+
 	switch (ui32TagID)
 	{
 		case  0: pszTagID = "META (Jones)"; i32SideBandType = RGXDBG_META; break;
 		case  1: pszTagID = "TLA (Jones)"; i32SideBandType = RGXDBG_TLA; break;
-#if defined(RGX_FEATURE_META_DMA)
 		case  2: pszTagID = "DMA (Jones)"; i32SideBandType = RGXDBG_DMA; break;
-#endif
 		case  3: pszTagID = "VDMM (Jones)"; i32SideBandType = RGXDBG_VDMM; break;
 		case  4: pszTagID = "CDM (Jones)"; i32SideBandType = RGXDBG_CDM; break;
 		case  5: pszTagID = "IPP (Jones)"; i32SideBandType = RGXDBG_IPP; break;
 		case  6: pszTagID = "PM (Jones)"; i32SideBandType = RGXDBG_PM; break;
 		case  7: pszTagID = "Tiling (Jones)"; i32SideBandType = RGXDBG_TILING; break;
 		case  8: pszTagID = "MCU (Texas 0)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case  9: pszTagID = "PBE (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
-		case 10: pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
-		case 11: pszTagID = "FBCDC (Texas 0)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case  9: pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
-		case 10: pszTagID = "PBE (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
-		case 11: pszTagID = "FBCDC (Texas 0)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case  9: pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
-		case 10: pszTagID = "PBE0 (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
-		case 11: pszTagID = "PBE1 (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 12: pszTagID = "VDMS (Black Pearl 0)"; i32SideBandType = RGXDBG_VDMS; break;
 		case 13: pszTagID = "IPF (Black Pearl 0)"; i32SideBandType = RGXDBG_IPF; break;
 		case 14: pszTagID = "ISP (Black Pearl 0)"; i32SideBandType = RGXDBG_ISP; break;
 		case 15: pszTagID = "TPF (Black Pearl 0)"; i32SideBandType = RGXDBG_TPF; break;
 		case 16: pszTagID = "USCS (Black Pearl 0)"; i32SideBandType = RGXDBG_USCS; break;
 		case 17: pszTagID = "PPP (Black Pearl 0)"; i32SideBandType = RGXDBG_PPP; break;
-#if defined(HW_ERN_50539) || (defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3))
-		case 18: pszTagID = "TPF_CPF (Black Pearl 0)"; i32SideBandType = RGXDBG_TPF_CPF; break;
-		case 19: pszTagID = "IPF_CPF (Black Pearl 0)"; i32SideBandType = RGXDBG_IPF_CPF; break;
-#else
-		case 18: pszTagID = "VCE (Black Pearl 0)"; i32SideBandType = RGXDBG_VCE; break;
-		case 19: pszTagID = "FBCDC (Black Pearl 0)"; i32SideBandType = RGXDBG_FBCDC; break;
-#endif
 		case 20: pszTagID = "MCU (Texas 1)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 21: pszTagID = "PBE (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
-		case 22: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
-		case 23: pszTagID = "FBCDC (Texas 1)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 21: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
-		case 22: pszTagID = "PBE (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
-		case 23: pszTagID = "FBCDC (Texas 1)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 21: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
-		case 22: pszTagID = "PBE0 (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
-		case 23: pszTagID = "PBE1 (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 24: pszTagID = "MCU (Texas 2)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 25: pszTagID = "PBE (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
-		case 26: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
-		case 27: pszTagID = "FBCDC (Texas 2)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 25: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
-		case 26: pszTagID = "PBE (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
-		case 27: pszTagID = "FBCDC (Texas 2)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 25: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
-		case 26: pszTagID = "PBE0 (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
-		case 27: pszTagID = "PBE1 (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 28: pszTagID = "VDMS (Black Pearl 1)"; i32SideBandType = RGXDBG_VDMS; break;
 		case 29: pszTagID = "IPF (Black Pearl 1)"; i32SideBandType = RGXDBG_IPF; break;
 		case 30: pszTagID = "ISP (Black Pearl 1)"; i32SideBandType = RGXDBG_ISP; break;
 		case 31: pszTagID = "TPF (Black Pearl 1)"; i32SideBandType = RGXDBG_TPF; break;
 		case 32: pszTagID = "USCS (Black Pearl 1)"; i32SideBandType = RGXDBG_USCS; break;
 		case 33: pszTagID = "PPP (Black Pearl 1)"; i32SideBandType = RGXDBG_PPP; break;
-#if defined(HW_ERN_50539) || (defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3))
-		case 34: pszTagID = "TPF_CPF (Black Pearl 1)"; i32SideBandType = RGXDBG_TPF_CPF; break;
-		case 35: pszTagID = "IPF_CPF (Black Pearl 1)"; i32SideBandType = RGXDBG_IPF_CPF; break;
-#else
-		case 34: pszTagID = "VCE (Black Pearl 1)"; i32SideBandType = RGXDBG_VCE; break;
-		case 35: pszTagID = "FBCDC (Black Pearl 1)"; i32SideBandType = RGXDBG_FBCDC; break;
-#endif
 		case 36: pszTagID = "MCU (Texas 3)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 37: pszTagID = "PBE (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
-		case 38: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
-		case 39: pszTagID = "FBCDC (Texas 3)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 37: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
-		case 38: pszTagID = "PBE (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
-		case 39: pszTagID = "FBCDC (Texas 3)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 37: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
-		case 38: pszTagID = "PBE0 (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
-		case 39: pszTagID = "PBE1 (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 40: pszTagID = "MCU (Texas 4)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 41: pszTagID = "PBE (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
-		case 42: pszTagID = "PDS (Texas 4)"; i32SideBandType = RGXDBG_PDS; break;
-		case 43: pszTagID = "FBCDC (Texas 4)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 41: pszTagID = "PDS (Texas 4)"; i32SideBandType = RGXDBG_PDS; break;
-		case 42: pszTagID = "PBE (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
-		case 43: pszTagID = "FBCDC (Texas 4)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 41: pszTagID = "PDS (Texas 4)"; i32SideBandType = RGXDBG_PDS; break;
-		case 42: pszTagID = "PBE0 (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
-		case 43: pszTagID = "PBE1 (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 44: pszTagID = "VDMS (Black Pearl 2)"; i32SideBandType = RGXDBG_VDMS; break;
 		case 45: pszTagID = "IPF (Black Pearl 2)"; i32SideBandType = RGXDBG_IPF; break;
 		case 46: pszTagID = "ISP (Black Pearl 2)"; i32SideBandType = RGXDBG_ISP; break;
 		case 47: pszTagID = "TPF (Black Pearl 2)"; i32SideBandType = RGXDBG_TPF; break;
 		case 48: pszTagID = "USCS (Black Pearl 2)"; i32SideBandType = RGXDBG_USCS; break;
 		case 49: pszTagID = "PPP (Black Pearl 2)"; i32SideBandType = RGXDBG_PPP; break;
-#if defined(HW_ERN_50539) || (defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3))
-		case 50: pszTagID = "TPF_CPF (Black Pearl 2)"; i32SideBandType = RGXDBG_TPF_CPF; break;
-		case 51: pszTagID = "IPF_CPF (Black Pearl 2)"; i32SideBandType = RGXDBG_IPF_CPF; break;
-#else
-		case 50: pszTagID = "VCE (Black Pearl 2)"; i32SideBandType = RGXDBG_VCE; break;
-		case 51: pszTagID = "FBCDC (Black Pearl 2)"; i32SideBandType = RGXDBG_FBCDC; break;
-#endif
 		case 52: pszTagID = "MCU (Texas 5)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 53: pszTagID = "PBE (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
-		case 54: pszTagID = "PDS (Texas 5)"; i32SideBandType = RGXDBG_PDS; break;
-		case 55: pszTagID = "FBCDC (Texas 5)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 53: pszTagID = "PDS (Texas 5)"; i32SideBandType = RGXDBG_PDS; break;
-		case 54: pszTagID = "PBE (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
-		case 55: pszTagID = "FBCDC (Texas 5)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 53: pszTagID = "PDS (Texas 5)"; i32SideBandType = RGXDBG_PDS; break;
-		case 54: pszTagID = "PBE0 (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
-		case 55: pszTagID = "PBE1 (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 56: pszTagID = "MCU (Texas 6)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 57: pszTagID = "PBE (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
-		case 58: pszTagID = "PDS (Texas 6)"; i32SideBandType = RGXDBG_PDS; break;
-		case 59: pszTagID = "FBCDC (Texas 6)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 57: pszTagID = "PDS (Texas 6)"; i32SideBandType = RGXDBG_PDS; break;
-		case 58: pszTagID = "PBE (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
-		case 59: pszTagID = "FBCDC (Texas 6)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 57: pszTagID = "PDS (Texas 6)"; i32SideBandType = RGXDBG_PDS; break;
-		case 58: pszTagID = "PBE0 (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
-		case 59: pszTagID = "PBE1 (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 		case 60: pszTagID = "VDMS (Black Pearl 3)"; i32SideBandType = RGXDBG_VDMS; break;
 		case 61: pszTagID = "IPF (Black Pearl 3)"; i32SideBandType = RGXDBG_IPF; break;
 		case 62: pszTagID = "ISP (Black Pearl 3)"; i32SideBandType = RGXDBG_ISP; break;
 		case 63: pszTagID = "TPF (Black Pearl 3)"; i32SideBandType = RGXDBG_TPF; break;
 		case 64: pszTagID = "USCS (Black Pearl 3)"; i32SideBandType = RGXDBG_USCS; break;
 		case 65: pszTagID = "PPP (Black Pearl 3)"; i32SideBandType = RGXDBG_PPP; break;
-#if defined(HW_ERN_50539) || (defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3))
-		case 66: pszTagID = "TPF_CPF (Black Pearl 3)"; i32SideBandType = RGXDBG_TPF_CPF; break;
-		case 67: pszTagID = "IPF_CPF (Black Pearl 3)"; i32SideBandType = RGXDBG_IPF_CPF; break;
-#else
-		case 66: pszTagID = "VCE (Black Pearl 3)"; i32SideBandType = RGXDBG_VCE; break;
-		case 67: pszTagID = "FBCDC (Black Pearl 3)"; i32SideBandType = RGXDBG_FBCDC; break;
-#endif
 		case 68: pszTagID = "MCU (Texas 7)"; i32SideBandType = RGXDBG_MCU; break;
-#if defined(HW_ERN_50539)
-		case 69: pszTagID = "PBE (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
-		case 70: pszTagID = "PDS (Texas 7)"; i32SideBandType = RGXDBG_PDS; break;
-		case 71: pszTagID = "FBCDC (Texas 7)"; i32SideBandType = RGXDBG_FBCDC; break;
-#elif defined(RGX_FEATURE_FBCDC_ARCHITECTURE) && (RGX_FEATURE_FBCDC_ARCHITECTURE >= 3)
-		case 69: pszTagID = "PDS (Texas 7)"; i32SideBandType = RGXDBG_PDS; break;
-		case 70: pszTagID = "PBE (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
-		case 71: pszTagID = "FBCDC (Texas 7)"; i32SideBandType = RGXDBG_FBCDC; break;
-#else
-		case 69: pszTagID = "PDS (Texas 7)"; i32SideBandType = RGXDBG_PDS; break;
-		case 70: pszTagID = "PBE0 (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
-		case 71: pszTagID = "PBE1 (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
-#endif
 	}
-	
+	if(('-' == pszTagID[0]) && '\n' == pszTagID[1])
+	{
+
+		if((psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_50539_BIT_MASK) || \
+				(psDevInfo->sDevFeatureCfg.ui32FBCDCArch >= 3))
+		{
+			switch(ui32TagID)
+			{
+			case 18: pszTagID = "TPF_CPF (Black Pearl 0)"; i32SideBandType = RGXDBG_TPF_CPF; break;
+			case 19: pszTagID = "IPF_CPF (Black Pearl 0)"; i32SideBandType = RGXDBG_IPF_CPF; break;
+			case 34: pszTagID = "TPF_CPF (Black Pearl 1)"; i32SideBandType = RGXDBG_TPF_CPF; break;
+			case 35: pszTagID = "IPF_CPF (Black Pearl 1)"; i32SideBandType = RGXDBG_IPF_CPF; break;
+			case 50: pszTagID = "TPF_CPF (Black Pearl 2)"; i32SideBandType = RGXDBG_TPF_CPF; break;
+			case 51: pszTagID = "IPF_CPF (Black Pearl 2)"; i32SideBandType = RGXDBG_IPF_CPF; break;
+			case 66: pszTagID = "TPF_CPF (Black Pearl 3)"; i32SideBandType = RGXDBG_TPF_CPF; break;
+			case 67: pszTagID = "IPF_CPF (Black Pearl 3)"; i32SideBandType = RGXDBG_IPF_CPF; break;
+			}
+
+			if(psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_50539_BIT_MASK)
+			{
+				switch(ui32TagID)
+				{
+				case 9:	pszTagID = "PBE (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
+				case 10: pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
+				case 11: pszTagID = "FBCDC (Texas 0)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 21: pszTagID = "PBE (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
+				case 22: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
+				case 23: pszTagID = "FBCDC (Texas 1)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 25: pszTagID = "PBE (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
+				case 26: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
+				case 27: pszTagID = "FBCDC (Texas 2)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 37: pszTagID = "PBE (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
+				case 38: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
+				case 39: pszTagID = "FBCDC (Texas 3)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 41: pszTagID = "PBE (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
+				case 42: pszTagID = "PDS (Texas 4)"; i32SideBandType = RGXDBG_PDS; break;
+				case 43: pszTagID = "FBCDC (Texas 4)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 53: pszTagID = "PBE (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
+				case 54: pszTagID = "PDS (Texas 5)"; i32SideBandType = RGXDBG_PDS; break;
+				case 55: pszTagID = "FBCDC (Texas 5)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 57: pszTagID = "PBE (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
+				case 58: pszTagID = "PDS (Texas 6)"; i32SideBandType = RGXDBG_PDS; break;
+				case 59: pszTagID = "FBCDC (Texas 6)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 69: pszTagID = "PBE (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
+				case 70: pszTagID = "PDS (Texas 7)"; i32SideBandType = RGXDBG_PDS; break;
+				case 71: pszTagID = "FBCDC (Texas 7)"; i32SideBandType = RGXDBG_FBCDC; break;
+				}
+			}else
+			{
+				switch(ui32TagID)
+				{
+				case 9:	pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
+				case 10: pszTagID = "PBE (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
+				case 11: pszTagID = "FBCDC (Texas 0)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 21: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
+				case 22: pszTagID = "PBE (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
+				case 23: pszTagID = "FBCDC (Texas 1)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 25: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
+				case 26: pszTagID = "PBE (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
+				case 27: pszTagID = "FBCDC (Texas 2)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 37: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
+				case 38: pszTagID = "PBE (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
+				case 39: pszTagID = "FBCDC (Texas 3)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 41: pszTagID = "PDS (Texas 4)"; i32SideBandType = RGXDBG_PDS; break;
+				case 42: pszTagID = "PBE (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
+				case 43: pszTagID = "FBCDC (Texas 4)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 53: pszTagID = "PDS (Texas 5)"; i32SideBandType = RGXDBG_PDS; break;
+				case 54: pszTagID = "PBE (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
+				case 55: pszTagID = "FBCDC (Texas 5)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 57: pszTagID = "PDS (Texas 6)"; i32SideBandType = RGXDBG_PDS; break;
+				case 58: pszTagID = "PBE (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
+				case 59: pszTagID = "FBCDC (Texas 6)"; i32SideBandType = RGXDBG_FBCDC; break;
+				case 69: pszTagID = "PDS (Texas 7)"; i32SideBandType = RGXDBG_PDS; break;
+				case 70: pszTagID = "PBE (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
+				case 71: pszTagID = "FBCDC (Texas 7)"; i32SideBandType = RGXDBG_FBCDC; break;
+				}
+			}
+		}else
+		{
+			switch(ui32TagID)
+			{
+			case 9:	pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
+			case 10: pszTagID = "PBE0 (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
+			case 11: pszTagID = "PBE1 (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
+			case 18: pszTagID = "VCE (Black Pearl 0)"; i32SideBandType = RGXDBG_VCE; break;
+			case 19: pszTagID = "FBCDC (Black Pearl 0)"; i32SideBandType = RGXDBG_FBCDC; break;
+			case 21: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
+			case 22: pszTagID = "PBE0 (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
+			case 23: pszTagID = "PBE1 (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
+			case 25: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
+			case 26: pszTagID = "PBE0 (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
+			case 27: pszTagID = "PBE1 (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
+			case 34: pszTagID = "VCE (Black Pearl 1)"; i32SideBandType = RGXDBG_VCE; break;
+			case 35: pszTagID = "FBCDC (Black Pearl 1)"; i32SideBandType = RGXDBG_FBCDC; break;
+			case 37: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
+			case 38: pszTagID = "PBE0 (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
+			case 39: pszTagID = "PBE1 (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
+			case 41: pszTagID = "PDS (Texas 4)"; i32SideBandType = RGXDBG_PDS; break;
+			case 42: pszTagID = "PBE0 (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
+			case 43: pszTagID = "PBE1 (Texas 4)"; i32SideBandType = RGXDBG_PBE; break;
+			case 50: pszTagID = "VCE (Black Pearl 2)"; i32SideBandType = RGXDBG_VCE; break;
+			case 51: pszTagID = "FBCDC (Black Pearl 2)"; i32SideBandType = RGXDBG_FBCDC; break;
+			case 53: pszTagID = "PDS (Texas 5)"; i32SideBandType = RGXDBG_PDS; break;
+			case 54: pszTagID = "PBE0 (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
+			case 55: pszTagID = "PBE1 (Texas 5)"; i32SideBandType = RGXDBG_PBE; break;
+			case 57: pszTagID = "PDS (Texas 6)"; i32SideBandType = RGXDBG_PDS; break;
+			case 58: pszTagID = "PBE0 (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
+			case 59: pszTagID = "PBE1 (Texas 6)"; i32SideBandType = RGXDBG_PBE; break;
+			case 66: pszTagID = "VCE (Black Pearl 3)"; i32SideBandType = RGXDBG_VCE; break;
+			case 67: pszTagID = "FBCDC (Black Pearl 3)"; i32SideBandType = RGXDBG_FBCDC; break;
+			case 69: pszTagID = "PDS (Texas 7)"; i32SideBandType = RGXDBG_PDS; break;
+			case 70: pszTagID = "PBE0 (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
+			case 71: pszTagID = "PBE1 (Texas 7)"; i32SideBandType = RGXDBG_PBE; break;
+			}
+		}
+
+	}
+
 	switch (i32SideBandType)
 	{
 		case RGXDBG_META:
@@ -1270,7 +1353,7 @@
 			}
 			break;
 		}
-		
+
 		case RGXDBG_IPF:
 		{
 			switch (ui32TagSB)
@@ -1343,7 +1426,7 @@
 			{
 				ui32TagSB |= 0x20;
 			}
-			
+
 			switch (ui32TagSB)
 			{
 				case 0x00: pszTagSB = "FBDC Request, originator ZLS"; break;
@@ -1396,8 +1479,16 @@
 	*ppszTagID = pszTagID;
 	*ppszTagSB = pszTagSB;
 }
-#endif
 
+static void ConvertOSTimestampToSAndNS(IMG_UINT64 ui64OSTimer,
+							IMG_UINT64 *pui64Seconds,
+							IMG_UINT64 *pui64Nanoseconds)
+{
+	IMG_UINT32 ui32Remainder;
+
+	*pui64Seconds = OSDivide64r64(ui64OSTimer, 1000000000, &ui32Remainder);
+	*pui64Nanoseconds = ui64OSTimer - (*pui64Seconds * 1000000000ULL);
+}
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
 
@@ -1435,35 +1526,57 @@
 						IMG_UINT32 ui32Index)
 {
 	IMG_UINT32 ui32Remainder;
+	IMG_UINT64 ui64Seconds, ui64Nanoseconds;
+
+	ConvertOSTimestampToSAndNS(psResult->ui64When,
+							&ui64Seconds,
+							&ui64Nanoseconds);
 
 	if(psFaultProcessInfo->uiPID != RGXMEM_SERVER_PID_FIRMWARE)
 	{
 		PVR_DUMPDEBUG_LOG("  [%u] Name: %s Base address: " IMG_DEV_VIRTADDR_FMTSPEC
 					" Size: " IMG_DEVMEM_SIZE_FMTSPEC
-					" Allocated: %c Modified %llu us ago (abs time %llu us)",
+					" Operation: %s Modified: %llu us ago (OS time %llu.%09llu us)",
 										ui32Index,
 										psResult->szString,
 						(unsigned long long) psResult->sBaseDevVAddr.uiAddr,
 						(unsigned long long) psResult->uiSize,
-						psResult->bAllocated ? 'Y' : 'N',
+						psResult->bMap ? "Map": "Unmap",
 						(unsigned long long) OSDivide64r64(psResult->ui64Age, 1000, &ui32Remainder),
-						(unsigned long long) OSDivide64r64(psResult->ui64When, 1000, &ui32Remainder));
+						(unsigned long long) ui64Seconds,
+						(unsigned long long) ui64Nanoseconds);
 	}
 	else
 	{
 		PVR_DUMPDEBUG_LOG("  [%u] Name: %s Base address: " IMG_DEV_VIRTADDR_FMTSPEC
 					" Size: " IMG_DEVMEM_SIZE_FMTSPEC
-					" Allocated: %c Modified %llu us ago (abs time %llu us) PID: %u (%s)",
+					" Operation: %s Modified: %llu us ago (OS time  %llu.%09llu) PID: %u (%s)",
 										ui32Index,
 										psResult->szString,
 						(unsigned long long) psResult->sBaseDevVAddr.uiAddr,
 						(unsigned long long) psResult->uiSize,
-						psResult->bAllocated ? 'Y' : 'N',
+						psResult->bMap ? "Map": "Unmap",
 						(unsigned long long) OSDivide64r64(psResult->ui64Age, 1000, &ui32Remainder),
-						(unsigned long long) OSDivide64r64(psResult->ui64When, 1000, &ui32Remainder),
+						(unsigned long long) ui64Seconds,
+						(unsigned long long) ui64Nanoseconds,
 						(unsigned int) psResult->sProcessInfo.uiPID,
 						psResult->sProcessInfo.szProcessName);
 	}
+
+	if(!psResult->bRange)
+	{
+		PVR_DUMPDEBUG_LOG("      Whole allocation was %s", psResult->bMap ? "mapped": "unmapped");
+	}
+	else
+	{
+		PVR_DUMPDEBUG_LOG("      Pages %u to %u (" IMG_DEV_VIRTADDR_FMTSPEC "-" IMG_DEV_VIRTADDR_FMTSPEC ") %s%s",
+										psResult->ui32StartPage,
+										psResult->ui32StartPage + psResult->ui32PageCount - 1,
+										psResult->sMapStartAddr.uiAddr,
+										psResult->sMapEndAddr.uiAddr,
+										psResult->bAll ? "(whole allocation) " : "",
+										psResult->bMap ? "mapped": "unmapped");
+	}
 }
 
 /*!
@@ -1603,7 +1716,13 @@
 				break;
 		}
 
-		bHits = DevicememHistoryQuery(&sQueryIn, &asQueryOut[i]);
+		/* First try matching any record at the exact address... */
+		bHits = DevicememHistoryQuery(&sQueryIn, &asQueryOut[i], ui32PageSizeBytes, IMG_FALSE);
+		if (!bHits)
+		{
+			/* If not matched then try matching any record in the same page... */
+			bHits = DevicememHistoryQuery(&sQueryIn, &asQueryOut[i], ui32PageSizeBytes, IMG_TRUE);
+		}
 
 		if(bHits)
 		{
@@ -1723,7 +1842,7 @@
 	psInfo->sProcessInfo = *psProcessInfo;
 	psInfo->sFaultDevVAddr = sFaultDevVAddr;
 	psInfo->ui64CRTimer = ui64CRTimer;
-	psInfo->ui64When = OSClockus64();
+	psInfo->ui64When = OSClockns64();
 
 	/* if the page fault was caused by the firmware then get information about
 	 * which client application created the related allocations.
@@ -1799,31 +1918,37 @@
 					const IMG_UINT32 *pui32Index)
 {
 	IMG_UINT32 i;
+	IMG_UINT64 ui64Seconds, ui64Nanoseconds;
 
 	IMG_PID uiPID;
 
 	uiPID = (psInfo->sProcessInfo.uiPID == RGXMEM_SERVER_PID_FIRMWARE) ? 0 : psInfo->sProcessInfo.uiPID;
 
+	ConvertOSTimestampToSAndNS(psInfo->ui64When, &ui64Seconds, &ui64Nanoseconds);
+
 	if(pui32Index)
 	{
 		PVR_DUMPDEBUG_LOG("(%u) Device memory history for page fault address 0x%010llX, CRTimer: 0x%016llX, "
-							"PID: %u (%s, unregistered: %u) Abs Time: %llu us",
+							"PID: %u (%s, unregistered: %u) OS time: %llu.%09llu",
 					*pui32Index,
 					(unsigned long long) psInfo->sFaultDevVAddr.uiAddr,
 					psInfo->ui64CRTimer,
 					(unsigned int) uiPID,
 					psInfo->sProcessInfo.szProcessName,
 					psInfo->sProcessInfo.bUnregistered,
-					(unsigned long long) psInfo->ui64When);
+					(unsigned long long) ui64Seconds,
+					(unsigned long long) ui64Nanoseconds);
 	}
 	else
 	{
-		PVR_DUMPDEBUG_LOG("Device memory history for page fault address 0x%010llX, PID: %u (%s, unregistered: %u) Abs Time: %llu us",
+		PVR_DUMPDEBUG_LOG("Device memory history for page fault address 0x%010llX, PID: %u "
+							"(%s, unregistered: %u) OS time: %llu.%09llu",
 					(unsigned long long) psInfo->sFaultDevVAddr.uiAddr,
 					(unsigned int) uiPID,
 					psInfo->sProcessInfo.szProcessName,
 					psInfo->sProcessInfo.bUnregistered,
-					(unsigned long long) psInfo->ui64When);
+					(unsigned long long) ui64Seconds,
+					(unsigned long long) ui64Nanoseconds);
 	}
 
 	for(i = DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING; i < DEVICEMEM_HISTORY_QUERY_INDEX_COUNT; i++)
@@ -1853,8 +1978,6 @@
 #endif
 
 
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-
 /*!
 *******************************************************************************
 
@@ -1912,15 +2035,15 @@
 
 		/* MMU Status */
 		{
-			IMG_UINT32 ui32PC = 
+			IMG_UINT32 ui32PC =
 				(ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_CLRMSK) >>
 					RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_SHIFT;
 
-			IMG_UINT32 ui32PageSize = 
+			IMG_UINT32 ui32PageSize =
 				(ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_CLRMSK) >>
 					RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_SHIFT;
 
-			IMG_UINT32 ui32MMUDataType = 
+			IMG_UINT32 ui32MMUDataType =
 				(ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_CLRMSK) >>
 					RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_SHIFT;
 
@@ -1949,24 +2072,23 @@
 			IMG_CHAR aszScratch[RGX_DEBUG_STR_SIZE];
 
 			IMG_BOOL bRead = (ui64ReqStatus & RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_RNW_EN) != 0;
-			IMG_UINT32 ui32TagSB = 
+			IMG_UINT32 ui32TagSB =
 				(ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_CLRMSK) >>
 					RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_SHIFT;
-			IMG_UINT32 ui32TagID = 
+			IMG_UINT32 ui32TagID =
 				(ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_CLRMSK) >>
 							RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_SHIFT;
 			IMG_UINT64 ui64Addr = ((ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_CLRMSK) >>
 							RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_SHIFT) <<
 							RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_ALIGNSHIFT;
 
-#if defined(RGX_FEATURE_RAY_TRACING)
 			/* RNW bit offset is different. The TAG_SB, TAG_ID and address fields are the same. */
-			if (eBankID == RGXDBG_DPX_BIF)
+			if( (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK) && (eBankID == RGXDBG_DPX_BIF))
 			{
 				bRead = (ui64ReqStatus & DPX_CR_BIF_FAULT_BANK_REQ_STATUS_RNW_EN) != 0;
 			}
-#endif
-			_RGXDecodeBIFReqTags(eBankID, ui32TagID, ui32TagSB, &pszTagID, &pszTagSB, &aszScratch[0], RGX_DEBUG_STR_SIZE);
+
+			_RGXDecodeBIFReqTags(psDevInfo, eBankID, ui32TagID, ui32TagSB, &pszTagID, &pszTagSB, &aszScratch[0], RGX_DEBUG_STR_SIZE);
 
 			PVR_DUMPDEBUG_LOG("%s  * Request (0x%016llX): %s (%s), %s 0x%010llX.",
 							  pszIndent,
@@ -1983,10 +2105,10 @@
 
 		if (bSummary)
 		{
-			IMG_UINT32 ui32PC = 
+			IMG_UINT32 ui32PC =
 				(ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_CLRMSK) >>
 					RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_SHIFT;
-				
+
 			/* Only the first 8 cat bases are application memory contexts which we can validate... */
 			if (ui32PC < 8)
 			{
@@ -1995,7 +2117,7 @@
 			}
 			else
 			{
-				sPCDevPAddr.uiAddr = 0;
+				sPCDevPAddr.uiAddr = RGXFWIF_INVALID_PC_PHYADDR;
 			}
 		}
 		else
@@ -2075,10 +2197,8 @@
 	}
 
 }
-#endif
 
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 /*!
 *******************************************************************************
 
@@ -2148,7 +2268,7 @@
 		FAULT_INFO *psInfo;
 #endif
 
-		_RGXDecodeMMUReqTags(ui32Requester, ui32SideBand, bRead, &pszTagID, &pszTagSB, aszScratch, RGX_DEBUG_STR_SIZE);
+		_RGXDecodeMMUReqTags(psDevInfo, ui32Requester, ui32SideBand, bRead, &pszTagID, &pszTagSB, aszScratch, RGX_DEBUG_STR_SIZE);
 
 		PVR_DUMPDEBUG_LOG("%sMMU (%s) - FAULT:", pszIndent, pszMetaOrCore);
 		PVR_DUMPDEBUG_LOG("%s  * MMU status (0x%016llX): PC = %d, %s 0x%010llX, %s (%s)%s%s%s%s.",
@@ -2169,8 +2289,49 @@
 
 		if (bSummary)
 		{
-			/* It is not possible for the host to obtain the cat base address while the FW is running. */
-			sPCDevPAddr.uiAddr = 0;
+			/*
+			 *  The first 7 or 8 cat bases are memory contexts used for PM
+			 *  or firmware. The rest are application contexts.
+			 *
+			 *  It is not possible for the host to obtain the cat base
+			 *  address while the FW is running (since the cat bases are
+			 *  indirectly accessed), but in the case of the 'live' PC
+			 *  we can see if the FW has already logged it in the HWR log.
+			 */
+#if defined(SUPPORT_TRUSTED_DEVICE)
+			 if (ui32PC > 7)
+#else
+			 if (ui32PC > 6)
+#endif
+			 {
+				IMG_UINT32  ui32LatestHWRNumber = 0;
+				IMG_UINT64	ui64LatestMMUStatus = 0;
+				IMG_UINT64	ui64LatestPCAddress = 0;
+				IMG_UINT32  ui32HWRIndex;
+
+				for (ui32HWRIndex = 0 ;  ui32HWRIndex < RGXFWIF_HWINFO_MAX ;  ui32HWRIndex++)
+				{
+					RGX_HWRINFO  *psHWRInfo = &psDevInfo->psRGXFWIfHWRInfoBuf->sHWRInfo[ui32HWRIndex];
+
+					if (psHWRInfo->ui32HWRNumber > ui32LatestHWRNumber  &&
+					    psHWRInfo->eHWRType == RGX_HWRTYPE_MMUFAULT)
+					{
+						ui32LatestHWRNumber = psHWRInfo->ui32HWRNumber;
+						ui64LatestMMUStatus = psHWRInfo->uHWRData.sMMUInfo.ui64MMUStatus;
+						ui64LatestPCAddress = psHWRInfo->uHWRData.sMMUInfo.ui64PCAddress;
+					}
+				}
+
+				if (ui64LatestMMUStatus == ui64MMUStatus  &&  ui64LatestPCAddress != 0)
+				{
+					sPCDevPAddr.uiAddr = ui64LatestPCAddress;
+					PVR_DUMPDEBUG_LOG("%sLocated PC address: 0x%016llX", pszIndent, sPCDevPAddr.uiAddr);
+				}
+			}
+			else
+			{
+				sPCDevPAddr.uiAddr = RGXFWIF_INVALID_PC_PHYADDR;
+			}
 		}
 		else
 		{
@@ -2179,7 +2340,7 @@
 			sPCDevPAddr.uiAddr = ui64PCAddress;
 		}
 
-		if (bSummary)
+		if (bSummary  &&  sPCDevPAddr.uiAddr != 0)
 		{
 			PVR_DUMPDEBUG_LOG("%sChecking faulting address 0x%010llX",
 			                  pszIndent, sFaultDevVAddr.uiAddr);
@@ -2224,6 +2385,7 @@
 					else
 					{
 						/* no hits, so no data to present */
+						PVR_DUMPDEBUG_LOG("%sNo matching Devmem History for fault address", pszIndent);
 						psInfo = NULL;
 					}
 				}
@@ -2281,36 +2443,69 @@
 			  "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
 static_assert((RGX_CR_MMU_FAULT_STATUS_TYPE_SHIFT == RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT),
 			  "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
-#endif
 
 
-#if defined(RGX_FEATURE_MIPS) && !defined(NO_HARDWARE)
+
+#if !defined(NO_HARDWARE)
 static PVRSRV_ERROR _RGXMipsExtraDebug(PVRSRV_RGXDEV_INFO *psDevInfo, PVRSRV_DEVICE_CONFIG *psDevConfig, RGX_MIPS_STATE *psMIPSState)
 {
-	void *pvRegsBaseKM = OSMapPhysToLin(psDevConfig->sRegsCpuPBase, psDevConfig->ui32RegsSize, 0);
+	void *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
 	IMG_UINT32 ui32RegRead;
 	IMG_UINT32 eError = PVRSRV_OK;
 	/* This pointer contains a kernel mapping of a particular memory area shared
 	   between the driver and the firmware. This area is used for exchanging info
 	   about the internal state of the MIPS*/
 	IMG_UINT32 *pui32NMIMemoryPointer;
+	IMG_UINT32 *pui32NMIPageBasePointer;
+	IMG_BOOL bValid;
+	IMG_CPU_PHYADDR sCPUPhyAddrStart;
+	IMG_CPU_PHYADDR sCPUPhyAddrEnd;
+	PMR *psPMR = (PMR *)(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR);
 
-	/* Map the NMI data area to the kernel */
-	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
+	/* Map the FW code area to the kernel */
+	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc,
 									 (void **)&pui32NMIMemoryPointer);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"_RGXMipsExtraDebug: Failed to acquire NMI shared memory area (%u)", eError));
 		goto map_error_fail;
 	}
-	pui32NMIMemoryPointer += RGXMIPSFW_NMI_BASE_PAGE * RGXMIPSFW_PAGE_SIZE / sizeof(IMG_UINT32);
-	pui32NMIMemoryPointer += RGXMIPSFW_SHARED_DATA_BASE/sizeof(IMG_UINT32);
+
+	eError = PMR_CpuPhysAddr(psPMR,
+							 RGXMIPSFW_LOG2_PAGE_SIZE,
+							 1,
+							 RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * RGXMIPSFW_PAGE_SIZE,
+							 &sCPUPhyAddrStart,
+							 &bValid);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXBootldrDataInit: PMR_CpuPhysAddr failed (%u)",
+				eError));
+		return eError;
+	}
+
+	sCPUPhyAddrEnd.uiAddr = sCPUPhyAddrStart.uiAddr + RGXMIPSFW_PAGE_SIZE;
+
+	/* Jump to the boot/NMI data page */
+	pui32NMIMemoryPointer += RGXMIPSFW_GET_OFFSET_IN_DWORDS(RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * RGXMIPSFW_PAGE_SIZE);
+	pui32NMIPageBasePointer = pui32NMIMemoryPointer;
+
+	/* Jump to the NMI shared data area within the page above */
+	pui32NMIMemoryPointer += RGXMIPSFW_GET_OFFSET_IN_DWORDS(RGXMIPSFW_NMI_SHARED_DATA_BASE);
 
 	/* Acquire the NMI operations lock */
 	OSLockAcquire(psDevInfo->hNMILock);
 
 	/* Make sure the synchronization flag is set to 0 */
-	*(pui32NMIMemoryPointer + RGXMIPSFW_NMI_SYNC_FLAG_OFFSET/sizeof(IMG_UINT32)) = 0;
+	pui32NMIMemoryPointer[RGXMIPSFW_NMI_SYNC_FLAG_OFFSET] = 0;
+
+	/* Flush out the dirty locations of the NMI page */
+	OSFlushCPUCacheRangeKM(PMR_DeviceNode(psPMR),
+	                       pui32NMIPageBasePointer,
+	                       pui32NMIPageBasePointer + RGXMIPSFW_PAGE_SIZE/(sizeof(IMG_UINT32)),
+	                       sCPUPhyAddrStart,
+	                       sCPUPhyAddrEnd);
 
 	/* Enable NMI issuing in the MIPS wrapper */
 	OSWriteHWReg64(pvRegsBaseKM,
@@ -2354,8 +2549,14 @@
 	ui32RegRead = 0;
 
 	/* Allow the firmware to proceed */
-	*(pui32NMIMemoryPointer + RGXMIPSFW_NMI_SYNC_FLAG_OFFSET/sizeof(IMG_UINT32)) = 1;
+	pui32NMIMemoryPointer[RGXMIPSFW_NMI_SYNC_FLAG_OFFSET] = 1;
 
+	/* Flush out the dirty locations of the NMI page */
+	OSFlushCPUCacheRangeKM(PMR_DeviceNode(psPMR),
+	                       pui32NMIPageBasePointer,
+	                       pui32NMIPageBasePointer + RGXMIPSFW_PAGE_SIZE/(sizeof(IMG_UINT32)),
+	                       sCPUPhyAddrStart,
+	                       sCPUPhyAddrEnd);
 
 	/* Wait for the FW to have finished the NMI routine */
 	ui32RegRead = OSReadHWReg32(pvRegsBaseKM,
@@ -2378,30 +2579,167 @@
 	}
 	ui32RegRead = 0;
 
-	/* If we arrive here, the firmware has successfully saved the state, so we can read and return it*/
-	psMIPSState->ui32ErrorEPC = *(pui32NMIMemoryPointer + RGXMIPSFW_NMI_ERROR_EPC_OFFSET/sizeof(IMG_UINT32)) - 1;
-	psMIPSState->ui32StatusRegister = *(pui32NMIMemoryPointer + RGXMIPSFW_NMI_STATUS_REGISTER_OFFSET/sizeof(IMG_UINT32));
-	psMIPSState->ui32CauseRegister = *(pui32NMIMemoryPointer + RGXMIPSFW_NMI_CAUSE_REGISTER_OFFSET/sizeof(IMG_UINT32));
-	psMIPSState->ui32BadRegister = *(pui32NMIMemoryPointer + RGXMIPSFW_NMI_BAD_REGISTER_OFFSET/sizeof(IMG_UINT32));
-	psMIPSState->ui32EPC = *(pui32NMIMemoryPointer + RGXMIPSFW_NMI_EPC_OFFSET/sizeof(IMG_UINT32)) - 1;
-	psMIPSState->ui32UserLocalRegister = *(pui32NMIMemoryPointer + RGXMIPSFW_NMI_USERLOCAL_OFFSET/sizeof(IMG_UINT32));
+	/* Copy state */
+	OSDeviceMemCopy(psMIPSState, pui32NMIMemoryPointer + RGXMIPSFW_NMI_STATE_OFFSET, sizeof(*psMIPSState));
 
+	--(psMIPSState->ui32ErrorEPC);
+	--(psMIPSState->ui32EPC);
 
 	/* Disable NMI issuing in the MIPS wrapper */
 	OSWriteHWReg32(pvRegsBaseKM,
 				   RGX_CR_MIPS_WRAPPER_NMI_ENABLE,
 				   0);
 
+fail:
 	/* Release the NMI operations lock */
 	OSLockRelease(psDevInfo->hNMILock);
-
-fail:
-	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc);
 map_error_fail:
-	OSUnMapPhysToLin(pvRegsBaseKM, psDevConfig->ui32RegsSize, 0);
 	return eError;
 }
-#endif
+
+/* Print decoded information from cause register */
+static void _RGXMipsDumpCauseDecode(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile, IMG_UINT32 ui32Cause)
+{
+#define INDENT "    "
+	const IMG_UINT32 ui32ExcCode = RGXMIPSFW_C0_CAUSE_EXCCODE(ui32Cause);
+	const IMG_CHAR * const pszException = apszMIPSExcCodes[ui32ExcCode];
+
+	if (pszException != NULL)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Cause exception: %s", pszException);
+	}
+
+	/* IP Bits */
+	{
+		IMG_UINT32  ui32HWIRQStatus = RGXMIPSFW_C0_CAUSE_PENDING_HWIRQ(ui32Cause);
+		IMG_UINT32 i;
+
+		for (i = 0; i < RGXMIPSFW_C0_NBHWIRQ; ++i)
+		{
+			if (ui32HWIRQStatus & (1 << i))
+			{
+				PVR_DUMPDEBUG_LOG(INDENT "Hardware interrupt %d pending", i);
+				/* Can there be more than one HW irq pending or should we break? */
+			}
+		}
+	}
+
+	if (ui32Cause & RGXMIPSFW_C0_CAUSE_FDCIPENDING)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "FDC interrupt pending");
+	}
+
+	if (ui32Cause & RGXMIPSFW_C0_CAUSE_IV)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Interrupt uses special interrupt vector");
+	}
+
+	if (ui32Cause & RGXMIPSFW_C0_CAUSE_PCIPENDING)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Performance Counter Interrupt pending");
+	}
+
+	/* Unusable Coproc exception */
+	if (ui32ExcCode == 11)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Unusable Coprocessor: %d", RGXMIPSFW_C0_CAUSE_UNUSABLE_UNIT(ui32Cause));
+	}
+
+	if (ui32Cause & RGXMIPSFW_C0_CAUSE_TIPENDING)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Timer Interrupt pending");
+	}
+
+#undef INDENT
+}
+
+static void _RGXMipsDumpDebugDecode(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile, IMG_UINT32 ui32Debug, IMG_UINT32 ui32DEPC)
+{
+	const IMG_CHAR *pszDException = NULL;
+	IMG_UINT32 i;
+#define INDENT "    "
+
+	if (!(ui32Debug & RGXMIPSFW_C0_DEBUG_DM))
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Debug Mode is OFF");
+		return;
+	}
+
+	pszDException = apszMIPSExcCodes[RGXMIPSFW_C0_DEBUG_EXCCODE(ui32Debug)];
+
+	if (pszDException != NULL)
+	{
+		PVR_DUMPDEBUG_LOG(INDENT "Debug exception: %s", pszDException);
+	}
+
+	for (i = 0; i < IMG_ARR_NUM_ELEMS(sMIPS_C0_DebugTable); ++i)
+	{
+	    const RGXMIPSFW_C0_DEBUG_TBL_ENTRY * const psDebugEntry = &sMIPS_C0_DebugTable[i];
+
+	    if (ui32Debug & psDebugEntry->ui32Mask)
+	    {
+		PVR_DUMPDEBUG_LOG(INDENT "%s", psDebugEntry->pszExplanation);
+	    }
+	}
+#undef INDENT
+	PVR_DUMPDEBUG_LOG("DEPC                    :0x%08X", ui32DEPC);
+}
+
+static inline void _RGXMipsDumpTLBEntry(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile, const RGX_MIPS_TLB_ENTRY *psEntry, IMG_UINT32 ui32Index)
+{
+#define INDENT "    "
+#define DUMP_TLB_LO(ENTRY_LO, ENTRY_NUM)                                          \
+	PVR_DUMPDEBUG_LOG(INDENT "EntryLo" #ENTRY_NUM                                 \
+					  ":%s PFN = 0x%05X, %s%s",                                   \
+					  apszPermissionInhibit[RGXMIPSFW_TLB_GET_INHIBIT(ENTRY_LO)], \
+					  RGXMIPSFW_TLB_GET_PFN(ENTRY_LO),                            \
+					  apszCoherencyTBL[RGXMIPSFW_TLB_GET_COHERENCY(ENTRY_LO)],    \
+					  apszDirtyGlobalValid[RGXMIPSFW_TLB_GET_DGV(ENTRY_LO)])
+
+	static const IMG_CHAR * const apszPermissionInhibit[4] =
+	{
+		"",
+		" XI,",
+		" RI,",
+		" RI/XI,"
+	};
+
+	static const IMG_CHAR * const apszCoherencyTBL[8] =
+	{
+		"Cacheable",
+		"Cacheable",
+		"Uncached",
+		"Cacheable",
+		"Cacheable",
+		"Cacheable",
+		"Cacheable",
+		"Uncached"
+	};
+
+	static const IMG_CHAR * const apszDirtyGlobalValid[8] =
+	{
+		"",
+		", V",
+		", G",
+		", GV",
+		", D",
+		", DV",
+		", DG",
+		", DGV"
+	};
+
+	PVR_DUMPDEBUG_LOG("Entry %u, Page Mask: 0x%04X, EntryHi: VPN2 = 0x%05X", ui32Index, RGXMIPSFW_TLB_GET_MASK(psEntry->ui32TLBPageMask),
+					  RGXMIPSFW_TLB_GET_VPN2(psEntry->ui32TLBHi));
+
+	DUMP_TLB_LO(psEntry->ui32TLBLo0, 0);
+
+	DUMP_TLB_LO(psEntry->ui32TLBLo1, 1);
+
+#undef DUMP_TLB_LO
+}
+
+#endif /* defined(RGX_FEATURE_MIPS) && !defined(NO_HARDWARE) */
 
 /*!
 *******************************************************************************
@@ -2471,11 +2809,8 @@
 	IMG_UINT32      	dm, i;
 	IMG_UINT32      	ui32LineSize;
 	IMG_CHAR	    	*pszLine, *pszTemp;
-	const IMG_CHAR 		*apszDmNames[RGXFWIF_DM_MAX + 1] = { "GP(", "2D(", "TA(", "3D(", "CDM(",
-#if defined(RGX_FEATURE_RAY_TRACING)
-								 "RTU(", "SHG(",
-#endif /* RGX_FEATURE_RAY_TRACING */
-								 NULL };
+	IMG_CHAR 		*apszDmNames[] = { "GP(", "TDM(", "TA(", "3D(", "CDM(",
+								 "RTU(", "SHG(",NULL };
 
 	const IMG_CHAR 		*pszMsgHeader = "Number of HWR: ";
 	IMG_CHAR 			*pszLockupType = "";
@@ -2485,13 +2820,18 @@
 	IMG_UINT32			ui32HWRRecoveryFlags;
 	IMG_UINT32			ui32ReadIndex;
 
-	for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+	if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
 	{
-		if (psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[dm]  ||
-		    psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[dm])
+		apszDmNames[RGXFWIF_DM_TDM] = "2D(";
+	}
+
+	for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
+	{
+		if (psRGXFWIfTraceBufCtl->aui32HwrDmLockedUpCount[dm]  ||
+		    psRGXFWIfTraceBufCtl->aui32HwrDmOverranCount[dm])
 		{
 			bAnyLocked = IMG_TRUE;
-			break;					
+			break;
 		}
 	}
 
@@ -2502,12 +2842,12 @@
 	}
 
 	ui32LineSize = sizeof(IMG_CHAR) * (	ui32MsgHeaderSize + 
-			(RGXFWIF_DM_MAX*(	4/*DM name + left parenthesis*/ + 
-								5/*UINT16 max num of digits*/ + 
+			(psDevInfo->sDevFeatureCfg.ui32MAXDMCount*(	4/*DM name + left parenthesis*/ +
+								10/*UINT32 max num of digits*/ + 
 								1/*slash*/ + 
-								5/*UINT16 max num of digits*/ + 
+								10/*UINT32 max num of digits*/ + 
 								3/*right parenthesis + comma + space*/)) + 
-			7 + (RGXFWIF_DM_MAX*6)/* FALSE() + (UINT16 max num + comma) per DM */ +
+			7 + (psDevInfo->sDevFeatureCfg.ui32MAXDMCount*6)/* FALSE() + (UINT16 max num + comma) per DM */ +
 			1/* \0 */);
 
 	pszLine = OSAllocMem(ui32LineSize);
@@ -2520,27 +2860,27 @@
 	OSStringCopy(pszLine,pszMsgHeader);
 	pszTemp = pszLine + ui32MsgHeaderSize;
 
-	for (dm = 0; (dm < RGXFWIF_DM_MAX) && (apszDmNames[dm] != NULL); dm++)
+	for (dm = 0; (dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount) && (apszDmNames[dm] != NULL); dm++)
 	{
 		OSStringCopy(pszTemp,apszDmNames[dm]);
 		pszTemp += OSStringLength(apszDmNames[dm]);
-		pszTemp += OSSNPrintf(pszTemp, 
-				5 + 1 + 5 + 1 + 5 + 1 + 1 + 1 + 1 /* UINT16 + slash + UINT16 + plus + UINT16 + right parenthesis + comma + space + \0 */,
+		pszTemp += OSSNPrintf(pszTemp,
+				10 + 1 + 10 + 1 + 10 + 1 + 1 + 1 + 1 /* UINT32 + slash + UINT32 + plus + UINT32 + right parenthesis + comma + space + \0 */,
 				"%u/%u+%u), ",
-				psRGXFWIfTraceBufCtl->aui16HwrDmRecoveredCount[dm],
-				psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[dm],
-				psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[dm]);
+				psRGXFWIfTraceBufCtl->aui32HwrDmRecoveredCount[dm],
+				psRGXFWIfTraceBufCtl->aui32HwrDmLockedUpCount[dm],
+				psRGXFWIfTraceBufCtl->aui32HwrDmOverranCount[dm]);
 	}
 
 	OSStringCopy(pszTemp, "FALSE(");
 	pszTemp += 6;
 
-	for (dm = 0; (dm < RGXFWIF_DM_MAX) && (apszDmNames[dm] != NULL); dm++)
+	for (dm = 0; (dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount) && (apszDmNames[dm] != NULL); dm++)
 	{
-		pszTemp += OSSNPrintf(pszTemp, 
-				5 + 1 + 1 /* UINT16 max num + comma + \0 */,
-				(dm < RGXFWIF_DM_MAX-1 ? "%u," : "%u)"),
-				psRGXFWIfTraceBufCtl->aui16HwrDmFalseDetectCount[dm]);
+		pszTemp += OSSNPrintf(pszTemp,
+				10 + 1 + 1 /* UINT32 max num + comma + \0 */,
+				(dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount-1 ? "%u," : "%u)"),
+				psRGXFWIfTraceBufCtl->aui32HwrDmFalseDetectCount[dm]);
 	}
 
 	PVR_DUMPDEBUG_LOG(pszLine);
@@ -2548,7 +2888,7 @@
 	OSFreeMem(pszLine);
 
 	/* Print out per HWR info */
-	for (dm = 0; (dm < RGXFWIF_DM_MAX) && (apszDmNames[dm] != NULL); dm++)
+	for (dm = 0; (dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount) && (apszDmNames[dm] != NULL); dm++)
 	{
 		if (dm == RGXFWIF_DM_GP)
 		{
@@ -2566,92 +2906,135 @@
 
 			if((psHWRInfo->eDM == dm) && (psHWRInfo->ui32HWRNumber != 0))
 			{
+				IMG_CHAR  aui8RecoveryNum[10+10+1];
 				IMG_UINT64 ui64Seconds, ui64Nanoseconds;
-				IMG_UINT32 ui32Remainder;
 
 				/* Split OS timestamp in seconds and nanoseconds */
-				ui64Seconds = OSDivide64r64(psHWRInfo->ui64OSTimer, 1000000000, &ui32Remainder);
-				ui64Nanoseconds = psHWRInfo->ui64OSTimer - (ui64Seconds * 1000000000ULL);
-				
+				ConvertOSTimestampToSAndNS(psHWRInfo->ui64OSTimer, &ui64Seconds, &ui64Nanoseconds);
+
 				ui32HWRRecoveryFlags = psHWRInfo->ui32HWRRecoveryFlags;
 				if(ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_GUILTY_LOCKUP) { pszLockupType = ", Guilty Lockup"; }
 				else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_INNOCENT_LOCKUP) { pszLockupType = ", Innocent Lockup"; }
 				else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_GUILTY_OVERRUNING) { pszLockupType = ", Guilty Overrun"; }
 				else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_GUILTY_LOCKUP) { pszLockupType = ", Innocent Overrun"; }
 
-				PVR_DUMPDEBUG_LOG("  Recovery %d: PID = %d, frame = %d, HWRTData = 0x%08X,"
-				                   " EventStatus = 0x%08X, CRTimer = 0x%012llX, OSTimer = %llu.%09llu%s",
-				                   psHWRInfo->ui32HWRNumber,
+				OSSNPrintf(aui8RecoveryNum, sizeof(aui8RecoveryNum), "Recovery %d:", psHWRInfo->ui32HWRNumber);
+				PVR_DUMPDEBUG_LOG("  %s PID = %d, frame = %d, HWRTData = 0x%08X, EventStatus = 0x%08X%s",
+				                   aui8RecoveryNum,
 				                   psHWRInfo->ui32PID,
 				                   psHWRInfo->ui32FrameNum,
 				                   psHWRInfo->ui32ActiveHWRTData,
 				                   psHWRInfo->ui32EventStatus,
+				                   pszLockupType);
+				pszTemp = &aui8RecoveryNum[0];
+				while (*pszTemp != '\0')
+				{
+					*pszTemp++ = ' ';
+				}
+				PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012llX, OSTimer = %llu.%09llu, CyclesElapsed = %lld",
+				                   aui8RecoveryNum,
 				                   psHWRInfo->ui64CRTimer,
 				                   ui64Seconds,
 				                   ui64Nanoseconds,
-				                   pszLockupType);
+				                   (psHWRInfo->ui64CRTimer-psHWRInfo->ui64CRTimeOfKick)*256);
+				if (psHWRInfo->ui64CRTimeHWResetFinish != 0)
+				{
+					if (psHWRInfo->ui64CRTimeFreelistReady != 0)
+					{
+						PVR_DUMPDEBUG_LOG("  %s PreResetTimeInCycles = %lld, HWResetTimeInCycles = %lld, FreelistReconTimeInCycles = %lld, TotalRecoveryTimeInCycles = %lld",
+										   aui8RecoveryNum,
+										   (psHWRInfo->ui64CRTimeHWResetStart-psHWRInfo->ui64CRTimer)*256,
+										   (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimeHWResetStart)*256,
+										   (psHWRInfo->ui64CRTimeFreelistReady-psHWRInfo->ui64CRTimeHWResetFinish)*256,
+										   (psHWRInfo->ui64CRTimeFreelistReady-psHWRInfo->ui64CRTimer)*256);
+					}
+					else
+					{
+						PVR_DUMPDEBUG_LOG("  %s PreResetTimeInCycles = %lld, HWResetTimeInCycles = %lld, TotalRecoveryTimeInCycles = %lld",
+										   aui8RecoveryNum,
+										   (psHWRInfo->ui64CRTimeHWResetStart-psHWRInfo->ui64CRTimer)*256,
+										   (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimeHWResetStart)*256,
+										   (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimer)*256);
+					}
+				}
 
 				switch(psHWRInfo->eHWRType)
 				{
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
 					case RGX_HWRTYPE_BIF0FAULT:
 					case RGX_HWRTYPE_BIF1FAULT:
 					{
-						_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXFWIF_HWRTYPE_BIF_BANK_GET(psHWRInfo->eHWRType),
-										psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
-										psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
-										psHWRInfo->uHWRData.sBIFInfo.ui64PCAddress,
-										psHWRInfo->ui64CRTimer,
-										IMG_FALSE);
+						if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+						{
+							_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXFWIF_HWRTYPE_BIF_BANK_GET(psHWRInfo->eHWRType),
+											psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
+											psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
+											psHWRInfo->uHWRData.sBIFInfo.ui64PCAddress,
+											psHWRInfo->ui64CRTimer,
+											IMG_FALSE);
+						}
 					}
 					break;
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
 					case RGX_HWRTYPE_TEXASBIF0FAULT:
 					{
-						_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_TEXAS_BIF,
-										psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
-										psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
-										psHWRInfo->uHWRData.sBIFInfo.ui64PCAddress,
-										psHWRInfo->ui64CRTimer,
-										IMG_FALSE);
+						if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+						{
+							if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK)
+							{
+								_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_TEXAS_BIF,
+											psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
+											psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
+											psHWRInfo->uHWRData.sBIFInfo.ui64PCAddress,
+											psHWRInfo->ui64CRTimer,
+											IMG_FALSE);
+							}
+						}
 					}
 					break;
-#endif
-#if defined(RGX_FEATURE_RAY_TRACING)
 					case RGX_HWRTYPE_DPXMMUFAULT:
 					{
-						_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_DPX_BIF,
-										psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
-										psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
-										psHWRInfo->uHWRData.sBIFInfo.ui64PCAddress,
-										psHWRInfo->ui64CRTimer,
-										IMG_FALSE);
+						if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+						{
+							if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+							{
+									_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_DPX_BIF,
+													psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
+													psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
+													psHWRInfo->uHWRData.sBIFInfo.ui64PCAddress,
+													psHWRInfo->ui64CRTimer,
+													IMG_FALSE);
+							}
+						}
 					}
 					break;
-#endif
-#else
 					case RGX_HWRTYPE_MMUFAULT:
 					{
-						_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo,
-						                          psHWRInfo->uHWRData.sMMUInfo.ui64MMUStatus,
-						                          psHWRInfo->uHWRData.sMMUInfo.ui64PCAddress,
-						                          psHWRInfo->ui64CRTimer,
-						                          IMG_FALSE,
-						                          IMG_FALSE);
+						if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+						{
+							_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo,
+													  psHWRInfo->uHWRData.sMMUInfo.ui64MMUStatus,
+													  psHWRInfo->uHWRData.sMMUInfo.ui64PCAddress,
+													  psHWRInfo->ui64CRTimer,
+													  IMG_FALSE,
+													  IMG_FALSE);
+						}
 					}
 					break;
 
 					case RGX_HWRTYPE_MMUMETAFAULT:
 					{
-						_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo,
+						if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+						{
+
+							_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo,
 						                          psHWRInfo->uHWRData.sMMUInfo.ui64MMUStatus,
 						                          psHWRInfo->uHWRData.sMMUInfo.ui64PCAddress,
 						                          psHWRInfo->ui64CRTimer,
 						                          IMG_TRUE,
 						                          IMG_FALSE);
+						}
 					}
 					break;
-#endif
+
 
 					case RGX_HWRTYPE_POLLFAILURE:
 					{
@@ -2683,7 +3066,7 @@
 			else
 				ui32ReadIndex = (ui32ReadIndex + 1) - (ui32ReadIndex / RGXFWIF_HWINFO_LAST_INDEX) * RGXFWIF_HWINFO_MAX_LAST;
 		}
-	}	
+	}
 }
 
 #if !defined(NO_HARDWARE)
@@ -2779,66 +3162,73 @@
 {
 	IMG_CHAR *pszState, *pszReason;
 	RGXFWIF_TRACEBUF *psRGXFWIfTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+	IMG_UINT32 ui32OSid;
 
 #if defined(NO_HARDWARE)
 	PVR_UNREFERENCED_PARAMETER(bRGXPoweredON);
 #else
 	if (bRGXPoweredON)
 	{
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-		IMG_UINT64	ui64RegValMMUStatus;
-
-		ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS);
-		_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, ui64RegValMMUStatus, 0, 0, IMG_FALSE, IMG_TRUE);
-
-		ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS_META);
-		_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, ui64RegValMMUStatus, 0, 0, IMG_TRUE, IMG_TRUE);
-#else
-		IMG_UINT64	ui64RegValMMUStatus, ui64RegValREQStatus;
-
-		ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK0_MMU_STATUS);
-		ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK0_REQ_STATUS);
-
-		_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_BIF0, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
-
-#if !defined(RGX_FEATURE_SINGLE_BIF)
-		ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK1_MMU_STATUS);
-		ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK1_REQ_STATUS);
-
-		_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_BIF1, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
-#endif
-
-#if defined(RGX_FEATURE_CLUSTER_GROUPING)
-#if defined(RGX_NUM_PHANTOMS)
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
 		{
-			IMG_UINT32  ui32Phantom;
-			
-			for (ui32Phantom = 0;  ui32Phantom < RGX_NUM_PHANTOMS;  ui32Phantom++)
+
+			IMG_UINT64	ui64RegValMMUStatus;
+
+			ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS);
+			_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, ui64RegValMMUStatus, 0, 0, IMG_FALSE, IMG_TRUE);
+
+			ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS_META);
+			_RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, ui64RegValMMUStatus, 0, 0, IMG_TRUE, IMG_TRUE);
+		}else
+		{
+			IMG_UINT64	ui64RegValMMUStatus, ui64RegValREQStatus;
+
+			ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK0_MMU_STATUS);
+			ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK0_REQ_STATUS);
+
+			_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_BIF0, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
+
+			if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SINGLE_BIF_BIT_MASK))
 			{
-				/* This can't be done as it may interfere with the FW... */
-				/*OSWriteHWReg64(RGX_CR_TEXAS_INDIRECT, ui32Phantom);*/
-				
-				ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS);
-				ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS);
-
-				_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_TEXAS_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
+				ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK1_MMU_STATUS);
+				ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK1_REQ_STATUS);
+				_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_BIF1, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
 			}
+
+			if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK)
+			{
+				IMG_UINT32  ui32PhantomCnt = RGX_GET_NUM_PHANTOMS(psDevInfo->sDevFeatureCfg.ui32NumClusters);
+
+				if(ui32PhantomCnt > 1)
+				{
+					IMG_UINT32  ui32Phantom;
+					for (ui32Phantom = 0;  ui32Phantom < ui32PhantomCnt;  ui32Phantom++)
+					{
+						/* This can't be done as it may interfere with the FW... */
+						/*OSWriteHWReg64(RGX_CR_TEXAS_INDIRECT, ui32Phantom);*/
+
+						ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS);
+						ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS);
+
+						_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_TEXAS_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
+					}
+				}else
+				{
+					ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS);
+					ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS);
+
+					_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_TEXAS_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
+				}
+			}
+
+			if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+			{
+				ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, DPX_CR_BIF_FAULT_BANK_MMU_STATUS);
+				ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, DPX_CR_BIF_FAULT_BANK_REQ_STATUS);
+				_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_DPX_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
+			}
+
 		}
-#else
-		ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS);
-		ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS);
-
-		_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_TEXAS_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
-#endif
-#endif
-#endif
-
-#if defined(RGX_FEATURE_RAY_TRACING)
-		ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, DPX_CR_BIF_FAULT_BANK_MMU_STATUS);
-		ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, DPX_CR_BIF_FAULT_BANK_REQ_STATUS);
-
-		_RGXDumpRGXBIFBank(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, RGXDBG_DPX_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, 0, 0, IMG_TRUE);
-#endif
 
 		if(_CheckForPendingPage(psDevInfo))
 		{
@@ -2873,7 +3263,7 @@
 #endif /* NO_HARDWARE */
 
 	/* Firmware state */
-	switch (psDevInfo->psDeviceNode->eHealthStatus)
+	switch (OSAtomicRead(&psDevInfo->psDeviceNode->eHealthStatus))
 	{
 		case PVRSRV_DEVICE_HEALTH_STATUS_OK:  pszState = "OK";  break;
 		case PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING:  pszState = "NOT RESPONDING";  break;
@@ -2881,7 +3271,7 @@
 		default:  pszState = "UNKNOWN";  break;
 	}
 
-	switch (psDevInfo->psDeviceNode->eHealthReason)
+	switch (OSAtomicRead(&psDevInfo->psDeviceNode->eHealthReason))
 	{
 		case PVRSRV_DEVICE_HEALTH_REASON_NONE:  pszReason = "";  break;
 		case PVRSRV_DEVICE_HEALTH_REASON_ASSERTED:  pszReason = " - FW Assert";  break;
@@ -2899,7 +3289,7 @@
 		/* can't dump any more information */
 		return;
 	}
-	
+
 	PVR_DUMPDEBUG_LOG("RGX FW State: %s%s (HWRState 0x%08x)", pszState, pszReason, psRGXFWIfTraceBuf->ui32HWRStateFlags);
 	PVR_DUMPDEBUG_LOG("RGX FW Power State: %s (APM %s: %d ok, %d denied, %d other, %d total)",
 	                  pszPowStateName[psRGXFWIfTraceBuf->ePowState],
@@ -2909,7 +3299,16 @@
 	                  psDevInfo->ui32ActivePMReqTotal - psDevInfo->ui32ActivePMReqOk - psDevInfo->ui32ActivePMReqDenied,
 	                  psDevInfo->ui32ActivePMReqTotal);
 
+	for (ui32OSid = 0; ui32OSid < RGXFW_NUM_OS; ui32OSid++)
+	{
+		IMG_UINT32 ui32OSStateFlags = psRGXFWIfTraceBuf->ui32OSStateFlags[ui32OSid];
 
+		PVR_DUMPDEBUG_LOG("RGX FW OS %u State: 0x%08x (Active: %s%s, Freelists: %s)", ui32OSid, ui32OSStateFlags,
+						   ((ui32OSStateFlags & RGXFW_OS_STATE_ACTIVE_OS) != 0)?"Yes":"No",
+						   ((ui32OSStateFlags & RGXFW_OS_STATE_OFFLOADING) != 0)?"- offloading":"",
+						   ((ui32OSStateFlags & RGXFW_OS_STATE_FREELIST_OK) != 0)?"Ok":"Not Ok"
+						   );
+	}
 	_RGXDumpFWAssert(pfnDumpDebugPrintf, pvDumpDebugFile, psRGXFWIfTraceBuf);
 
 	_RGXDumpFWPoll(pfnDumpDebugPrintf, pvDumpDebugFile, psRGXFWIfTraceBuf);
@@ -2917,7 +3316,6 @@
 	_RGXDumpFWHWRInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psRGXFWIfTraceBuf, psDevInfo);
 }
 
-#if defined (RGX_FEATURE_META)
 static void _RGXDumpMetaSPExtraDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 						void *pvDumpDebugFile,
 						PVRSRV_RGXDEV_INFO *psDevInfo)
@@ -2926,6 +3324,7 @@
 #define RGX_META_SP_EXTRA_DEBUG \
 			X(RGX_CR_META_SP_MSLVCTRL0) \
 			X(RGX_CR_META_SP_MSLVCTRL1) \
+			X(RGX_CR_META_SP_MSLVDATAX) \
 			X(RGX_CR_META_SP_MSLVIRQSTATUS) \
 			X(RGX_CR_META_SP_MSLVIRQENABLE) \
 			X(RGX_CR_META_SP_MSLVIRQLEVEL)
@@ -2981,21 +3380,11 @@
 	}
 
 }
-#endif /* RGX_FEATURE_META */
-#endif /* PVRSRV_GPUVIRT_GUESTDRV  */
 
-/*
-	RGXDumpDebugInfo
-*/
 void RGXDumpDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 			void *pvDumpDebugFile,
 			PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	PVR_UNREFERENCED_PARAMETER(psDevInfo);
-	PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-	PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
-#else
 	IMG_UINT32 i;
 
 	for(i=0;i<=DEBUG_REQUEST_VERBOSITY_MAX;i++)
@@ -3003,12 +3392,8 @@
 		RGXDebugRequestProcess(pfnDumpDebugPrintf, pvDumpDebugFile,
 					psDevInfo, i);
 	}
-#endif
 }
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest driver do not support Firmware Trace log */
-#else
 /*
  *  Array of all the Firmware Trace log IDs used to convert the trace data.
  */
@@ -3019,9 +3404,10 @@
 	IMG_UINT32		 ui32ArgNum;
 } TRACEBUF_LOG;
 
-TRACEBUF_LOG aLogDefinitions[] = {
+static TRACEBUF_LOG aLogDefinitions[] =
+{
 #define X(a, b, c, d, e) {RGXFW_LOG_CREATESFID(a,b,e), #c, d, e},
-	RGXFW_LOG_SFIDLIST 
+	RGXFW_LOG_SFIDLIST
 #undef X
 };
 
@@ -3130,7 +3516,6 @@
 	/* Dump FW trace information... */
 	if (psRGXFWIfTraceBufCtl != NULL)
 	{
-		IMG_CHAR    szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
 		IMG_UINT32  tid;
 
 		/* Print the log type settings... */
@@ -3153,7 +3538,7 @@
 			IMG_UINT32  ui32TracePtr  = psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer;
 			IMG_UINT32  ui32Count     = 0;
 
-			if (pui32TraceBuf == 0x0)
+			if (pui32TraceBuf == NULL)
 			{
 				/* trace buffer not yet allocated */
 				continue;
@@ -3184,7 +3569,9 @@
 
 				if (ui32Count < RGXFW_TRACE_BUFFER_SIZE)
 				{
+					IMG_CHAR    szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN] = "%llu:T%u-%s> ";
 					IMG_UINT64  ui64Timestamp;
+					IMG_UINT    uiLen;
 
 					/* If we hit the ASSERT message then this is the end of the log... */
 					if (ui32Data == RGXFW_SF_MAIN_ASSERT_FAILED)
@@ -3201,9 +3588,9 @@
 					 *  printf function will be able to use. We have already checked
 					 *  that no string uses more than this.
 					 */
-					OSStringCopy(szBuffer, "%llu:T%u-%s> ");
 					OSStringCopy(&szBuffer[OSStringLength(szBuffer)], SFs[ui32DataToId].name);
-					szBuffer[OSStringLength(szBuffer)-1] = '\0';
+					uiLen = OSStringLength(szBuffer);
+					szBuffer[uiLen ? uiLen - 1 : 0] = '\0';
 					ui64Timestamp = (IMG_UINT64)(pui32TraceBuf[(ui32TracePtr +  0) % RGXFW_TRACE_BUFFER_SIZE]) << 32 |
 					               (IMG_UINT64)(pui32TraceBuf[(ui32TracePtr +  1) % RGXFW_TRACE_BUFFER_SIZE]);
 					PVR_DUMPDEBUG_LOG(szBuffer, ui64Timestamp, tid, groups[RGXFW_SF_GID(ui32Data)],
@@ -3237,6 +3624,22 @@
 	}
 }
 
+static const IMG_CHAR *_RGXGetDebugDevStateString(PVRSRV_DEVICE_STATE eDevState)
+{
+	switch (eDevState)
+	{
+		case PVRSRV_DEVICE_STATE_INIT:
+			return "Initialising";
+		case PVRSRV_DEVICE_STATE_ACTIVE:
+			return "Active";
+		case PVRSRV_DEVICE_STATE_DEINIT:
+			return "De-initialising";
+		case PVRSRV_DEVICE_STATE_UNDEFINED:
+			PVR_ASSERT(!"Device has undefined state");
+		default:
+			return "Unknown";
+	}
+}
 
 static IMG_CHAR* _RGXGetDebugDevPowerStateString(PVRSRV_DEV_POWER_STATE ePowerState)
 {
@@ -3248,7 +3651,6 @@
 		default: return "UNKNOWN";
 	}
 }
-#endif
 
 void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 				void *pvDumpDebugFile,
@@ -3256,14 +3658,8 @@
 				IMG_UINT32 ui32VerbLevel)
 {
 	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers do not perform device management */
-	PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-	PVR_UNREFERENCED_PARAMETER(psDevInfo);
-	PVR_UNREFERENCED_PARAMETER(ui32VerbLevel);
-#else
-	PVRSRV_ERROR eError = PVRSRVPowerLock();
+	PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+	PVRSRV_ERROR eError = PVRSRVPowerLock(psDeviceNode);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,	"RGXDebugRequestProcess : failed to acquire lock, error:0x%x", eError));
@@ -3274,13 +3670,10 @@
 	{
 		case DEBUG_REQUEST_VERBOSITY_LOW :
 		{
-			IMG_UINT32              ui32DeviceIndex;
 			PVRSRV_DEV_POWER_STATE  ePowerState;
 			IMG_BOOL                bRGXPoweredON;
 
-			ui32DeviceIndex = psDevInfo->psDeviceNode->sDevId.ui32DeviceIndex;
-
-			eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState);
+			eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 			if (eError != PVRSRV_OK)
 			{
 				PVR_DPF((PVR_DBG_ERROR, "RGXDebugRequestProcess: Error retrieving RGX power state. No debug info dumped."));
@@ -3296,7 +3689,11 @@
 			}
 
 			PVR_DUMPDEBUG_LOG("------[ RGX summary ]------");
-			PVR_DUMPDEBUG_LOG("RGX BVNC: %s", RGX_BVNC_KM);
+			PVR_DUMPDEBUG_LOG("RGX BVNC: %d.%d.%d.%d", psDevInfo->sDevFeatureCfg.ui32B, \
+													   psDevInfo->sDevFeatureCfg.ui32V,	\
+													   psDevInfo->sDevFeatureCfg.ui32N, \
+													   psDevInfo->sDevFeatureCfg.ui32C);
+			PVR_DUMPDEBUG_LOG("RGX Device State: %s", _RGXGetDebugDevStateString(psDeviceNode->eDevState));
 			PVR_DUMPDEBUG_LOG("RGX Power State: %s", _RGXGetDebugDevPowerStateString(ePowerState));
 
 			_RGXDumpRGXDebugSummary(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, bRGXPoweredON);
@@ -3308,18 +3705,29 @@
 				PVR_DUMPDEBUG_LOG("RGX Register Base Address (Linear):   0x%p", psDevInfo->pvRegsBaseKM);
 				PVR_DUMPDEBUG_LOG("RGX Register Base Address (Physical): 0x%08lX", (unsigned long)psDevInfo->sRegsPhysBase.uiAddr);
 
-#if defined(RGX_FEATURE_META)
-				/* Forcing bit 6 of MslvCtrl1 to 0 to avoid internal reg read going though the core */
-				OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x0);
-#endif
+				if(psDevInfo->sDevFeatureCfg.ui32META)
+				{
+					/* Forcing bit 6 of MslvCtrl1 to 0 to avoid internal reg read going through the core */
+					OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x0);
+				}
 
 				eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asDbgCommands, RGX_MAX_DEBUG_COMMANDS, PDUMP_FLAGS_CONTINUOUS, pfnDumpDebugPrintf, pvDumpDebugFile);
-#if defined(RGX_FEATURE_MIPS) && !defined(NO_HARDWARE)
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR,"RGXDebugRequestProcess: RGXRunScript failed (%d)", eError));
+					if(psDevInfo->sDevFeatureCfg.ui32META)
+					{
+						PVR_DPF((PVR_DBG_ERROR,"Dump Slave Port debug information"));
+						_RGXDumpMetaSPExtraDebugInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+					}
+				}
+#if !defined(NO_HARDWARE)
+				if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
 				{
 					RGX_MIPS_STATE sMIPSState;
 					PVRSRV_ERROR eError;
-					OSMemSet((void *)&sMIPSState, 0x00, sizeof(RGX_MIPS_STATE));
-					eError = _RGXMipsExtraDebug(psDevInfo, psDevInfo->psDeviceNode->psDevConfig, &sMIPSState);
+					OSCachedMemSet((void *)&sMIPSState, 0x00, sizeof(RGX_MIPS_STATE));
+					eError = _RGXMipsExtraDebug(psDevInfo, psDeviceNode->psDevConfig, &sMIPSState);
 					PVR_DUMPDEBUG_LOG("---- [ MIPS internal state ] ----");
 					if (eError != PVRSRV_OK)
 					{
@@ -3330,20 +3738,29 @@
 						PVR_DUMPDEBUG_LOG("PC                      :0x%08X", sMIPSState.ui32ErrorEPC);
 						PVR_DUMPDEBUG_LOG("STATUS_REGISTER         :0x%08X", sMIPSState.ui32StatusRegister);
 						PVR_DUMPDEBUG_LOG("CAUSE_REGISTER          :0x%08X", sMIPSState.ui32CauseRegister);
+						_RGXMipsDumpCauseDecode(pfnDumpDebugPrintf, pvDumpDebugFile, sMIPSState.ui32CauseRegister);
 						PVR_DUMPDEBUG_LOG("BAD_REGISTER            :0x%08X", sMIPSState.ui32BadRegister);
 						PVR_DUMPDEBUG_LOG("EPC                     :0x%08X", sMIPSState.ui32EPC);
+						PVR_DUMPDEBUG_LOG("SP                      :0x%08X", sMIPSState.ui32SP);
+						PVR_DUMPDEBUG_LOG("BAD_INSTRUCTION         :0x%08X", sMIPSState.ui32BadInstr);
+						PVR_DUMPDEBUG_LOG("DEBUG                   :");
+						_RGXMipsDumpDebugDecode(pfnDumpDebugPrintf, pvDumpDebugFile, sMIPSState.ui32Debug, sMIPSState.ui32DEPC);
+
+						{
+							IMG_UINT32 ui32Idx;
+
+							PVR_DUMPDEBUG_LOG("TLB                     :");
+							for (ui32Idx = 0; 
+								 ui32Idx < IMG_ARR_NUM_ELEMS(sMIPSState.asTLB);
+								 ++ui32Idx)
+							{
+								_RGXMipsDumpTLBEntry(pfnDumpDebugPrintf, pvDumpDebugFile, &sMIPSState.asTLB[ui32Idx], ui32Idx);
+							}
+						}
 					}
 					PVR_DUMPDEBUG_LOG("--------------------------------");
 				}
 #endif
-				if (eError != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_ERROR,"RGXDebugRequestProcess: RGXRunScript failed (%d)", eError));
-#if defined(RGX_FEATURE_META)
-					PVR_DPF((PVR_DBG_ERROR,"Dump Slave Port debug information"));
-					_RGXDumpMetaSPExtraDebugInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
-#endif
-				}
 			}
 			else
 			{
@@ -3380,11 +3797,17 @@
 				                  psDevInfo->psRGXFWIfTraceBuf->ui32KCCBCmdsExecuted);
 			}
 
-			/* Dump the IRQ info */
+			/* Dump the IRQ info for threads*/
 			{
-				PVR_DUMPDEBUG_LOG("RGX FW IRQ count = %d, last sampled in LISR = %d",
-				                  psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount,
-				                  g_ui32HostSampleIRQCount);
+				IMG_UINT32 ui32TID;
+
+				for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+				{
+					PVR_DUMPDEBUG_LOG("RGX FW thread %u: FW IRQ count = %u, Last sampled IRQ count in LISR = %u",
+									  ui32TID,
+									  psDevInfo->psRGXFWIfTraceBuf->aui32InterruptCount[ui32TID],
+									  psDevInfo->aui32SampleIRQCount[ui32TID]);
+				}
 			}
 
 			/* Dump the FW config flags */
@@ -3441,7 +3864,7 @@
 					pui32TraceBuffer = psRGXFWIfTraceBufCtl->sTraceBuf[tid].pui32TraceBuffer;
 
 					/* Skip if trace buffer is not allocated */
-					if (pui32TraceBuffer == 0x0)
+					if (pui32TraceBuffer == NULL)
 					{
 						PVR_DUMPDEBUG_LOG("RGX FW thread %d: Trace buffer not yet allocated",tid);
 						continue;
@@ -3458,25 +3881,25 @@
 					PVR_DUMPDEBUG_LOG("------[ RGX FW thread %d trace START ]------", tid);
 					PVR_DUMPDEBUG_LOG("FWT[traceptr]: %X", psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer);
 					PVR_DUMPDEBUG_LOG("FWT[tracebufsize]: %X", RGXFW_TRACE_BUFFER_SIZE);
-		
+
 					for (i = 0; i < RGXFW_TRACE_BUFFER_SIZE; i += RGXFW_TRACE_BUFFER_LINESIZE)
 					{
 						IMG_UINT32 k = 0;
 						IMG_UINT32 ui32Line = 0x0;
 						IMG_UINT32 ui32LineOffset = i*sizeof(IMG_UINT32);
 						IMG_CHAR   *pszBuf = pszLine;
-		
+
 						for (k = 0; k < RGXFW_TRACE_BUFFER_LINESIZE; k++)
 						{
 							ui32Line |= pui32TraceBuffer[i + k];
-		
+
 							/* prepare the line to print it. The '+1' is because of the trailing '\0' added */
 							OSSNPrintf(pszBuf, 9 + 1, " %08x", pui32TraceBuffer[i + k]);
 							pszBuf += 9; /* write over the '\0' */
 						}
-		
+
 						bLineIsAllZeros = (ui32Line == 0x0);
-		
+
 						if (bLineIsAllZeros)
 						{
 							if (bPrevLineWasZero)
@@ -3500,19 +3923,19 @@
 
 							PVR_DUMPDEBUG_LOG("FWT[%08x]:%s", ui32LineOffset, pszLine);
 						}
-		
+
 					}
 					if (bPrevLineWasZero)
 					{
 						PVR_DUMPDEBUG_LOG("FWT[END]: %d lines were all zero", ui32CountLines);
 					}
-		
+
 					PVR_DUMPDEBUG_LOG("------[ RGX FW thread %d trace END ]------", tid);
-		
+
 					OSFreeMem(pszLine);
 				}
 
-#if defined(RGX_FEATURE_META)
+				if(psDevInfo->sDevFeatureCfg.ui32META)
 				{
 					RGXFWIF_INIT *psRGXFWInit;
 
@@ -3547,7 +3970,6 @@
 
 					DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
 				}
-#endif
 			}
 
 			{
@@ -3558,25 +3980,25 @@
 #endif
 				CheckForStalledTransferCtxt(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile);
 				CheckForStalledRenderCtxt(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile);
-#if defined(RGX_FEATURE_COMPUTE)
-				CheckForStalledComputeCtxt(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile);
-#endif
-#if defined(RGX_FEATURE_RAY_TRACING)
-				CheckForStalledRayCtxt(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile);
-#endif
+				if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_COMPUTE_BIT_MASK)
+				{
+					CheckForStalledComputeCtxt(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile);
+				}
+				
+				if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+				{
+					CheckForStalledRayCtxt(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile);
+				}
 			}
 			break;
 		}
 		case DEBUG_REQUEST_VERBOSITY_HIGH:
 		{
 			PVRSRV_ERROR            eError;
-			IMG_UINT32              ui32DeviceIndex;
 			PVRSRV_DEV_POWER_STATE  ePowerState;
 			IMG_BOOL                bRGXPoweredON;
 
-			ui32DeviceIndex = psDevInfo->psDeviceNode->sDevId.ui32DeviceIndex;
-
-			eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState);
+			eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 			if (eError != PVRSRV_OK)
 			{
 				PVR_DPF((PVR_DBG_ERROR, "RGXDebugRequestProcess: Error retrieving RGX power state. No debug info dumped."));
@@ -3585,28 +4007,18 @@
 
 			bRGXPoweredON = (ePowerState == PVRSRV_DEV_POWER_STATE_ON);
 
-			PVR_DUMPDEBUG_LOG("------[ Debug bus ]------");
+			PVR_DUMPDEBUG_LOG("------[ Debug summary ]------");
 
 			_RGXDumpRGXDebugSummary(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, bRGXPoweredON);
-
-			if (bRGXPoweredON)
-			{
-				eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asDbgBusCommands, RGX_MAX_DBGBUS_COMMANDS, PDUMP_FLAGS_CONTINUOUS, pfnDumpDebugPrintf, pvDumpDebugFile);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_WARNING,"RGXDebugRequestProcess: RGXRunScript failed (%s)", PVRSRVGetErrorStringKM(eError)));
-				}
-				break;
-			}
 		}
 		default:
 			break;
 	}
 
 Exit:
-	PVRSRVPowerUnlock();
-#endif
+	PVRSRVPowerUnlock(psDeviceNode);
 }
+#endif
 
 /*
 	RGXPanic
@@ -3614,7 +4026,8 @@
 void RGXPanic(PVRSRV_RGXDEV_INFO	*psDevInfo)
 {
 	PVR_LOG(("RGX panic"));
-	PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+	PVRSRVDebugRequest(psDevInfo->psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX,
+					   NULL, NULL);
 	OSPanic();
 }
 
diff --git a/drivers/staging/imgtec/rogue/rgxdebug.h b/drivers/staging/imgtec/rogue/rgxdebug.h
index 84e6351..b05112b 100644
--- a/drivers/staging/imgtec/rogue/rgxdebug.h
+++ b/drivers/staging/imgtec/rogue/rgxdebug.h
@@ -47,10 +47,30 @@
 #include "pvrsrv_error.h"
 #include "img_types.h"
 #include "device.h"
+#include "pvr_notifier.h"
 #include "pvrsrv.h"
 #include "rgxdevice.h"
 
 
+/**
+ * Debug utility macro for printing FW IRQ count and Last sampled IRQ count in 
+ * LISR for each RGX FW thread.
+ * Macro takes pointer to PVRSRV_RGXDEV_INFO as input.
+ */
+#define RGXDEBUG_PRINT_IRQ_COUNT(psRgxDevInfo) \
+	do \
+	{ \
+		IMG_UINT32 ui32TID; \
+		for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++) \
+		{ \
+			PVR_DPF((DBGPRIV_VERBOSE, \
+					"RGX FW thread %u: FW IRQ count = %u, Last sampled IRQ count in LISR = %u)", \
+					ui32TID, \
+					(psRgxDevInfo)->psRGXFWIfTraceBuf->aui32InterruptCount[ui32TID], \
+					(psRgxDevInfo)->aui32SampleIRQCount[ui32TID])); \
+		} \
+	} while(0)
+
 /*!
 *******************************************************************************
 
diff --git a/drivers/staging/imgtec/rogue/rgxdevice.h b/drivers/staging/imgtec/rogue/rgxdevice.h
index b828ad4..754ba09 100644
--- a/drivers/staging/imgtec/rogue/rgxdevice.h
+++ b/drivers/staging/imgtec/rogue/rgxdevice.h
@@ -50,16 +50,19 @@
 #include "rgx_fwif_km.h"
 #include "rgx_fwif.h"
 #include "rgxscript.h"
-#include "cache_external.h"
+#include "cache_ops.h"
 #include "device.h"
 #include "osfunc.h"
 #include "rgxlayer_km_impl.h"
-
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "hash.h"
+#endif
 typedef struct _RGX_SERVER_COMMON_CONTEXT_ RGX_SERVER_COMMON_CONTEXT;
 
 typedef struct {
 	DEVMEM_MEMDESC		*psFWFrameworkMemDesc;
 	IMG_DEV_VIRTADDR	*psMCUFenceAddr;
+	IMG_DEV_VIRTADDR	*psResumeSignalAddr;
 } RGX_COMMON_CONTEXT_INFO;
 
 
@@ -70,7 +73,7 @@
 #define RGXKM_DEVICE_STATE_ZERO_FREELIST			(0x1 << 0)		/*!< Zeroing the physical pages of reconstructed free lists */
 #define RGXKM_DEVICE_STATE_FTRACE_EN				(0x1 << 1)		/*!< Used to enable device FTrace thread to consume HWPerf data */
 #define RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN 	(0x1 << 2)		/*!< Used to disable the Devices Watchdog logging */
-#define RGXKM_DEVICE_STATE_DUST_REQUEST_INJECT_EN		(0x1 << 3)		/*!< Used for validation to inject dust requests every TA/3D kick */
+#define RGXKM_DEVICE_STATE_DUST_REQUEST_INJECT_EN	(0x1 << 3)		/*!< Used for validation to inject dust requests every TA/3D kick */
 
 /*!
  ******************************************************************************
@@ -131,9 +134,92 @@
 	IMG_BOOL			bToggle;
 } RGX_DUST_STATE;
 
+typedef struct _PVRSRV_DEVICE_FEATURE_CONFIG_
+{
+	IMG_UINT64 ui64ErnsBrns;
+	IMG_UINT64 ui64Features;
+	IMG_UINT32 ui32B;
+	IMG_UINT32 ui32V;
+	IMG_UINT32 ui32N;
+	IMG_UINT32 ui32C;
+	IMG_UINT32 ui32NumClusters;
+	IMG_UINT32 ui32CtrlStreamFormat;
+	IMG_UINT32 ui32FBCDCArch;
+	IMG_UINT32 ui32META;
+	IMG_UINT32 ui32MCMB;
+	IMG_UINT32 ui32MCMS;
+	IMG_UINT32 ui32MDMACount;
+	IMG_UINT32 ui32NIIP;
+	IMG_UINT32 ui32PBW;
+	IMG_UINT32 ui32STEArch;
+	IMG_UINT32 ui32SVCE;
+	IMG_UINT32 ui32SLCBanks;
+	IMG_UINT32 ui32CacheLineSize;
+	IMG_UINT32 ui32SLCSize;
+	IMG_UINT32 ui32VASB;
+	IMG_UINT32 ui32MAXDMCount;
+	IMG_UINT32 ui32MAXDMMTSCount;
+	IMG_UINT32 ui32MAXDustCount;
+#define 	MAX_BVNC_STRING_LEN		(50)
+	IMG_PCHAR  pszBVNCString;
+}PVRSRV_DEVICE_FEATURE_CONFIG;
+
 /* there is a corresponding define in rgxapi.h */
 #define RGX_MAX_TIMER_QUERIES 16
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+/* For the workload estimation return data array */
+/* The max amount of commands the MTS can have is 255, therefore 512 (LOG2 = 9)
+ * is large enough to account for all corner cases.
+ */
+#define RETURN_DATA_ARRAY_SIZE_LOG2 (9)
+#define RETURN_DATA_ARRAY_SIZE      ((1UL) << RETURN_DATA_ARRAY_SIZE_LOG2)
+#define RETURN_DATA_ARRAY_WRAP_MASK (RETURN_DATA_ARRAY_SIZE - 1)
+
+#define WORKLOAD_HASH_SIZE 64
+
+typedef struct _WORKEST_HOST_DATA_ WORKEST_HOST_DATA;
+
+typedef struct _RGX_WORKLOAD_TA3D_
+{
+	IMG_UINT32				ui32RenderTargetSize;
+	IMG_UINT32				ui32NumberOfDrawCalls;
+	IMG_UINT32				ui32NumberOfIndices;
+	IMG_UINT32				ui32NumberOfMRTs;
+} RGX_WORKLOAD_TA3D;
+
+typedef struct _WORKLOAD_MATCHING_DATA_
+{
+	HASH_TABLE                  *psWorkloadDataHash;
+	RGX_WORKLOAD_TA3D           asWorkloadHashKeys[WORKLOAD_HASH_SIZE];
+	IMG_UINT64                  aui64HashCycleData[WORKLOAD_HASH_SIZE];
+	IMG_UINT32                  ui32HashArrayWO;
+	POS_LOCK                    psWorkEstHashLock;
+} WORKLOAD_MATCHING_DATA;
+
+struct _WORKEST_HOST_DATA_{
+	WORKLOAD_MATCHING_DATA      sWorkloadMatchingDataTA;
+	WORKLOAD_MATCHING_DATA      sWorkloadMatchingData3D;
+	IMG_UINT32                  ui32WorkEstCCBReceived;
+};
+typedef struct _WORKEST_RETURN_DATA_ {
+	WORKEST_HOST_DATA           *psWorkEstHostData;
+	WORKLOAD_MATCHING_DATA      *psWorkloadMatchingData;
+	RGX_WORKLOAD_TA3D           sWorkloadCharacteristics;
+} WORKEST_RETURN_DATA;
+#endif
+
+
+typedef struct
+{
+#if defined(PDUMP)
+	IMG_HANDLE      hPdumpPages;
+#endif
+	PG_HANDLE       sPages;
+	IMG_DEV_PHYADDR sPhysAddr;
+} RGX_MIPS_ADDRESS_TRAMPOLINE;
+
+
 /*!
  ******************************************************************************
  * RGX Device info
@@ -141,21 +227,22 @@
 
 typedef struct _PVRSRV_RGXDEV_INFO_
 {
-	PVRSRV_DEVICE_TYPE		eDeviceType;
-	PVRSRV_DEVICE_CLASS		eDeviceClass;
 	PVRSRV_DEVICE_NODE		*psDeviceNode;
 
-	IMG_UINT8				ui8VersionMajor;
-	IMG_UINT8				ui8VersionMinor;
-	IMG_UINT32				ui32CoreConfig;
-	IMG_UINT32				ui32CoreFlags;
+	PVRSRV_DEVICE_FEATURE_CONFIG	sDevFeatureCfg;
+
+	/* FIXME: This is a workaround due to having 2 inits but only 1 deinit */
+	IMG_BOOL				bDevInit2Done;
 
 	IMG_BOOL                bFirmwareInitialised;
 	IMG_BOOL				bPDPEnabled;
 
+	IMG_HANDLE				hDbgReqNotify;
+
 	/* Kernel mode linear address of device registers */
 	void					*pvRegsBaseKM;
 
+	/* FIXME: The alloc for this should go through OSAllocMem in future */
 	IMG_HANDLE				hRegMapping;
 
 	/* System physical address of device registers*/
@@ -184,9 +271,18 @@
 	DEVMEM_MEMDESC			*psFirmwareCCBMemDesc;      /*!< memdesc for Firmware CCB */
 	IMG_UINT8				*psFirmwareCCB;             /*!< kernel mapping for Firmware CCB */
 
+	/* Workload Estimation Firmware CCB */
+	DEVMEM_MEMDESC			*psWorkEstFirmwareCCBCtlMemDesc;   /*!< memdesc for Workload Estimation Firmware CCB control */
+	RGXFWIF_CCB_CTL			*psWorkEstFirmwareCCBCtl;          /*!< kernel mapping for Workload Estimation Firmware CCB control */
+	DEVMEM_MEMDESC			*psWorkEstFirmwareCCBMemDesc;      /*!< memdesc for Workload Estimation Firmware CCB */
+	IMG_UINT8				*psWorkEstFirmwareCCB;             /*!< kernel mapping for Workload Estimation Firmware CCB */
+
+	IMG_BOOL				bEnableFWPoisonOnFree;             /*!< Enable poisoning of FW allocations when freed */
+	IMG_BYTE				ubFWPoisonOnFreeValue;             /*!< Byte value used when poisoning FW allocations */
+
 	/*
-		if we don't preallocate the pagetables we must 
-		insert newly allocated page tables dynamically 
+		if we don't preallocate the pagetables we must
+		insert newly allocated page tables dynamically
 	*/
 	void					*pvMMUContextList;
 
@@ -198,6 +294,7 @@
 	IMG_DEV_VIRTADDR		sFWCodeDevVAddrBase;
 	DEVMEM_MEMDESC			*psRGXFWDataMemDesc;
 	IMG_DEV_VIRTADDR		sFWDataDevVAddrBase;
+	RGX_MIPS_ADDRESS_TRAMPOLINE	sTrampoline;
 
 	DEVMEM_MEMDESC			*psRGXFWCorememMemDesc;
 	IMG_DEV_VIRTADDR		sFWCorememCodeDevVAddrBase;
@@ -213,28 +310,30 @@
 	DEVMEM_MEMDESC			*psRGXFWSig3DChecksMemDesc;
 	IMG_UINT32				ui32Sig3DChecksSize;
 
-#if defined(RGX_FEATURE_RAY_TRACING)
 	DEVMEM_MEMDESC			*psRGXFWSigRTChecksMemDesc;
 	IMG_UINT32				ui32SigRTChecksSize;
-	
+
 	DEVMEM_MEMDESC			*psRGXFWSigSHChecksMemDesc;
 	IMG_UINT32				ui32SigSHChecksSize;
+
+#if defined (PDUMP)
+	IMG_BOOL				bDumpedKCCBCtlAlready;
 #endif
 
-	DEVMEM_MEMDESC			*psRGXFWIfTraceBufCtlMemDesc;			/*!< memdesc of trace buffer control structure */
-	DEVMEM_MEMDESC			*psRGXFWIfTraceBufferMemDesc[RGXFW_THREAD_NUM];	/*!< memdesc of actual FW trace (log) buffer(s) */
-	RGXFWIF_TRACEBUF		*psRGXFWIfTraceBuf;	/* structure containing trace control data and actual trace buffer */
-
 #if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* 
-		Guest drivers do not support these functionality:
-			- H/W perf & reset
-			- GPU dvfs, trace & utilization
+	/*
+		Guest drivers do not support these functionalities:
+			- H/W perf & device power management
 			- F/W initialization & management
+			- GPU dvfs, trace & utilization
 	 */
 	DEVMEM_MEMDESC			*psRGXFWIfInitMemDesc;
 	RGXFWIF_DEV_VIRTADDR	sFWInitFWAddr;
 #else
+	DEVMEM_MEMDESC			*psRGXFWIfTraceBufCtlMemDesc;	/*!< memdesc of trace buffer control structure */
+	DEVMEM_MEMDESC			*psRGXFWIfTraceBufferMemDesc[RGXFW_THREAD_NUM];	/*!< memdesc of actual FW trace (log) buffer(s) */
+	RGXFWIF_TRACEBUF		*psRGXFWIfTraceBuf;		/* structure containing trace control data and actual trace buffer */
+
 	DEVMEM_MEMDESC			*psRGXFWIfHWRInfoBufCtlMemDesc;
 	RGXFWIF_HWRINFOBUF		*psRGXFWIfHWRInfoBuf;
 
@@ -261,35 +360,54 @@
 	DEVMEM_HEAP				*psGuestFirmwareHeap[RGXFW_NUM_OS-1];
 	DEVMEM_MEMDESC			*psGuestFirmwareMemDesc[RGXFW_NUM_OS-1];
 #endif
-
 	DEVMEM_MEMDESC			*psMETAT1StackMemDesc;
 
-#if defined (PDUMP)
-	IMG_BOOL				bDumpedKCCBCtlAlready;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	/* Array to store data needed for workload estimation when a workload
+	 * has finished and its cycle time is returned to the host.
+	 */
+	WORKEST_RETURN_DATA		asReturnData[RETURN_DATA_ARRAY_SIZE];
+	IMG_UINT32				ui32ReturnDataWO;
 #endif
 
-	/*! Handles to the lock and stream objects used to transport
-	 * HWPerf data to user side clients. See RGXHWPerfInitOnDemandResources()
-	 * and RGXHWPerfDeinit().
-	 * Set during initialisation if the application hint turns bit 7
-	 * 'Enable HWPerf' on in the ConfigFlags sent to the FW. FW stores this
-	 * bit in the RGXFW_CTL.ui32StateFlags member. They may also get
-	 * set by the API RGXCtrlHWPerf(). Thus these members may be 0 if HWPerf is
-	 * not enabled as these members are created on demand and destroyed at
-	 * driver unload.
+#if defined (SUPPORT_PDVFS)
+	/**
+	 * Host memdesc and pointer to memory containing core clock rate in Hz.
+	 * Firmware (PDVFS) updates the memory on changing the core clock rate over
+	 * GPIO.
+	 * Note: Shared memory needs atomic access from Host driver and firmware,
+	 * hence size should not be greater than memory transaction granularity.
+	 * Currently it's is chosen to be 32 bits.
 	 */
-	POS_LOCK 				hLockHWPerfModule;
-	IMG_HANDLE				hHWPerfStream;
-	IMG_UINT64				ui64HWPerfFilter; /*! Event filter for HWPerf stream (settable by AppHint) */
-	IMG_BOOL				bHWPerfHostEnabled; /*! HWPerfHost enable flag (settable by AppHint */
-	IMG_UINT32				ui32HWPerfHostFilter; /*! Event filter for HWPerfHost stream (settable by AppHint) */
-	POS_LOCK 				hLockHWPerfHostStream; /*! Lock guarding access to HWPerfHost stream */
-	IMG_HANDLE				hHWPerfHostStream; /*! Host side only HWPerf stream */
-	IMG_UINT32				ui32HWPerfHostNextOrdinal; /*! Ordinal number for HWPerfHost */
-#if defined(SUPPORT_GPUTRACE_EVENTS)
-	void					*pvGpuFtraceData;
+	DEVMEM_MEMDESC			*psRGXFWIFCoreClkRateMemDesc;
+	volatile IMG_UINT32		*pui32RGXFWIFCoreClkRate;
+	/**
+	 * Last sampled core clk rate.
+	 */
+	volatile IMG_UINT32		ui32CoreClkRateSnapshot;
 #endif
-	
+	/*
+	   HWPerf data for the RGX device
+	 */
+
+	POS_LOCK    hHWPerfLock;  /*! Critical section lock that protects HWPerf code
+	                           *  from multiple thread duplicate init/deinit
+	                           *  and loss/freeing of FW & Host resources while in
+	                           *  use in another thread e.g. MSIR. */
+
+	IMG_UINT64  ui64HWPerfFilter; /*! Event filter for FW events (settable by AppHint) */
+	IMG_HANDLE  hHWPerfStream;    /*! TL Stream buffer (L2) for firmware event stream */
+
+	IMG_UINT32  ui32HWPerfHostFilter;      /*! Event filter for HWPerfHost stream (settable by AppHint) */
+	POS_LOCK    hLockHWPerfHostStream;     /*! Lock guarding access to HWPerfHost stream from multiple threads */
+	IMG_HANDLE  hHWPerfHostStream;         /*! TL Stream buffer for host only event stream */
+	IMG_UINT32  ui32HWPerfHostBufSize;     /*! Host side buffer size in bytes */
+	IMG_UINT32  ui32HWPerfHostNextOrdinal; /*! Ordinal number for HWPerfHost events */
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+	void        *pvGpuFtraceData;
+#endif
+
 	/* Poll data for detecting firmware fatal errors */
 	IMG_UINT32				aui32CrLastPollAddr[RGXFW_THREAD_NUM];
 	IMG_UINT32				ui32KCCBCmdsExecutedLastTime;
@@ -297,24 +415,26 @@
 	IMG_UINT32				ui32GEOTimeoutsLastTime;
 
 	/* Client stall detection */
-	IMG_BOOL				bStalledClient;
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
+	IMG_UINT32				ui32StalledClientMask;
+#endif
+
+	IMG_BOOL				bWorkEstEnabled;
+	IMG_BOOL				bPDVFSEnabled;
 
 	void					*pvLISRData;
 	void					*pvMISRData;
 	void					*pvAPMISRData;
-	
+	RGX_ACTIVEPM_CONF		eActivePMConf;
+
+	volatile IMG_UINT32		aui32SampleIRQCount[RGXFW_THREAD_NUM];
+
 	DEVMEM_MEMDESC			*psRGXFaultAddressMemDesc;
 
-#if defined(FIX_HW_BRN_37200)
 	DEVMEM_MEMDESC			*psRGXFWHWBRN37200MemDesc;
-#endif
 
-#if defined(RGX_FEATURE_SLC_VIVT)
 	DEVMEM_MEMDESC			*psSLC3FenceMemDesc;
-#endif
 
-	/* If we do 10 deferred memory allocations per second, then the ID would warp around after 13 years */
+	/* If we do 10 deferred memory allocations per second, then the ID would wrap around after 13 years */
 	IMG_UINT32				ui32ZSBufferCurrID;	/*!< ID assigned to the next deferred devmem allocation */
 	IMG_UINT32				ui32FreelistCurrID;	/*!< ID assigned to the next freelist */
 	IMG_UINT32				ui32RPMFreelistCurrID;	/*!< ID assigned to the next RPM freelist */
@@ -325,16 +445,17 @@
 	DLLIST_NODE				sFreeListHead;		/*!< List of growable Freelists */
 	POS_LOCK 				hLockRPMFreeList;	/*!< Lock to protect simultaneous access to RPM Freelists */
 	DLLIST_NODE				sRPMFreeListHead;	/*!< List of growable RPM Freelists */
+	POS_LOCK				hLockRPMContext;	/*!< Lock to protect simultaneous access to RPM contexts */
 	PSYNC_PRIM_CONTEXT		hSyncPrimContext;
 	PVRSRV_CLIENT_SYNC_PRIM *psPowSyncPrim;
 
 	IMG_UINT32				ui32ActivePMReqOk;
 	IMG_UINT32				ui32ActivePMReqDenied;
 	IMG_UINT32				ui32ActivePMReqTotal;
-	
+
 	IMG_HANDLE				hProcessQueuesMISR;
 
-	IMG_UINT32 				ui32DeviceFlags;		/*!< Flags to track general device state  */
+	IMG_UINT32 				ui32DeviceFlags;		/*!< Flags to track general device state */
 
 	/* Timer Queries */
 	IMG_UINT32				ui32ActiveQueryId;		/*!< id of the active line */
@@ -351,9 +472,7 @@
 	DEVMEM_MEMDESC			*psCompletedMemDesc;	/*!< kicks Completed on QueryId */
 	IMG_UINT32				*pui32CompletedById;	/*!< CPU mapping of the above */
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers currently do not support GPU DVFS/Utilization  */
-#else
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	/* GPU DVFS Table */
 	RGX_GPU_DVFS_TABLE  *psGpuDVFSTable;
 
@@ -372,7 +491,7 @@
 	                                    RGXFWIF_GPU_UTIL_STATS *psReturnStats);
 #endif
 
-	POS_LOCK    			hGPUUtilLock;
+	POS_LOCK				hGPUUtilLock;
 
 	/* Register configuration */
 	RGX_REG_CONFIG			sRegCongfig;
@@ -383,35 +502,40 @@
 	POSWR_LOCK				hRenderCtxListLock;
 	POSWR_LOCK				hComputeCtxListLock;
 	POSWR_LOCK				hTransferCtxListLock;
+	POSWR_LOCK				hTDMCtxListLock;
 	POSWR_LOCK				hRaytraceCtxListLock;
 	POSWR_LOCK				hMemoryCtxListLock;
 	POSWR_LOCK				hKickSyncCtxListLock;
 
 	/* Linked list of deferred KCCB commands due to a full KCCB */
-	DLLIST_NODE 			sKCCBDeferredCommandsListHead;
+	DLLIST_NODE				sKCCBDeferredCommandsListHead;
 
 	/* Linked lists of contexts on this device */
-	DLLIST_NODE 			sRenderCtxtListHead;
-	DLLIST_NODE 			sComputeCtxtListHead;
-	DLLIST_NODE 			sTransferCtxtListHead;
-	DLLIST_NODE 			sRaytraceCtxtListHead;
-	DLLIST_NODE 			sKickSyncCtxtListHead;	
+	DLLIST_NODE				sRenderCtxtListHead;
+	DLLIST_NODE				sComputeCtxtListHead;
+	DLLIST_NODE				sTransferCtxtListHead;
+	DLLIST_NODE				sTDMCtxtListHead;
+	DLLIST_NODE				sRaytraceCtxtListHead;
+	DLLIST_NODE				sKickSyncCtxtListHead;
 
 	DLLIST_NODE 			sCommonCtxtListHead;
 	IMG_UINT32				ui32CommonCtxtCurrentID;	/*!< ID assigned to the next common context */
 
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	POS_LOCK 				hDebugFaultInfoLock;		/*!< Lock to protect the debug fault info list */
-	POS_LOCK 				hMMUCtxUnregLock;	/*!< Lock to protect list of unregistered MMU contexts */
+	POS_LOCK 				hDebugFaultInfoLock;	/*!< Lock to protect the debug fault info list */
+	POS_LOCK 				hMMUCtxUnregLock;		/*!< Lock to protect list of unregistered MMU contexts */
 #endif
 
-#if defined(RGX_FEATURE_MIPS)
 	POS_LOCK				hNMILock; /*!< Lock to protect NMI operations */
-#endif
 
 	RGX_DUST_STATE			sDustReqState;
 
 	RGX_POWER_LAYER_PARAMS	sPowerParams;
+
+	RGXFWIF_DM				eBPDM;					/*!< Current breakpoint data master */
+	IMG_BOOL				bBPSet;					/*!< A Breakpoint has been set */
+
+	IMG_UINT32				ui32CoherencyTestsDone;
 } PVRSRV_RGXDEV_INFO;
 
 
@@ -426,7 +550,7 @@
 
 	/*! Enable the GPU to power off internal Power Islands independently from the host driver */
 	IMG_BOOL			bEnableRDPowIsland;
-	
+
 	/*! Active Power Management: Delay between the GPU idle and the request to the host */
 	IMG_UINT32			ui32ActivePMLatencyms;
 
@@ -436,8 +560,8 @@
 {
 	/*! Timing information */
 	RGX_TIMING_INFORMATION	*psRGXTimingInfo;
-	IMG_BOOL bHasTDMetaCodePhysHeap;
-	IMG_UINT32 uiTDMetaCodePhysHeapID;
+	IMG_BOOL bHasTDFWCodePhysHeap;
+	IMG_UINT32 uiTDFWCodePhysHeapID;
 	IMG_BOOL bHasTDSecureBufPhysHeap;
 	IMG_UINT32 uiTDSecureBufPhysHeapID;
 } RGX_DATA;
diff --git a/drivers/staging/imgtec/rogue/rgxfw_log_helper.h b/drivers/staging/imgtec/rogue/rgxfw_log_helper.h
index ade2e9b..a68366a 100644
--- a/drivers/staging/imgtec/rogue/rgxfw_log_helper.h
+++ b/drivers/staging/imgtec/rogue/rgxfw_log_helper.h
@@ -48,7 +48,7 @@
 
 #include "rgx_fwif_sf.h"
 
-static IMG_CHAR *groups[]= {
+static IMG_CHAR *const groups[]= {
 #define X(A,B) #B,
 	RGXFW_LOG_SFGROUPLIST
 #undef X
@@ -61,7 +61,7 @@
 
 /*  The tuple pairs that will be generated using XMacros will be stored here.
  *   This macro definition must match the definition of SFids in rgx_fwif_sf.h */
-tuple SFs[]= {
+static const tuple SFs[]= {
 #define X(a, b, c, d, e) { RGXFW_LOG_CREATESFID(a,b,e) , d },
 	RGXFW_LOG_SFIDLIST
 #undef X
diff --git a/drivers/staging/imgtec/rogue/rgxfwimageutils.c b/drivers/staging/imgtec/rogue/rgxfwimageutils.c
index 4fc0b6e..437147f 100644
--- a/drivers/staging/imgtec/rogue/rgxfwimageutils.c
+++ b/drivers/staging/imgtec/rogue/rgxfwimageutils.c
@@ -41,12 +41,14 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+/* The routines implemented here are built on top of an abstraction layer to
+ * hide DDK/OS-specific details in case they are used outside of the DDK
+ * (e.g. when trusted device is enabled).
+ * Any new dependency should be added to rgxlayer.h.
+ * Any new code should be built on top of the existing abstraction layer,
+ * which should be extended when necessary. */
 #include "rgxfwimageutils.h"
 
-#if defined(RGX_FEATURE_MIPS)
-#include "pvr_debug.h"
-#endif
-
 
 /************************************************************************
 * FW Segments configuration
@@ -57,37 +59,116 @@
 	IMG_UINT32 ui32SegStartAddr; /*!< Segment Start Addr */
 	IMG_UINT32 ui32SegAllocSize; /*!< Amount of memory to allocate for that segment */
 	IMG_UINT32 ui32FWMemOffset;  /*!< Offset of this segment in the collated FW mem allocation */
-	IMG_CHAR   *pszSegName;
+	const IMG_CHAR *pszSegName;
 } RGX_FW_SEGMENT;
 
+typedef struct _RGX_FW_SEGMENT_LIST_
+{
+	RGX_FW_SEGMENT *psRGXFWCodeSeg;
+	RGX_FW_SEGMENT *psRGXFWDataSeg;
+	IMG_UINT32 ui32CodeSegCount;
+	IMG_UINT32 ui32DataSegCount;
+} RGX_FW_SEGMENT_LIST;
 
-#if defined(RGX_FEATURE_META)
-static RGX_FW_SEGMENT asRGXFWCodeSegments[] = {
+
+#if defined(RGX_FEATURE_META) || defined(SUPPORT_KERNEL_SRVINIT)
+static RGX_FW_SEGMENT asRGXMetaFWCodeSegments[] = {
 /* Seg ID                 Seg Start Addr           Alloc size   FWMem offset  Name */
-{RGXFW_SEGMMU_BOOTLDR_ID, RGXFW_BOOTLDR_META_ADDR, 0x1000,      0,            "Bootldr"}, /* Has to be the first one to get the proper DevV addr */
-{RGXFW_SEGMMU_TEXT_ID,    0x18880000,              0x30000,     0x1000,       "Local Text"},
+{RGXFW_SEGMMU_TEXT_ID,    RGXFW_BOOTLDR_META_ADDR, 0x31000,      0,           "Bootldr and Code"}, /* Has to be the first one to get the proper DevV addr */
 };
-static RGX_FW_SEGMENT asRGXFWDataSegments[] = {
+static RGX_FW_SEGMENT asRGXMetaFWDataSegments[] = {
 /* Seg ID                 Seg Start Addr           Alloc size   FWMem offset  Name */
-{RGXFW_SEGMMU_SHARED_ID,  0x38880000,              0x5000,      0,            "Local Shared"},
-{RGXFW_SEGMMU_DATA_ID,    0x78880000,              0x12000,     0x5000,       "Local Data"},
+{RGXFW_SEGMMU_DATA_ID,    0x38880000,              0x17000,      0,           "Local Shared and Data"},
 };
-#else
-static RGX_FW_SEGMENT asRGXFWCodeSegments[] = {
-/* Seg ID                 Seg Start Addr           Alloc size             FWMem offset           Name */
-{    0,                   0xC0000000,          RGXMIPSFW_CODE_SIZE,         0x0,         "Text and static data"},
-};
-static RGX_FW_SEGMENT asRGXFWDataSegments[] = {
-/* Seg ID                 Seg Start Addr           Alloc size             FWMem offset           Name */
-{    0,                   0xC0000000,          RGXMIPSFW_PAGE_SIZE,          0x0,              "Stack"},
-};
+#define RGXFW_META_NUM_CODE_SEGMENTS  (sizeof(asRGXMetaFWCodeSegments)/sizeof(asRGXMetaFWCodeSegments[0]))
+#define RGXFW_META_NUM_DATA_SEGMENTS  (sizeof(asRGXMetaFWDataSegments)/sizeof(asRGXMetaFWDataSegments[0]))
 #endif
 
-#define RGXFW_NUM_CODE_SEGMENTS  (sizeof(asRGXFWCodeSegments)/sizeof(asRGXFWCodeSegments[0]))
-#define RGXFW_NUM_DATA_SEGMENTS  (sizeof(asRGXFWDataSegments)/sizeof(asRGXFWDataSegments[0]))
+#if defined(RGX_FEATURE_MIPS) || defined(SUPPORT_KERNEL_SRVINIT)
+static RGX_FW_SEGMENT asRGXMipsFWCodeSegments[] = {
+/* Seg ID   Seg Start Addr                         Alloc size                         FWMem offset                         Name */
+{    0,     RGXMIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE,  RGXMIPSFW_BOOT_NMI_CODE_SIZE,      RGXMIPSFW_BOOT_NMI_CODE_OFFSET,      "Bootldr and NMI code"},
+{    1,     RGXMIPSFW_EXCEPTIONS_VIRTUAL_BASE,     RGXMIPSFW_EXCEPTIONSVECTORS_SIZE,  RGXMIPSFW_EXCEPTIONSVECTORS_OFFSET,  "Exception vectors"},
+{    2,     RGXMIPSFW_CODE_VIRTUAL_BASE,           RGXMIPSFW_CODE_SIZE,               RGXMIPSFW_CODE_OFFSET,               "Text"},
+};
+static RGX_FW_SEGMENT asRGXMipsFWDataSegments[] = {
+/* Seg ID   Seg Start Addr                         Alloc size                         FWMem offset                         Name */
+{    3,     RGXMIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE,  RGXMIPSFW_BOOT_NMI_DATA_SIZE,      RGXMIPSFW_BOOT_NMI_DATA_OFFSET,      "Bootldr and NMI data"},
+{    4,     RGXMIPSFW_DATA_VIRTUAL_BASE,           RGXMIPSFW_DATA_SIZE,               RGXMIPSFW_DATA_OFFSET,               "Local Data"},
+{    5,     RGXMIPSFW_STACK_VIRTUAL_BASE,          RGXMIPSFW_STACK_SIZE,              RGXMIPSFW_DATA_SIZE,                 "Stack"},
+};
 
+#define RGXFW_MIPS_NUM_CODE_SEGMENTS  (sizeof(asRGXMipsFWCodeSegments)/sizeof(asRGXMipsFWCodeSegments[0]))
+#define RGXFW_MIPS_NUM_DATA_SEGMENTS  (sizeof(asRGXMipsFWDataSegments)/sizeof(asRGXMipsFWDataSegments[0]))
+#endif
 
-#if defined(RGX_FEATURE_META)
+/*!
+*******************************************************************************
+
+ @Function      FindMMUSegment
+
+ @Description   Given a 32 bit FW address attempt to find the corresponding
+                pointer to FW allocation
+
+ @Input         ui32OffsetIn      : 32 bit FW address
+ @Input         pvHostFWCodeAddr  : Pointer to FW code
+ @Input         pvHostFWDataAddr  : Pointer to FW data
+ @Input         uiHostAddrOut     : CPU pointer equivalent to ui32OffsetIn
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR FindMMUSegment(IMG_UINT32 ui32OffsetIn,
+                                   void *pvHostFWCodeAddr,
+                                   void *pvHostFWDataAddr,
+                                   void **uiHostAddrOut,
+                                   RGX_FW_SEGMENT_LIST *psRGXFWSegList)
+{
+	RGX_FW_SEGMENT *psSegArr;
+	IMG_UINT32 i;
+
+	psSegArr = psRGXFWSegList->psRGXFWCodeSeg;
+	for (i = 0; i < psRGXFWSegList->ui32CodeSegCount; i++)
+	{
+		if ((ui32OffsetIn >= psSegArr[i].ui32SegStartAddr) &&
+		    (ui32OffsetIn < (psSegArr[i].ui32SegStartAddr + psSegArr[i].ui32SegAllocSize)))
+		{
+			*uiHostAddrOut = pvHostFWCodeAddr;
+			goto found;
+		}
+	}
+
+	psSegArr = psRGXFWSegList->psRGXFWDataSeg;
+	for (i = 0; i < psRGXFWSegList->ui32DataSegCount; i++)
+	{
+		if ((ui32OffsetIn >= psSegArr[i].ui32SegStartAddr) &&
+		   (ui32OffsetIn < (psSegArr[i].ui32SegStartAddr + psSegArr[i].ui32SegAllocSize)))
+		{
+			*uiHostAddrOut = pvHostFWDataAddr;
+			goto found;
+		}
+	}
+
+	return PVRSRV_ERROR_INIT_FAILURE;
+
+found:
+	/* Direct Mem write to mapped memory */
+	ui32OffsetIn -= psSegArr[i].ui32SegStartAddr;
+	ui32OffsetIn += psSegArr[i].ui32FWMemOffset;
+
+	/* Add offset to pointer to FW allocation only if
+	 * that allocation is available
+	 */
+	if (*uiHostAddrOut)
+	{
+		*(IMG_UINT8 **)uiHostAddrOut += ui32OffsetIn;
+	}
+
+	return PVRSRV_OK;
+}
+
+#if defined(RGX_FEATURE_META)  || defined(SUPPORT_KERNEL_SRVINIT)
+
 /*!
 *******************************************************************************
 
@@ -112,7 +193,7 @@
                                 IMG_UINT32 ui32SegBase,
                                 IMG_UINT32 ui32SegLimit,
                                 IMG_UINT32 ui32SegID,
-                                IMG_CHAR* pszName,
+                                const IMG_CHAR *pszName,
                                 IMG_UINT32 **ppui32BootConf)
 {
 	IMG_UINT32 *pui32BootConf = *ppui32BootConf;
@@ -168,106 +249,46 @@
                                  IMG_DEV_VIRTADDR *psFWDataDevVAddrBase,
                                  IMG_UINT32       **ppui32BootConf)
 {
-	IMG_UINT64 ui64SegOutAddr;
+	IMG_UINT64 ui64SegOutAddrTop;
 	IMG_UINT32 i;
 
+	PVR_UNREFERENCED_PARAMETER(psFWCodeDevVAddrBase);
+
 	/* Configure Segment MMU */
 	RGXCommentLogInit(hPrivate, "********** FW configure Segment MMU **********");
 
-	/* Set-up the Segment MMU except for the bootloader segment, (skip it) */
-	for (i = 1; i < RGXFW_NUM_CODE_SEGMENTS; i++)
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	if (RGXDeviceHasErnBrnInit(hPrivate, HW_ERN_49144_BIT_MASK))
 	{
-		ui64SegOutAddr = (psFWCodeDevVAddrBase->uiAddr |
-		                  RGXFW_SEGMMU_OUTADDR_TOP(0, RGXFW_SEGMMU_META_DM_ID)) +
-		                  asRGXFWCodeSegments[i].ui32FWMemOffset;
+		ui64SegOutAddrTop = RGXFW_SEGMMU_OUTADDR_TOP_ERN_49144(META_MMU_CONTEXT_MAPPING, RGXFW_SEGMMU_META_DM_ID);
+	}
+	else if (RGXDeviceHasErnBrnInit(hPrivate, HW_ERN_45914_BIT_MASK))
+	{
+		ui64SegOutAddrTop = RGXFW_SEGMMU_OUTADDR_TOP_ERN_45914(META_MMU_CONTEXT_MAPPING, RGXFW_SEGMMU_META_DM_ID);
+	}
+	else
+	{
+		ui64SegOutAddrTop = RGXFW_SEGMMU_OUTADDR_TOP_PRE_S7(META_MMU_CONTEXT_MAPPING, RGXFW_SEGMMU_META_DM_ID);
+	}
+#else
+	ui64SegOutAddrTop =  RGXFW_SEGMMU_OUTADDR_TOP(META_MMU_CONTEXT_MAPPING, RGXFW_SEGMMU_META_DM_ID);
+#endif
+
+	for (i = 0; i < RGXFW_META_NUM_DATA_SEGMENTS ; i++)
+	{
+		IMG_UINT64 ui64SegOutAddr;
+
+		ui64SegOutAddr = (psFWDataDevVAddrBase->uiAddr | ui64SegOutAddrTop) +
+		                  asRGXMetaFWDataSegments[i].ui32FWMemOffset;
 
 		RGXFWConfigureSegID(hPrivate,
 		                    ui64SegOutAddr,
-		                    asRGXFWCodeSegments[i].ui32SegStartAddr,
-		                    asRGXFWCodeSegments[i].ui32SegAllocSize,
-		                    asRGXFWCodeSegments[i].ui32SegId,
-		                    asRGXFWCodeSegments[i].pszSegName,
+		                    asRGXMetaFWDataSegments[i].ui32SegStartAddr,
+		                    asRGXMetaFWDataSegments[i].ui32SegAllocSize,
+		                    asRGXMetaFWDataSegments[i].ui32SegId,
+		                    asRGXMetaFWDataSegments[i].pszSegName,
 		                    ppui32BootConf); /*write the sequence to the bootldr */
 	}
-
-	for (i = 0; i < RGXFW_NUM_DATA_SEGMENTS; i++)
-	{
-		ui64SegOutAddr = (psFWDataDevVAddrBase->uiAddr |
-		                  RGXFW_SEGMMU_OUTADDR_TOP(0, RGXFW_SEGMMU_META_DM_ID)) +
-		                  asRGXFWDataSegments[i].ui32FWMemOffset;
-
-		RGXFWConfigureSegID(hPrivate,
-		                    ui64SegOutAddr,
-		                    asRGXFWDataSegments[i].ui32SegStartAddr,
-		                    asRGXFWDataSegments[i].ui32SegAllocSize,
-		                    asRGXFWDataSegments[i].ui32SegId,
-		                    asRGXFWDataSegments[i].pszSegName,
-		                    ppui32BootConf); /*write the sequence to the bootldr */
-	}
-}
-
-/*!
-*******************************************************************************
-
- @Function      FindMMUSegment
-
- @Description   Given a 32 bit FW address attempt to find the corresponding
-                pointer to FW allocation
-
- @Input         ui32OffsetIn      : 32 bit FW address
- @Input         pvHostFWCodeAddr  : Pointer to FW code
- @Input         pvHostFWDataAddr  : Pointer to FW data
- @Input         uiHostAddrOut     : CPU pointer equivalent to ui32OffsetIn
-
- @Return        PVRSRV_ERROR
-
-******************************************************************************/
-static PVRSRV_ERROR FindMMUSegment(IMG_UINT32 ui32OffsetIn,
-                                   void *pvHostFWCodeAddr,
-                                   void *pvHostFWDataAddr,
-                                   void **uiHostAddrOut)
-{
-	RGX_FW_SEGMENT *psSegArr;
-	IMG_UINT32 i;
-
-	psSegArr = asRGXFWCodeSegments;
-	for (i = 0; i < RGXFW_NUM_CODE_SEGMENTS; i++)
-	{
-		if ((ui32OffsetIn >= psSegArr[i].ui32SegStartAddr) &&
-		    (ui32OffsetIn < (psSegArr[i].ui32SegStartAddr + psSegArr[i].ui32SegAllocSize)))
-		{
-			*uiHostAddrOut = pvHostFWCodeAddr;
-			goto found;
-		}
-	}
-
-	psSegArr = asRGXFWDataSegments;
-	for (i = 0; i < RGXFW_NUM_DATA_SEGMENTS; i++)
-	{
-		if ((ui32OffsetIn >= psSegArr[i].ui32SegStartAddr) &&
-		   (ui32OffsetIn < (psSegArr[i].ui32SegStartAddr + psSegArr[i].ui32SegAllocSize)))
-		{
-			*uiHostAddrOut = pvHostFWDataAddr;
-			goto found;
-		}
-	}
-
-	return PVRSRV_ERROR_INIT_FAILURE;
-
-found:
-	/* Direct Mem write to mapped memory */
-	ui32OffsetIn -= psSegArr[i].ui32SegStartAddr;
-	ui32OffsetIn += psSegArr[i].ui32FWMemOffset;
-
-	/* Add offset to pointer to FW allocation only if
-	 * that allocation is available
-	 */
-	if (*uiHostAddrOut)
-	{
-		*(IMG_UINT8 **)uiHostAddrOut += ui32OffsetIn;
-	}
-
-	return PVRSRV_OK;
 }
 
 /*!
@@ -443,7 +464,9 @@
 	RGX_META_LDR_L1_DATA_BLK *psL1Data =
 	    (RGX_META_LDR_L1_DATA_BLK*) ((IMG_UINT8 *) pbLDR + psHeader->ui32SLData);
 
-	IMG_UINT32 *pui32BootConf = *ppui32BootConf;
+	IMG_UINT32 *pui32BootConf  = *ppui32BootConf;
+	IMG_UINT32 ui32CorememSize = RGXGetFWCorememSize(hPrivate);
+	IMG_UINT32 ui32CorememCodeStartAddr = 0xFFFFFFFF;
 
 	RGXCommentLogInit(hPrivate, "**********************************************");
 	RGXCommentLogInit(hPrivate, "************** Begin LDR Parsing *************");
@@ -451,9 +474,15 @@
 
 	while (psL1Data != NULL)
 	{
+		RGX_FW_SEGMENT_LIST sRGXFWSegList;
+		sRGXFWSegList.psRGXFWCodeSeg = asRGXMetaFWCodeSegments;
+		sRGXFWSegList.psRGXFWDataSeg = asRGXMetaFWDataSegments;
+		sRGXFWSegList.ui32CodeSegCount = RGXFW_META_NUM_CODE_SEGMENTS;
+		sRGXFWSegList.ui32DataSegCount = RGXFW_META_NUM_DATA_SEGMENTS;
+
 		if (RGX_META_LDR_BLK_IS_COMMENT(psL1Data->ui16Cmd))
 		{
-			/* Dont process comment blocks */
+			/* Don't process comment blocks */
 			goto NextBlock;
 		}
 
@@ -468,28 +497,39 @@
 				void *pvWriteAddr;
 				PVRSRV_ERROR eError;
 
-				if (RGX_META_IS_COREMEM_CODE(ui32Offset))
+				if (RGX_META_IS_COREMEM_CODE(ui32Offset, ui32CorememSize))
 				{
-					if(pvHostFWCorememAddr == NULL)
+					if (ui32Offset < ui32CorememCodeStartAddr)
 					{
-						RGXErrorLogInit(hPrivate,
-						                "ProcessLDRCommandStream: Coremem code found"
- 						                "but no coremem allocation available!");
+						if (ui32CorememCodeStartAddr == 0xFFFFFFFF)
+						{
+							/* Take the first coremem code address as the coremem code start address */
+							ui32CorememCodeStartAddr = ui32Offset;
 
-						return PVRSRV_ERROR_INIT_FAILURE;
+							/* Also check that there is a valid allocation for the coremem code */
+							if (pvHostFWCorememAddr == NULL)
+							{
+								RGXErrorLogInit(hPrivate,
+								                "ProcessLDRCommandStream: Coremem code found"
+								                "but no coremem allocation available!");
+
+								return PVRSRV_ERROR_INIT_FAILURE;
+							}
+						}
+						else
+						{
+							/* The coremem addresses should be ordered in the LDR command stream */
+							return PVRSRV_ERROR_INIT_FAILURE;
+						}
 					}
 
 					/* Copy coremem data to buffer. The FW copies it to the actual coremem */
-					ui32Offset -= RGX_META_COREMEM_CODE_BADDR;
-#if defined(RGX_META_COREMEM_CODE) || defined(RGX_META_COREMEM_DATA)
+					ui32Offset -= ui32CorememCodeStartAddr;
+
 					RGXMemCopy(hPrivate,
 					           (void*)((IMG_UINT8 *)pvHostFWCorememAddr + ui32Offset),
 					           psL2Block->aui32BlockData,
 					           ui32DataSize);
-#else
-					/* no need to copy the dummy symbols */
-					PVR_UNREFERENCED_PARAMETER(pvHostFWCorememAddr);
-#endif
 				}
 				else
 				{
@@ -499,7 +539,8 @@
 					eError = FindMMUSegment(ui32Offset,
 					                        pvHostFWCodeAddr,
 					                        pvHostFWDataAddr,
-					                        &pvWriteAddr);
+					                        &pvWriteAddr,
+					                        &sRGXFWSegList);
 
 					if (eError != PVRSRV_OK)
 					{
@@ -538,7 +579,7 @@
 				void *pvWriteAddr;
 				PVRSRV_ERROR  eError;
 
-				if (RGX_META_IS_COREMEM_DATA(ui32Offset))
+				if (RGX_META_IS_COREMEM_DATA(ui32Offset, ui32CorememSize))
 				{
 					/* cannot zero coremem directly */
 					break;
@@ -550,9 +591,10 @@
 				eError = FindMMUSegment(ui32Offset,
 				                        pvHostFWCodeAddr,
 				                        pvHostFWDataAddr,
-				                        &pvWriteAddr);
+				                        &pvWriteAddr,
+				                        &sRGXFWSegList);
 
-				if(eError != PVRSRV_OK)
+				if (eError != PVRSRV_OK)
 				{
 					RGXErrorLogInit(hPrivate,
 					                "ProcessLDRCommandStream: Addr 0x%x (size: %d) not found in any segment",
@@ -576,7 +618,7 @@
 				IMG_UINT32 ui32L2BlockSize = psL2Block->ui16Length - 6 /* L2 Tag length and checksum */;
 				IMG_UINT32 ui32CurrBlockSize = 0;
 
-				while(ui32L2BlockSize)
+				while (ui32L2BlockSize)
 				{
 					switch (psConfigCommand->ui32Type)
 					{
@@ -650,7 +692,9 @@
 
 	return PVRSRV_OK;
 }
-#else /* RGX_FEATURE_META */
+#endif /* RGX_FEATURE_META */
+
+#if defined(RGX_FEATURE_MIPS) || defined(SUPPORT_KERNEL_SRVINIT)
 /*!
 *******************************************************************************
 
@@ -662,110 +706,104 @@
  @Input         hPrivate          : Implementation specific data
  @Input         pbELF             : Pointer to FW blob
  @Input         pvHostFWCodeAddr  : Pointer to FW code
+ @Input         pvHostFWDataAddr  : Pointer to FW data
 
  @Return        PVRSRV_ERROR
 
 ******************************************************************************/
 static PVRSRV_ERROR ProcessELFCommandStream(const void *hPrivate,
                                             const IMG_BYTE *pbELF,
-                                            void *pvHostFWCodeAddr)
+                                            void *pvHostFWCodeAddr,
+                                            void *pvHostFWDataAddr)
 {
 	IMG_UINT32 ui32Entry;
-	IMG_UINT8 *pui8BootBase = pvHostFWCodeAddr;
-	IMG_UINT32 ui32FWBootCodeBase = RGXMIPSFW_BOOTCODE_BASE_PAGE * RGXMIPSFW_PAGE_SIZE;
-	IMG_UINT32 ui32NMIBase = RGXMIPSFW_NMI_BASE_PAGE * RGXMIPSFW_PAGE_SIZE;
-	IMG_UINT32 ui32FWExceptionsCodeBase = RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * RGXMIPSFW_PAGE_SIZE;
-	IMG_UINT32 ui32FWCodeBase = RGXMIPSFW_CODE_BASE_PAGE * RGXMIPSFW_PAGE_SIZE;
 	RGX_MIPS_ELF_HDR *psHeader = (RGX_MIPS_ELF_HDR *)pbELF;
 	RGX_MIPS_ELF_PROGRAM_HDR *psProgramHeader =
 	    (RGX_MIPS_ELF_PROGRAM_HDR *)(pbELF + psHeader->ui32Ephoff);
+	PVRSRV_ERROR eError;
 
-/*
- * The final image in memory is as follows:
- * FWCODE
- * FWDATA
- * EXCEPTION
- * BOOT CODE
- * INJECTED BOOT DATA
- * NMI_DEBUG_CODE
- */
-
-	for (ui32Entry = 0; ui32Entry < psHeader->ui32Ephnum; ui32Entry++, psProgramHeader ++)
+	for (ui32Entry = 0; ui32Entry < psHeader->ui32Ephnum; ui32Entry++, psProgramHeader++)
 	{
-		if (psProgramHeader->ui32Pvaddr >= RGXMIPSFW_BOOT_VIRTUAL_BASE &&
-		    psProgramHeader->ui32Pvaddr < RGXMIPSFW_BOOT_VIRTUAL_BASE + RGXMIPSFW_PAGE_SIZE &&
-		    psProgramHeader->ui32Ptype == ELF_PT_LOAD)
+		void *pvWriteAddr;
+		RGX_FW_SEGMENT_LIST sRGXFWSegList;
+		sRGXFWSegList.psRGXFWCodeSeg = asRGXMipsFWCodeSegments;
+		sRGXFWSegList.psRGXFWDataSeg = asRGXMipsFWDataSegments;
+		sRGXFWSegList.ui32CodeSegCount = RGXFW_MIPS_NUM_CODE_SEGMENTS;
+		sRGXFWSegList.ui32DataSegCount = RGXFW_MIPS_NUM_DATA_SEGMENTS;
+
+		/* Only consider loadable entries in the ELF segment table */
+		if (psProgramHeader->ui32Ptype != ELF_PT_LOAD) continue;
+
+		eError = FindMMUSegment(psProgramHeader->ui32Pvaddr,
+		                        pvHostFWCodeAddr,
+		                        pvHostFWDataAddr,
+		                        &pvWriteAddr,
+		                        &sRGXFWSegList);
+
+		if (eError != PVRSRV_OK)
 		{
-			/*Copy the FW boot code*/
-			/*The AND operation is to retain the offset in the page*/
-			RGXMemCopy(hPrivate,
-			           pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32FWBootCodeBase,
-			           (IMG_UINT8 *)(pbELF + psProgramHeader->ui32Poffset),
-			           psProgramHeader->ui32Pfilesz);
-			RGXMemSet(hPrivate,
-			          pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32FWBootCodeBase + psProgramHeader->ui32Pfilesz,
-			          0,
-			          psProgramHeader->ui32Pmemsz - psProgramHeader->ui32Pfilesz);
+			RGXErrorLogInit(hPrivate,
+			                "%s: Addr 0x%x (size: %d) not found in any segment",__func__,
+			                psProgramHeader->ui32Pvaddr,
+			                psProgramHeader->ui32Pfilesz);
+			return eError;
 		}
 
-		else if (psProgramHeader->ui32Pvaddr >= (IMG_UINT32)RGXMIPSFW_EXCEPTIONS_VIRTUAL_BASE &&
-		         psProgramHeader->ui32Pvaddr < RGXMIPSFW_PAGE_SIZE + (IMG_UINT32)RGXMIPSFW_EXCEPTIONS_VIRTUAL_BASE &&
-		         psProgramHeader->ui32Ptype == ELF_PT_LOAD)
+		/* Write to FW allocation only if available */
+		if (pvWriteAddr)
 		{
-			/*Copy the exception_vectors*/
 			RGXMemCopy(hPrivate,
-			           pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32FWExceptionsCodeBase,
-			           (IMG_UINT8 *)(pbELF + psProgramHeader->ui32Poffset),
+			           pvWriteAddr,
+			           (IMG_PBYTE)(pbELF + psProgramHeader->ui32Poffset),
 			           psProgramHeader->ui32Pfilesz);
-			RGXMemSet(hPrivate,
-			          pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32FWExceptionsCodeBase + psProgramHeader->ui32Pfilesz,
-			          0,
-			          psProgramHeader->ui32Pmemsz - psProgramHeader->ui32Pfilesz);
-		}
 
-		else if (psProgramHeader->ui32Pvaddr >= (asRGXFWCodeSegments[0]).ui32SegStartAddr &&
-		         psProgramHeader->ui32Pvaddr < (asRGXFWCodeSegments[0]).ui32SegStartAddr + RGXMIPSFW_FWCODE_SIZE &&
-		         psProgramHeader->ui32Ptype == ELF_PT_LOAD)
-		{
-			/*Copy the FW code*/
-			RGXMemCopy(hPrivate,
-			           pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32FWCodeBase,
-			           (IMG_UINT8 *)(pbELF + psProgramHeader->ui32Poffset),
-			           psProgramHeader->ui32Pfilesz);
 			RGXMemSet(hPrivate,
-			          pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32FWCodeBase + psProgramHeader->ui32Pfilesz,
+			          (IMG_PBYTE)pvWriteAddr + psProgramHeader->ui32Pfilesz,
 			          0,
 			          psProgramHeader->ui32Pmemsz - psProgramHeader->ui32Pfilesz);
 		}
-		else if (psProgramHeader->ui32Pvaddr >= RGXMIPSFW_NMI_VIRTUAL_BASE &&
-		         psProgramHeader->ui32Pvaddr < RGXMIPSFW_NMI_VIRTUAL_BASE + RGXMIPSFW_PAGE_SIZE &&
-		         psProgramHeader->ui32Ptype == ELF_PT_LOAD)
-		{
-			/*Copy the NMI handling code*/
-			RGXMemCopy(hPrivate,
-			           pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32NMIBase,
-			           (IMG_UINT8 *)(pbELF + psProgramHeader->ui32Poffset),
-			           psProgramHeader->ui32Pfilesz);
-			RGXMemSet(hPrivate,
-			          pui8BootBase + (psProgramHeader->ui32Pvaddr & (RGXMIPSFW_PAGE_SIZE - 1)) + ui32NMIBase + psProgramHeader->ui32Pfilesz,
-			          0,
-			          psProgramHeader->ui32Pmemsz - psProgramHeader->ui32Pfilesz);
-		}
-		else
-		{
-			/* Ignore anything else */
-		}
 	}
+
 	return PVRSRV_OK;
 }
-#endif /* RGX_FEATURE_META */
+#endif /* RGX_FEATURE_MIPS */
 
 
-void RGXGetFWImageAllocSize(IMG_DEVMEM_SIZE_T *puiFWCodeAllocSize,
-                            IMG_DEVMEM_SIZE_T *puiFWDataAllocSize,
-                            IMG_DEVMEM_SIZE_T *puiFWCorememAllocSize)
+PVRSRV_ERROR RGXGetFWImageAllocSize(const void *hPrivate,
+                                    IMG_DEVMEM_SIZE_T *puiFWCodeAllocSize,
+                                    IMG_DEVMEM_SIZE_T *puiFWDataAllocSize,
+                                    IMG_DEVMEM_SIZE_T *puiFWCorememAllocSize)
 {
-	IMG_UINT32 i;
+	IMG_UINT32 i, ui32NumCodeSegments = 0, ui32NumDataSegments = 0;
+	RGX_FW_SEGMENT *pasRGXFWCodeSegments = NULL, *pasRGXFWDataSegments = NULL;
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	IMG_BOOL bMIPS = RGXDeviceHasFeatureInit(hPrivate, RGX_FEATURE_MIPS_BIT_MASK);
+#elif defined(RGX_FEATURE_MIPS)
+	IMG_BOOL bMIPS = IMG_TRUE;
+#else
+	IMG_BOOL bMIPS = IMG_FALSE;
+#endif
+
+#if defined(RGX_FEATURE_META) || defined(SUPPORT_KERNEL_SRVINIT)
+	if (!bMIPS)
+	{
+		pasRGXFWCodeSegments = asRGXMetaFWCodeSegments;
+		pasRGXFWDataSegments = asRGXMetaFWDataSegments;
+		ui32NumCodeSegments = RGXFW_META_NUM_CODE_SEGMENTS;
+		ui32NumDataSegments = RGXFW_META_NUM_DATA_SEGMENTS;
+	}
+#endif
+
+#if defined(RGX_FEATURE_MIPS) || defined(SUPPORT_KERNEL_SRVINIT)
+	if (bMIPS)
+	{
+		pasRGXFWCodeSegments = asRGXMipsFWCodeSegments;
+		pasRGXFWDataSegments = asRGXMipsFWDataSegments;
+		ui32NumCodeSegments = RGXFW_MIPS_NUM_CODE_SEGMENTS;
+		ui32NumDataSegments = RGXFW_MIPS_NUM_DATA_SEGMENTS;
+	}
+#endif
 
 	*puiFWCodeAllocSize = 0;
 	*puiFWDataAllocSize = 0;
@@ -773,22 +811,41 @@
 
 	/* Calculate how much memory the FW needs for its code and data segments */
 
-	for(i = 0; i < RGXFW_NUM_CODE_SEGMENTS; i++) {
-		*puiFWCodeAllocSize += asRGXFWCodeSegments[i].ui32SegAllocSize;
+	for(i = 0; i < ui32NumCodeSegments; i++) {
+		*puiFWCodeAllocSize += ((pasRGXFWCodeSegments + i)->ui32SegAllocSize);
 	}
 
-	for(i = 0; i < RGXFW_NUM_DATA_SEGMENTS; i++) {
-		*puiFWDataAllocSize += asRGXFWDataSegments[i].ui32SegAllocSize;
+	for(i = 0; i < ui32NumDataSegments; i++) {
+		*puiFWDataAllocSize += ((pasRGXFWDataSegments + i)->ui32SegAllocSize);
 	}
 
-#if defined(RGX_META_COREMEM_CODE)
-	*puiFWCorememAllocSize = RGX_META_COREMEM_CODE_SIZE;
-#endif
+	*puiFWCorememAllocSize = RGXGetFWCorememSize(hPrivate);
 
-#if defined(RGX_FEATURE_MIPS)
-	PVR_ASSERT((*puiFWCodeAllocSize % RGXMIPSFW_PAGE_SIZE) == 0);
-	PVR_ASSERT((*puiFWDataAllocSize % RGXMIPSFW_PAGE_SIZE) == 0);
-#endif
+	if (*puiFWCorememAllocSize != 0)
+	{
+		*puiFWCorememAllocSize = *puiFWCorememAllocSize - RGX_META_COREMEM_DATA_SIZE;
+	}
+
+	if (bMIPS)
+	{
+		if ((*puiFWCodeAllocSize % RGXMIPSFW_PAGE_SIZE) != 0)
+		{
+			RGXErrorLogInit(hPrivate,
+			                "%s: The MIPS FW code allocation is not"
+			                " a multiple of the page size!", __func__);
+			return PVRSRV_ERROR_INIT_FAILURE;
+		}
+
+		if ((*puiFWDataAllocSize % RGXMIPSFW_PAGE_SIZE) != 0)
+		{
+			RGXErrorLogInit(hPrivate,
+			                "%s: The MIPS FW data allocation is not"
+			                " a multiple of the page size!", __func__);
+			return PVRSRV_ERROR_INIT_FAILURE;
+		}
+	}
+
+	return PVRSRV_OK;
 }
 
 
@@ -807,102 +864,131 @@
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
 
-#if defined(RGX_FEATURE_META)
-	IMG_UINT32 *pui32BootConf = NULL;
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	IMG_BOOL bMIPS = RGXDeviceHasFeatureInit(hPrivate, RGX_FEATURE_MIPS_BIT_MASK);
+#elif defined(RGX_FEATURE_MIPS)
+	IMG_BOOL bMIPS = IMG_TRUE;
+#else
+	IMG_BOOL bMIPS = IMG_FALSE;
+#endif
 
-	/* Skip bootloader configuration if a pointer to the FW code
-	 * allocation is not available
-	 */
-	if (pvFWCode)
+#if defined(RGX_FEATURE_META) || defined(SUPPORT_KERNEL_SRVINIT)
+	if (!bMIPS)
 	{
-		/* This variable points to the bootloader code which is mostly
-		 * a sequence of <register address,register value> pairs
+		IMG_UINT32 *pui32BootConf = NULL;
+		/* Skip bootloader configuration if a pointer to the FW code
+		 * allocation is not available
 		 */
-		pui32BootConf = ((IMG_UINT32*) pvFWCode) + RGXFW_BOOTLDR_CONF_OFFSET;
-	
-		/* Slave port and JTAG accesses are privileged */
-		*pui32BootConf++ = META_CR_SYSC_JTAG_THREAD;
-		*pui32BootConf++ = META_CR_SYSC_JTAG_THREAD_PRIV_EN;
-
-		RGXFWConfigureSegMMU(hPrivate,
-		                     psFWCodeDevVAddrBase,
-		                     psFWDataDevVAddrBase,
-		                     &pui32BootConf);
-	}
-
-	/* Process FW image data stream */
-	eError = ProcessLDRCommandStream(hPrivate,
-	                                 pbRGXFirmware,
-	                                 pvFWCode,
-	                                 pvFWData,
-	                                 pvFWCorememCode,
-	                                 &pui32BootConf);
-	if (eError != PVRSRV_OK)
-	{
-		RGXErrorLogInit(hPrivate, "RGXProcessFWImage: Processing FW image failed (%d)", eError);
-		return eError;
-	}
-
-	/* Skip bootloader configuration if a pointer to the FW code
-	 * allocation is not available
-	 */
-	if (pvFWCode)
-	{
-		if ((ui32NumThreads == 0) || (ui32NumThreads > 2) || (ui32MainThreadID >= 2))
+		if (pvFWCode)
 		{
-			RGXErrorLogInit(hPrivate,
-			                "ProcessFWImage: Wrong Meta threads configuration, using one thread only");
+			/* This variable points to the bootloader code which is mostly
+			 * a sequence of <register address,register value> pairs
+			 */
+			pui32BootConf = ((IMG_UINT32*) pvFWCode) + RGXFW_BOOTLDR_CONF_OFFSET;
 
-			ui32NumThreads = 1;
-			ui32MainThreadID = 0;
+			/* Slave port and JTAG accesses are privileged */
+			*pui32BootConf++ = META_CR_SYSC_JTAG_THREAD;
+			*pui32BootConf++ = META_CR_SYSC_JTAG_THREAD_PRIV_EN;
+
+			RGXFWConfigureSegMMU(hPrivate,
+			                     psFWCodeDevVAddrBase,
+			                     psFWDataDevVAddrBase,
+			                     &pui32BootConf);
+		}
+	
+		/* Process FW image data stream */
+		eError = ProcessLDRCommandStream(hPrivate,
+		                                 pbRGXFirmware,
+		                                 pvFWCode,
+		                                 pvFWData,
+		                                 pvFWCorememCode,
+		                                 &pui32BootConf);
+		if (eError != PVRSRV_OK)
+		{
+			RGXErrorLogInit(hPrivate, "RGXProcessFWImage: Processing FW image failed (%d)", eError);
+			return eError;
 		}
 
-		RGXFWConfigureMetaCaches(hPrivate,
-		                         ui32NumThreads,
-		                         ui32MainThreadID,
-		                         &pui32BootConf);
+		/* Skip bootloader configuration if a pointer to the FW code
+		 * allocation is not available
+		 */
+		if (pvFWCode)
+		{
+			if ((ui32NumThreads == 0) || (ui32NumThreads > 2) || (ui32MainThreadID >= 2))
+			{
+				RGXErrorLogInit(hPrivate,
+				                "ProcessFWImage: Wrong Meta threads configuration, using one thread only");
 
-		/* Signal the end of the conf sequence */
-		*pui32BootConf++ = 0x0;
-		*pui32BootConf++ = 0x0;
+				ui32NumThreads = 1;
+				ui32MainThreadID = 0;
+			}
 
-		/* The FW main argv arguments start here */
-		*pui32BootConf++ = psRGXFwInit->ui32Addr;
+			RGXFWConfigureMetaCaches(hPrivate,
+			                         ui32NumThreads,
+			                         ui32MainThreadID,
+			                         &pui32BootConf);
 
-#if defined(RGX_META_COREMEM_CODE) || defined(RGX_META_COREMEM_DATA)
-		*pui32BootConf++ = psFWCorememFWAddr->ui32Addr;
+			/* Signal the end of the conf sequence */
+			*pui32BootConf++ = 0x0;
+			*pui32BootConf++ = 0x0;
+
+			/* The FW main argv arguments start here */
+			*pui32BootConf++ = psRGXFwInit->ui32Addr;
+
+			if ((RGXGetFWCorememSize(hPrivate) != 0) && (psFWCorememFWAddr != NULL))
+			{
+				*pui32BootConf++ = psFWCorememFWAddr->ui32Addr;
+			}
+			else
+			{
+				*pui32BootConf++ = 0;
+			}
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+			if (RGXDeviceHasFeatureInit(hPrivate, RGX_FEATURE_META_DMA_BIT_MASK))
+#elif defined(RGX_FEATURE_META_DMA)
+			if (IMG_TRUE)
 #else
-		PVR_UNREFERENCED_PARAMETER(psFWCorememFWAddr);
+			if (IMG_FALSE)
 #endif
+			{
+				*pui32BootConf++ = (IMG_UINT32) (psFWCorememDevVAddrBase->uiAddr >> 32);
+				*pui32BootConf++ = (IMG_UINT32) psFWCorememDevVAddrBase->uiAddr;
+			}
+			else
+			{
+				*pui32BootConf++ = 0;
+				*pui32BootConf++ = 0;
+			}
 
-#if defined(RGX_FEATURE_META_DMA)
-		*pui32BootConf++ = (IMG_UINT32) (psFWCorememDevVAddrBase->uiAddr >> 32);
-		*pui32BootConf++ = (IMG_UINT32) psFWCorememDevVAddrBase->uiAddr;
-#else
-		PVR_UNREFERENCED_PARAMETER(psFWCorememDevVAddrBase);
-#endif
+		}
 	}
+#endif
 
-#else /* defined(RGX_FEATURE_META) */
-	/* Process FW image data stream */
-	eError = ProcessELFCommandStream(hPrivate,
-	                                 pbRGXFirmware,
-	                                 pvFWCode);
-	if (eError != PVRSRV_OK)
+#if defined(RGX_FEATURE_MIPS) || defined(SUPPORT_KERNEL_SRVINIT)
+	if (bMIPS)
 	{
-		RGXErrorLogInit(hPrivate, "RGXProcessFWImage: Processing FW image failed (%d)", eError);
-		return eError;
-	}
+		/* Process FW image data stream */
+		eError = ProcessELFCommandStream(hPrivate,
+		                                 pbRGXFirmware,
+		                                 pvFWCode,
+		                                 pvFWData);
+		if (eError != PVRSRV_OK)
+		{
+			RGXErrorLogInit(hPrivate, "RGXProcessFWImage: Processing FW image failed (%d)", eError);
+			return eError;
+		}
 
-	PVR_UNREFERENCED_PARAMETER(pvFWData); /* No need to touch the data segment in MIPS */
-	PVR_UNREFERENCED_PARAMETER(pvFWCorememCode); /* Coremem N/A in MIPS */
-	PVR_UNREFERENCED_PARAMETER(psFWCodeDevVAddrBase);
-	PVR_UNREFERENCED_PARAMETER(psFWDataDevVAddrBase);
-	PVR_UNREFERENCED_PARAMETER(psFWCorememDevVAddrBase);
-	PVR_UNREFERENCED_PARAMETER(psFWCorememFWAddr);
-	PVR_UNREFERENCED_PARAMETER(psRGXFwInit);
-	PVR_UNREFERENCED_PARAMETER(ui32NumThreads);
-	PVR_UNREFERENCED_PARAMETER(ui32MainThreadID);
+		PVR_UNREFERENCED_PARAMETER(pvFWData); /* No need to touch the data segment in MIPS */
+		PVR_UNREFERENCED_PARAMETER(pvFWCorememCode); /* Coremem N/A in MIPS */
+		PVR_UNREFERENCED_PARAMETER(psFWCodeDevVAddrBase);
+		PVR_UNREFERENCED_PARAMETER(psFWDataDevVAddrBase);
+		PVR_UNREFERENCED_PARAMETER(psFWCorememDevVAddrBase);
+		PVR_UNREFERENCED_PARAMETER(psFWCorememFWAddr);
+		PVR_UNREFERENCED_PARAMETER(psRGXFwInit);
+		PVR_UNREFERENCED_PARAMETER(ui32NumThreads);
+		PVR_UNREFERENCED_PARAMETER(ui32MainThreadID);
+	}
 #endif
 
 	return eError;
diff --git a/drivers/staging/imgtec/rogue/rgxfwimageutils.h b/drivers/staging/imgtec/rogue/rgxfwimageutils.h
index 2f8bca2..56b7d08 100644
--- a/drivers/staging/imgtec/rogue/rgxfwimageutils.h
+++ b/drivers/staging/imgtec/rogue/rgxfwimageutils.h
@@ -46,8 +46,10 @@
 
 /* The routines declared here are built on top of an abstraction layer to
  * hide DDK/OS-specific details in case they are used outside of the DDK
- * (e.g. when security v1 is enabled).
- * Any new dependency should be added to rgxlayer.h. */
+ * (e.g. when DRM security is enabled).
+ * Any new dependency should be added to rgxlayer.h.
+ * Any new code should be built on top of the existing abstraction layer,
+ * which should be extended when necessary. */
 #include "rgxlayer.h"
 
 
@@ -62,13 +64,14 @@
  @Input        puiFWDataAllocSize : Returned data size
  @Input        puiFWCorememCodeAllocSize : Returned coremem code size (0 if N/A)
 
- @Return       void
+ @Return       PVRSRV_ERROR
 
 ******************************************************************************/
 IMG_INTERNAL
-void RGXGetFWImageAllocSize(IMG_DEVMEM_SIZE_T *puiFWCodeAllocSize,
-                            IMG_DEVMEM_SIZE_T *puiFWDataAllocSize,
-                            IMG_DEVMEM_SIZE_T *puiFWCorememCodeAllocSize);
+PVRSRV_ERROR RGXGetFWImageAllocSize(const void *hPrivate,
+                                    IMG_DEVMEM_SIZE_T *puiFWCodeAllocSize,
+                                    IMG_DEVMEM_SIZE_T *puiFWDataAllocSize,
+                                    IMG_DEVMEM_SIZE_T *puiFWCorememCodeAllocSize);
 
 /*!
 *******************************************************************************
@@ -96,7 +99,7 @@
  @Input        ui32MainThreadID     : ID of the FW thread in use
                                       (only meaningful if ui32NumThreads == 1)
 
- @Return       void
+ @Return       PVRSRV_ERROR
 
 ******************************************************************************/
 IMG_INTERNAL
diff --git a/drivers/staging/imgtec/rogue/rgxfwload.c b/drivers/staging/imgtec/rogue/rgxfwload.c
index 5ed5329..526f191 100644
--- a/drivers/staging/imgtec/rogue/rgxfwload.c
+++ b/drivers/staging/imgtec/rogue/rgxfwload.c
@@ -44,7 +44,9 @@
 #include <linux/firmware.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
+#include <linux/err.h>
 
+#include "device.h"
 #include "module_common.h"
 #include "rgxfwload.h"
 #include "pvr_debug.h"
@@ -88,7 +90,7 @@
 	uint8_t i;
 	int res;
 
-	if (psFW->size < FW_BLOCK_SIZE)
+	if (psFW->size < FW_SIGN_BACKWARDS_OFFSET)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Firmware is too small (%zu bytes)",
 								__func__, psFW->size));
@@ -96,7 +98,7 @@
 	}
 
 	psHeader = (struct FirmwareSignatureHeader *)
-					(psFW->data + (psFW->size - FW_BLOCK_SIZE));
+					(psFW->data + (psFW->size - FW_SIGN_BACKWARDS_OFFSET));
 
 	/* All derived from u8 so can't be exploited to flow out of this page */
 	pvSigner    = (u8 *)psHeader + sizeof(struct FirmwareSignatureHeader);
@@ -162,7 +164,7 @@
 		goto err_free_pks;
 	}
 
-	res = crypto_shash_finup(psDesc, psFW->data, psFW->size - FW_BLOCK_SIZE,
+	res = crypto_shash_finup(psDesc, psFW->data, psFW->size - FW_SIGN_BACKWARDS_OFFSET,
 							 psPKS->digest);
 	if (res < 0)
 	{
@@ -243,16 +245,38 @@
 #endif /* defined(RGX_FW_SIGNED) */
 
 IMG_INTERNAL struct RGXFW *
-RGXLoadFirmware(void)
+RGXLoadFirmware(SHARED_DEV_CONNECTION psDeviceNode, const IMG_CHAR *pszBVNCString, const IMG_CHAR *pszBVpNCString)
 {
 	const struct firmware *psFW;
 	int res;
 
-	res = request_firmware(&psFW, RGX_FW_FILENAME, &gpsPVRLDMDev->dev);
+	if(pszBVNCString != NULL)
+	{
+		res = request_firmware(&psFW, pszBVNCString, psDeviceNode->psDevConfig->pvOSDevice);
+		if (res != 0)
+		{
+			if(pszBVpNCString != NULL)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') failed (%d), trying '%s'",
+										__func__, pszBVNCString, res, pszBVpNCString));
+				res = request_firmware(&psFW, pszBVpNCString, psDeviceNode->psDevConfig->pvOSDevice);
+			}
+			if (res != 0)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') failed (%d), trying '%s'",
+										__func__, pszBVpNCString, res, RGX_FW_FILENAME));
+				res = request_firmware(&psFW, RGX_FW_FILENAME, psDeviceNode->psDevConfig->pvOSDevice);
+			}
+		}
+	}
+	else
+	{
+		res = request_firmware(&psFW, RGX_FW_FILENAME, psDeviceNode->psDevConfig->pvOSDevice);
+	}
 	if (res != 0)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: request_firmware() failed (%d)",
-								__func__, res));
+		PVR_DPF((PVR_DBG_ERROR, "%s: request_firmware('%s') failed (%d)",
+								__func__, RGX_FW_FILENAME, res));
 		return NULL;
 	}
 
diff --git a/drivers/staging/imgtec/rogue/rgxfwload.h b/drivers/staging/imgtec/rogue/rgxfwload.h
index 84b0b75..2e96b53 100644
--- a/drivers/staging/imgtec/rogue/rgxfwload.h
+++ b/drivers/staging/imgtec/rogue/rgxfwload.h
@@ -46,6 +46,7 @@
 
 #include "img_defs.h"
 #include "rgxdefs_km.h"
+#include "device_connection.h"
 
 #if defined (__cplusplus)
 extern "C" {
@@ -53,7 +54,7 @@
 
 struct RGXFW;
 
-IMG_INTERNAL struct RGXFW *RGXLoadFirmware(void);
+IMG_INTERNAL struct RGXFW *RGXLoadFirmware(SHARED_DEV_CONNECTION psDeviceNode, const IMG_CHAR *pszBVNCString, const IMG_CHAR *pszBVpNCString);
 
 IMG_INTERNAL void RGXUnloadFirmware(struct RGXFW *psRGXFW);
 
diff --git a/drivers/staging/imgtec/rogue/rgxfwutils.c b/drivers/staging/imgtec/rogue/rgxfwutils.c
index 1d53a4f..55991ff 100644
--- a/drivers/staging/imgtec/rogue/rgxfwutils.c
+++ b/drivers/staging/imgtec/rogue/rgxfwutils.c
@@ -49,22 +49,24 @@
 #include "rgx_fwif_km.h"
 #include "pdump_km.h"
 #include "osfunc.h"
+#include "cache_km.h"
 #include "allocmem.h"
 #include "devicemem.h"
 #include "devicemem_pdump.h"
 #include "devicemem_server.h"
-#include "devicemem_utils.h"
 
 #include "pvr_debug.h"
+#include "pvr_notifier.h"
 #include "rgxfwutils.h"
+#include "rgx_options.h"
 #include "rgx_fwif.h"
-#include "rgx_fwif_alignchecks_km.h"
+#include "rgx_fwif_alignchecks.h"
 #include "rgx_fwif_resetframework.h"
 #include "rgx_pdump_panics.h"
 #include "rgxheapconfig.h"
 #include "pvrsrv.h"
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
-#include "rgxfwutils_virt.h"
+#include "rgxfwutils_vz.h"
 #endif
 #include "rgxdebug.h"
 #include "rgxhwperf.h"
@@ -72,9 +74,7 @@
 #include "rgxcompute.h"
 #include "rgxtransfer.h"
 #include "rgxpower.h"
-#if defined(RGX_FEATURE_RAY_TRACING)
 #include "rgxray.h"
-#endif
 #if defined(SUPPORT_DISPLAY_CLASS)
 #include "dc_server.h"
 #endif
@@ -82,9 +82,11 @@
 #include "rgxta3d.h"
 #include "rgxutils.h"
 #include "sync_internal.h"
+#include "sync.h"
 #include "tlstream.h"
 #include "devicemem_server_utils.h"
 #include "htbuffer.h"
+#include "rgx_bvnc_defs_km.h"
 
 #if defined(SUPPORT_TRUSTED_DEVICE)
 #include "physmem_osmem.h"
@@ -96,17 +98,36 @@
 #include "rogue_trace_events.h"
 #else
 #include <stdio.h>
+#include <string.h>
 #endif
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #include "process_stats.h"
 #endif
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+#endif
+
+#if defined(SUPPORT_PDVFS)
+#include "rgxpdvfs.h"
+#endif
+
 /* Kernel CCB length */
-#define RGXFWIF_KCCB_NUMCMDS_LOG2    (7)
+	/* Reducing the size of the KCCB in an attempt to avoid flooding and overflowing the FW kick queue
+	 * in the case of multiple OSes */
+#define RGXFWIF_KCCB_NUMCMDS_LOG2_GPUVIRT_ONLY    (6)
+#define RGXFWIF_KCCB_NUMCMDS_LOG2_FEAT_GPU_VIRTUALISATION    (7)
+
 
 /* Firmware CCB length */
+#if defined(SUPPORT_PDVFS)
+#define RGXFWIF_FWCCB_NUMCMDS_LOG2   (8)
+#else
 #define RGXFWIF_FWCCB_NUMCMDS_LOG2   (5)
+#endif
 
+/* Workload Estimation Firmware CCB length */
+#define RGXFWIF_WORKEST_FWCCB_NUMCMDS_LOG2   (7)
 
 typedef struct
 {
@@ -126,17 +147,18 @@
 		"generates WRW commands for loading the PID values");
 #endif
 
-#if defined(RGX_FEATURE_SLC_VIVT)
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 static PVRSRV_ERROR _AllocateSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo, RGXFWIF_INIT* psRGXFWInit)
 {
 	PVRSRV_ERROR eError;
 	DEVMEM_MEMDESC** ppsSLC3FenceMemDesc = &psDevInfo->psSLC3FenceMemDesc;
+	IMG_UINT32	ui32CacheLineSize = GET_ROGUE_CACHE_LINE_SIZE(psDevInfo->sDevFeatureCfg.ui32CacheLineSize);
 
 	PVR_DPF_ENTERED;
 
 	eError = DevmemAllocate(psDevInfo->psFirmwareHeap,
 							1,
-							ROGUE_CACHE_LINE_SIZE,
+							ui32CacheLineSize,
 							PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                             PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | 
 							PVRSRV_MEMALLOCFLAG_UNCACHED | 
@@ -157,7 +179,7 @@
 							   &psRGXFWInit->sSLC3FenceDevVAddr);
 	if (eError != PVRSRV_OK)
 	{
-		DevmemFwFree(*ppsSLC3FenceMemDesc);
+		DevmemFwFree(psDevInfo, *ppsSLC3FenceMemDesc);
 		*ppsSLC3FenceMemDesc = NULL;
 	}
 
@@ -191,23 +213,23 @@
 /*!
 *******************************************************************************
  @Function		RGXFWSetupSignatureChecks
- @Description	
+ @Description
  @Input			psDevInfo
- 
+
  @Return		PVRSRV_ERROR
 ******************************************************************************/
 static PVRSRV_ERROR RGXFWSetupSignatureChecks(PVRSRV_RGXDEV_INFO* psDevInfo,
-                                              DEVMEM_MEMDESC**    ppsSigChecksMemDesc, 
+                                              DEVMEM_MEMDESC**    ppsSigChecksMemDesc,
                                               IMG_UINT32          ui32SigChecksBufSize,
                                               RGXFWIF_SIGBUF_CTL* psSigBufCtl,
                                               const IMG_CHAR*     pszBufferName)
 {
 	PVRSRV_ERROR	eError;
 	DEVMEM_FLAGS_T	uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-									  PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
+									  PVRSRV_MEMALLOCFLAG_GPU_READABLE |
 					                  PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
 									  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-									  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | 
+									  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
 									  PVRSRV_MEMALLOCFLAG_UNCACHED |
 									  PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
@@ -227,7 +249,7 @@
 	}
 
 	/* Prepare the pointer for the fw to access that memory */
-	RGXSetFirmwareAddress(&psSigBufCtl->psBuffer,
+	RGXSetFirmwareAddress(&psSigBufCtl->sBuffer,
 						  *ppsSigChecksMemDesc,
 						  0, RFW_FWADDR_NOREF_FLAG);
 
@@ -245,27 +267,58 @@
 /*!
 *******************************************************************************
  @Function		RGXFWSetupAlignChecks
- @Description	
+ @Description   This functions allocates and fills memory needed for the
+                aligns checks of the UM and KM structures shared with the
+                firmware. The format of the data in the memory is as follows:
+                    <number of elements in the KM array>
+                    <array of KM structures' sizes and members' offsets>
+                    <number of elements in the UM array>
+                    <array of UM structures' sizes and members' offsets>
+                The UM array is passed from the user side. If the
+                SUPPORT_KERNEL_SRVINIT macro is defined the firmware is
+                is responsible for filling this part of the memory. If that
+                happens the check of the UM structures will be performed
+                by the host driver on client's connect.
+                If the macro is not defined the client driver fills the memory
+                and the firmware checks for the alignment of all structures.
  @Input			psDevInfo
- 
+
  @Return		PVRSRV_ERROR
 ******************************************************************************/
-static PVRSRV_ERROR RGXFWSetupAlignChecks(PVRSRV_RGXDEV_INFO* psDevInfo, 
+static PVRSRV_ERROR RGXFWSetupAlignChecks(PVRSRV_RGXDEV_INFO* psDevInfo,
 								RGXFWIF_DEV_VIRTADDR	*psAlignChecksDevFW,
 								IMG_UINT32				*pui32RGXFWAlignChecks,
-								IMG_UINT32				ui32RGXFWAlignChecksSize)
+								IMG_UINT32				ui32RGXFWAlignChecksArrLength)
 {
 	IMG_UINT32		aui32RGXFWAlignChecksKM[] = { RGXFW_ALIGN_CHECKS_INIT_KM };
-	IMG_UINT32		ui32RGXFWAlingChecksTotal = sizeof(aui32RGXFWAlignChecksKM) + ui32RGXFWAlignChecksSize;
+	IMG_UINT32		ui32RGXFWAlingChecksTotal;
 	IMG_UINT32*		paui32AlignChecks;
 	PVRSRV_ERROR	eError;
 
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	/* In this case we don't know the number of elements in UM array.
+	 * We have to assume something so we assume RGXFW_ALIGN_CHECKS_UM_MAX. */
+	PVR_ASSERT(ui32RGXFWAlignChecksArrLength == 0);
+	ui32RGXFWAlingChecksTotal = sizeof(aui32RGXFWAlignChecksKM)
+	        + RGXFW_ALIGN_CHECKS_UM_MAX * sizeof(IMG_UINT32)
+	        + 2 * sizeof(IMG_UINT32);
+#else
+	/* '2 * sizeof(IMG_UINT32)' if for sizes of km and um arrays. */
+	PVR_ASSERT(ui32RGXFWAlignChecksArrLength != 0);
+	ui32RGXFWAlingChecksTotal = sizeof(aui32RGXFWAlignChecksKM)
+	        + ui32RGXFWAlignChecksArrLength * sizeof(IMG_UINT32)
+	        + 2 * sizeof(IMG_UINT32);
+#endif
+
 	/* Allocate memory for the checks */
 	PDUMPCOMMENT("Allocate memory for alignment checks");
 	eError = DevmemFwAllocate(psDevInfo,
 							ui32RGXFWAlingChecksTotal,
 							PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
 							PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+#if defined(SUPPORT_KERNEL_SRVINIT)
+							PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+#endif
 							PVRSRV_MEMALLOCFLAG_CPU_READABLE |
 							PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
 							PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | PVRSRV_MEMALLOCFLAG_UNCACHED,
@@ -289,10 +342,20 @@
 	}
 
 	/* Copy the values */
-	OSMemCopy(paui32AlignChecks, &aui32RGXFWAlignChecksKM[0], sizeof(aui32RGXFWAlignChecksKM));
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	*paui32AlignChecks++ = sizeof(aui32RGXFWAlignChecksKM)/sizeof(IMG_UINT32);
+	OSDeviceMemCopy(paui32AlignChecks, &aui32RGXFWAlignChecksKM[0], sizeof(aui32RGXFWAlignChecksKM));
 	paui32AlignChecks += sizeof(aui32RGXFWAlignChecksKM)/sizeof(IMG_UINT32);
 
-	OSMemCopy(paui32AlignChecks, pui32RGXFWAlignChecks, ui32RGXFWAlignChecksSize);
+	*paui32AlignChecks = 0;
+#else
+	*paui32AlignChecks++ = sizeof(aui32RGXFWAlignChecksKM)/sizeof(IMG_UINT32);
+	OSDeviceMemCopy(paui32AlignChecks, &aui32RGXFWAlignChecksKM[0], sizeof(aui32RGXFWAlignChecksKM));
+	paui32AlignChecks += sizeof(aui32RGXFWAlignChecksKM)/sizeof(IMG_UINT32);
+
+	*paui32AlignChecks++ = ui32RGXFWAlignChecksArrLength;
+	OSDeviceMemCopy(paui32AlignChecks, pui32RGXFWAlignChecks, ui32RGXFWAlignChecksArrLength * sizeof(IMG_UINT32));
+#endif
 
 	DevmemPDumpLoadMem(	psDevInfo->psRGXFWAlignChecksMemDesc,
 						0,
@@ -310,7 +373,7 @@
 
 
 failAqCpuAddr:
-	DevmemFwFree(psDevInfo->psRGXFWAlignChecksMemDesc);
+	DevmemFwFree(psDevInfo, psDevInfo->psRGXFWAlignChecksMemDesc);
 	psDevInfo->psRGXFWAlignChecksMemDesc = NULL;
 failAlloc:
 
@@ -323,7 +386,7 @@
 	if (psDevInfo->psRGXFWAlignChecksMemDesc != NULL)
 	{
 		DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc);
-		DevmemFwFree(psDevInfo->psRGXFWAlignChecksMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWAlignChecksMemDesc);
 		psDevInfo->psRGXFWAlignChecksMemDesc = NULL;
 	}
 }
@@ -337,60 +400,70 @@
 {
 	PVRSRV_ERROR		eError;
 	IMG_DEV_VIRTADDR	psDevVirtAddr;
-#if defined(RGX_FEATURE_META)
-	IMG_UINT64			ui64Offset;
-	IMG_BOOL            bCachedInMETA;
-	DEVMEM_FLAGS_T      uiDevFlags;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	IMG_UINT64			ui64ErnsBrns = 0;
+	PVRSRV_RGXDEV_INFO	*psDevInfo;
 
-	eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
-	PVR_ASSERT(eError == PVRSRV_OK);
+	psDeviceNode = (PVRSRV_DEVICE_NODE *) DevmemGetConnection(psSrc);
+	psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+	ui64ErnsBrns = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
 
-	/* Convert to an address in META memmap */
-	ui64Offset = psDevVirtAddr.uiAddr + uiExtraOffset - RGX_FIRMWARE_HEAP_BASE;
+	if(psDevInfo->sDevFeatureCfg.ui32META)
+	{
+		IMG_UINT32	    ui32Offset;
+		IMG_BOOL            bCachedInMETA;
+		DEVMEM_FLAGS_T      uiDevFlags;
+		IMG_UINT32          uiGPUCacheMode;
 
-	/* The biggest offset for the Shared region that can be addressed */
-	PVR_ASSERT(ui64Offset < 3*RGXFW_SEGMMU_DMAP_SIZE);
+		eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
+		PVR_ASSERT(eError == PVRSRV_OK);
 
-	/* Check in the devmem flags whether this memory is cached/uncached */
-	DevmemGetFlags(psSrc, &uiDevFlags);
+		/* Convert to an address in META memmap */
+		ui32Offset = psDevVirtAddr.uiAddr + uiExtraOffset - RGX_FIRMWARE_HEAP_BASE ;
 
-	/* Honour the META cache flags */	
-	bCachedInMETA = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) & uiDevFlags) != 0;
+		/* Check in the devmem flags whether this memory is cached/uncached */
+		DevmemGetFlags(psSrc, &uiDevFlags);
 	
-#if defined(HW_ERN_45914)
-	/* We only cache in META if it's also cached in the SLC */
-	{
-		IMG_BOOL bCachedInSLC = (DevmemDeviceCacheMode(uiDevFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHED);
+		/* Honour the META cache flags */
+		bCachedInMETA = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) & uiDevFlags) != 0;
 
-		bCachedInMETA = bCachedInMETA && bCachedInSLC;
-	}
-#endif
+		/* Honour the SLC cache flags */
+		uiGPUCacheMode = DevmemDeviceCacheMode(psDeviceNode, uiDevFlags);
 
-	if (bCachedInMETA)
+		ui32Offset += RGXFW_SEGMMU_DATA_BASE_ADDRESS;
+
+		if (bCachedInMETA)
+		{
+			ui32Offset |= RGXFW_SEGMMU_DATA_META_CACHED;
+		}
+		else
+		{	
+			ui32Offset |= RGXFW_SEGMMU_DATA_META_UNCACHED;
+		}
+
+		if (PVRSRV_CHECK_GPU_CACHED(uiGPUCacheMode))
+		{
+			ui32Offset |= RGXFW_SEGMMU_DATA_VIVT_SLC_CACHED;
+		}
+		else
+		{
+			ui32Offset |= RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED;
+		}
+		ppDest->ui32Addr = ui32Offset;
+	}else
 	{
-		ppDest->ui32Addr = ((IMG_UINT32) ui64Offset) | RGXFW_BOOTLDR_META_ADDR;
-	}
-	else
-	{
-		ppDest->ui32Addr = ((IMG_UINT32) ui64Offset) | RGXFW_SEGMMU_DMAP_ADDR_START;
+		eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
+		PVR_ASSERT(eError == PVRSRV_OK);
+		ppDest->ui32Addr = (IMG_UINT32)((psDevVirtAddr.uiAddr + uiExtraOffset) & 0xFFFFFFFF);
 	}
 
 	if (ui32Flags & RFW_FWADDR_NOREF_FLAG)
 	{
 		DevmemReleaseDevVirtAddr(psSrc);
 	}
-#else
-	eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
-	PVR_ASSERT(eError == PVRSRV_OK);
-	ppDest->ui32Addr = (IMG_UINT32)((psDevVirtAddr.uiAddr + uiExtraOffset) & 0xFFFFFFFF);
-	if (ui32Flags & RFW_FWADDR_NOREF_FLAG)
-	{
-		DevmemReleaseDevVirtAddr(psSrc);
-	}
-#endif
+	
 }
 
-#if defined(RGX_FEATURE_META_DMA)
 void RGXSetMetaDMAAddress(RGXFWIF_DMA_ADDR		*psDest,
 						  DEVMEM_MEMDESC		*psSrcMemDesc,
 						  RGXFWIF_DEV_VIRTADDR	*psSrcFWDevVAddr,
@@ -408,7 +481,7 @@
 
 	DevmemReleaseDevVirtAddr(psSrcMemDesc);
 }
-#endif
+
 
 void RGXUnsetFirmwareAddress(DEVMEM_MEMDESC *psSrc)
 {
@@ -416,6 +489,7 @@
 }
 
 struct _RGX_SERVER_COMMON_CONTEXT_ {
+	PVRSRV_RGXDEV_INFO *psDevInfo;
 	DEVMEM_MEMDESC *psFWCommonContextMemDesc;
 	PRGXFWIF_FWCOMMONCONTEXT sFWCommonContextFWAddr;
 	DEVMEM_MEMDESC *psFWMemContextMemDesc;
@@ -461,6 +535,8 @@
 		goto fail_alloc;
 	}
 
+	psServerCommonContext->psDevInfo = psDevInfo;
+
 	if (psAllocatedMemDesc)
 	{
 		PDUMPCOMMENT("Using existing MemDesc for Rogue firmware %s context (offset = %d)",
@@ -538,12 +614,14 @@
 	RGXSetFirmwareAddress(&psFWCommonContext->psCCBCtl,
 						  psServerCommonContext->psClientCCBCtrlMemDesc,
 						  0, RFW_FWADDR_FLAG_NONE);
-#if defined(RGX_FEATURE_META_DMA)
-	RGXSetMetaDMAAddress(&psFWCommonContext->sCCBMetaDMAAddr,
-	                     psServerCommonContext->psClientCCBMemDesc,
-	                     &psFWCommonContext->psCCB,
-	                     0);
-#endif
+
+	if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_META_DMA_BIT_MASK)
+	{
+		RGXSetMetaDMAAddress(&psFWCommonContext->sCCBMetaDMAAddr,
+							 psServerCommonContext->psClientCCBMemDesc,
+							 &psFWCommonContext->psCCB,
+							 0);
+	}
 
 	/* Set the memory context device address */
 	psServerCommonContext->psFWMemContextMemDesc = psFWMemContextMemDesc;
@@ -575,6 +653,18 @@
 		psFWCommonContext->ui64MCUFenceAddr = psInfo->psMCUFenceAddr->uiAddr;
 	}
 
+	if((psDevInfo->sDevFeatureCfg.ui32CtrlStreamFormat == 2) && \
+				(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK))
+	{
+		if (eDM == RGXFWIF_DM_CDM)
+		{
+			if(psInfo->psResumeSignalAddr != NULL)
+			{
+				psFWCommonContext->ui64ResumeSignalAddr = psInfo->psResumeSignalAddr->uiAddr;
+			}
+		}
+	}
+
 	/* Store a references to Server Common Context and PID for notifications back from the FW. */
 	psFWCommonContext->ui32ServerCommonContextID = psServerCommonContext->ui32ContextID;
 	psFWCommonContext->ui32PID                   = OSGetCurrentClientProcessIDKM();
@@ -638,7 +728,7 @@
 	RGXUnsetFirmwareAddress(psServerCommonContext->psFWCommonContextMemDesc);
 	if (!psServerCommonContext->bCommonContextMemProvided)
 	{
-		DevmemFwFree(psServerCommonContext->psFWCommonContextMemDesc);
+		DevmemFwFree(psDevInfo, psServerCommonContext->psFWCommonContextMemDesc);
 		psServerCommonContext->psFWCommonContextMemDesc = NULL;
 	}
 fail_contextalloc:
@@ -676,13 +766,14 @@
 	RGXUnsetFirmwareAddress(psServerCommonContext->psFWMemContextMemDesc);
 
 	/* Destroy the client CCB */
-	RGXDestroyCCB(psServerCommonContext->psClientCCB);
-	
+	RGXDestroyCCB(psServerCommonContext->psDevInfo, psServerCommonContext->psClientCCB);
+
 
 	/* Free the FW common context (if there was one) */
 	if (!psServerCommonContext->bCommonContextMemProvided)
 	{
-		DevmemFwFree(psServerCommonContext->psFWCommonContextMemDesc);
+		DevmemFwFree(psServerCommonContext->psDevInfo,
+						psServerCommonContext->psFWCommonContextMemDesc);
 		psServerCommonContext->psFWCommonContextMemDesc = NULL;
 	}
 	/* Free the hosts representation of the common context */
@@ -703,10 +794,10 @@
                                                                IMG_UINT32 *pui32LastResetJobRef)
 {
 	RGXFWIF_CONTEXT_RESET_REASON  eLastResetReason;
-	
+
 	PVR_ASSERT(psServerCommonContext != NULL);
 	PVR_ASSERT(pui32LastResetJobRef != NULL);
-	
+
 	/* Take the most recent reason & job ref and reset for next time... */
 	eLastResetReason      = psServerCommonContext->eLastResetReason;
 	*pui32LastResetJobRef = psServerCommonContext->ui32LastResetJobRef;
@@ -721,7 +812,7 @@
  @Function		RGXFreeKernelCCB
  @Description	Free the kernel CCB
  @Input			psDevInfo
- 
+
  @Return		PVRSRV_ERROR
 ******************************************************************************/
 static void RGXFreeKernelCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
@@ -733,7 +824,7 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psKernelCCBMemDesc);
 			psDevInfo->psKernelCCB = NULL;
 		}
-		DevmemFwFree(psDevInfo->psKernelCCBMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psKernelCCBMemDesc);
 		psDevInfo->psKernelCCBMemDesc = NULL;
 	}
 	if (psDevInfo->psKernelCCBCtlMemDesc != NULL)
@@ -743,7 +834,7 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psKernelCCBCtlMemDesc);
 			psDevInfo->psKernelCCBCtl = NULL;
 		}
-		DevmemFwFree(psDevInfo->psKernelCCBCtlMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psKernelCCBCtlMemDesc);
 		psDevInfo->psKernelCCBCtlMemDesc = NULL;
 	}
 }
@@ -756,7 +847,7 @@
  @Input			psRGXFWInit
  @Input			ui32NumCmdsLog2
  @Input			ui32CmdSize
- 
+
  @Return		PVRSRV_ERROR
 ******************************************************************************/
 static PVRSRV_ERROR RGXSetupKernelCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
@@ -770,13 +861,18 @@
 	IMG_UINT32			ui32kCCBSize = (1U << ui32NumCmdsLog2);
 
 
+	/*
+	 * FIXME: the write offset need not be writeable by the firmware, indeed may
+	 * not even be needed for reading. Consider moving it to its own data
+	 * structure.
+	 */
 	uiCCBCtlMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
 							PVRSRV_MEMALLOCFLAG_GPU_READABLE |
 							PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
 							PVRSRV_MEMALLOCFLAG_CPU_READABLE |
 							PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
 							PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-							PVRSRV_MEMALLOCFLAG_UNCACHED | 
+							PVRSRV_MEMALLOCFLAG_UNCACHED |
 							 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
 	/* Allocation flags for Kernel CCB */
@@ -786,7 +882,7 @@
 						 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
 						 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
 						 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-						 PVRSRV_MEMALLOCFLAG_UNCACHED | 
+						 PVRSRV_MEMALLOCFLAG_UNCACHED |
 						 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
 	/*
@@ -884,54 +980,85 @@
  @Function		RGXFreeFirmwareCCB
  @Description	Free the firmware CCB
  @Input			psDevInfo
+ @Input			ppsFirmwareCCBCtl
+ @Input			ppsFirmwareCCBCtlMemDesc
+ @Input			ppui8FirmwareCCB
+ @Input			ppsFirmwareCCBMemDesc
 
- @Return		PVRSRV_ERROR
+ @Return		void
 ******************************************************************************/
-static void RGXFreeFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
+static void RGXFreeFirmwareCCB(PVRSRV_RGXDEV_INFO	*psDevInfo,
+							   RGXFWIF_CCB_CTL		**ppsFirmwareCCBCtl,
+							   DEVMEM_MEMDESC		**ppsFirmwareCCBCtlMemDesc,
+							   IMG_UINT8			**ppui8FirmwareCCB,
+							   DEVMEM_MEMDESC		**ppsFirmwareCCBMemDesc)
 {
-	if (psDevInfo->psFirmwareCCBMemDesc != NULL)
+	if (*ppsFirmwareCCBMemDesc != NULL)
 	{
-		if (psDevInfo->psFirmwareCCB != NULL)
+		if (*ppui8FirmwareCCB != NULL)
 		{
-			DevmemReleaseCpuVirtAddr(psDevInfo->psFirmwareCCBMemDesc);
-			psDevInfo->psFirmwareCCB = NULL;
+			DevmemReleaseCpuVirtAddr(*ppsFirmwareCCBMemDesc);
+			*ppui8FirmwareCCB = NULL;
 		}
-		DevmemFwFree(psDevInfo->psFirmwareCCBMemDesc);
-		psDevInfo->psFirmwareCCBMemDesc = NULL;
+		DevmemFwFree(psDevInfo, *ppsFirmwareCCBMemDesc);
+		*ppsFirmwareCCBMemDesc = NULL;
 	}
-	if (psDevInfo->psFirmwareCCBCtlMemDesc != NULL)
+	if (*ppsFirmwareCCBCtlMemDesc != NULL)
 	{
-		if (psDevInfo->psFirmwareCCBCtl != NULL)
+		if (*ppsFirmwareCCBCtl != NULL)
 		{
-			DevmemReleaseCpuVirtAddr(psDevInfo->psFirmwareCCBCtlMemDesc);
-			psDevInfo->psFirmwareCCBCtl = NULL;
+			DevmemReleaseCpuVirtAddr(*ppsFirmwareCCBCtlMemDesc);
+			*ppsFirmwareCCBCtl = NULL;
 		}
-		DevmemFwFree(psDevInfo->psFirmwareCCBCtlMemDesc);
-		psDevInfo->psFirmwareCCBCtlMemDesc = NULL;
+		DevmemFwFree(psDevInfo, *ppsFirmwareCCBCtlMemDesc);
+		*ppsFirmwareCCBCtlMemDesc = NULL;
 	}
 }
 
+#define INPUT_STR_SIZE_MAX 13
+#define APPEND_STR_SIZE 7
+#define COMBINED_STR_LEN_MAX (INPUT_STR_SIZE_MAX + APPEND_STR_SIZE + 1)
+
 /*!
 *******************************************************************************
  @Function		RGXSetupFirmwareCCB
  @Description	Allocate and initialise a Firmware CCB
  @Input			psDevInfo
- @Input			psRGXFWInit
+ @Input			ppsFirmwareCCBCtl
+ @Input			ppsFirmwareCCBCtlMemDesc
+ @Input			ppui8FirmwareCCB
+ @Input			ppsFirmwareCCBMemDesc
+ @Input			psFirmwareCCBCtlFWAddr
+ @Input			psFirmwareCCBFWAddr
  @Input			ui32NumCmdsLog2
  @Input			ui32CmdSize
-
+ @Input			pszName                   Must be less than or equal to
+                                          INPUT_STR_SIZE_MAX
  @Return		PVRSRV_ERROR
 ******************************************************************************/
-static PVRSRV_ERROR RGXSetupFirmwareCCB(PVRSRV_RGXDEV_INFO 	*psDevInfo,
-									  RGXFWIF_INIT			*psRGXFWInit,
-									  IMG_UINT32			ui32NumCmdsLog2,
-									  IMG_UINT32			ui32CmdSize)
+static PVRSRV_ERROR RGXSetupFirmwareCCB(PVRSRV_RGXDEV_INFO		*psDevInfo,
+										RGXFWIF_CCB_CTL			**ppsFirmwareCCBCtl,
+										DEVMEM_MEMDESC			**ppsFirmwareCCBCtlMemDesc,
+										IMG_UINT8				**ppui8FirmwareCCB,
+										DEVMEM_MEMDESC			**ppsFirmwareCCBMemDesc,
+										PRGXFWIF_CCB_CTL		*psFirmwareCCBCtlFWAddr,
+										PRGXFWIF_CCB			*psFirmwareCCBFWAddr,
+										IMG_UINT32				ui32NumCmdsLog2,
+										IMG_UINT32				ui32CmdSize,
+										IMG_PCHAR				pszName)
 {
 	PVRSRV_ERROR		eError;
 	RGXFWIF_CCB_CTL		*psFWCCBCtl;
 	DEVMEM_FLAGS_T		uiCCBCtlMemAllocFlags, uiCCBMemAllocFlags;
 	IMG_UINT32			ui32FWCCBSize = (1U << ui32NumCmdsLog2);
+	IMG_CHAR			sCCBCtlName[COMBINED_STR_LEN_MAX] = "";
+	IMG_CHAR			sAppend[] = "Control";
 
+	/*
+	 * FIXME: the write offset need not be writeable by the host, indeed may
+	 * not even be needed for reading. Consider moving it to its own data
+	 * structure.
+	 */
 	uiCCBCtlMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
 							PVRSRV_MEMALLOCFLAG_GPU_READABLE |
 							PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
@@ -950,19 +1077,27 @@
 						 PVRSRV_MEMALLOCFLAG_UNCACHED |
 						 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
+	PVR_ASSERT(strlen(sCCBCtlName) == 0);
+	PVR_ASSERT(strlen(sAppend) == APPEND_STR_SIZE);
+	PVR_ASSERT(strlen(pszName) <= INPUT_STR_SIZE_MAX);
+
+	/* Append "Control" to the name for the control struct. */
+	strncat(sCCBCtlName, pszName, INPUT_STR_SIZE_MAX);
+	strncat(sCCBCtlName, sAppend, APPEND_STR_SIZE);
+
 	/*
 		Allocate memory for the Firmware CCB control.
 	*/
-	PDUMPCOMMENT("Allocate memory for firmware CCB control");
+	PDUMPCOMMENT("Allocate memory for %s", sCCBCtlName);
 	eError = DevmemFwAllocate(psDevInfo,
 							sizeof(RGXFWIF_CCB_CTL),
 							uiCCBCtlMemAllocFlags,
-							"FwCCBControl",
-                            &psDevInfo->psFirmwareCCBCtlMemDesc);
+							sCCBCtlName,
+                            ppsFirmwareCCBCtlMemDesc);
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to allocate Firmware CCB ctl (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to allocate %s (%u)", sCCBCtlName,  eError));
 		goto fail;
 	}
 
@@ -970,45 +1105,45 @@
 		Allocate memory for the Firmware CCB.
 		(this will reference further command data in non-shared CCBs)
 	*/
-	PDUMPCOMMENT("Allocate memory for firmware CCB");
+	PDUMPCOMMENT("Allocate memory for %s", pszName);
 	eError = DevmemFwAllocate(psDevInfo,
 							ui32FWCCBSize * ui32CmdSize,
 							uiCCBMemAllocFlags,
-							"FwCCB",
-                            &psDevInfo->psFirmwareCCBMemDesc);
+							pszName,
+                            ppsFirmwareCCBMemDesc);
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to allocate Firmware CCB (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to allocate %s (%u)", pszName, eError));
 		goto fail;
 	}
 
 	/*
 		Map the Firmware CCB control to the kernel.
 	*/
-	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psFirmwareCCBCtlMemDesc,
-                                      (void **)&psDevInfo->psFirmwareCCBCtl);
+	eError = DevmemAcquireCpuVirtAddr(*ppsFirmwareCCBCtlMemDesc,
+                                      (void **)ppsFirmwareCCBCtl);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to acquire cpu firmware CCB Ctl (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to acquire cpu %s (%u)", sCCBCtlName, eError));
 		goto fail;
 	}
 
 	/*
 		Map the firmware CCB to the kernel.
 	*/
-	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psFirmwareCCBMemDesc,
-                                      (void **)&psDevInfo->psFirmwareCCB);
+	eError = DevmemAcquireCpuVirtAddr(*ppsFirmwareCCBMemDesc,
+                                      (void **)ppui8FirmwareCCB);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to acquire cpu firmware CCB (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to acquire cpu %s (%u)", pszName, eError));
 		goto fail;
 	}
 
 	/*
 	 * Initialise the firmware CCB control.
 	 */
-	psFWCCBCtl = psDevInfo->psFirmwareCCBCtl;
+	psFWCCBCtl = *ppsFirmwareCCBCtl;
 	psFWCCBCtl->ui32WriteOffset = 0;
 	psFWCCBCtl->ui32ReadOffset = 0;
 	psFWCCBCtl->ui32WrapMask = ui32FWCCBSize - 1;
@@ -1017,19 +1152,19 @@
 	/*
 	 * Set-up RGXFWIfCtl pointers to access the kCCBs
 	 */
-	RGXSetFirmwareAddress(&psRGXFWInit->psFirmwareCCBCtl,
-						  psDevInfo->psFirmwareCCBCtlMemDesc,
+	RGXSetFirmwareAddress(psFirmwareCCBCtlFWAddr,
+						  *ppsFirmwareCCBCtlMemDesc,
 						  0, RFW_FWADDR_NOREF_FLAG);
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psFirmwareCCB,
-						  psDevInfo->psFirmwareCCBMemDesc,
+	RGXSetFirmwareAddress(psFirmwareCCBFWAddr,
+						  *ppsFirmwareCCBMemDesc,
 						  0, RFW_FWADDR_NOREF_FLAG);
 
 	/*
 	 * Pdump the kernel CCB control.
 	 */
-	PDUMPCOMMENT("Initialise firmware CCB ctl");
-	DevmemPDumpLoadMem(psDevInfo->psFirmwareCCBCtlMemDesc,
+	PDUMPCOMMENT("Initialise %s", sCCBCtlName);
+	DevmemPDumpLoadMem(*ppsFirmwareCCBCtlMemDesc,
 					   0,
 					   sizeof(RGXFWIF_CCB_CTL),
 					   0);
@@ -1037,7 +1172,11 @@
 	return PVRSRV_OK;
 
 fail:
-	RGXFreeFirmwareCCB(psDevInfo);
+	RGXFreeFirmwareCCB(psDevInfo,
+					   ppsFirmwareCCBCtl,
+					   ppsFirmwareCCBCtlMemDesc,
+					   ppui8FirmwareCCB,
+					   ppsFirmwareCCBMemDesc);
 
 	PVR_ASSERT(eError != PVRSRV_OK);
 	return eError;
@@ -1046,14 +1185,14 @@
 static void RGXSetupFaultReadRegisterRollback(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 	PMR *psPMR;
-	
+
 	if (psDevInfo->psRGXFaultAddressMemDesc)
 	{
 		if (DevmemServerGetImportHandle(psDevInfo->psRGXFaultAddressMemDesc,(void **)&psPMR) == PVRSRV_OK)
 		{
 			PMRUnlockSysPhysAddresses(psPMR);
 		}
-		DevmemFwFree(psDevInfo->psRGXFaultAddressMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFaultAddressMemDesc);
 		psDevInfo->psRGXFaultAddressMemDesc = NULL;
 	}
 }
@@ -1061,6 +1200,7 @@
 static PVRSRV_ERROR RGXSetupFaultReadRegister(PVRSRV_DEVICE_NODE	*psDeviceNode, RGXFWIF_INIT *psRGXFWInit)
 {
 	PVRSRV_ERROR		eError = PVRSRV_OK;
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	IMG_UINT32			*pui32MemoryVirtAddr;
 	IMG_UINT32			i;
 	size_t			ui32PageSize;
@@ -1078,10 +1218,11 @@
 						PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
 						PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
 						PVRSRV_MEMALLOCFLAG_UNCACHED;
-	
+
 	psDevInfo->psRGXFaultAddressMemDesc = NULL;
 	eError = DevmemFwAllocateExportable(psDeviceNode,
 										ui32PageSize,
+										ui32PageSize,
 										uiMemAllocFlags,
 										"FwExFaultAddress",
 										&psDevInfo->psRGXFaultAddressMemDesc);
@@ -1098,7 +1239,7 @@
 									  (void **)&pui32MemoryVirtAddr);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire mem for fault adress (%u)",
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire mem for fault address (%u)",
 				eError));
 		goto failFaultAddressDescAqCpuVirt;
 	}
@@ -1109,36 +1250,36 @@
 	}
 
 	eError = DevmemServerGetImportHandle(psDevInfo->psRGXFaultAddressMemDesc,(void **)&psPMR);
-		
+
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error getting PMR for fault adress (%u)",
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error getting PMR for fault address (%u)",
 				eError));
-		
+
 		goto failFaultAddressDescGetPMR;
 	}
 	else
 	{
 		IMG_BOOL bValid;
 		IMG_UINT32 ui32Log2PageSize = OSGetPageShift();
-		
-		eError = PMRLockSysPhysAddresses(psPMR,ui32Log2PageSize);
-			
+
+		eError = PMRLockSysPhysAddresses(psPMR);
+
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error locking physical address for fault address MemDesc (%u)",
 					eError));
-			
+
 			goto failFaultAddressDescLockPhys;
 		}
-			
+
 		eError = PMR_DevPhysAddr(psPMR,ui32Log2PageSize,1,0,&(psRGXFWInit->sFaultPhysAddr),&bValid);
 
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error getting physical address for fault address MemDesc (%u)",
 					eError));
-			
+
 			goto failFaultAddressDescGetPhys;
 		}
 
@@ -1153,7 +1294,7 @@
 	}
 
 	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc);
-	
+
 	return PVRSRV_OK;
 
 failFaultAddressDescGetPhys:
@@ -1165,11 +1306,11 @@
 	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc);
 
 failFaultAddressDescAqCpuVirt:
-	DevmemFwFree(psDevInfo->psRGXFaultAddressMemDesc);
+	DevmemFwFree(psDevInfo, psDevInfo->psRGXFaultAddressMemDesc);
 	psDevInfo->psRGXFaultAddressMemDesc = NULL;
 
 failFaultAddressDescAlloc:
-
+#endif
 	return eError;
 }
 
@@ -1177,80 +1318,89 @@
 {
 	PVRSRV_ERROR			eError = PVRSRV_OK;
 
-#if defined(FIX_HW_BRN_37200)
-	struct _DEVMEM_HEAP_	*psBRNHeap;
-	DEVMEM_FLAGS_T			uiFlags;
-	IMG_DEV_VIRTADDR		sTmpDevVAddr;
-	size_t				uiPageSize;
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	IMG_UINT64	ui64ErnsBrns = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
+	IMG_UINT32	ui32CacheLineSize = GET_ROGUE_CACHE_LINE_SIZE(psDevInfo->sDevFeatureCfg.ui32CacheLineSize);
 
-	uiPageSize = OSGetPageSize();
+	if(ui64ErnsBrns & FIX_HW_BRN_37200_BIT_MASK)
+	{
+		struct _DEVMEM_HEAP_	*psBRNHeap;
+		DEVMEM_FLAGS_T			uiFlags;
+		IMG_DEV_VIRTADDR		sTmpDevVAddr;
+		size_t				uiPageSize;
 	
-	uiFlags =	PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-				PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
-				PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-				PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-				PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-				PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | 
-				PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-				PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
-				PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
-
-	eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
-							  "HWBRN37200",
-							  &psBRNHeap);
-
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: HWBRN37200 Failed DevmemFindHeapByName (%u)", eError));
-		goto failFWHWBRN37200FindHeapByName;
-	}
-
-	psDevInfo->psRGXFWHWBRN37200MemDesc = NULL;
-	eError = DevmemAllocate(psBRNHeap,
-						uiPageSize,
-						ROGUE_CACHE_LINE_SIZE,
-						uiFlags,
-						"HWBRN37200",
-						&psDevInfo->psRGXFWHWBRN37200MemDesc);
-
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: Failed to allocate %u bytes for HWBRN37200 (%u)",
-				(IMG_UINT32)uiPageSize,
-				eError));
-		goto failFWHWBRN37200MemDescAlloc;
-	}
+		uiPageSize = OSGetPageSize();
 		
-	/*
-		We need to map it so the heap for this allocation
-		is set
-	*/
-	eError = DevmemMapToDevice(psDevInfo->psRGXFWHWBRN37200MemDesc,
-						   psBRNHeap,
-						   &sTmpDevVAddr);
-		
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: Failed to allocate %u bytes for HWBRN37200 (%u)",
-				(IMG_UINT32)uiPageSize,
-				eError));
-		goto failFWHWBRN37200DevmemMapToDevice;
+		uiFlags =	PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+					PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+					PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+					PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+					PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+					PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+					PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+					PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+					PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+		eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
+								  "HWBRN37200", /* FIXME: We need to create an IDENT macro for this string.
+												 Make sure the IDENT macro is not accessible to userland */
+								  &psBRNHeap);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: HWBRN37200 Failed DevmemFindHeapByName (%u)", eError));
+			goto failFWHWBRN37200FindHeapByName;
+		}
+
+		psDevInfo->psRGXFWHWBRN37200MemDesc = NULL;
+		eError = DevmemAllocate(psBRNHeap,
+							uiPageSize,
+							ui32CacheLineSize,
+							uiFlags,
+							"HWBRN37200",
+							&psDevInfo->psRGXFWHWBRN37200MemDesc);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: Failed to allocate %u bytes for HWBRN37200 (%u)",
+					(IMG_UINT32)uiPageSize,
+					eError));
+			goto failFWHWBRN37200MemDescAlloc;
+		}
+
+		/*
+			We need to map it so the heap for this allocation
+			is set
+		*/
+		eError = DevmemMapToDevice(psDevInfo->psRGXFWHWBRN37200MemDesc,
+							   psBRNHeap,
+							   &sTmpDevVAddr);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: Failed to allocate %u bytes for HWBRN37200 (%u)",
+					(IMG_UINT32)uiPageSize,
+					eError));
+			goto failFWHWBRN37200DevmemMapToDevice;
+		}
+
+
+
+		return PVRSRV_OK;
+
+	failFWHWBRN37200DevmemMapToDevice:
+
+	failFWHWBRN37200MemDescAlloc:
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWHWBRN37200MemDesc);
+		psDevInfo->psRGXFWHWBRN37200MemDesc = NULL;
+
+	failFWHWBRN37200FindHeapByName:;
 	}
-
-	return PVRSRV_OK;
-
-failFWHWBRN37200DevmemMapToDevice:
-
-failFWHWBRN37200MemDescAlloc:
-	DevmemFwFree(psDevInfo->psRGXFWHWBRN37200MemDesc);
-	psDevInfo->psRGXFWHWBRN37200MemDesc = NULL;
-
-failFWHWBRN37200FindHeapByName:
 #endif
-
 	return eError;
 }
 
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 /*************************************************************************/ /*!
 @Function       RGXTraceBufferIsInitRequired
 
@@ -1268,7 +1418,7 @@
 {
 	RGXFWIF_TRACEBUF*  psTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
 
-	/* The firmware expects a trace buffer only when: 
+	/* The firmware expects a trace buffer only when:
 	 *	- Logtype is "trace" AND
 	 *	- at least one LogGroup is configured
 	 */
@@ -1307,8 +1457,6 @@
 				PVRSRV_MEMALLOCFLAG_UNCACHED |
 				PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
-	PMRLock();
-
 	for (ui32FwThreadNum = 0; ui32FwThreadNum < RGXFW_THREAD_NUM; ui32FwThreadNum++)
 	{
 		/* Ensure allocation API is only called when not already allocated */
@@ -1350,13 +1498,9 @@
 
 /* Just return error in-case of failures, clean-up would be handled by DeInit function */
 fail:
-	PMRUnlock();
 	return eError;
 }
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Functionality n/a in guest drivers */
-#else
 /*************************************************************************/ /*!
 @Function       RGXTraceBufferDeinit
 
@@ -1381,7 +1525,7 @@
 				psTraceBufCtl->sTraceBuf[i].pui32TraceBuffer = NULL;
 			}
 
-			DevmemFwFree(psDevInfo->psRGXFWIfTraceBufferMemDesc[i]);
+			DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfTraceBufferMemDesc[i]);
 			psDevInfo->psRGXFWIfTraceBufferMemDesc[i] = NULL;
 		}
 	}
@@ -1407,10 +1551,11 @@
                               IMG_UINT32               ui32SignatureChecksBufSize,
                               IMG_UINT32               ui32HWPerfFWBufSizeKB,
                               IMG_UINT64               ui64HWPerfFilter,
-                              IMG_UINT32               ui32RGXFWAlignChecksSize,
+                              IMG_UINT32               ui32RGXFWAlignChecksArrLength,
                               IMG_UINT32               *pui32RGXFWAlignChecks,
                               IMG_UINT32               ui32ConfigFlags,
                               IMG_UINT32               ui32LogType,
+                              RGXFWIF_BIFTILINGMODE    eBifTilingMode,
                               IMG_UINT32               ui32NumTilingCfgs,
                               IMG_UINT32               *pui32BIFTilingXStrides,
                               IMG_UINT32               ui32FilterFlags,
@@ -1427,13 +1572,16 @@
 	DEVMEM_FLAGS_T		uiMemAllocFlags;
 	RGXFWIF_INIT		*psRGXFWInit = NULL;
 	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
-	IMG_UINT32			dm;
-
-#if defined(RGX_FEATURE_META_DMA)
-	RGXFWIF_DEV_VIRTADDR sRGXTmpCorememDataStoreFWAddr;
+	IMG_UINT32			dm, ui32Temp = 0;
+	IMG_UINT64			ui64ErnsBrns;
+#if defined (SUPPORT_PDVFS)
+	RGXFWIF_PDVFS_OPP   *psPDVFSOPPInfo;
+	IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg;
 #endif
+	ui64ErnsBrns = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
 
 	/* Fw init data */
+
 	uiMemAllocFlags =	PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
 						PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
 						PVRSRV_MEMALLOCFLAG_GPU_READABLE |
@@ -1443,12 +1591,11 @@
 						PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
 						PVRSRV_MEMALLOCFLAG_UNCACHED |
 						PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+						/* FIXME: Change to Cached */
 
 
 	PDUMPCOMMENT("Allocate RGXFWIF_INIT structure");
 
-	PMRLock();
-
 	eError = DevmemFwAllocate(psDevInfo,
 							sizeof(RGXFWIF_INIT),
 							uiMemAllocFlags,
@@ -1472,19 +1619,19 @@
 		goto fail;
 	}
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/*
-	 * Guest drivers do not support the following functionality:
-	 *  - Perform actual on-chip fw loading & initialization
-	 *  - Perform actual on-chip fw management (i.e. reset)
-	 * 	- Perform actual on-chip fw HWPerf,Trace,Utils,ActivePM
-	 */
-#else
 	RGXSetFirmwareAddress(&psDevInfo->sFWInitFWAddr,
 	                      psDevInfo->psRGXFWIfInitMemDesc,
 	                      0, RFW_FWADDR_NOREF_FLAG);
 	*psRGXFWInitFWAddr = psDevInfo->sFWInitFWAddr;
 
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/*
+	 * Guest drivers do not support the following functionality:
+	 *  - Perform actual on-chip fw loading & initialisation
+	 *  - Perform actual on-chip fw management (i.e. reset)
+	 * 	- Perform actual on-chip fw HWPerf,Trace,Utils,ActivePM
+	 */
+#else
 	/* FW trace control structure */
 	uiMemAllocFlags =	PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
 						PVRSRV_MEMALLOCFLAG_GPU_READABLE |
@@ -1509,7 +1656,7 @@
 		goto fail;
 	}
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psTraceBufCtl,
+	RGXSetFirmwareAddress(&psRGXFWInit->sTraceBufCtl,
 						psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
 						0, RFW_FWADDR_NOREF_FLAG);
 
@@ -1522,8 +1669,6 @@
 		goto fail;
 	}
 
-	PMRUnlock();
-
 	/* Set initial firmware log type/group(s) */
 	if (ui32LogType & ~RGXFWIF_LOG_TYPE_MASK)
 	{
@@ -1555,44 +1700,58 @@
 						PVRSRV_MEMALLOCFLAG_GPU_READABLE |
 						PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
 						PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-						PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | 
 						PVRSRV_MEMALLOCFLAG_UNCACHED |
 						PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
-	PMRLock();
-
-#if defined(RGX_META_COREMEM)
-	PDUMPCOMMENT("Allocate buffer to store FW data");
-	eError = DevmemFwAllocate(psDevInfo,
-							  RGX_META_COREMEM_DATA_SIZE,
-							  uiMemAllocFlags,
-							  "FwCorememDataStore",
-							  &psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
-	
-	if (eError != PVRSRV_OK)
+	if ((0 != psDevInfo->sDevFeatureCfg.ui32MCMS) && \
+			(0 == (ui64ErnsBrns & FIX_HW_BRN_50767_BIT_MASK)))
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXSetupFirmware: Failed to allocate coremem data store (%u)",
-				 eError));
-		goto fail;
+		IMG_BOOL bMetaDMA = psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_META_DMA_BIT_MASK;
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+		if (bMetaDMA)
+		{
+			IMG_UINT64 ui64SecBufHandle;
+
+			PDUMPCOMMENT("Import secure buffer to store FW coremem data");
+			eError = DevmemImportTDSecureBuf(psDeviceNode,
+			                                 RGX_META_COREMEM_BSS_SIZE,
+			                                 OSGetPageShift(),
+			                                 uiMemAllocFlags,
+			                                 &psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+			                                 &ui64SecBufHandle);
+		}
+		else
+#endif
+		{
+			PDUMPCOMMENT("Allocate buffer to store FW coremem data");
+			eError = DevmemFwAllocate(psDevInfo,
+									  RGX_META_COREMEM_BSS_SIZE,
+									  uiMemAllocFlags,
+									  "FwCorememDataStore",
+									  &psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+		}
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXSetupFirmware: Failed to allocate coremem data store (%u)",
+					 eError));
+			goto fail;
+		}
+
+		RGXSetFirmwareAddress(&psRGXFWInit->sCorememDataStore.pbyFWAddr,
+							  psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+							  0, RFW_FWADDR_NOREF_FLAG);
+	
+		if (bMetaDMA)
+		{
+			RGXSetMetaDMAAddress(&psRGXFWInit->sCorememDataStore,
+								 psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+								 &psRGXFWInit->sCorememDataStore.pbyFWAddr,
+								 0);
+		}
 	}
 
-
-#if defined(RGX_FEATURE_META_DMA)
-	RGXSetFirmwareAddress(&sRGXTmpCorememDataStoreFWAddr,
-						  psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
-						  0, RFW_FWADDR_NOREF_FLAG);
-
-	RGXSetMetaDMAAddress(&psRGXFWInit->sCorememDataStore,
-						 psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
-						 &sRGXTmpCorememDataStoreFWAddr,
-						 0);
-#else
-	RGXSetFirmwareAddress(&psRGXFWInit->sCorememDataStore.pbyFWAddr,
-						  psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
-						  0, RFW_FWADDR_NOREF_FLAG);
-#endif
-#endif
-
 	/* init HW frame info */
 	PDUMPCOMMENT("Allocate rgxfw HW info buffer");
 	eError = DevmemFwAllocate(psDevInfo,
@@ -1609,7 +1768,7 @@
 		goto fail;
 	}
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psRGXFWIfHWRInfoBufCtl,
+	RGXSetFirmwareAddress(&psRGXFWInit->sRGXFWIfHWRInfoBufCtl,
 						psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc,
 						0, RFW_FWADDR_NOREF_FLAG);
 
@@ -1621,7 +1780,9 @@
 				eError));
 		goto fail;
 	}
-	OSMemSet(psDevInfo->psRGXFWIfHWRInfoBuf, 0, sizeof(RGXFWIF_HWRINFOBUF));
+
+	/* Might be uncached. Be conservative and use a DeviceMemSet */
+	OSDeviceMemSet(psDevInfo->psRGXFWIfHWRInfoBuf, 0, sizeof(RGXFWIF_HWRINFOBUF));
 
 	/* Allocate shared buffer for GPU utilisation */
 	uiMemAllocFlags =	PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
@@ -1647,7 +1808,7 @@
 		goto fail;
 	}
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psGpuUtilFWCbCtl,
+	RGXSetFirmwareAddress(&psRGXFWInit->sGpuUtilFWCbCtl,
 						psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc,
 						0, RFW_FWADDR_NOREF_FLAG);
 
@@ -1688,7 +1849,7 @@
 		goto fail;
 	}
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psRuntimeCfg,
+	RGXSetFirmwareAddress(&psRGXFWInit->sRuntimeCfg,
 						psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
 						0, RFW_FWADDR_NOREF_FLAG);
 
@@ -1701,37 +1862,38 @@
 		goto fail;
 	}
 
-	PMRUnlock();
 
-	/* HWPerf initialization */
-
-	/* Determine the size of the HWPerf FW buffer */
-	if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MAX>>10))
+	/* HWPerf: Determine the size of the FW buffer */
+	if (ui32HWPerfFWBufSizeKB == 0 ||
+			ui32HWPerfFWBufSizeKB == RGXFW_HWPERF_L1_SIZE_DEFAULT)
+	{
+		/* Under pvrsrvctl 0 size implies AppHint not set or is set to zero,
+		 * use default size from driver constant.  Under SUPPORT_KERNEL_SRVINIT
+		 * default is the above macro. In either case, set it to the default,
+		 * size, no logging.
+		 */
+		psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_DEFAULT<<10;
+	}
+	else if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MAX))
 	{
 		/* Size specified as a AppHint but it is too big */
 		PVR_DPF((PVR_DBG_WARNING,"RGXSetupFirmware: HWPerfFWBufSizeInKB value (%u) too big, using maximum (%u)",
-				ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MAX>>10));
-		psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_MAX;
+				ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MAX));
+		psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_MAX<<10;
 	}
-	else if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MIN>>10))
+	else if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MIN))
 	{
 		/* Size specified as in AppHint HWPerfFWBufSizeInKB */
 		PVR_DPF((PVR_DBG_WARNING,"RGXSetupFirmware: Using HWPerf FW buffer size of %u KB",
 				ui32HWPerfFWBufSizeKB));
 		psDevInfo->ui32RGXFWIfHWPerfBufSize = ui32HWPerfFWBufSizeKB<<10;
 	}
-	else if (ui32HWPerfFWBufSizeKB > 0)
+	else
 	{
 		/* Size specified as a AppHint but it is too small */
 		PVR_DPF((PVR_DBG_WARNING,"RGXSetupFirmware: HWPerfFWBufSizeInKB value (%u) too small, using minimum (%u)",
-				ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MIN>>10));
-		psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_MIN;
-	}
-	else
-	{
-		/* 0 size implies AppHint not set or is set to zero,
-		 * use default size from driver constant. */
-		psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_DEFAULT;
+				ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MIN));
+		psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_MIN<<10;
 	}
 
 	/* init HWPERF data */
@@ -1746,7 +1908,8 @@
 	psDevInfo->psRGXFWIfTraceBuf->ui32LastDropOrdinal = 0;
 	psDevInfo->psRGXFWIfTraceBuf->ui32PowMonEnergy = 0;
 
-	/* RGXHWPerfInit called in RGXRegisterDevice(). */
+	/* Second stage initialisation or HWPerf, hHWPerfLock created in first
+	 * stage. See RGXRegisterDevice() call to RGXHWPerfInit(). */
 	if (psDevInfo->ui64HWPerfFilter == 0)
 	{
 		psDevInfo->ui64HWPerfFilter = ui64HWPerfFilter;
@@ -1763,7 +1926,7 @@
 #if defined (PDUMP)
 	/* When PDUMP is enabled, ALWAYS allocate on-demand HWPerf resources
 	 * (irrespective of HWPerf enabled or not), given that HWPerf can be
-	 * enabled during PDump playback via RTCONF at any point of time */
+	 * enabled during PDump playback via RTCONF at any point of time. */
 	eError = RGXHWPerfInitOnDemandResources();
 #else
 	/* Otherwise, only allocate if HWPerf is enabled via apphint */
@@ -1774,7 +1937,7 @@
 #endif
 	PVR_LOGG_IF_ERROR(eError, "RGXHWPerfInitOnDemandResources", fail);
 
-	PMRLock();
+	RGXHWPerfInitAppHintCallbacks(psDeviceNode);
 
 #if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
 	PDUMPCOMMENT("Allocate rgxfw register configuration structure");
@@ -1792,7 +1955,7 @@
 		goto fail;
 	}
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psRegCfg,
+	RGXSetFirmwareAddress(&psRGXFWInit->sRegCfg,
 						psDevInfo->psRGXFWIfRegCfgMemDesc,
 						0, RFW_FWADDR_NOREF_FLAG);
 #endif
@@ -1808,6 +1971,7 @@
 	PDUMPCOMMENT("Allocate rgxfw hwperfctl structure");
 	eError = DevmemFwAllocateExportable(psDeviceNode,
 							ui32HWPerfCountersDataSize,
+							OSGetPageSize(),
 							uiMemAllocFlags,
 							"FwExHWPerfControlStructure",
 							&psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
@@ -1828,7 +1992,8 @@
 		goto fail;
 	}
 
-	RGXSetFirmwareAddress(&psRGXFWInit->psHWPerfCtl,
+
+	RGXSetFirmwareAddress(&psRGXFWInit->sHWPerfCtl,
 						psDevInfo->psRGXFWIfHWPerfCountersMemDesc,
 						0, 0);
 
@@ -1846,7 +2011,7 @@
 		psRuntimeCfg->bActivePMLatencyPersistant = IMG_TRUE;
 
 		/* Initialize the DefaultDustsNumInit Field to Max Dusts */
-		psRuntimeCfg->ui32DefaultDustsNumInit = MAX(1, RGX_FEATURE_NUM_CLUSTERS/2);
+		psRuntimeCfg->ui32DefaultDustsNumInit = MAX(1, (psDevInfo->sDevFeatureCfg.ui32NumClusters/2));
 	}
 #if defined(PDUMP)
 	PDUMPCOMMENT("Dump initial state of FW runtime configuration");
@@ -1873,7 +2038,15 @@
 		goto fail;
 	}
 
-	psRGXFWInit->uiPowerSync = SyncPrimGetFirmwareAddr(psDevInfo->psPowSyncPrim);
+	eError = SyncPrimGetFirmwareAddr(psDevInfo->psPowSyncPrim,
+			&psRGXFWInit->sPowerSync.ui32Addr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+			"%s: Failed to get Sync Prim FW address with error (%u)",
+			__FUNCTION__, eError));
+		goto fail;
+	}
 
 	/* Setup Fault read register */
 	eError = RGXSetupFaultReadRegister(psDeviceNode, psRGXFWInit);
@@ -1891,12 +2064,21 @@
 		goto fail;
 	}
 
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_GPU_VIRTUALISATION_BIT_MASK))
+	{
+		ui32Temp = RGXFWIF_KCCB_NUMCMDS_LOG2_GPUVIRT_ONLY;
+	}else
+#endif
+	{
+		ui32Temp = RGXFWIF_KCCB_NUMCMDS_LOG2_FEAT_GPU_VIRTUALISATION;
+	}
 	/*
 	 * Set up kernel CCB.
 	 */
 	eError = RGXSetupKernelCCB(psDevInfo,
 	                           psRGXFWInit,
-	                           RGXFWIF_KCCB_NUMCMDS_LOG2,
+	                           ui32Temp,
 	                           sizeof(RGXFWIF_KCCB_CMD));
 	if (eError != PVRSRV_OK)
 	{
@@ -1908,18 +2090,101 @@
 	 * Set up firmware CCB.
 	 */
 	eError = RGXSetupFirmwareCCB(psDevInfo,
-							   psRGXFWInit,
-							   RGXFWIF_FWCCB_NUMCMDS_LOG2,
-							   sizeof(RGXFWIF_FWCCB_CMD));
+								 &psDevInfo->psFirmwareCCBCtl,
+								 &psDevInfo->psFirmwareCCBCtlMemDesc,
+								 &psDevInfo->psFirmwareCCB,
+								 &psDevInfo->psFirmwareCCBMemDesc,
+								 &psRGXFWInit->psFirmwareCCBCtl,
+								 &psRGXFWInit->psFirmwareCCB,
+								 RGXFWIF_FWCCB_NUMCMDS_LOG2,
+								 sizeof(RGXFWIF_FWCCB_CMD),
+								 "FwCCB");
+
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware CCB"));
 		goto fail;
 	}
+	/* RD Power Island */
+	{
+		RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+		IMG_BOOL bSysEnableRDPowIsland = psRGXData->psRGXTimingInfo->bEnableRDPowIsland;
+		IMG_BOOL bEnableRDPowIsland = ((eRGXRDPowerIslandConf == RGX_RD_POWER_ISLAND_DEFAULT) && bSysEnableRDPowIsland) ||
+						(eRGXRDPowerIslandConf == RGX_RD_POWER_ISLAND_FORCE_ON);
+
+		ui32ConfigFlags |= bEnableRDPowIsland? RGXFWIF_INICFG_POW_RASCALDUST : 0;
+	}
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	ui32ConfigFlags |= RGXFWIF_INICFG_WORKEST_V2;
+
+#if defined(SUPPORT_PDVFS)
+	/* Proactive DVFS depends on Workload Estimation */
+	psPDVFSOPPInfo = &(psRGXFWInit->sPDVFSOPPInfo);
+	psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+
+	if(psDVFSDeviceCfg->pasOPPTable != NULL)
+	{
+		if(psDVFSDeviceCfg->ui32OPPTableSize >
+		   sizeof(psPDVFSOPPInfo->asOPPValues)/sizeof(psPDVFSOPPInfo->asOPPValues[0]))
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "RGXSetupFirmware: OPP Table too large :"
+			         " Size = %u, Maximum size = %lu",
+			         psDVFSDeviceCfg->ui32OPPTableSize,
+			         (unsigned long)(sizeof(psPDVFSOPPInfo->asOPPValues)/sizeof(psPDVFSOPPInfo->asOPPValues[0]))));
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto fail;
+		}
+
+		memcpy(psPDVFSOPPInfo->asOPPValues,
+			   psDVFSDeviceCfg->pasOPPTable,
+			   sizeof(psPDVFSOPPInfo->asOPPValues));
+		psPDVFSOPPInfo->ui32MaxOPPPoint =
+			(psDVFSDeviceCfg->ui32OPPTableSize) - 1;
+
+		ui32ConfigFlags |= RGXFWIF_INICFG_PDVFS_V2;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Missing OPP Table"));
+	}
+#endif
+#endif
+
+	psRGXFWInit->ui32ConfigFlags = ui32ConfigFlags & RGXFWIF_INICFG_ALL;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	/*
+	 * Set up Workload Estimation firmware CCB.
+	 */
+	eError = RGXSetupFirmwareCCB(psDevInfo,
+								 &psDevInfo->psWorkEstFirmwareCCBCtl,
+								 &psDevInfo->psWorkEstFirmwareCCBCtlMemDesc,
+								 &psDevInfo->psWorkEstFirmwareCCB,
+								 &psDevInfo->psWorkEstFirmwareCCBMemDesc,
+								 &psRGXFWInit->psWorkEstFirmwareCCBCtl,
+								 &psRGXFWInit->psWorkEstFirmwareCCB,
+								 RGXFWIF_WORKEST_FWCCB_NUMCMDS_LOG2,
+								 sizeof(RGXFWIF_WORKEST_FWCCB_CMD),
+								 "FwWEstCCB");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Workload Estimation Firmware CCB"));
+		goto fail;
+	}
+#endif
+
+	/* Require a minimum amount of memory for the signature buffers */
+	if (ui32SignatureChecksBufSize < RGXFW_SIG_BUFFER_SIZE_MIN)
+	{
+		ui32SignatureChecksBufSize = RGXFW_SIG_BUFFER_SIZE_MIN;
+	}
 
 	/* Setup Signature and Checksum Buffers for TA and 3D */
 	eError = RGXFWSetupSignatureChecks(psDevInfo,
-	                                   &psDevInfo->psRGXFWSigTAChecksMemDesc, 
+	                                   &psDevInfo->psRGXFWSigTAChecksMemDesc,
 	                                   ui32SignatureChecksBufSize,
 	                                   &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_TA],
 	                                   "TA");
@@ -1931,7 +2196,7 @@
 	psDevInfo->ui32SigTAChecksSize = ui32SignatureChecksBufSize;
 
 	eError = RGXFWSetupSignatureChecks(psDevInfo,
-	                                   &psDevInfo->psRGXFWSig3DChecksMemDesc, 
+	                                   &psDevInfo->psRGXFWSig3DChecksMemDesc,
 	                                   ui32SignatureChecksBufSize,
 	                                   &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_3D],
 	                                   "3D");
@@ -1942,44 +2207,46 @@
 	}
 	psDevInfo->ui32Sig3DChecksSize = ui32SignatureChecksBufSize;
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	eError = RGXFWSetupSignatureChecks(psDevInfo,
-	                                   &psDevInfo->psRGXFWSigRTChecksMemDesc, 
-	                                   ui32SignatureChecksBufSize,
-	                                   &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_RTU],
-	                                   "RTU");
-	if (eError != PVRSRV_OK)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup RTU signature checks"));
-		goto fail;
+		eError = RGXFWSetupSignatureChecks(psDevInfo,
+										   &psDevInfo->psRGXFWSigRTChecksMemDesc,
+										   ui32SignatureChecksBufSize,
+										   &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_RTU],
+										   "RTU");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup RTU signature checks"));
+			goto fail;
+		}
+		psDevInfo->ui32SigRTChecksSize = ui32SignatureChecksBufSize;
+
+		eError = RGXFWSetupSignatureChecks(psDevInfo,
+										   &psDevInfo->psRGXFWSigSHChecksMemDesc,
+										   ui32SignatureChecksBufSize,
+										   &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_SHG],
+										   "SHG");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup SHG signature checks"));
+			goto fail;
+		}
+		psDevInfo->ui32SigSHChecksSize = ui32SignatureChecksBufSize;
 	}
-	psDevInfo->ui32SigRTChecksSize = ui32SignatureChecksBufSize;
-	
-	eError = RGXFWSetupSignatureChecks(psDevInfo,
-	                                   &psDevInfo->psRGXFWSigSHChecksMemDesc, 
-	                                   ui32SignatureChecksBufSize,
-	                                   &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_SHG],
-	                                   "SHG");
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup SHG signature checks"));
-		goto fail;
-	}
-	psDevInfo->ui32SigSHChecksSize = ui32SignatureChecksBufSize;
-#endif
 
 #if defined(RGXFW_ALIGNCHECKS)
-	eError = RGXFWSetupAlignChecks(psDevInfo, 
-								&psRGXFWInit->paui32AlignChecks, 
-								pui32RGXFWAlignChecks, 
-								ui32RGXFWAlignChecksSize);
+	eError = RGXFWSetupAlignChecks(psDevInfo,
+								&psRGXFWInit->sAlignChecks,
+								pui32RGXFWAlignChecks,
+								ui32RGXFWAlignChecksArrLength);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup alignment checks"));
 		goto fail;
 	}
 #endif
-	PMRUnlock();
+
+	psRGXFWInit->ui32FilterFlags = ui32FilterFlags;
 
 #if defined(PVRSRV_GPUVIRT_GUESTDRV)
 	/*
@@ -1991,46 +2258,48 @@
 	PVR_UNREFERENCED_PARAMETER(dm);
 	PVR_UNREFERENCED_PARAMETER(eFirmwarePerf);
 #else
-	/* Fill the remaining bits of fw the init data */
-	psRGXFWInit->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
-	psRGXFWInit->sUSCExecBase.uiAddr = RGX_USCCODE_HEAP_BASE;
+
+	if(ui64ErnsBrns & FIX_HW_BRN_52402_BIT_MASK)
+	{
+		/* Fill the remaining bits of fw the init data */
+		psRGXFWInit->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_BRN_52402_HEAP_BASE;
+		psRGXFWInit->sUSCExecBase.uiAddr = RGX_USCCODE_BRN_52402_HEAP_BASE;
+	}else
+	{
+		/* Fill the remaining bits of fw the init data */
+		psRGXFWInit->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
+		psRGXFWInit->sUSCExecBase.uiAddr = RGX_USCCODE_HEAP_BASE;
+	}
+
 	psRGXFWInit->sDPXControlStreamBase.uiAddr = RGX_DOPPLER_HEAP_BASE;
 	psRGXFWInit->sResultDumpBase.uiAddr = RGX_DOPPLER_OVERFLOW_HEAP_BASE;
 	psRGXFWInit->sRTUHeapBase.uiAddr = RGX_DOPPLER_HEAP_BASE;
+	psRGXFWInit->sTDMTPUYUVCeoffsHeapBase.uiAddr = RGX_TDM_TPU_YUV_COEFFS_HEAP_BASE;
 
-	/* RD Power Island */
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
 	{
-		RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
-		IMG_BOOL bSysEnableRDPowIsland = psRGXData->psRGXTimingInfo->bEnableRDPowIsland;
-		IMG_BOOL bEnableRDPowIsland = ((eRGXRDPowerIslandConf == RGX_RD_POWER_ISLAND_DEFAULT) && bSysEnableRDPowIsland) ||
-						(eRGXRDPowerIslandConf == RGX_RD_POWER_ISLAND_FORCE_ON);
-
-		ui32ConfigFlags |= bEnableRDPowIsland? RGXFWIF_INICFG_POW_RASCALDUST : 0;
+		psRGXFWInit->ui32JonesDisableMask = ui32JonesDisableMask;
 	}
-
-	psRGXFWInit->ui32ConfigFlags = ui32ConfigFlags & RGXFWIF_INICFG_ALL;
-	psRGXFWInit->ui32FilterFlags = ui32FilterFlags;
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	psRGXFWInit->ui32JonesDisableMask = ui32JonesDisableMask;
-#endif
 	psDevInfo->bPDPEnabled = (ui32ConfigFlags & RGXFWIF_SRVCFG_DISABLE_PDP_EN)
 			? IMG_FALSE : IMG_TRUE;
 	psRGXFWInit->ui32HWRDebugDumpLimit = ui32HWRDebugDumpLimit;
 
 	psRGXFWInit->eFirmwarePerf = eFirmwarePerf;
 
-#if defined(RGX_FEATURE_SLC_VIVT)
-	eError = _AllocateSLC3Fence(psDevInfo, psRGXFWInit);
-	if (eError != PVRSRV_OK)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SLC_VIVT_BIT_MASK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate memory for SLC3Fence"));
-		goto fail;
+		eError = _AllocateSLC3Fence(psDevInfo, psRGXFWInit);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate memory for SLC3Fence"));
+			goto fail;
+		}
 	}
-#endif
 
-	PMRLock();
-#if defined(RGX_FEATURE_META)
-	if ((ui32ConfigFlags & RGXFWIF_INICFG_METAT1_ENABLED) != 0)
+
+	if ( (psDevInfo->sDevFeatureCfg.ui32META) && \
+			((ui32ConfigFlags & RGXFWIF_INICFG_METAT1_ENABLED) != 0))
 	{
 		/* Allocate a page for T1 stack */
 		eError = DevmemFwAllocate(psDevInfo,
@@ -2044,13 +2313,52 @@
 			goto fail;
 		}
 
-		RGXSetFirmwareAddress(&psRGXFWInit->pbT1Stack,
+		RGXSetFirmwareAddress(&psRGXFWInit->sT1Stack,
 		                      psDevInfo->psMETAT1StackMemDesc,
 		                      0, RFW_FWADDR_NOREF_FLAG);
 
 		PVR_DPF((PVR_DBG_MESSAGE, "RGXSetupFirmware: T1 Stack Frame allocated at %x",
-		         psRGXFWInit->pbT1Stack.ui32Addr));
+				 psRGXFWInit->sT1Stack.ui32Addr));
 	}
+
+#if defined(SUPPORT_PDVFS)
+		/* Core clock rate */
+		uiMemAllocFlags =
+			PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+			PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+			PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+			PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+			PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+			PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+			PVRSRV_MEMALLOCFLAG_UNCACHED |
+			PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+		eError = DevmemFwAllocate(psDevInfo,
+								  sizeof(IMG_UINT32),
+								  uiMemAllocFlags,
+								  "FwCoreClkRate",
+								  &psDevInfo->psRGXFWIFCoreClkRateMemDesc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate PDVFS core clock rate"));
+			goto fail;
+		}
+
+		RGXSetFirmwareAddress(&psRGXFWInit->sCoreClockRate,
+							  psDevInfo->psRGXFWIFCoreClkRateMemDesc,
+							  0, RFW_FWADDR_NOREF_FLAG);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "RGXSetupFirmware: PDVFS core clock rate allocated at %x",
+				 psRGXFWInit->sCoreClockRate.ui32Addr));
+
+		eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIFCoreClkRateMemDesc,
+										  (void **)&psDevInfo->pui32RGXFWIFCoreClkRate);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire core clk rate (%u)",
+					eError));
+			goto fail;
+		}
 #endif
 
 	/* Timestamps */
@@ -2062,7 +2370,7 @@
 		PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
 		PVRSRV_MEMALLOCFLAG_UNCACHED |
 		PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
-	
+
 	/*
 	  the timer query arrays
 	*/
@@ -2120,7 +2428,7 @@
 
 	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psCompletedMemDesc,
 	                                  (void **)& psDevInfo->pui32CompletedById);
-	
+
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to map completed ops array"));
@@ -2130,18 +2438,11 @@
 		/* Initialize FW started flag */
 	psRGXFWInit->bFirmwareStarted = IMG_FALSE;
 	psRGXFWInit->ui32MarkerVal = 1;
-	
+
 	/* Initialise the compatibility check data */
 	RGXFWIF_COMPCHECKS_BVNC_INIT(psRGXFWInit->sRGXCompChecks.sFWBVNC);
 	RGXFWIF_COMPCHECKS_BVNC_INIT(psRGXFWInit->sRGXCompChecks.sHWBVNC);
-	
-	{
-		/* Below line is to make sure (compilation time check) that 
-				RGX_BVNC_KM_V_ST fits into RGXFWIF_COMPCHECKS_BVNC structure */
-		IMG_CHAR _tmp_[RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX] = RGX_BVNC_KM_V_ST;
-		_tmp_[0] = '\0';
-	}
-	
+
 	PDUMPCOMMENT("Dump RGXFW Init data");
 	if (!bEnableSignatureChecks)
 	{
@@ -2149,25 +2450,27 @@
 		PDUMPCOMMENT("(to enable rgxfw signatures place the following line after the RTCONF line)");
 		DevmemPDumpLoadMem(	psDevInfo->psRGXFWIfInitMemDesc,
 							offsetof(RGXFWIF_INIT, asSigBufCtl),
-							sizeof(RGXFWIF_SIGBUF_CTL)*RGXFWIF_DM_MAX,
+							sizeof(RGXFWIF_SIGBUF_CTL)*(psDevInfo->sDevFeatureCfg.ui32MAXDMCount),
 							PDUMP_FLAGS_CONTINUOUS);
 #endif
-		psRGXFWInit->asSigBufCtl[RGXFWIF_DM_3D].psBuffer.ui32Addr = 0x0;
-		psRGXFWInit->asSigBufCtl[RGXFWIF_DM_TA].psBuffer.ui32Addr = 0x0;
+		psRGXFWInit->asSigBufCtl[RGXFWIF_DM_3D].sBuffer.ui32Addr = 0x0;
+		psRGXFWInit->asSigBufCtl[RGXFWIF_DM_TA].sBuffer.ui32Addr = 0x0;
 	}
-	
-	for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+
+	for (dm = 0; dm < (psDevInfo->sDevFeatureCfg.ui32MAXDMCount); dm++)
 	{
-		psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmLockedUpCount[dm] = 0;
-		psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmOverranCount[dm] = 0;
-		psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmRecoveredCount[dm] = 0;
-		psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmFalseDetectCount[dm] = 0;
+		psDevInfo->psRGXFWIfTraceBuf->aui32HwrDmLockedUpCount[dm] = 0;
+		psDevInfo->psRGXFWIfTraceBuf->aui32HwrDmOverranCount[dm] = 0;
+		psDevInfo->psRGXFWIfTraceBuf->aui32HwrDmRecoveredCount[dm] = 0;
+		psDevInfo->psRGXFWIfTraceBuf->aui32HwrDmFalseDetectCount[dm] = 0;
 	}
-	
+
 	/*
 	 * BIF Tiling configuration
 	 */
 
+	psRGXFWInit->eBifTilingMode = eBifTilingMode;
+
 	psRGXFWInit->sBifTilingCfg[0].uiBase = RGX_BIF_TILING_HEAP_1_BASE;
 	psRGXFWInit->sBifTilingCfg[0].uiLen = RGX_BIF_TILING_HEAP_SIZE;
 	psRGXFWInit->sBifTilingCfg[0].uiXStride = pui32BIFTilingXStrides[0];
@@ -2187,7 +2490,7 @@
 	                        0,
 							ui32HWPerfCountersDataSize,
 	                        PDUMP_FLAGS_CONTINUOUS);
-	
+
 	PDUMPCOMMENT("Dump rgxfw trace control structure");
 	DevmemPDumpLoadMem(	psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
 						0,
@@ -2205,18 +2508,22 @@
 						0,
 						sizeof(RGXFWIF_INIT),
 						PDUMP_FLAGS_CONTINUOUS);
-#if defined(RGX_META_COREMEM)
-	PDUMPCOMMENT("Dump rgxfw coremem data store");
-	DevmemPDumpLoadMem(	psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
-						0,
-						RGX_META_COREMEM_DATA_SIZE,
-						PDUMP_FLAGS_CONTINUOUS);
-#endif
+	if ((0 != psDevInfo->sDevFeatureCfg.ui32MCMS) && \
+				(0 == (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & FIX_HW_BRN_50767_BIT_MASK)))
+	{
+		PDUMPCOMMENT("Dump rgxfw coremem data store");
+		DevmemPDumpLoadMem(	psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+							0,
+							RGX_META_COREMEM_BSS_SIZE,
+							PDUMP_FLAGS_CONTINUOUS);
+	}
 
 	PDUMPCOMMENT("RTCONF: run-time configuration");
 
-	
+
 	/* Dump the config options so they can be edited.
+	 *
+	 * FIXME: Need new DevmemPDumpWRW API which writes a WRW to load ui32ConfigFlags
 	 */
 	PDUMPCOMMENT("(Set the FW config options here)");
 	PDUMPCOMMENT("( Ctx Switch TA Enable: 0x%08x)", RGXFWIF_INICFG_CTXSWITCH_TA_EN);
@@ -2231,11 +2538,14 @@
 	PDUMPCOMMENT("( Check MList: 0x%08x)", RGXFWIF_INICFG_CHECK_MLIST_EN);
 	PDUMPCOMMENT("( Disable Auto Clock Gating: 0x%08x)", RGXFWIF_INICFG_DISABLE_CLKGATING_EN);
 	PDUMPCOMMENT("( Enable HWPerf Polling Perf Counter: 0x%08x)", RGXFWIF_INICFG_POLL_COUNTERS_EN);
-#if defined(RGX_FEATURE_VDM_OBJECT_LEVEL_LLS)
-	PDUMPCOMMENT("( Ctx Switch Object mode Index: 0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX);
-	PDUMPCOMMENT("( Ctx Switch Object mode Instance: 0x%08x)", RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INSTANCE);
-	PDUMPCOMMENT("( Ctx Switch Object mode List: 0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST);
-#endif
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_BIT_MASK)
+	{
+		PDUMPCOMMENT("( Ctx Switch Object mode Index: 0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX);
+		PDUMPCOMMENT("( Ctx Switch Object mode Instance: 0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE);
+		PDUMPCOMMENT("( Ctx Switch Object mode List: 0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST);
+	}
+
 	PDUMPCOMMENT("( Enable SHG Bypass mode: 0x%08x)", RGXFWIF_INICFG_SHG_BYPASS_EN);
 	PDUMPCOMMENT("( Enable RTU Bypass mode: 0x%08x)", RGXFWIF_INICFG_RTU_BYPASS_EN);
 	PDUMPCOMMENT("( Enable register configuration: 0x%08x)", RGXFWIF_INICFG_REGCONFIG_EN);
@@ -2243,9 +2553,11 @@
 	PDUMPCOMMENT("( Disable HWPerf custom counter filter: 0x%08x)", RGXFWIF_INICFG_HWP_DISABLE_FILTER);
 	PDUMPCOMMENT("( Enable HWPerf custom performance timer: 0x%08x)", RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN);
 	PDUMPCOMMENT("( Enable CDM Killing Rand mode: 0x%08x)", RGXFWIF_INICFG_CDM_KILL_MODE_RAND_EN);
+	PDUMPCOMMENT("( Enable Ctx Switch profile mode: 0x%08x (none=b'000, fast=b'001, medium=b'010, slow=b'011, nodelay=b'100))", RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK);
 	PDUMPCOMMENT("( Disable DM overlap (except TA during SPM): 0x%08x)", RGXFWIF_INICFG_DISABLE_DM_OVERLAP);
 	PDUMPCOMMENT("( Enable Meta T1 running main code: 0x%08x)", RGXFWIF_INICFG_METAT1_MAIN);
 	PDUMPCOMMENT("( Enable Meta T1 running dummy code: 0x%08x)", RGXFWIF_INICFG_METAT1_DUMMY);
+	PDUMPCOMMENT("( Assert on HWR trigger (page fault, lockup, overrun or poll failure): 0x%08x)", RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER);
 
 	DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfInitMemDesc,
 							offsetof(RGXFWIF_INIT, ui32ConfigFlags),
@@ -2273,23 +2585,34 @@
 		/* generate a few WRWs in the pdump stream as an example */
 		for(i = 0; i < MIN(RGXFWIF_PID_FILTER_MAX_NUM_PIDS, 8); i++)
 		{
+			/*
+			 * Some compilers cannot cope with the uses of offsetof() below - the specific problem being the use of
+			 * a non-const variable in the expression, which it needs to be const. Typical compiler output is
+			 * "expression must have a constant value".
+			 */
+			const IMG_DEVMEM_OFFSET_T uiPIDOff
+			= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_INIT *)0)->sPIDFilter.asItems[i].uiPID);
+
+			const IMG_DEVMEM_OFFSET_T uiOSIDOff
+			= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_INIT *)0)->sPIDFilter.asItems[i].ui32OSID);
+			
 			PDUMPCOMMENT("(PID and OSID pair %u)", i);
 
 			PDUMPCOMMENT("(PID)");
 			DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfInitMemDesc,
-						offsetof(RGXFWIF_INIT, sPIDFilter.asItems[i].uiPID),
+						uiPIDOff,
 						0,
 						PDUMP_FLAGS_CONTINUOUS);
 
 			PDUMPCOMMENT("(OSID)");
 			DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfInitMemDesc,
-						offsetof(RGXFWIF_INIT, sPIDFilter.asItems[i].ui32OSID),
+						uiOSIDOff,
 						0,
 						PDUMP_FLAGS_CONTINUOUS);
 		}
 	}
 
-	/* 
+	/*
 	 * Dump the log config so it can be edited.
 	 */
 	PDUMPCOMMENT("(Set the log config here)");
@@ -2305,12 +2628,16 @@
 	PDUMPCOMMENT("( POW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_POW);
 	PDUMPCOMMENT("( HWR Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWR);
 	PDUMPCOMMENT("( HWP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWP);
-#if defined(RGX_FEATURE_RAY_TRACING)
-	PDUMPCOMMENT("( RPM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_RPM);
-#endif
-#if defined(RGX_FEATURE_META_DMA)
-	PDUMPCOMMENT("( DMA Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DMA);
-#endif
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+	{
+		PDUMPCOMMENT("( RPM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_RPM);
+	}
+
+	if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_META_DMA_BIT_MASK)
+	{
+		PDUMPCOMMENT("( DMA Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DMA);
+	}
 	PDUMPCOMMENT("( DEBUG Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DEBUG);
 	DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
 							offsetof(RGXFWIF_TRACEBUF, ui32LogType),
@@ -2321,10 +2648,10 @@
 	DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfInitMemDesc,
 						offsetof(RGXFWIF_INIT, ui64HWPerfFilter),
 						psRGXFWInit->ui64HWPerfFilter,
-						PDUMP_FLAGS_CONTINUOUS);						
-							
+						PDUMP_FLAGS_CONTINUOUS);
+
 #if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
-	PDUMPCOMMENT("(Number of registers configurations at pow on, dust change, ta, 3d, cdm and tla)");
+	PDUMPCOMMENT("(Number of registers configurations at pow on, dust change, ta, 3d, cdm and tla/tdm)");
 	DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
 							offsetof(RGXFWIF_REG_CFG, aui8NumRegsType[RGXFWIF_REG_CFG_TYPE_PWR_ON]),
 							0,
@@ -2345,10 +2672,23 @@
 							offsetof(RGXFWIF_REG_CFG, aui8NumRegsType[RGXFWIF_REG_CFG_TYPE_CDM]),
 							0,
 							PDUMP_FLAGS_CONTINUOUS);
-	DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
-							offsetof(RGXFWIF_REG_CFG, aui8NumRegsType[RGXFWIF_REG_CFG_TYPE_TLA]),
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK)
+	{
+		DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
+								offsetof(RGXFWIF_REG_CFG, aui8NumRegsType[RGXFWIF_REG_CFG_TYPE_TLA]),
+								0,
+								PDUMP_FLAGS_CONTINUOUS);
+	}
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
+	{
+		DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
+							offsetof(RGXFWIF_REG_CFG, aui8NumRegsType[RGXFWIF_REG_CFG_TYPE_TDM]),
 							0,
 							PDUMP_FLAGS_CONTINUOUS);
+	}
+
 	PDUMPCOMMENT("(Set registers here: address, mask, value)");
 	DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
 							offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Addr),
@@ -2367,11 +2707,11 @@
 #endif /* PVRSRV_GPUVIRT_GUESTDRV */
 
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
-	/* Perform additional virtualization initialization */
-	eError = RGXVirtSetupFirmware(psDeviceNode);
+	/* Perform additional virtualisation initialisation */
+	eError = RGXVzSetupFirmware(psDeviceNode);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed RGXVirtSetupFirmware"));
+		PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed RGXVzSetupFirmware"));
 		goto fail;
 	}
 #endif
@@ -2382,13 +2722,10 @@
 
 	psDevInfo->bFirmwareInitialised = IMG_TRUE;
 
-	PMRUnlock();
 	return PVRSRV_OK;
 
 fail:
-#if defined(PVRSRV_GPUVIRT_GUESTDRV) 
-	/* Functionality n/a to guest drivers */
-#else
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	if (psDevInfo->psRGXFWIfInitMemDesc != NULL && psRGXFWInit != NULL)
 	{
 		DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
@@ -2397,7 +2734,6 @@
 	RGXFreeFirmware(psDevInfo);
 
 	PVR_ASSERT(eError != PVRSRV_OK);
-	PMRUnlock();
 	return eError;
 }
 
@@ -2417,10 +2753,25 @@
 ******************************************************************************/
 void RGXFreeFirmware(PVRSRV_RGXDEV_INFO 	*psDevInfo)
 {
+	IMG_UINT64	ui64ErnsBrns = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
+
 	psDevInfo->bFirmwareInitialised = IMG_FALSE;
 
 	RGXFreeKernelCCB(psDevInfo);
-	RGXFreeFirmwareCCB(psDevInfo);
+
+	RGXFreeFirmwareCCB(psDevInfo,
+					   &psDevInfo->psFirmwareCCBCtl,
+					   &psDevInfo->psFirmwareCCBCtlMemDesc,
+					   &psDevInfo->psFirmwareCCB,
+					   &psDevInfo->psFirmwareCCBMemDesc);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	RGXFreeFirmwareCCB(psDevInfo,
+					   &psDevInfo->psWorkEstFirmwareCCBCtl,
+					   &psDevInfo->psWorkEstFirmwareCCBCtlMemDesc,
+					   &psDevInfo->psWorkEstFirmwareCCB,
+					   &psDevInfo->psWorkEstFirmwareCCBMemDesc);
+#endif
 
 #if defined(RGXFW_ALIGNCHECKS)
 	if (psDevInfo->psRGXFWAlignChecksMemDesc)
@@ -2431,38 +2782,40 @@
 
 	if (psDevInfo->psRGXFWSigTAChecksMemDesc)
 	{
-		DevmemFwFree(psDevInfo->psRGXFWSigTAChecksMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWSigTAChecksMemDesc);
 		psDevInfo->psRGXFWSigTAChecksMemDesc = NULL;
 	}
 
 	if (psDevInfo->psRGXFWSig3DChecksMemDesc)
 	{
-		DevmemFwFree(psDevInfo->psRGXFWSig3DChecksMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWSig3DChecksMemDesc);
 		psDevInfo->psRGXFWSig3DChecksMemDesc = NULL;
 	}
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	if (psDevInfo->psRGXFWSigRTChecksMemDesc)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
 	{
-		DevmemFwFree(psDevInfo->psRGXFWSigRTChecksMemDesc);
-		psDevInfo->psRGXFWSigRTChecksMemDesc = NULL;
-	}
-	
-	if (psDevInfo->psRGXFWSigSHChecksMemDesc)
-	{
-		DevmemFwFree(psDevInfo->psRGXFWSigSHChecksMemDesc);
-		psDevInfo->psRGXFWSigSHChecksMemDesc = NULL;
-	}
-#endif
+		if (psDevInfo->psRGXFWSigRTChecksMemDesc)
+		{
+			DevmemFwFree(psDevInfo, psDevInfo->psRGXFWSigRTChecksMemDesc);
+			psDevInfo->psRGXFWSigRTChecksMemDesc = NULL;
+		}
 
-#if defined(FIX_HW_BRN_37200)
-	if (psDevInfo->psRGXFWHWBRN37200MemDesc)
-	{
-		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWHWBRN37200MemDesc);
-		DevmemFree(psDevInfo->psRGXFWHWBRN37200MemDesc);
-		psDevInfo->psRGXFWHWBRN37200MemDesc = NULL;
+		if (psDevInfo->psRGXFWSigSHChecksMemDesc)
+		{
+			DevmemFwFree(psDevInfo, psDevInfo->psRGXFWSigSHChecksMemDesc);
+			psDevInfo->psRGXFWSigSHChecksMemDesc = NULL;
+		}
 	}
-#endif
+
+	if(ui64ErnsBrns & FIX_HW_BRN_37200_BIT_MASK)
+	{
+		if (psDevInfo->psRGXFWHWBRN37200MemDesc)
+		{
+			DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWHWBRN37200MemDesc);
+			DevmemFree(psDevInfo->psRGXFWHWBRN37200MemDesc);
+			psDevInfo->psRGXFWHWBRN37200MemDesc = NULL;
+		}
+	}
 
 	RGXSetupFaultReadRegisterRollback(psDevInfo);
 
@@ -2471,16 +2824,14 @@
 		SyncPrimFree(psDevInfo->psPowSyncPrim);
 		psDevInfo->psPowSyncPrim = NULL;
 	}
-	
+
 	if (psDevInfo->hSyncPrimContext != 0)
 	{
 		SyncPrimContextDestroy(psDevInfo->hSyncPrimContext);
 		psDevInfo->hSyncPrimContext = 0;
 	}
 
-#if  defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Deinitialize functionality n/a in guest drivers */
-#else
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	if (psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc)
 	{
 		if (psDevInfo->psRGXFWIfGpuUtilFWCb != NULL)
@@ -2488,7 +2839,7 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
 			psDevInfo->psRGXFWIfGpuUtilFWCb = NULL;
 		}
-		DevmemFwFree(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
 		psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc = NULL;
 	}
 
@@ -2501,7 +2852,7 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
 			psDevInfo->psRGXFWIfRuntimeCfg = NULL;
 		}
-		DevmemFwFree(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
 		psDevInfo->psRGXFWIfRuntimeCfgMemDesc = NULL;
 	}
 
@@ -2512,17 +2863,20 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
 			psDevInfo->psRGXFWIfHWRInfoBuf = NULL;
 		}
-		DevmemFwFree(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
 		psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc = NULL;
 	}
 
-#if defined(RGX_META_COREMEM)
-	if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
+	if ((0 != psDevInfo->sDevFeatureCfg.ui32MCMS) && \
+				(0 == (ui64ErnsBrns & FIX_HW_BRN_50767_BIT_MASK)))
 	{
-		DevmemFwFree(psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
-		psDevInfo->psRGXFWIfCorememDataStoreMemDesc = NULL;
+		if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
+		{
+			DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+			psDevInfo->psRGXFWIfCorememDataStoreMemDesc = NULL;
+		}
 	}
-#endif
+
 	if (psDevInfo->psRGXFWIfTraceBufCtlMemDesc)
 	{
 		if (psDevInfo->psRGXFWIfTraceBuf != NULL)
@@ -2533,40 +2887,53 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
 			psDevInfo->psRGXFWIfTraceBuf = NULL;
 		}
-		DevmemFwFree(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
 		psDevInfo->psRGXFWIfTraceBufCtlMemDesc = NULL;
 	}
 #if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
 	if (psDevInfo->psRGXFWIfRegCfgMemDesc)
 	{
-		DevmemFwFree(psDevInfo->psRGXFWIfRegCfgMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfRegCfgMemDesc);
 		psDevInfo->psRGXFWIfRegCfgMemDesc = NULL;
 	}
 #endif
 	if (psDevInfo->psRGXFWIfHWPerfCountersMemDesc)
 	{
 		RGXUnsetFirmwareAddress(psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
-		DevmemFwFree(psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
 		psDevInfo->psRGXFWIfHWPerfCountersMemDesc = NULL;
 	}
-#if defined(RGX_FEATURE_SLC_VIVT)
-	_FreeSLC3Fence(psDevInfo);
-#endif
-
-#if defined(RGX_FEATURE_META)
-	if (psDevInfo->psMETAT1StackMemDesc)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SLC_VIVT_BIT_MASK)
 	{
-		DevmemFwFree(psDevInfo->psMETAT1StackMemDesc);
+		_FreeSLC3Fence(psDevInfo);
+	}
+
+	if( (psDevInfo->sDevFeatureCfg.ui32META) && (psDevInfo->psMETAT1StackMemDesc))
+	{
+		DevmemFwFree(psDevInfo, psDevInfo->psMETAT1StackMemDesc);
 		psDevInfo->psMETAT1StackMemDesc = NULL;
 	}
+
+#if defined(SUPPORT_PDVFS)
+	if (psDevInfo->psRGXFWIFCoreClkRateMemDesc)
+	{
+		if (psDevInfo->pui32RGXFWIFCoreClkRate != NULL)
+		{
+			DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIFCoreClkRateMemDesc);
+			psDevInfo->pui32RGXFWIFCoreClkRate = NULL;
+		}
+
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIFCoreClkRateMemDesc);
+		psDevInfo->psRGXFWIFCoreClkRateMemDesc = NULL;
+	}
 #endif
 
 	if (psDevInfo->psRGXFWIfInitMemDesc)
 	{
-		DevmemFwFree(psDevInfo->psRGXFWIfInitMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWIfInitMemDesc);
 		psDevInfo->psRGXFWIfInitMemDesc = NULL;
 	}
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
+#endif
 
 	if (psDevInfo->psCompletedMemDesc)
 	{
@@ -2575,7 +2942,7 @@
 			DevmemReleaseCpuVirtAddr(psDevInfo->psCompletedMemDesc);
 			psDevInfo->pui32CompletedById = NULL;
 		}
-		DevmemFwFree(psDevInfo->psCompletedMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psCompletedMemDesc);
 		psDevInfo->psCompletedMemDesc = NULL;
 	}
 	if (psDevInfo->psEndTimeMemDesc)
@@ -2586,7 +2953,7 @@
 			psDevInfo->pui64EndTimeById = NULL;
 		}
 
-		DevmemFwFree(psDevInfo->psEndTimeMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psEndTimeMemDesc);
 		psDevInfo->psEndTimeMemDesc = NULL;
 	}
 	if (psDevInfo->psStartTimeMemDesc)
@@ -2597,7 +2964,7 @@
 			psDevInfo->pui64StartTimeById = NULL;
 		}
 
-		DevmemFwFree(psDevInfo->psStartTimeMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psStartTimeMemDesc);
 		psDevInfo->psStartTimeMemDesc = NULL;
 	}
 }
@@ -2626,7 +2993,7 @@
 	 * Hence the kernel CCB should not queue more 254 commands
 	 */
 	PVR_ASSERT(psKCCBCtl->ui32WrapMask < 255);
-	
+
 #if defined(PDUMP)
 	/* Wait for sufficient CCB space to become available */
 	PDUMPCOMMENTWITHFLAGS(0, "Wait for kCCB woff=%u", ui32NextWriteOffset);
@@ -2646,7 +3013,7 @@
 			return PVRSRV_OK;
 		}
 		{
-			/* 
+			/*
 			 * The following sanity check doesn't impact performance,
 			 * since the CPU has to wait for the GPU anyway (full kernel CCB).
 			 */
@@ -2668,15 +3035,15 @@
 										 RGXFWIF_DM			eKCCBType,
 										 RGXFWIF_KCCB_CMD	*psKCCBCmd,
 										 IMG_UINT32			ui32CmdSize,
-										 IMG_BOOL			bPDumpContinuous)
+										 IMG_UINT32			ui32PDumpFlags)
 {
 	PVRSRV_ERROR		eError;
 	PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
 
 	/* Ensure Rogue is powered up before kicking MTS */
-	eError = PVRSRVPowerLock();
+	eError = PVRSRVPowerLock(psDeviceNode);
 
-	if (eError != PVRSRV_OK) 
+	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_WARNING, "RGXSendCommandWithPowLock: failed to acquire powerlock (%s)",
 					PVRSRVGetErrorStringKM(eError)));
@@ -2685,12 +3052,12 @@
 	}
 
 	PDUMPPOWCMDSTART();
-	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
 										 PVRSRV_DEV_POWER_STATE_ON,
 										 IMG_FALSE);
 	PDUMPPOWCMDEND();
 
-	if (eError != PVRSRV_OK) 
+	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_WARNING, "RGXSendCommandWithPowLock: failed to transition Rogue to ON (%s)",
 					PVRSRVGetErrorStringKM(eError)));
@@ -2698,21 +3065,21 @@
 		goto _PVRSRVSetDevicePowerStateKM_Exit;
 	}
 
-	eError = RGXSendCommand(psDevInfo, eKCCBType,  psKCCBCmd, ui32CmdSize, bPDumpContinuous?PDUMP_FLAGS_CONTINUOUS:0);
+	eError = RGXSendCommand(psDevInfo, eKCCBType,  psKCCBCmd, ui32CmdSize, ui32PDumpFlags);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "RGXSendCommandWithPowLock: failed to schedule command (%s)",
 					PVRSRVGetErrorStringKM(eError)));
 #if defined(DEBUG)
 		/* PVRSRVDebugRequest must be called without powerlock */
-		PVRSRVPowerUnlock();
-		PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+		PVRSRVPowerUnlock(psDeviceNode);
+		PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
 		goto _PVRSRVPowerLock_Exit;
 #endif
 	}
 
 _PVRSRVSetDevicePowerStateKM_Exit:
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 _PVRSRVPowerLock_Exit:
 	return eError;
@@ -2722,9 +3089,10 @@
 								 RGXFWIF_DM			eKCCBType,
 								 RGXFWIF_KCCB_CMD	*psKCCBCmd,
 								 IMG_UINT32			ui32CmdSize,
-								 PDUMP_FLAGS_T		uiPdumpFlags)
+								 IMG_UINT32             uiPdumpFlags)
 {
 	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = psDevInfo->psDeviceNode;
 	RGXFWIF_CCB_CTL		*psKCCBCtl = psDevInfo->psKernelCCBCtl;
 	IMG_UINT8			*pui8KCCB = psDevInfo->psKernelCCB;
 	IMG_UINT32			ui32NewWriteOffset;
@@ -2735,11 +3103,10 @@
 #else
 	IMG_BOOL bIsInCaptureRange;
 	IMG_BOOL bPdumpEnabled;
-	IMG_BOOL bPDumpContinuous = (uiPdumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0;
 	IMG_BOOL bPDumpPowTrans = PDUMPPOWCMDINTRANS();
 
 	PDumpIsCaptureFrameKM(&bIsInCaptureRange);
-	bPdumpEnabled = (bIsInCaptureRange || bPDumpContinuous) && !bPDumpPowTrans;
+	bPdumpEnabled = (bIsInCaptureRange || PDUMP_IS_CONTINUOUS(uiPdumpFlags)) && !bPDumpPowTrans;
 
 	/* in capture range */
 	if (bPdumpEnabled)
@@ -2769,15 +3136,15 @@
 	psKCCBCmd->eDM = eKCCBType;
 
 	PVR_ASSERT(ui32CmdSize == psKCCBCtl->ui32CmdSize);
-	if (!OSLockIsLocked(PVRSRVGetPVRSRVData()->hPowerLock))
+	if (!OSLockIsLocked(psDeviceNode->hPowerLock))
 	{
 		PVR_DPF((PVR_DBG_ERROR, "RGXSendCommandRaw called without power lock held!"));
-		PVR_ASSERT(OSLockIsLocked(PVRSRVGetPVRSRVData()->hPowerLock));
+		PVR_ASSERT(OSLockIsLocked(psDeviceNode->hPowerLock));
 	}
 
 	/*
 	 * Acquire a slot in the CCB.
-	 */ 
+	 */
 	eError = RGXAcquireKernelCCBSlot(psDevInfo->psKernelCCBCtlMemDesc, psKCCBCtl, &ui32NewWriteOffset);
 	if (eError != PVRSRV_OK)
 	{
@@ -2785,11 +3152,11 @@
 				eKCCBType, eError));
 		goto _RGXSendCommandRaw_Exit;
 	}
-	
+
 	/*
 	 * Copy the command into the CCB.
 	 */
-	OSMemCopy(&pui8KCCB[ui32OldWriteOffset * psKCCBCtl->ui32CmdSize],
+	OSDeviceMemCopy(&pui8KCCB[ui32OldWriteOffset * psKCCBCtl->ui32CmdSize],
 			  psKCCBCmd, psKCCBCtl->ui32CmdSize);
 
 	/* ensure kCCB data is written before the offsets */
@@ -2839,15 +3206,24 @@
 	/*
 	 * Kick the MTS to schedule the firmware.
 	 */
-	{
-		IMG_UINT32 ui32MTSRegVal = (RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) |
-		                           RGX_CR_MTS_SCHEDULE_TASK_COUNTED;
-		
-		__MTSScheduleWrite(psDevInfo, ui32MTSRegVal);
+    {
+        IMG_UINT32 ui32MTSRegVal;
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+        if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_GPU_VIRTUALISATION_BIT_MASK))
+        {
+        	ui32MTSRegVal = ((RGXFWIF_DM_GP + PVRSRV_GPUVIRT_OSID) & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) | RGX_CR_MTS_SCHEDULE_TASK_COUNTED;
+        }else
+#endif
+        {
+            ui32MTSRegVal = (RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) | RGX_CR_MTS_SCHEDULE_TASK_COUNTED;
+        }
 
-		PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_MTS_SCHEDULE, ui32MTSRegVal, uiPdumpFlags);
-	}
-	
+
+        __MTSScheduleWrite(psDevInfo, ui32MTSRegVal);
+
+        PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_MTS_SCHEDULE, ui32MTSRegVal, uiPdumpFlags);
+    }
+
 #if defined (NO_HARDWARE)
 	/* keep the roff updated because fw isn't there to update it */
 	psKCCBCtl->ui32ReadOffset = psKCCBCtl->ui32WriteOffset;
@@ -2862,7 +3238,7 @@
                             RGXFWIF_DM          eKCCBType,
                             RGXFWIF_KCCB_CMD	*psKCCBCmd,
                             IMG_UINT32		ui32CmdSize,
-                            PDUMP_FLAGS_T	uiPdumpFlags)
+                            IMG_UINT32		uiPdumpFlags)
 {
 
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -2959,8 +3335,8 @@
 
 	/* We don't need to acquire the BridgeLock as this power transition won't
 	   send a command to the FW */
-	eError = PVRSRVPowerLock();
-	if (eError != PVRSRV_OK) 
+	eError = PVRSRVPowerLock(psDeviceNode);
+	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_WARNING, "RGXScheduleProcessQueuesKM: failed to acquire powerlock (%s)",
 					PVRSRVGetErrorStringKM(eError)));
@@ -2969,13 +3345,12 @@
 	}
 
 	/* Check whether it's worth waking up the GPU */
-	eError = PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
+	eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 
 	if ((eError == PVRSRV_OK) && (ePowerState == PVRSRV_DEV_POWER_STATE_OFF))
 	{
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 		/* For now, guest drivers will always wake-up the GPU */
-#else
 		RGXFWIF_GPU_UTIL_FWCB  *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
 		IMG_BOOL               bGPUHasWorkWaiting;
 
@@ -2985,7 +3360,7 @@
 		if (!bGPUHasWorkWaiting)
 		{
 			/* all queues are empty, don't wake up the GPU */
-			PVRSRVPowerUnlock();
+			PVRSRVPowerUnlock(psDeviceNode);
 			return;
 		}
 #endif
@@ -2993,29 +3368,38 @@
 
 	PDUMPPOWCMDSTART();
 	/* wake up the GPU */
-	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
 										 PVRSRV_DEV_POWER_STATE_ON,
 										 IMG_FALSE);
 	PDUMPPOWCMDEND();
 
-	if (eError != PVRSRV_OK) 
+	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_WARNING, "RGXScheduleProcessQueuesKM: failed to transition Rogue to ON (%s)",
 					PVRSRVGetErrorStringKM(eError)));
 
-		PVRSRVPowerUnlock();
+		PVRSRVPowerUnlock(psDeviceNode);
 		return;
 	}
 
 	/* uncounted kick to the FW */
 	{
-		IMG_UINT32 ui32MTSRegVal = (RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) |
-		                           RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED;
+		IMG_UINT32 ui32MTSRegVal;
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+        if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_GPU_VIRTUALISATION_BIT_MASK))
+        {
+			ui32MTSRegVal = ((RGXFWIF_DM_GP + PVRSRV_GPUVIRT_OSID) & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) |  RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED;
+        }else
+#endif
+        {
+        	ui32MTSRegVal = (RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) | RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED;
+        }
+
 		HTBLOGK(HTB_SF_MAIN_KICK_UNCOUNTED);
 		__MTSScheduleWrite(psDevInfo, ui32MTSRegVal);
 	}
 
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 }
 
 PVRSRV_ERROR RGXInstallProcessQueuesMISR(IMG_HANDLE *phMISR, PVRSRV_DEVICE_NODE *psDeviceNode)
@@ -3031,40 +3415,31 @@
  @Function	RGXScheduleCommand
 
  @Description - Submits a CCB command and kicks the firmware but first schedules
-                any commands which have to happen before handle  
+                any commands which have to happen before handle
 
- @Input psDevInfo - pointer to device info
- @Input eKCCBType - see RGXFWIF_CMD_*
- @Input pvKCCBCmd - kernel CCB command
- @Input ui32CmdSize -
- @Input bPDumpContinuous - TRUE if the pdump flags should be continuous
+ @Input psDevInfo 		 - pointer to device info
+ @Input eKCCBType 		 - see RGXFWIF_CMD_*
+ @Input psKCCBCmd 		 - kernel CCB command
+ @Input ui32CmdSize 	 - kernel CCB SIZE
+ @Input ui32CacheOpFence - CPU dcache operation fence
+ @Input ui32PDumpFlags - PDUMP_FLAGS_CONTINUOUS bit set if the pdump flags should be continuous
 
 
- @Return ui32Error - success or failure
+ @Return PVRSRV_ERROR
 
 ******************************************************************************/
 PVRSRV_ERROR RGXScheduleCommand(PVRSRV_RGXDEV_INFO 	*psDevInfo,
 								RGXFWIF_DM			eKCCBType,
 								RGXFWIF_KCCB_CMD	*psKCCBCmd,
 								IMG_UINT32			ui32CmdSize,
-								IMG_BOOL			bPDumpContinuous)
+								IMG_UINT32			ui32CacheOpFence,
+								IMG_UINT32			ui32PDumpFlags)
 {
-	PVRSRV_DATA *psData = PVRSRVGetPVRSRVData();
 	PVRSRV_ERROR eError;
+	IMG_UINT32 uiMMUSyncUpdate;
 
-	if ((eKCCBType == RGXFWIF_DM_3D) || (eKCCBType == RGXFWIF_DM_2D) || (eKCCBType == RGXFWIF_DM_CDM))
-	{
-		/* This handles the no operation case */
-		if (OSCPUOperation(psData->uiCacheOp) == PVRSRV_OK)
-		{
-			psData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
-		}
-		else
-		{
-			PVR_DPF((PVR_DBG_ERROR, "RGXScheduleCommand: OSCPUOperation failed"));
-			PVR_ASSERT(0);
-		}
-	}
+	eError = CacheOpFence(eKCCBType, ui32CacheOpFence);
+	if (eError != PVRSRV_OK) goto RGXScheduleCommand_exit;
 
 #if defined (SUPPORT_VALIDATION)
 	/* For validation, force the core to different dust count states with each kick */
@@ -3072,19 +3447,18 @@
 	{
 		if (psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_DUST_REQUEST_INJECT_EN)
 		{
-			IMG_UINT32 ui32NumDusts = RGXGetNextDustCount(&psDevInfo->sDustReqState, RGX_MAX_DUST);
-			PVRSRVDeviceDustCountChange(psDevInfo->psDeviceNode->sDevId.ui32DeviceIndex, ui32NumDusts);
+			IMG_UINT32 ui32NumDusts = RGXGetNextDustCount(&psDevInfo->sDustReqState, psDevInfo->sDevFeatureCfg.ui32MAXDustCount);
+			PVRSRVDeviceDustCountChange(psDevInfo->psDeviceNode, ui32NumDusts);
 		}
 	}
 #endif
 
-	eError = RGXPreKickCacheCommand(psDevInfo, eKCCBType);
+	eError = RGXPreKickCacheCommand(psDevInfo, eKCCBType, &uiMMUSyncUpdate, IMG_FALSE);
 	if (eError != PVRSRV_OK) goto RGXScheduleCommand_exit;
 
-	eError = RGXSendCommandWithPowLock(psDevInfo, eKCCBType, psKCCBCmd, ui32CmdSize, bPDumpContinuous);
+	eError = RGXSendCommandWithPowLock(psDevInfo, eKCCBType, psKCCBCmd, ui32CmdSize, ui32PDumpFlags);
 	if (eError != PVRSRV_OK) goto RGXScheduleCommand_exit;
 
-
 RGXScheduleCommand_exit:
 	return eError;
 }
@@ -3111,7 +3485,7 @@
 			{
 				if (psDevInfo->bPDPEnabled)
 				{
-					PDUMP_PANIC(RGX, ZSBUFFER_BACKING, "Request to add backing to ZSBuffer");
+					PDUMP_PANIC(ZSBUFFER_BACKING, "Request to add backing to ZSBuffer");
 				}
 				RGXProcessRequestZSBufferBacking(psDevInfo,
 				        psFwCCBCmd->uCmdData.sCmdZSBufferBacking.ui32ZSBufferID);
@@ -3122,7 +3496,7 @@
 			{
 				if (psDevInfo->bPDPEnabled)
 				{
-					PDUMP_PANIC(RGX, ZSBUFFER_UNBACKING, "Request to remove backing from ZSBuffer");
+					PDUMP_PANIC(ZSBUFFER_UNBACKING, "Request to remove backing from ZSBuffer");
 				}
 				RGXProcessRequestZSBufferUnbacking(psDevInfo,
 				        psFwCCBCmd->uCmdData.sCmdZSBufferBacking.ui32ZSBufferID);
@@ -3133,7 +3507,7 @@
 			{
 				if (psDevInfo->bPDPEnabled)
 				{
-					PDUMP_PANIC(RGX, FREELIST_GROW, "Request to grow the free list");
+					PDUMP_PANIC(FREELIST_GROW, "Request to grow the free list");
 				}
 				RGXProcessRequestGrow(psDevInfo,
 				        psFwCCBCmd->uCmdData.sCmdFreeListGS.ui32FreelistID);
@@ -3144,7 +3518,7 @@
 			{
 				if (psDevInfo->bPDPEnabled)
 				{
-					PDUMP_PANIC(RGX, FREELISTS_RECONSTRUCTION, "Request to reconstruct free lists");
+					PDUMP_PANIC(FREELISTS_RECONSTRUCTION, "Request to reconstruct free lists");
 				}
 #if defined(PVRSRV_GPUVIRT_GUESTDRV)
 				PVR_DPF((PVR_DBG_MESSAGE, "RGXCheckFirmwareCCBs: Freelist reconstruction request (%d) for %d freelists",
@@ -3163,11 +3537,26 @@
 				break;
 			}
 
+			case RGXFWIF_FWCCB_CMD_DOPPLER_MEMORY_GROW:
+			{
+				if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+				{
+					if (psDevInfo->bPDPEnabled)
+					{
+						PDUMP_PANIC(FREELIST_GROW, "Request to grow the RPM free list");
+					}
+					RGXProcessRequestRPMGrow(psDevInfo,
+							psFwCCBCmd->uCmdData.sCmdFreeListGS.ui32FreelistID);
+				}
+			}
+
 			case RGXFWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION:
 			{
 				DLLIST_NODE *psNode, *psNext;
+				RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA *psCmdContextResetNotification =
+					&psFwCCBCmd->uCmdData.sCmdContextResetNotification;
 				IMG_UINT32 ui32ServerCommonContextID =
-					psFwCCBCmd->uCmdData.sCmdContextResetNotification.ui32ServerCommonContextID;
+					psCmdContextResetNotification->ui32ServerCommonContextID;
 				RGX_SERVER_COMMON_CONTEXT *psServerCommonContext = NULL;
 
 				dllist_foreach_node(&psDevInfo->sCommonCtxtListHead, psNode, psNext)
@@ -3184,14 +3573,20 @@
 
 				PVR_DPF((PVR_DBG_MESSAGE, "RGXCheckFirmwareCCBs: Context 0x%p reset (ID=0x%08x, Reason=%d, JobRef=0x%08x)",
 				        psServerCommonContext,
-				        psFwCCBCmd->uCmdData.sCmdContextResetNotification.ui32ServerCommonContextID,
-				        (IMG_UINT32)(psFwCCBCmd->uCmdData.sCmdContextResetNotification.eResetReason),
-				        psFwCCBCmd->uCmdData.sCmdContextResetNotification.ui32ResetJobRef));
+				        psCmdContextResetNotification->ui32ServerCommonContextID,
+				        (IMG_UINT32)(psCmdContextResetNotification->eResetReason),
+				        psCmdContextResetNotification->ui32ResetJobRef));
 
 				if (psServerCommonContext != NULL)
 				{
-					psServerCommonContext->eLastResetReason    = psFwCCBCmd->uCmdData.sCmdContextResetNotification.eResetReason;
-					psServerCommonContext->ui32LastResetJobRef = psFwCCBCmd->uCmdData.sCmdContextResetNotification.ui32ResetJobRef;
+					psServerCommonContext->eLastResetReason    = psCmdContextResetNotification->eResetReason;
+					psServerCommonContext->ui32LastResetJobRef = psCmdContextResetNotification->ui32ResetJobRef;
+				}
+
+				if (psCmdContextResetNotification->bPageFault)
+				{
+					DevmemIntPFNotify(psDevInfo->psDeviceNode,
+					                  psCmdContextResetNotification->ui64PCAddress);
 				}
 				break;
 			}
@@ -3199,6 +3594,7 @@
 			case RGXFWIF_FWCCB_CMD_DEBUG_DUMP:
 			{
 				RGXDumpDebugInfo(NULL,NULL,psDevInfo);
+				OSWarnOn(IMG_TRUE);
 				break;
 			}
 
@@ -3244,7 +3640,14 @@
 #endif
 				break;
 			}
-
+			case RGXFWIF_FWCCB_CMD_CORE_CLK_RATE_CHANGE:
+			{
+#if defined(SUPPORT_PDVFS)
+				PDVFSProcessCoreClkRateChange(psDevInfo,
+											  psFwCCBCmd->uCmdData.sCmdCoreClkRateChange.ui32CoreClkRate);
+#endif
+				break;
+			}
 			default:
 			{
 				PVR_ASSERT(IMG_FALSE);
@@ -3258,7 +3661,7 @@
 
 /*
  * PVRSRVRGXFrameworkCopyCommand
- */ 
+ */
 PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(DEVMEM_MEMDESC	*psFWFrameworkMemDesc,
 										   IMG_PBYTE		pbyGPUFRegisterList,
 										   IMG_UINT32		ui32FrameworkRegisterSize)
@@ -3275,8 +3678,8 @@
 		return eError;
 	}
 
-	OSMemCopy(psRFReg, pbyGPUFRegisterList, ui32FrameworkRegisterSize);
-	
+	OSDeviceMemCopy(psRFReg, pbyGPUFRegisterList, ui32FrameworkRegisterSize);
+
 	/* Release the CPU mapping */
 	DevmemReleaseCpuVirtAddr(psFWFrameworkMemDesc);
 
@@ -3298,7 +3701,7 @@
 {
 	PVRSRV_ERROR			eError;
 	PVRSRV_RGXDEV_INFO 		*psDevInfo = psDeviceNode->pvDevice;
-	
+
 	/*
 		Allocate device memory for the firmware GPU framework state.
 		Sufficient info to kick one or more DMs should be contained in this buffer
@@ -3322,81 +3725,98 @@
 }
 
 PVRSRV_ERROR RGXWaitForFWOp(PVRSRV_RGXDEV_INFO	*psDevInfo,
-							RGXFWIF_DM eDM,
-							PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
-							IMG_BOOL bPDumpContinuous)
+			    RGXFWIF_DM eDM,
+			    PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+			    IMG_UINT32 ui32PDumpFlags)
 {
 	PVRSRV_ERROR		eError = PVRSRV_OK;
 	PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
 	RGXFWIF_KCCB_CMD	sCmdSyncPrim;
 
 	/* Ensure Rogue is powered up before kicking MTS */
-	eError = PVRSRVPowerLock();
+	eError = PVRSRVPowerLock(psDeviceNode);
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXWaitForFWOp: failed to acquire powerlock (%s)",
+		PVR_DPF((PVR_DBG_ERROR, "%s: failed to acquire powerlock (%s)",
+					__FUNCTION__,
 					PVRSRVGetErrorStringKM(eError)));
 
 		goto _PVRSRVPowerLock_Exit;
 	}
 
 	PDUMPPOWCMDSTART();
-	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
-										 PVRSRV_DEV_POWER_STATE_ON,
-										 IMG_FALSE);
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+					     PVRSRV_DEV_POWER_STATE_ON,
+					     IMG_FALSE);
 	PDUMPPOWCMDEND();
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXWaitForFWOp: failed to transition Rogue to ON (%s)",
+		PVR_DPF((PVR_DBG_ERROR, "%s: failed to transition Rogue to ON (%s)",
+					__FUNCTION__,
 					PVRSRVGetErrorStringKM(eError)));
 
 		goto _PVRSRVSetDevicePowerStateKM_Exit;
 	}
 
-
-
-
 	/* Setup sync primitive */
-	SyncPrimSet(psSyncPrim, 0);
+	eError = SyncPrimSet(psSyncPrim, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to set SyncPrim (%u)",
+			__FUNCTION__, eError));
+		goto _SyncPrimSet_Exit;
+	}
 
 	/* prepare a sync command */
+	eError = SyncPrimGetFirmwareAddr(psSyncPrim,
+			&sCmdSyncPrim.uCmdData.sSyncData.sSyncObjDevVAddr.ui32Addr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to get SyncPrim FW address(%u)",
+			__FUNCTION__, eError));
+		goto _SyncPrimGetFirmwareAddr_Exit;
+	}
 	sCmdSyncPrim.eCmdType = RGXFWIF_KCCB_CMD_SYNC;
-	sCmdSyncPrim.uCmdData.sSyncData.sSyncObjDevVAddr.ui32Addr = SyncPrimGetFirmwareAddr(psSyncPrim);
 	sCmdSyncPrim.uCmdData.sSyncData.uiUpdateVal = 1;
 
-	PDUMPCOMMENT("RGXWaitForFWOp: Submit Kernel SyncPrim [0x%08x] to DM %d ", sCmdSyncPrim.uCmdData.sSyncData.sSyncObjDevVAddr.ui32Addr, eDM);
+	PDUMPCOMMENT("RGXWaitForFWOp: Submit Kernel SyncPrim [0x%08x] to DM %d ",
+		sCmdSyncPrim.uCmdData.sSyncData.sSyncObjDevVAddr.ui32Addr, eDM);
 
 	/* submit the sync primitive to the kernel CCB */
 	eError = RGXSendCommand(psDevInfo,
-								eDM,
-								&sCmdSyncPrim,
-								sizeof(RGXFWIF_KCCB_CMD),
-								bPDumpContinuous  ? PDUMP_FLAGS_CONTINUOUS:0);
+				eDM,
+				&sCmdSyncPrim,
+				sizeof(RGXFWIF_KCCB_CMD),
+				ui32PDumpFlags);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXScheduleCommandAndWait: Failed to schedule Kernel SyncPrim with error (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to schedule Kernel SyncPrim with error (%u)",
+					__FUNCTION__,
+					eError));
 		goto _RGXSendCommandRaw_Exit;
 	}
 
 	/* Wait for sync primitive to be updated */
 #if defined(PDUMP)
-	PDUMPCOMMENT("RGXScheduleCommandAndWait: Poll for Kernel SyncPrim [0x%08x] on DM %d ", sCmdSyncPrim.uCmdData.sSyncData.sSyncObjDevVAddr.ui32Addr, eDM);
+	PDUMPCOMMENT("RGXScheduleCommandAndWait: Poll for Kernel SyncPrim [0x%08x] on DM %d ",
+		sCmdSyncPrim.uCmdData.sSyncData.sSyncObjDevVAddr.ui32Addr, eDM);
 
 	SyncPrimPDumpPol(psSyncPrim,
-					1,
-					0xffffffff,
-					PDUMP_POLL_OPERATOR_EQUAL,
-					bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+			 1,
+			 0xffffffff,
+			 PDUMP_POLL_OPERATOR_EQUAL,
+			 ui32PDumpFlags);
 #endif
 
 	{
-		RGXFWIF_CCB_CTL  *psKCCBCtl = psDevInfo->psKernelCCBCtl;
-		IMG_UINT32       ui32CurrentQueueLength = (psKCCBCtl->ui32WrapMask+1 +
-												   psKCCBCtl->ui32WriteOffset -
-												   psKCCBCtl->ui32ReadOffset) & psKCCBCtl->ui32WrapMask;
-		IMG_UINT32       ui32MaxRetries;
+		RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
+		IMG_UINT32 ui32CurrentQueueLength =
+				(psKCCBCtl->ui32WrapMask+1 +
+				psKCCBCtl->ui32WriteOffset -
+				psKCCBCtl->ui32ReadOffset) & psKCCBCtl->ui32WrapMask;
+		IMG_UINT32 ui32MaxRetries;
 
 		for (ui32MaxRetries = (ui32CurrentQueueLength + 1) * 3;
 			 ui32MaxRetries > 0;
@@ -3412,25 +3832,105 @@
 
 		if (eError == PVRSRV_ERROR_TIMEOUT)
 		{
-			PVR_DPF((PVR_DBG_ERROR,"RGXScheduleCommandAndWait: PVRSRVWaitForValueKMAndHoldBridgeLock timed out. Dump debug information."));
-			PVRSRVPowerUnlock();
+			PVR_DPF((PVR_DBG_ERROR,"%s: PVRSRVWaitForValueKMAndHoldBridgeLock timed out. Dump debug information.",
+					__FUNCTION__));
+			PVRSRVPowerUnlock(psDeviceNode);
 
-			PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX,NULL,NULL);
+			PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
 			PVR_ASSERT(eError != PVRSRV_ERROR_TIMEOUT);
 			goto _PVRSRVDebugRequest_Exit;
 		}
 	}
 
 _RGXSendCommandRaw_Exit:
+_SyncPrimGetFirmwareAddr_Exit:
+_SyncPrimSet_Exit:
 _PVRSRVSetDevicePowerStateKM_Exit:
 
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 _PVRSRVDebugRequest_Exit:
 _PVRSRVPowerLock_Exit:
 	return eError;
 }
 
+PVRSRV_ERROR RGXStateFlagCtrl(PVRSRV_RGXDEV_INFO *psDevInfo,
+				IMG_UINT32 ui32Config,
+				IMG_UINT32 *pui32ConfigState,
+				IMG_BOOL bSetNotClear)
+{
+	PVRSRV_ERROR eError;
+	RGXFWIF_KCCB_CMD sStateFlagCmd;
+	PVRSRV_CLIENT_SYNC_PRIM *psResponseSync;
+
+	if (!psDevInfo)
+	{
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto return_;
+	}
+
+	if (psDevInfo->psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
+	{
+		eError = PVRSRV_ERROR_NOT_INITIALISED;
+		goto return_;
+	}
+
+	sStateFlagCmd.eCmdType = RGXFWIF_KCCB_CMD_STATEFLAGS_CTRL;
+	sStateFlagCmd.eDM = RGXFWIF_DM_GP;
+	sStateFlagCmd.uCmdData.sStateFlagCtrl.ui32Config = ui32Config;
+	sStateFlagCmd.uCmdData.sStateFlagCtrl.bSetNotClear = bSetNotClear;
+
+	eError = SyncPrimAlloc(psDevInfo->hSyncPrimContext, &psResponseSync, "rgx config flags");
+	if (PVRSRV_OK != eError)
+	{
+		goto return_;
+	}
+	eError = SyncPrimSet(psResponseSync, 0);
+	if (eError != PVRSRV_OK)
+	{
+		goto return_freesync_;
+	}
+
+	eError = SyncPrimGetFirmwareAddr(psResponseSync, &sStateFlagCmd.uCmdData.sStateFlagCtrl.sSyncObjDevVAddr.ui32Addr);
+	if (PVRSRV_OK != eError)
+	{
+		goto return_freesync_;
+	}
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+					RGXFWIF_DM_GP,
+					&sStateFlagCmd,
+					sizeof(sStateFlagCmd),
+					0,
+					PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+	PVR_LOGG_IF_ERROR(eError, "RGXScheduleCommand", return_);
+
+	/* Wait for FW to complete */
+	eError = RGXWaitForFWOp(psDevInfo,
+				RGXFWIF_DM_GP,
+	                        psDevInfo->psDeviceNode->psSyncPrim,
+				PDUMP_FLAGS_CONTINUOUS);
+	PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", return_);
+
+	if (pui32ConfigState)
+	{
+		*pui32ConfigState = *psResponseSync->pui32LinAddr;
+	}
+
+return_freesync_:
+	SyncPrimFree(psResponseSync);
+return_:
+	return eError;
+}
+
 static
 PVRSRV_ERROR RGXScheduleCleanupCommand(PVRSRV_RGXDEV_INFO 	*psDevInfo,
 									   RGXFWIF_DM			eDM,
@@ -3438,16 +3938,24 @@
 									   IMG_UINT32			ui32CmdSize,
 									   RGXFWIF_CLEANUP_TYPE	eCleanupType,
 									   PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
-									   IMG_BOOL				bPDumpContinuous)
+									   IMG_UINT32				ui32PDumpFlags)
 {
 	PVRSRV_ERROR eError;
 
 	psKCCBCmd->eCmdType = RGXFWIF_KCCB_CMD_CLEANUP;
 
 	psKCCBCmd->uCmdData.sCleanupData.eCleanupType = eCleanupType;
-	psKCCBCmd->uCmdData.sCleanupData.sSyncObjDevVAddr.ui32Addr = SyncPrimGetFirmwareAddr(psSyncPrim);
+	eError = SyncPrimGetFirmwareAddr(psSyncPrim, &psKCCBCmd->uCmdData.sCleanupData.sSyncObjDevVAddr.ui32Addr);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_command;
+	}
 
-	SyncPrimSet(psSyncPrim, 0);
+	eError = SyncPrimSet(psSyncPrim, 0);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_command;
+	}
 
 	/*
 		Send the cleanup request to the firmware. If the resource is still busy
@@ -3457,7 +3965,8 @@
 								eDM,
 								psKCCBCmd,
 								ui32CmdSize,
-								bPDumpContinuous);
+								0,
+								ui32PDumpFlags);
 	if (eError != PVRSRV_OK)
 	{
 		goto fail_command;
@@ -3470,7 +3979,7 @@
 					RGXFWIF_CLEANUP_RUN,
 					RGXFWIF_CLEANUP_RUN,
 					PDUMP_POLL_OPERATOR_EQUAL,
-					bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+					ui32PDumpFlags);
 
 	/*
 	 * The cleanup request to the firmware will tell us if a given resource is busy or not.
@@ -3491,7 +4000,7 @@
 					0,
 					RGXFWIF_CLEANUP_BUSY,
 					PDUMP_POLL_OPERATOR_EQUAL,
-					bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+					ui32PDumpFlags);
 #endif
 
 	{
@@ -3523,7 +4032,8 @@
 
 			eError = PVRSRV_ERROR_RETRY;
 #if defined(DEBUG)
-			PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX,NULL,NULL);
+			PVRSRVDebugRequest(psDevInfo->psDeviceNode,
+							   DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
 #endif
 			goto fail_poll;
 		}
@@ -3559,7 +4069,8 @@
 PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
 											  RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
 											  PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
-											  RGXFWIF_DM eDM)
+											  RGXFWIF_DM eDM,
+											  IMG_UINT32 ui32PDumpFlags)
 {
 	RGXFWIF_KCCB_CMD			sRCCleanUpCmd = {0};
 	PVRSRV_ERROR				eError;
@@ -3571,8 +4082,7 @@
 					eDM, psFWCommonContextFWAddr.ui32Addr);
 	PDUMPCOMMENT("Wait for CCB to be empty before common ctx cleanup");
 
-	RGXCCBPDumpDrainCCB(FWCommonContextGetClientCCB(psServerCommonContext), IMG_FALSE);
-
+	RGXCCBPDumpDrainCCB(FWCommonContextGetClientCCB(psServerCommonContext), ui32PDumpFlags);
 
 	/* Setup our command data, the cleanup call will fill in the rest */
 	sRCCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psContext = psFWCommonContextFWAddr;
@@ -3584,7 +4094,7 @@
 									   sizeof(RGXFWIF_KCCB_CMD),
 									   RGXFWIF_CLEANUP_FWCOMMONCONTEXT,
 									   psSyncPrim,
-									   IMG_FALSE);
+									   ui32PDumpFlags);
 
 	if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
 	{
@@ -3691,7 +4201,6 @@
 }
 
 
-#if defined(RGX_FEATURE_RAY_TRACING)
 PVRSRV_ERROR RGXFWRequestRayFrameDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
 											 PRGXFWIF_RAY_FRAME_DATA psHWFrameData,
 											 PVRSRV_CLIENT_SYNC_PRIM *psSync,
@@ -3751,7 +4260,207 @@
 
 	return eError;
 }
+
+PVRSRV_ERROR RGXFWSetHCSDeadline(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32HCSDeadlineMs)
+{
+	PVRSRV_ERROR eError;
+	RGXFWIF_KCCB_CMD	sSetHCSDeadline;
+
+	sSetHCSDeadline.eCmdType                            = RGXFWIF_KCCB_CMD_HCS_SET_DEADLINE;
+	sSetHCSDeadline.eDM                                 = RGXFWIF_DM_GP;
+	sSetHCSDeadline.uCmdData.sHCSCtrl.ui32HCSDeadlineMS = ui32HCSDeadlineMs;
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+									RGXFWIF_DM_GP,
+									&sSetHCSDeadline,
+									sizeof(sSetHCSDeadline),
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
+
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	return eError;
+}
+
+PVRSRV_ERROR RGXFWOSConfig(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	PVRSRV_ERROR eError;
+	RGXFWIF_KCCB_CMD   sOSConfigCmdData;
+
+	sOSConfigCmdData.eCmdType                            = RGXFWIF_KCCB_CMD_OS_CFG_INIT;
+	sOSConfigCmdData.eDM                                 = RGXFWIF_DM_GP;
+	sOSConfigCmdData.uCmdData.sCmdOSConfigData.sOSInit   = psDevInfo->sFWInitFWAddr;
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+									RGXFWIF_DM_GP,
+									&sOSConfigCmdData,
+									sizeof(sOSConfigCmdData),
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	return eError;
+}
+
+PVRSRV_ERROR RGXFWSetOSIsolationThreshold(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32IsolationPriorityThreshold)
+{
+	PVRSRV_ERROR eError;
+	RGXFWIF_KCCB_CMD	sOSidIsoConfCmd;
+
+	sOSidIsoConfCmd.eCmdType = RGXFWIF_KCCB_CMD_OS_ISOLATION_GROUP_CHANGE;
+	sOSidIsoConfCmd.uCmdData.sCmdOSidIsolationData.ui32IsolationPriorityThreshold = ui32IsolationPriorityThreshold;
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+									RGXFWIF_DM_GP,
+									&sOSidIsoConfCmd,
+									sizeof(sOSidIsoConfCmd),
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	return eError;
+}
+
+PVRSRV_ERROR RGXFWSetVMOnlineState(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32OSid,
+								RGXFWIF_OS_STATE_CHANGE eOSOnlineState)
+{
+	PVRSRV_ERROR         eError = PVRSRV_OK;
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	RGXFWIF_KCCB_CMD     sOSOnlineStateCmd;
+	RGXFWIF_TRACEBUF    *psRGXFWIfTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+	volatile IMG_UINT32 *pui32OSStateFlags;
+
+	sOSOnlineStateCmd.eCmdType = RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE;
+	sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.ui32OSid = ui32OSid;
+	sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.eNewOSState = eOSOnlineState;
+
+	if (eOSOnlineState == RGXFWIF_OS_ONLINE)
+	{
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			eError = RGXScheduleCommand(psDevInfo,
+										RGXFWIF_DM_GP,
+										&sOSOnlineStateCmd,
+										sizeof(sOSOnlineStateCmd),
+										0,
+										PDUMP_FLAGS_CONTINUOUS);
+			if (eError != PVRSRV_ERROR_RETRY)
+			{
+				break;
+			}
+			OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+		} END_LOOP_UNTIL_TIMEOUT();
+
+		return eError;
+	}
+
+	if (psRGXFWIfTraceBuf == NULL)
+	{
+		return PVRSRV_ERROR_NOT_INITIALISED;
+	}
+	pui32OSStateFlags = (volatile IMG_UINT32*) &psRGXFWIfTraceBuf->ui32OSStateFlags[ui32OSid];
+
+	/* Attempt several times until the FW manages to offload the OS */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		IMG_UINT32 ui32OSStateFlags;
+
+		/* Send request */
+		eError = RGXScheduleCommand(psDevInfo,
+									RGXFWIF_DM_GP,
+									&sOSOnlineStateCmd,
+									sizeof(sOSOnlineStateCmd),
+									0,
+									IMG_TRUE);
+		if (unlikely(eError == PVRSRV_ERROR_RETRY))
+		{
+			continue;
+		}
+		PVR_LOGG_IF_ERROR(eError, "RGXScheduleCommand", return_);
+
+		/* Wait for FW to process the cmd */
+		eError = RGXWaitForFWOp(psDevInfo,
+								RGXFWIF_DM_GP,
+								psDevInfo->psDeviceNode->psSyncPrim,
+								PDUMP_FLAGS_CONTINUOUS);
+		PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", return_);
+
+		/* read the OS state */
+		OSMemoryBarrier();
+		ui32OSStateFlags = *pui32OSStateFlags;
+
+		if ((ui32OSStateFlags & RGXFW_OS_STATE_ACTIVE_OS) == 0)
+		{
+			/* FW finished offloading the OSID */
+			eError = PVRSRV_OK;
+			break;
+		}
+		else
+		{
+			eError = PVRSRV_ERROR_TIMEOUT;
+		}
+
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+
+	} END_LOOP_UNTIL_TIMEOUT();
+
+return_ :
 #endif
+	return eError;
+}
+
+PVRSRV_ERROR RGXFWChangeOSidPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32OSid,
+								IMG_UINT32 ui32Priority)
+{
+	PVRSRV_ERROR eError;
+	RGXFWIF_KCCB_CMD	sOSidPriorityCmd;
+
+	sOSidPriorityCmd.eCmdType = RGXFWIF_KCCB_CMD_OSID_PRIORITY_CHANGE;
+	sOSidPriorityCmd.uCmdData.sCmdOSidPriorityData.ui32OSidNum = ui32OSid;
+	sOSidPriorityCmd.uCmdData.sCmdOSidPriorityData.ui32Priority = ui32Priority;
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+									RGXFWIF_DM_GP,
+									&sOSidPriorityCmd,
+									sizeof(sOSidPriorityCmd),
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	return eError;
+}
 
 PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
 								CONNECTION_DATA *psConnection,
@@ -3762,7 +4471,7 @@
 	IMG_UINT32				ui32CmdSize;
 	IMG_UINT8				*pui8CmdPtr;
 	RGXFWIF_KCCB_CMD		sPriorityCmd;
-	RGXFWIF_CCB_CMD_HEADER	*psCmdHeader;	
+	RGXFWIF_CCB_CMD_HEADER	*psCmdHeader;
 	RGXFWIF_CMD_PRIORITY	*psCmd;
 	PVRSRV_ERROR			eError;
 
@@ -3774,10 +4483,13 @@
 	eError = RGXAcquireCCB(FWCommonContextGetClientCCB(psContext),
 						   ui32CmdSize,
 						   (void **) &pui8CmdPtr,
-						   IMG_TRUE);
+						   PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire space for client CCB", __FUNCTION__));
+		if(eError != PVRSRV_ERROR_RETRY)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire space for client CCB", __FUNCTION__));
+		}
 		goto fail_ccbacquire;
 	}
 
@@ -3788,7 +4500,7 @@
 	psCmdHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_PRIORITY;
 	psCmdHeader->ui32CmdSize = RGX_CCB_FWALLOC_ALIGN(sizeof(RGXFWIF_CMD_PRIORITY));
 	pui8CmdPtr += sizeof(*psCmdHeader);
-	
+
 	psCmd = (RGXFWIF_CMD_PRIORITY *) pui8CmdPtr;
 	psCmd->ui32Priority = ui32Priority;
 	pui8CmdPtr += sizeof(*psCmd);
@@ -3805,7 +4517,7 @@
 	*/
 	RGXReleaseCCB(FWCommonContextGetClientCCB(psContext),
 				  ui32CmdSize,
-				  IMG_TRUE);
+				  PDUMP_FLAGS_CONTINUOUS);
 
 	if (eError != PVRSRV_OK)
 	{
@@ -3818,6 +4530,8 @@
 	sPriorityCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psContext);
 	sPriorityCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psContext));
 	sPriorityCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+	sPriorityCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
+	sPriorityCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
 
 	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 	{
@@ -3825,7 +4539,8 @@
 									eDM,
 									&sPriorityCmd,
 									sizeof(sPriorityCmd),
-									IMG_TRUE);
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_ERROR_RETRY)
 		{
 			break;
@@ -3835,7 +4550,7 @@
 
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXFlushComputeDataKM: Failed to schedule SLC flush command with error (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR,"ContextSetPriority: Failed to submit set priority command with error (%u)", eError));
 	}
 
 	return PVRSRV_OK;
@@ -3885,16 +4600,13 @@
 	return PVRSRV_OK;
 }
 
-
 /*
 	RGXUpdateHealthStatus
 */
 PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
                                    IMG_BOOL bCheckAfterTimePassed)
 {
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers do not perform device management */
-#else
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	PVRSRV_DATA*                 psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_DEVICE_HEALTH_STATUS  eNewStatus   = PVRSRV_DEVICE_HEALTH_STATUS_OK;
 	PVRSRV_DEVICE_HEALTH_REASON  eNewReason   = PVRSRV_DEVICE_HEALTH_REASON_NONE;
@@ -3903,11 +4615,11 @@
 	RGXFWIF_CCB_CTL *psKCCBCtl;
 	IMG_UINT32  ui32ThreadCount;
 	IMG_BOOL  bKCCBCmdsWaiting;
-	
+
 	PVR_ASSERT(psDevNode != NULL);
 	psDevInfo = psDevNode->pvDevice;
 	psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
-	
+
 	/* If the firmware is not initialised, there is not much point continuing! */
 	if (!psDevInfo->bFirmwareInitialised  ||  psDevInfo->pvRegsBaseKM == NULL  ||
 	    psDevInfo->psDeviceNode == NULL)
@@ -3915,23 +4627,23 @@
 		return PVRSRV_OK;
 	}
 
-	/* If Rogue is not powered on, don't continue 
-	   (there is a race condition where PVRSRVIsDevicePowered returns TRUE when the GPU is actually powering down. 
+	/* If Rogue is not powered on, don't continue
+	   (there is a race condition where PVRSRVIsDevicePowered returns TRUE when the GPU is actually powering down.
 	   That's not a problem as this function does not touch the HW except for the RGXScheduleCommand function,
 	   which is already powerlock safe. The worst thing that could happen is that Rogue might power back up
 	   but the chances of that are very low */
-	if (!PVRSRVIsDevicePowered(psDevNode->sDevId.ui32DeviceIndex))
+	if (!PVRSRVIsDevicePowered(psDevNode))
 	{
 		return PVRSRV_OK;
 	}
-	
+
 	/* If this is a quick update, then include the last current value... */
 	if (!bCheckAfterTimePassed)
 	{
-		eNewStatus = psDevNode->eHealthStatus;
-		eNewReason = psDevNode->eHealthReason;
+		eNewStatus = OSAtomicRead(&psDevNode->eHealthStatus);
+		eNewReason = OSAtomicRead(&psDevNode->eHealthReason);
 	}
-	
+
 	/*
 	   Firmware thread checks...
 	*/
@@ -3959,16 +4671,16 @@
 			   Check the threads to see if they are in the same poll locations as last time...
 			*/
 			if (bCheckAfterTimePassed)
-			{	
+			{
 				if (psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] != 0  &&
 					psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] == psDevInfo->aui32CrLastPollAddr[ui32ThreadCount])
 				{
 					PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Firmware stuck on CR poll: T%u polling %s (reg:0x%08X mask:0x%08X)",
 							ui32ThreadCount,
-							((psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] & RGXFW_POLL_TYPE_SET)?("set"):("unset")), 
-							psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] & ~RGXFW_POLL_TYPE_SET, 
+							((psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] & RGXFW_POLL_TYPE_SET)?("set"):("unset")),
+							psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] & ~RGXFW_POLL_TYPE_SET,
 							psRGXFWIfTraceBufCtl->aui32CrPollMask[ui32ThreadCount]));
-					eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_DEAD;
+					eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
 					eNewReason = PVRSRV_DEVICE_HEALTH_REASON_POLL_FAILING;
 					goto _RGXUpdateHealthStatus_Exit;
 				}
@@ -3980,15 +4692,18 @@
 	/*
 	   Event Object Timeouts check...
 	*/
-	if (psDevInfo->ui32GEOTimeoutsLastTime > 1  &&  psPVRSRVData->ui32GEOConsecutiveTimeouts > psDevInfo->ui32GEOTimeoutsLastTime)
+	if (!bCheckAfterTimePassed)
 	{
-		PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Global Event Object Timeouts have risen (from %d to %d)",
-				psDevInfo->ui32GEOTimeoutsLastTime, psPVRSRVData->ui32GEOConsecutiveTimeouts));
-		eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
-		eNewReason = PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS;
+		if (psDevInfo->ui32GEOTimeoutsLastTime > 1  &&  psPVRSRVData->ui32GEOConsecutiveTimeouts > psDevInfo->ui32GEOTimeoutsLastTime)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Global Event Object Timeouts have risen (from %d to %d)",
+					psDevInfo->ui32GEOTimeoutsLastTime, psPVRSRVData->ui32GEOConsecutiveTimeouts));
+			eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+			eNewReason = PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS;
+		}
+		psDevInfo->ui32GEOTimeoutsLastTime = psPVRSRVData->ui32GEOConsecutiveTimeouts;
 	}
-	psDevInfo->ui32GEOTimeoutsLastTime = psPVRSRVData->ui32GEOConsecutiveTimeouts;
-	
+
 	/*
 	   Check the Kernel CCB pointer is valid. If any commands were waiting last time, then check
 	   that some have executed since then.
@@ -4016,7 +4731,7 @@
 	if (bCheckAfterTimePassed && psDevInfo->psRGXFWIfTraceBuf != NULL)
 	{
 		IMG_UINT32  ui32KCCBCmdsExecuted = psDevInfo->psRGXFWIfTraceBuf->ui32KCCBCmdsExecuted;
-		
+
 		if (psDevInfo->ui32KCCBCmdsExecutedLastTime == ui32KCCBCmdsExecuted)
 		{
 			/*
@@ -4028,7 +4743,7 @@
 				eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
 				eNewReason = PVRSRV_DEVICE_HEALTH_REASON_QUEUE_STALLED;
 			}
-		
+
 			/*
 			   If no commands are currently pending and nothing happened since the last poll, then
 			   schedule a dummy command to ping the firmware so we know it is alive and processing.
@@ -4040,21 +4755,12 @@
 
 				sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_HEALTH_CHECK;
 
-#if defined(PDUMP)
-				/* Protect the PDumpLoadMem. RGXScheduleCommand() cannot take the
-				 * PMR lock itself, because some bridge functions will take the PMR lock
-				 * before calling RGXScheduleCommand
-				 */
-				PMRLock();
-#endif
 				eError = RGXScheduleCommand(psDevNode->pvDevice,
 											RGXFWIF_DM_GP,
 											&sCmpKCCBCmd,
 											sizeof(sCmpKCCBCmd),
+											0,
 											IMG_TRUE);
-#if defined(PDUMP)
-				PMRUnlock();
-#endif
 				if (eError != PVRSRV_OK)
 				{
 					PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Cannot schedule Health Check command! (0x%x)", eError));
@@ -4072,57 +4778,81 @@
 
 	if (bCheckAfterTimePassed && (PVRSRV_DEVICE_HEALTH_STATUS_OK==eNewStatus))
 	{
-		/* Attempt to detect and deal with any stalled client contexts */
-		IMG_BOOL bStalledClient = IMG_FALSE;
-		if (CheckForStalledClientTransferCtxt(psDevInfo))
+		/* Attempt to detect and deal with any stalled client contexts.
+		 * Currently, ui32StalledClientMask is not a reliable method of detecting a stalled
+		 * application as the app could just be busy with a long running task,
+		 * or a lots of smaller workloads. Also the definition of stalled is
+		 * effectively subject to the timer frequency calling this function
+		 * (which is a platform config value with no guarantee it is correctly tuned).
+		 */
+
+		IMG_UINT32 ui32StalledClientMask = 0;
+
+		ui32StalledClientMask |= CheckForStalledClientTransferCtxt(psDevInfo);
+
+		ui32StalledClientMask |= CheckForStalledClientRenderCtxt(psDevInfo);
+
+#if	!defined(UNDER_WDDM)
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_COMPUTE_BIT_MASK)
 		{
-			PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client transfer context"));
-			bStalledClient = IMG_TRUE;
-		}
-		if (CheckForStalledClientRenderCtxt(psDevInfo))
-		{
-			PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client render context"));
-			bStalledClient = IMG_TRUE;
-		}
-#if defined(RGX_FEATURE_COMPUTE) && !defined(UNDER_WDDM)
-		if (CheckForStalledClientComputeCtxt(psDevInfo))
-		{
-			PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client compute context"));
-			bStalledClient = IMG_TRUE;
+			ui32StalledClientMask |= CheckForStalledClientComputeCtxt(psDevInfo);
 		}
 #endif
-#if defined(RGX_FEATURE_RAY_TRACING)
-		if (CheckForStalledClientRayCtxt(psDevInfo))
+
+		if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
 		{
-			PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client raytrace context"));
-			bStalledClient = IMG_TRUE;
+			ui32StalledClientMask |= CheckForStalledClientRayCtxt(psDevInfo);
 		}
-#endif
-		/* try the unblock routines only on the transition from OK to stalled */
-		if (!psDevInfo->bStalledClient && bStalledClient)
+        
+		/* If at least one DM stalled bit is different than before */
+		if (psDevInfo->ui32StalledClientMask ^ ui32StalledClientMask)
 		{
-#if defined(SUPPORT_DISPLAY_CLASS)
-			//DCDisplayContextFlush();
-#endif
+			/* Print all the stalled DMs */
+			PVR_LOG(("RGXGetDeviceHealthStatus: Possible stalled client contexts detected: %s%s%s%s%s%s%s%s%s",
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_GP), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TDM_2D), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TA), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_3D), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_CDM), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_RTU), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_SHG), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TQ2D), 
+			         RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TQ3D))); 
 		}
-		psDevInfo->bStalledClient = bStalledClient;
+		psDevInfo->ui32StalledClientMask = ui32StalledClientMask;
 	}
 
 	/*
 	   Finished, save the new status...
 	*/
 _RGXUpdateHealthStatus_Exit:
-	psDevNode->eHealthStatus = eNewStatus;
-	psDevNode->eHealthReason = eNewReason;
+	OSAtomicWrite(&psDevNode->eHealthStatus, eNewStatus);
+	OSAtomicWrite(&psDevNode->eHealthReason, eNewReason);
+
+	/*
+	 * Attempt to service the HWPerf buffer to regularly transport idle/periodic
+	 * packets to host buffer.
+	 */
+	if (psDevNode->pfnServiceHWPerf != NULL)
+	{
+		PVRSRV_ERROR eError = psDevNode->pfnServiceHWPerf(psDevNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
+					 "Error occurred when servicing HWPerf buffer (%d)",
+					 eError));
+		}
+	}
+
 #endif
 	return PVRSRV_OK;
 } /* RGXUpdateHealthStatus */
 
-PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext)
+PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext, RGX_KICK_TYPE_DM eKickTypeDM)
 {
 	RGX_CLIENT_CCB 	*psCurrentClientCCB = psCurrentServerCommonContext->psClientCCB;
 
-	return CheckForStalledCCB(psCurrentClientCCB);
+	return CheckForStalledCCB(psCurrentClientCCB, eKickTypeDM);
 }
 
 void DumpStalledFWCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext,
@@ -4133,7 +4863,8 @@
 	PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext = psCurrentServerCommonContext->sFWCommonContextFWAddr;
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) || defined(PVRSRV_ENABLE_FULL_CCB_DUMP)
-	DumpCCB(sFWCommonContext, psCurrentClientCCB, pfnDumpDebugPrintf, pvDumpDebugFile);
+	DumpCCB(psCurrentServerCommonContext->psDevInfo, sFWCommonContext,
+			psCurrentClientCCB, pfnDumpDebugPrintf, pvDumpDebugFile);
 #else
 	DumpStalledCCBCommand(sFWCommonContext, psCurrentClientCCB, pfnDumpDebugPrintf, pvDumpDebugFile);
 #endif
@@ -4218,13 +4949,13 @@
 	psHWRInfoBuf = psDevInfo->psRGXFWIfHWRInfoBuf;
 	psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
 
-	for(i = 0 ; i < RGXFWIF_DM_MAX ; i++)
+	for(i = 0 ; i < psDevInfo->sDevFeatureCfg.ui32MAXDMCount ; i++)
 	{
 		/* Reset the HWR numbers */
-		psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[i] = 0;
-		psRGXFWIfTraceBufCtl->aui16HwrDmFalseDetectCount[i] = 0;
-		psRGXFWIfTraceBufCtl->aui16HwrDmRecoveredCount[i] = 0;
-		psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[i] = 0;
+		psRGXFWIfTraceBufCtl->aui32HwrDmLockedUpCount[i] = 0;
+		psRGXFWIfTraceBufCtl->aui32HwrDmFalseDetectCount[i] = 0;
+		psRGXFWIfTraceBufCtl->aui32HwrDmRecoveredCount[i] = 0;
+		psRGXFWIfTraceBufCtl->aui32HwrDmOverranCount[i] = 0;
 	}
 
 	for(i = 0 ; i < RGXFWIF_HWINFO_MAX ; i++)
@@ -4254,8 +4985,7 @@
 
 	PVRSRV_ERROR eError;
 
-	eError = PMRLockSysPhysAddresses(psPMR,
-										 ui32Log2PageSize);
+	eError = PMRLockSysPhysAddresses(psPMR);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXGetPhyAddr: PMRLockSysPhysAddresses failed (%u)",
@@ -4324,6 +5054,117 @@
 }
 #endif
 
+/*!
+*******************************************************************************
+
+ @Function	RGXClientConnectCompatCheck_ClientAgainstFW
+
+ @Description
+
+ Check compatibility of client and firmware (build options)
+ at the connection time.
+
+ @Input psDeviceNode - device node
+ @Input ui32ClientBuildOptions - build options for the client
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV RGXClientConnectCompatCheck_ClientAgainstFW(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32ClientBuildOptions)
+{
+	PVRSRV_ERROR		eError;
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	eError = PVRSRV_OK;
+#else
+#if !defined(NO_HARDWARE) || defined(PDUMP)
+	PVRSRV_RGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+#endif
+#if !defined(NO_HARDWARE)
+	RGXFWIF_INIT	*psRGXFWInit = NULL;
+	IMG_UINT32		ui32BuildOptionsMismatch;
+	IMG_UINT32		ui32BuildOptionsFW;      
+
+	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
+												(void **)&psRGXFWInit);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to acquire kernel fw compatibility check info (%u)",
+				__FUNCTION__, eError));
+		return eError;
+	}
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
+		{
+			/* No need to wait if the FW has already updated the values */
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+#endif
+
+#if defined(PDUMP)                                                                                                                             
+	PDUMPCOMMENT("Compatibility check: client and FW build options");
+	eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+												offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+												offsetof(RGXFWIF_COMPCHECKS, ui32BuildOptions),
+												ui32ClientBuildOptions,
+												0xffffffff,
+												PDUMP_POLL_OPERATOR_EQUAL,
+												PDUMP_FLAGS_CONTINUOUS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+		return eError;
+	}
+#endif                                                                                                                                         
+
+#if !defined(NO_HARDWARE)
+	if (psRGXFWInit == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to acquire kernel fw compatibility check info, psRGXFWInit is NULL", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto chk_exit;
+	}
+
+	ui32BuildOptionsFW = psRGXFWInit->sRGXCompChecks.ui32BuildOptions;
+	ui32BuildOptionsMismatch = ui32ClientBuildOptions ^ ui32BuildOptionsFW;
+
+	if (ui32BuildOptionsMismatch != 0)
+	{
+		if ( (ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
+			"extra options present in client: (0x%x). Please check rgx_options.h",
+			ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
+		}
+
+		if ( (ui32BuildOptionsFW & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
+			"extra options present in Firmware: (0x%x). Please check rgx_options.h",
+			ui32BuildOptionsFW & ui32BuildOptionsMismatch ));
+		}
+		eError = PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and client build options match. [ OK ]"));
+	}
+#endif
+
+	eError = PVRSRV_OK;
+#if !defined(NO_HARDWARE)
+chk_exit:
+	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+#endif
+#endif
+	return eError;
+
+}
+
 /******************************************************************************
  End of file (rgxfwutils.c)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxfwutils.h b/drivers/staging/imgtec/rogue/rgxfwutils.h
index 4d50625..6978e5f 100644
--- a/drivers/staging/imgtec/rogue/rgxfwutils.h
+++ b/drivers/staging/imgtec/rogue/rgxfwutils.h
@@ -48,12 +48,15 @@
 #include "rgxccb.h"
 #include "devicemem.h"
 #include "device.h"
+#include "pvr_notifier.h"
 #include "pvrsrv.h"
 #include "connection_server.h"
 #include "rgxta3d.h"
+#include "devicemem_utils.h"
 
 #if defined(SUPPORT_TRUSTED_DEVICE)
-#include "physmem_tdmetacode.h"
+#include "physmem_tdfwcode.h"
+#include "physmem_tdsecbuf.h"
 #endif
 
 
@@ -74,12 +77,17 @@
 
 	PVR_DPF_ENTERED;
 
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	uiFlags |= PVRSRV_MEMALLOCFLAG_UNCACHED;
+	uiFlags &= ~PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED);
+#endif
+
 	/* Ensure all RI labels begin 'Fw' for the FW heap. */
 	PVR_ASSERT((pszText != NULL) && (pszText[0] == 'F') && (pszText[1] == 'w'));
 
 	eError = DevmemAllocate(psDevInfo->psFirmwareHeap,
 							uiSize,
-							ROGUE_CACHE_LINE_SIZE,
+							GET_ROGUE_CACHE_LINE_SIZE(psDevInfo->sDevFeatureCfg.ui32CacheLineSize),
 							uiFlags | PVRSRV_MEMALLOCFLAG_FW_LOCAL,
 							pszText,
 							ppsMemDescPtr);
@@ -106,6 +114,7 @@
 
 static INLINE PVRSRV_ERROR DevmemFwAllocateExportable(PVRSRV_DEVICE_NODE *psDeviceNode,
 													  IMG_DEVMEM_SIZE_T uiSize,
+													  IMG_DEVMEM_ALIGN_T uiAlign,
 													  DEVMEM_FLAGS_T uiFlags,
 									                  IMG_PCHAR pszText,
 													  DEVMEM_MEMDESC **ppsMemDescPtr)
@@ -114,6 +123,11 @@
 	IMG_DEV_VIRTADDR sTmpDevVAddr;
 	PVRSRV_ERROR eError;
 
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	uiFlags |= PVRSRV_MEMALLOCFLAG_UNCACHED;
+	uiFlags &= ~PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED);
+#endif
+
 	PVR_DPF_ENTERED;
 
 	PVR_ASSERT((pszText != NULL) &&
@@ -122,7 +136,8 @@
 
 	eError = DevmemAllocateExportable(psDeviceNode,
 									  uiSize,
-									  ROGUE_CACHE_LINE_SIZE,
+									  uiAlign,
+									  DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
 									  uiFlags | PVRSRV_MEMALLOCFLAG_FW_LOCAL,
 									  pszText,
 									  ppsMemDescPtr);
@@ -147,9 +162,37 @@
 	PVR_DPF_RETURN_RC1(eError, *ppsMemDescPtr);
 }
 
-static INLINE void DevmemFwFree(DEVMEM_MEMDESC *psMemDesc)
+static void DevmemFWPoison(DEVMEM_MEMDESC *psMemDesc, IMG_BYTE ubPoisonValue)
+{
+	void *pvLinAddr;
+	PVRSRV_ERROR eError;
+
+	eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvLinAddr);
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire FW allocation mapping "
+					"to poison: %s",
+							__func__,
+							PVRSRVGETERRORSTRING(eError)));
+		return;
+	}
+
+	OSDeviceMemSet(pvLinAddr, ubPoisonValue, psMemDesc->uiAllocSize);
+
+	DevmemReleaseCpuVirtAddr(psMemDesc);
+}
+
+static INLINE void DevmemFwFree(PVRSRV_RGXDEV_INFO *psDevInfo,
+								DEVMEM_MEMDESC *psMemDesc)
 {
 	PVR_DPF_ENTERED1(psMemDesc);
+
+	if(psDevInfo->bEnableFWPoisonOnFree)
+	{
+		DevmemFWPoison(psMemDesc, psDevInfo->ubFWPoisonOnFreeValue);
+	}
+
 	DevmemReleaseDevVirtAddr(psMemDesc);
 	DevmemFree(psMemDesc);
 
@@ -158,37 +201,51 @@
 
 #if defined(SUPPORT_TRUSTED_DEVICE)
 static INLINE
-PVRSRV_ERROR DevmemImportTDMetaCode(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                    IMG_UINT32 uiMemAllocFlags,
-                                    DEVMEM_MEMDESC **ppsMemDescPtr)
+PVRSRV_ERROR DevmemImportTDFWCode(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  IMG_DEVMEM_SIZE_T uiSize,
+                                  PMR_LOG2ALIGN_T uiLog2Align,
+                                  IMG_UINT32 uiMemAllocFlags,
+                                  IMG_BOOL bFWCorememCode,
+                                  DEVMEM_MEMDESC **ppsMemDescPtr)
 {
 	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
-	PMR *psTDMetaCodePMR;
+	PMR *psTDFWCodePMR;
 	IMG_DEV_VIRTADDR sTmpDevVAddr;
 	IMG_DEVMEM_SIZE_T uiMemDescSize;
+	IMG_DEVMEM_ALIGN_T uiAlign = 1 << uiLog2Align;
 	PVRSRV_ERROR eError;
 
-	eError = PhysmemNewTDMetaCodePMR(psDeviceNode,
-	                                 uiMemAllocFlags,
-	                                 &psTDMetaCodePMR);
+	PVR_ASSERT(ppsMemDescPtr);
+
+	DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
+	                                    &uiSize,
+	                                    &uiAlign);
+
+	eError = PhysmemNewTDFWCodePMR(psDeviceNode,
+	                               uiSize,
+	                               uiLog2Align,
+	                               uiMemAllocFlags,
+	                               bFWCorememCode,
+	                               &psTDFWCodePMR);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PhysmemNewTDMetaCodePMR failed (%u)", eError));
+		PVR_DPF((PVR_DBG_ERROR, "PhysmemNewTDFWCodePMR failed (%u)", eError));
 		goto PMRCreateError;
 	}
 
-	/* NB: TDMetaCodePMR refcount: 1 -> 2 */
+	/* NB: TDFWCodePMR refcount: 1 -> 2 */
 	eError = DevmemLocalImport(psDeviceNode,
-	                           psTDMetaCodePMR,
+	                           psTDFWCodePMR,
 	                           uiMemAllocFlags,
 	                           ppsMemDescPtr,
-	                           &uiMemDescSize);
+	                           &uiMemDescSize,
+	                           "TDFWCode");
 	if(eError != PVRSRV_OK)
 	{
 		goto ImportError;
 	}
 
-	eError = DevmemMapToDevice(psDevInfo->psRGXFWCodeMemDesc,
+	eError = DevmemMapToDevice(*ppsMemDescPtr,
 	                           psDevInfo->psFirmwareHeap,
 	                           &sTmpDevVAddr);
 	if(eError != PVRSRV_OK)
@@ -197,20 +254,94 @@
 		goto MapError;
 	}
 
-	/* NB: TDMetaCodePMR refcount: 2 -> 1
+	/* NB: TDFWCodePMR refcount: 2 -> 1
 	 * The PMR will be unreferenced again (and destroyed) when
 	 * the memdesc tracking it is cleaned up
 	 */
-	PMRUnrefPMR(psTDMetaCodePMR);
+	PMRUnrefPMR(psTDFWCodePMR);
 
 	return PVRSRV_OK;
 
 MapError:
-	DevmemFree(psDevInfo->psRGXFWCodeMemDesc);
-	psDevInfo->psRGXFWCodeMemDesc = NULL;
+	DevmemFree(*ppsMemDescPtr);
+	*ppsMemDescPtr = NULL;
 ImportError:
 	/* Unref and destroy the PMR */
-	PMRUnrefPMR(psTDMetaCodePMR);
+	PMRUnrefPMR(psTDFWCodePMR);
+PMRCreateError:
+
+	return eError;
+}
+
+static INLINE
+PVRSRV_ERROR DevmemImportTDSecureBuf(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_DEVMEM_SIZE_T uiSize,
+                                     PMR_LOG2ALIGN_T uiLog2Align,
+                                     IMG_UINT32 uiMemAllocFlags,
+                                     DEVMEM_MEMDESC **ppsMemDescPtr,
+                                     IMG_UINT64 *pui64SecBufHandle)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+	PMR *psTDSecureBufPMR;
+	IMG_DEV_VIRTADDR sTmpDevVAddr;
+	IMG_DEVMEM_SIZE_T uiMemDescSize;
+	IMG_DEVMEM_ALIGN_T uiAlign = 1 << uiLog2Align;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(ppsMemDescPtr);
+
+	DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
+	                                    &uiSize,
+	                                    &uiAlign);
+
+	eError = PhysmemNewTDSecureBufPMR(NULL,
+	                                  psDeviceNode,
+	                                  uiSize,
+	                                  uiLog2Align,
+	                                  uiMemAllocFlags,
+	                                  &psTDSecureBufPMR,
+	                                  pui64SecBufHandle);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PhysmemNewTDSecureBufPMR failed (%u)", eError));
+		goto PMRCreateError;
+	}
+
+	/* NB: psTDSecureBufPMR refcount: 1 -> 2 */
+	eError = DevmemLocalImport(psDeviceNode,
+	                           psTDSecureBufPMR,
+	                           uiMemAllocFlags,
+	                           ppsMemDescPtr,
+	                           &uiMemDescSize,
+	                           "TDSecureBuffer");
+	if(eError != PVRSRV_OK)
+	{
+		goto ImportError;
+	}
+
+	eError = DevmemMapToDevice(*ppsMemDescPtr,
+	                           psDevInfo->psFirmwareHeap,
+	                           &sTmpDevVAddr);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Failed to map TD secure buffer PMR (%u)", eError));
+		goto MapError;
+	}
+
+	/* NB: psTDSecureBufPMR refcount: 2 -> 1
+	 * The PMR will be unreferenced again (and destroyed) when
+	 * the memdesc tracking it is cleaned up
+	 */
+	PMRUnrefPMR(psTDSecureBufPMR);
+
+	return PVRSRV_OK;
+
+MapError:
+	DevmemFree(*ppsMemDescPtr);
+	*ppsMemDescPtr = NULL;
+ImportError:
+	/* Unref and destroy the PMR */
+	PMRUnrefPMR(psTDSecureBufPMR);
 PMRCreateError:
 
 	return eError;
@@ -273,10 +404,11 @@
                               IMG_UINT32               ui32SignatureChecksBufSize,
                               IMG_UINT32               ui32HWPerfFWBufSizeKB,
                               IMG_UINT64               ui64HWPerfFilter,
-                              IMG_UINT32               ui32RGXFWAlignChecksSize,
+                              IMG_UINT32               ui32RGXFWAlignChecksArrLength,
                               IMG_UINT32               *pui32RGXFWAlignChecks,
                               IMG_UINT32               ui32ConfigFlags,
                               IMG_UINT32               ui32LogType,
+                              RGXFWIF_BIFTILINGMODE    eBifTilingMode,
                               IMG_UINT32               ui32NumTilingCfgs,
                               IMG_UINT32               *pui32BIFTilingXStrides,
                               IMG_UINT32               ui32FilterFlags,
@@ -308,7 +440,7 @@
 						   IMG_UINT32			uiOffset,
 						   IMG_UINT32			ui32Flags);
 
-#if defined(RGX_FEATURE_META_DMA)
+
 /*************************************************************************/ /*!
 @Function       RGXSetMetaDMAAddress
 
@@ -326,7 +458,7 @@
 						  DEVMEM_MEMDESC		*psSrcMemDesc,
 						  RGXFWIF_DEV_VIRTADDR	*psSrcFWDevVAddr,
 						  IMG_UINT32			uiOffset);
-#endif
+
 
 /*************************************************************************/ /*!
 @Function       RGXUnsetFirmwareAddress
@@ -342,7 +474,7 @@
 /*************************************************************************/ /*!
 @Function       FWCommonContextAllocate
 
-@Description    Allocate a FW common coontext. This allocates the HW memory
+@Description    Allocate a FW common context. This allocates the HW memory
                 for the context, the CCB and wires it all together.
 
 @Input          psConnection            Connection this context is being created on
@@ -427,10 +559,10 @@
 				pending cache operations but taking the power lock.
 
 @Input          psDevInfo			Device Info
-@Input          eDM					To which DM the cmd is sent.
+@Input          eDM				To which DM the cmd is sent.
 @Input          psKCCBCmd			The cmd to send.
 @Input          ui32CmdSize			The cmd size.
-@Input          bPDumpContinuous
+@Input          ui32PDumpFlags			Pdump flags
 
 @Return			PVRSRV_ERROR
 */ /**************************************************************************/
@@ -438,28 +570,27 @@
 										RGXFWIF_DM			eKCCBType,
 									 	RGXFWIF_KCCB_CMD	*psKCCBCmd,
 									 	IMG_UINT32			ui32CmdSize,
-									 	IMG_BOOL			bPDumpContinuous);
+									 	IMG_UINT32			ui32PDumpFlags);
 
 /*************************************************************************/ /*!
 @Function       RGXSendCommand
 
 @Description    Sends a command to a particular DM without honouring
 				pending cache operations or the power lock. 
-                                The function flushes any
-				deferred KCCB commands first.
+                The function flushes any deferred KCCB commands first.
 
 @Input          psDevInfo			Device Info
-@Input          eDM					To which DM the cmd is sent.
+@Input          eDM				To which DM the cmd is sent.
 @Input          psKCCBCmd			The cmd to send.
 @Input          ui32CmdSize			The cmd size.
-@Input          bPDumpContinuous
+@Input          uiPdumpFlags			PDump flags.
 
 @Return			PVRSRV_ERROR
 */ /**************************************************************************/
 PVRSRV_ERROR RGXSendCommand(PVRSRV_RGXDEV_INFO 	*psDevInfo,
-								 RGXFWIF_DM			eKCCBType,
+								 RGXFWIF_DM		eKCCBType,
 								 RGXFWIF_KCCB_CMD	*psKCCBCmd,
-								 IMG_UINT32			ui32CmdSize,
+								 IMG_UINT32		ui32CmdSize,
 								 PDUMP_FLAGS_T		uiPdumpFlags);
 
 
@@ -469,18 +600,20 @@
 @Description    Sends a command to a particular DM
 
 @Input          psDevInfo			Device Info
-@Input          eDM					To which DM the cmd is sent.
+@Input          eDM				To which DM the cmd is sent.
 @Input          psKCCBCmd			The cmd to send.
 @Input          ui32CmdSize			The cmd size.
-@Input          bPDumpContinuous
+@Input          ui32CacheOpFence		Pending cache op. fence value.
+@Input          ui32PDumpFlags			PDump flags
 
 @Return			PVRSRV_ERROR
 */ /**************************************************************************/
 PVRSRV_ERROR RGXScheduleCommand(PVRSRV_RGXDEV_INFO 	*psDevInfo,
-								RGXFWIF_DM			eKCCBType,
+								RGXFWIF_DM		eKCCBType,
 								RGXFWIF_KCCB_CMD	*psKCCBCmd,
-								IMG_UINT32			ui32CmdSize,
-								IMG_BOOL			bPDumpContinuous);
+								IMG_UINT32		ui32CmdSize,
+								IMG_UINT32		ui32CacheOpFence,
+								IMG_UINT32 		ui32PDumpFlags);
 
 /*************************************************************************/ /*!
 @Function       RGXScheduleCommandAndWait
@@ -493,14 +626,14 @@
 				UpdateValue for that cmd.
 
 @Input          psDevInfo			Device Info
-@Input          eDM					To which DM the cmd is sent.
+@Input          eDM				To which DM the cmd is sent.
 @Input          psKCCBCmd			The cmd to send.
 @Input          ui32CmdSize			The cmd size.
 @Input          puiSyncObjFWAddr	Pointer to the location with the FWAddr of 
 									the sync.
 @Input          puiUpdateValue		Pointer to the location with the update 
 									value of the sync.
-@Input          bPDumpContinuous
+@Input          ui32PDumpFlags		PDump flags
 
 @Return			PVRSRV_ERROR
 */ /**************************************************************************/
@@ -510,8 +643,8 @@
 									   IMG_UINT32			ui32CmdSize,
 									   IMG_UINT32			*puiSyncObjDevVAddr,
 									   IMG_UINT32			*puiUpdateValue,
-									   PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
-									   IMG_BOOL				bPDumpContinuous);
+									   PVRSRV_CLIENT_SYNC_PRIM 	*psSyncPrim,
+									   IMG_UINT32			ui32PDumpFlags);
 
 PVRSRV_ERROR RGXFirmwareUnittests(PVRSRV_RGXDEV_INFO *psDevInfo);
 
@@ -546,18 +679,35 @@
 /*************************************************************************/ /*!
 @Function       RGXWaitForFWOp
 
-@Description    Send a sync command and wait to be signaled.
+@Description    Send a sync command and wait to be signalled.
 
 @Input          psDevInfo			Device Info
-@Input          eDM					To which DM the cmd is sent.
-@Input          bPDumpContinuous	
+@Input          eDM				To which DM the cmd is sent.
+@Input          ui32PDumpFlags			PDump flags
 
 @Return			void
 */ /**************************************************************************/
 PVRSRV_ERROR RGXWaitForFWOp(PVRSRV_RGXDEV_INFO	*psDevInfo,
 									RGXFWIF_DM	eDM,
 									PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
-									IMG_BOOL	bPDumpContinuous);
+									IMG_UINT32	ui32PDumpFlags);
+
+/*************************************************************************/ /*!
+@Function       RGXStateFlagCtrl
+
+@Description    Set and return FW internal state flags.
+
+@Input          psDevInfo       Device Info
+@Input          ui32Config      AppHint config flags
+@Output         pui32State      Current AppHint state flag configuration
+@Input          bSetNotClear    Set or clear the provided config flags
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXStateFlagCtrl(PVRSRV_RGXDEV_INFO *psDevInfo,
+				IMG_UINT32 ui32Config,
+				IMG_UINT32 *pui32State,
+				IMG_BOOL bSetNotClear);
 
 /*!
 ******************************************************************************
@@ -574,11 +724,14 @@
 
  @Input eDM - Data master, to which the cleanup command should be send
 
+ @Input ui32PDumpFlags - PDump continuous flag
+
 ******************************************************************************/
 PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
 											  RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
 											  PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
-											  RGXFWIF_DM eDM);
+											  RGXFWIF_DM eDM,
+											  IMG_UINT32 ui32PDumpFlags);
 
 /*!
 ******************************************************************************
@@ -601,8 +754,6 @@
 										 PVRSRV_CLIENT_SYNC_PRIM *psSync,
 										 RGXFWIF_DM eDM);
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-
 PVRSRV_ERROR RGXFWRequestRayFrameDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
 											 PRGXFWIF_RAY_FRAME_DATA psHWFrameData,
 											 PVRSRV_CLIENT_SYNC_PRIM *psSync,
@@ -627,7 +778,7 @@
 PVRSRV_ERROR RGXFWRequestRPMFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
 											PRGXFWIF_RPM_FREELIST psFWRPMFreeList,
 											PVRSRV_CLIENT_SYNC_PRIM *psSync);
-#endif
+
 
 /*!
 ******************************************************************************
@@ -679,6 +830,94 @@
 /*!
 ******************************************************************************
 
+ @Function				RGXFWSetHCSDeadline
+
+ @Description			Requests the Firmware to set a new Hard Context
+						Switch timeout deadline. Context switches that
+						surpass that deadline cause the system to kill
+						the currently running workloads.
+
+ @Input psDeviceNode	pointer to device node
+
+ @Input ui32HCSDeadlineMs	The deadline in milliseconds.
+ ******************************************************************************/
+PVRSRV_ERROR RGXFWSetHCSDeadline(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32HCSDeadlineMs);
+
+/*!
+******************************************************************************
+
+ @Function				RGXFWChangeOSidPriority
+
+ @Description			Requests the Firmware to change the priority of an
+						operating system. Higher priority number equals
+						higher priority on the scheduling system.
+
+ @Input psDeviceNode	pointer to device node
+
+ @Input ui32OSid		The OSid whose priority is to be altered
+
+ @Input ui32Priority	The new priority number for the specified OSid
+ ******************************************************************************/
+PVRSRV_ERROR RGXFWChangeOSidPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
+									 IMG_UINT32 ui32OSid,
+									 IMG_UINT32 ui32Priority);
+
+/*!
+****************************************************************************
+
+ @Function				RGXFWSetOSIsolationThreshold
+
+ @Description			Requests the Firmware to change the priority
+						threshold of the OS Isolation group. Any OS with a
+						priority higher or equal than the threshold is
+						considered to be belonging to the isolation group.
+
+ @Input psDeviceNode	pointer to device node
+
+ @Input ui32IsolationPriorityThreshold	The new priority threshold
+ ***************************************************************************/
+PVRSRV_ERROR RGXFWSetOSIsolationThreshold(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32IsolationPriorityThreshold);
+
+/*!
+****************************************************************************
+
+ @Function              RGXFWOSConfig
+
+ @Description           Sends the OS Init structure to the FW to complete
+                        the initialization process. The FW will then set all
+                        the OS specific parameters for that DDK
+
+ @Input psDeviceNode    pointer to device node
+ ***************************************************************************/
+PVRSRV_ERROR RGXFWOSConfig(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+****************************************************************************
+
+ @Function				RGXFWSetVMOnlineState
+
+ @Description			Requests the Firmware to change the guest OS Online
+						states. This should be initiated by the VMM when a
+						guest VM comes online or goes offline. If offline,
+						the FW offloads any current resource from that OSID.
+						The request is repeated until the FW has had time to
+						free all the resources or has waited for workloads
+						to finish.
+
+ @Input psDeviceNode	pointer to device node
+
+ @Input ui32OSid		The Guest OSid whose state is being altered
+
+ @Input eOSOnlineState	The new state (Online or Offline)
+ ***************************************************************************/
+PVRSRV_ERROR RGXFWSetVMOnlineState(PVRSRV_RGXDEV_INFO *psDevInfo,
+								IMG_UINT32 ui32OSid,
+								RGXFWIF_OS_STATE_CHANGE eOSOnlineState);
+/*!
+******************************************************************************
+
  @Function	RGXReadMETAAddr
 
  @Description Reads a value at given address in META memory space
@@ -731,7 +970,7 @@
                                    IMG_BOOL bCheckAfterTimePassed);
 
 
-PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext);
+PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext, RGX_KICK_TYPE_DM eKickTypeDM);
 
 void DumpStalledFWCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext,
 					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
diff --git a/drivers/staging/imgtec/rogue/rgxheapconfig.h b/drivers/staging/imgtec/rogue/rgxheapconfig.h
index ec5e231..2c532df 100644
--- a/drivers/staging/imgtec/rogue/rgxheapconfig.h
+++ b/drivers/staging/imgtec/rogue/rgxheapconfig.h
@@ -41,101 +41,97 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+//#warning FIXME:  add the MMU specialisation defines here (or in hwdefs, perhaps?)
+
 #ifndef __RGXHEAPCONFIG_H__
 #define __RGXHEAPCONFIG_H__
 
 #include "rgxdefs_km.h"
 
-#define DEV_DEVICE_TYPE			PVRSRV_DEVICE_TYPE_RGX
-#define DEV_DEVICE_CLASS		PVRSRV_DEVICE_CLASS_3D
+/*
+	RGX Device Virtual Address Space Definitions
+	NOTES:
+		Base addresses have to be a multiple of 4MiB
 
-#define DEV_MAJOR_VERSION		1
-#define DEV_MINOR_VERSION		0
+		RGX_PDSCODEDATA_HEAP_BASE and RGX_USCCODE_HEAP_BASE will be programmed,
+		on a global basis, into RGX_CR_PDS_EXEC_BASE and RGX_CR_USC_CODE_BASE_*
+		respectively. Therefore if clients use multiple configs they must still
+		be consistent with their definitions for these heaps.
 
-/*      
-	RGX Device Virtual Address Space Definitions:
-
-	Notes:
-	Base addresses have to be a multiple of 4MiB
-	
-	RGX_PDSCODEDATA_HEAP_BASE and RGX_USCCODE_HEAP_BASE will be programmed, on a
-	global basis, into RGX_CR_PDS_EXEC_BASE and RGX_CR_USC_CODE_BASE_*
-	respectively.
-	Therefore if clients use multiple configs they must still be consistent with
-	their definitions for these heaps.
+		Shared virtual memory (GENERAL_SVM) support requires half of the address
+		space be reserved for SVM allocations unless BRN fixes are required in
+		which case the SVM heap is disabled. This is reflected in the device
+		connection capability bits returned to userspace.
+		
+		Variable page-size heap (GENERAL_NON4K) support splits available fixed
+		4K page-size heap (GENERAL) address space in half. The actual page size
+		defaults to 16K; AppHint PVRSRV_APPHINT_GENERAL_NON4K_HEAP_PAGE_SIZE
+		can be used to forced it to these values: 4K,64K,256K,1M,2M.
 */
 
-#if RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS == 40
+	/* Start at 4 MiB Size of 512 GiB less 4 MiB (managed by OS/Services) */
+	#define RGX_GENERAL_SVM_HEAP_BASE			IMG_UINT64_C(0x0000400000)
+	#define RGX_GENERAL_SVM_HEAP_SIZE			IMG_UINT64_C(0x7FFFC00000)
 
-	/* Start at 128 Kb. Size of 256 Mb */
-//	#define RGX_3DPARAMETERS_HEAP_BASE			IMG_UINT64_C(0x0000020000)
-//  #define RGX_3DPARAMETERS_HEAP_SIZE			IMG_UINT64_C(0x0010000000)
+	/* Start at 512GiB. Size of 256 GiB */
+	#define RGX_GENERAL_HEAP_BASE				IMG_UINT64_C(0x8000000000)
+	#define RGX_GENERAL_HEAP_SIZE				IMG_UINT64_C(0x4000000000)
 
-	/* Start at 4GiB. Size of 512 GiB */
-	#define RGX_GENERAL_HEAP_BASE				IMG_UINT64_C(0x0100000000)
-    #define RGX_GENERAL_HEAP_SIZE				IMG_UINT64_C(0x8000000000)
+	/* Start at 768GiB. Size of 64 GiB */
+	#define RGX_GENERAL_NON4K_HEAP_BASE			IMG_UINT64_C(0xC000000000)
+	#define RGX_GENERAL_NON4K_HEAP_SIZE			IMG_UINT64_C(0x1000000000)
 
-	/* start at 516 GiB. Size of 32 GiB */
-	#define RGX_BIF_TILING_NUM_HEAPS            4
-	#define RGX_BIF_TILING_HEAP_SIZE            IMG_UINT64_C(0x0200000000)
-	#define RGX_BIF_TILING_HEAP_1_BASE          IMG_UINT64_C(0x8100000000)
-	#define RGX_BIF_TILING_HEAP_2_BASE          (RGX_BIF_TILING_HEAP_1_BASE + RGX_BIF_TILING_HEAP_SIZE)
-	#define RGX_BIF_TILING_HEAP_3_BASE          (RGX_BIF_TILING_HEAP_2_BASE + RGX_BIF_TILING_HEAP_SIZE)
-	#define RGX_BIF_TILING_HEAP_4_BASE          (RGX_BIF_TILING_HEAP_3_BASE + RGX_BIF_TILING_HEAP_SIZE)
+	/* Start at 832 GiB. Size of 32 GiB */
+	#define RGX_BIF_TILING_NUM_HEAPS			4
+	#define RGX_BIF_TILING_HEAP_SIZE			IMG_UINT64_C(0x0200000000)
+	#define RGX_BIF_TILING_HEAP_1_BASE			IMG_UINT64_C(0xD000000000)
+	#define RGX_BIF_TILING_HEAP_2_BASE			(RGX_BIF_TILING_HEAP_1_BASE + RGX_BIF_TILING_HEAP_SIZE)
+	#define RGX_BIF_TILING_HEAP_3_BASE			(RGX_BIF_TILING_HEAP_2_BASE + RGX_BIF_TILING_HEAP_SIZE)
+	#define RGX_BIF_TILING_HEAP_4_BASE			(RGX_BIF_TILING_HEAP_3_BASE + RGX_BIF_TILING_HEAP_SIZE)
 
-#if defined(FIX_HW_BRN_52402)
 	/* HWBRN52402 workaround requires PDS memory to be below 16GB. Start at 8GB. Size of 4GB. */
-	#define RGX_PDSCODEDATA_HEAP_BASE			IMG_UINT64_C(0x0200000000)
-    #define RGX_PDSCODEDATA_HEAP_SIZE			IMG_UINT64_C(0x0100000000)
-#else
-	/* Start at 600GiB. Size of 4 GiB */
-	#define RGX_PDSCODEDATA_HEAP_BASE			IMG_UINT64_C(0x9600000000)
-    #define RGX_PDSCODEDATA_HEAP_SIZE			IMG_UINT64_C(0x0100000000)
-#endif
+	#define RGX_PDSCODEDATA_BRN_52402_HEAP_BASE	IMG_UINT64_C(0x0200000000)
+	#define RGX_PDSCODEDATA_BRN_52402_HEAP_SIZE	IMG_UINT64_C(0x0100000000)
 
-/* start at 604GiB, size of 1 MiB */
-	#define RGX_VISTEST_HEAP_BASE			IMG_UINT64_C(0x9700000000)
-    #define RGX_VISTEST_HEAP_SIZE			IMG_UINT64_C(0x0000100000)
- 
-#if defined(FIX_HW_BRN_52402)
+	/* Start at 872 GiB. Size of 4 GiB */
+	#define RGX_PDSCODEDATA_HEAP_BASE			IMG_UINT64_C(0xDA00000000)
+    #define RGX_PDSCODEDATA_HEAP_SIZE			IMG_UINT64_C(0x0100000000)
+
+	/* HWBRN63142 workaround requires Region Header memory to be at the top
+	   of a 16GB aligned range. This is so when masked with 0x03FFFFFFFF the
+	   address will avoid aliasing PB addresses. Start at 879.75GB. Size of 256MB. */
+	#define RGX_RGNHDR_BRN_63142_HEAP_BASE		IMG_UINT64_C(0xDBF0000000)
+	#define RGX_RGNHDR_BRN_63142_HEAP_SIZE		IMG_UINT64_C(0x0010000000)
+
+	/* Start at 880 GiB, Size of 1 MiB */
+	#define RGX_VISTEST_HEAP_BASE				IMG_UINT64_C(0xDC00000000)
+	#define RGX_VISTEST_HEAP_SIZE				IMG_UINT64_C(0x0000100000)
+
 	/* HWBRN52402 workaround requires PDS memory to be below 16GB. Start at 12GB. Size of 4GB. */
-	#define RGX_USCCODE_HEAP_BASE				IMG_UINT64_C(0x0300000000)
-    #define RGX_USCCODE_HEAP_SIZE				IMG_UINT64_C(0x0100000000)
-#else
-	/* Start at 800GiB. Size of 4 GiB */
-	#define RGX_USCCODE_HEAP_BASE				IMG_UINT64_C(0xC800000000)
-    #define RGX_USCCODE_HEAP_SIZE				IMG_UINT64_C(0x0100000000)
-#endif
- 
-	/* Start at 903GiB. Size of 4 GiB for META and 32MB for MIPS*/
-#if defined(SUPPORT_PVRSRV_GPUVIRT) && defined(PVRSRV_GPUVIRT_GUESTDRV)
-	#define RGX_FIRMWARE_HEAP_BASE				(0xE1C0000000 + (PVRSRV_GPUVIRT_OSID * PVRSRV_GPUVIRT_FWHEAP_SIZE))
-#else
-	#define RGX_FIRMWARE_HEAP_BASE				IMG_UINT64_C(0xE1C0000000)
-#endif
+	#define RGX_USCCODE_BRN_52402_HEAP_BASE		IMG_UINT64_C(0x0300000000)
+	#define RGX_USCCODE_BRN_52402_HEAP_SIZE		IMG_UINT64_C(0x0100000000)
 
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	#define RGX_FIRMWARE_HEAP_SIZE				PVRSRV_GPUVIRT_FWHEAP_SIZE
-#else
-	/* Three SEGMMU available for the fw heap */
-	#define RGX_FIRMWARE_HEAP_SIZE              (3 * RGXFW_SEGMMU_DMAP_SIZE)
-#endif
+	/* Start at 896 GiB Size of 4 GiB */
+	#define RGX_USCCODE_HEAP_BASE				IMG_UINT64_C(0xE000000000)
+	#define RGX_USCCODE_HEAP_SIZE				IMG_UINT64_C(0x0100000000)
 
-#if defined(FIX_HW_BRN_52402) || defined(FIX_HW_BRN_55091)
+
+	/* Start at 903GiB. Size of 32MB per OSID (defined in rgxdefs_km.h)
+	   #define RGX_FIRMWARE_HEAP_BASE			IMG_UINT64_C(0xE1C0000000)
+	   #define RGX_FIRMWARE_HEAP_SIZE			(1<<RGX_FW_HEAP_SHIFT) 
+	   #define RGX_FIRMWARE_HEAP_SHIFT			RGX_FW_HEAP_SHIFT */
+
 	/* HWBRN52402 & HWBRN55091 workarounds requires TQ memory to be below 16GB and 16GB aligned. Start at 0GB. Size of 8GB. */
-    #define RGX_TQ3DPARAMETERS_HEAP_BASE		IMG_UINT64_C(0x0000000000)
-    #define RGX_TQ3DPARAMETERS_HEAP_SIZE		IMG_UINT64_C(0x0200000000)
-#else
+	#define RGX_TQ3DPARAMETERS_BRN_52402_55091_HEAP_BASE		IMG_UINT64_C(0x0000000000)
+	#define RGX_TQ3DPARAMETERS_BRN_52402_55091_HEAP_SIZE		IMG_UINT64_C(0x0200000000)
+
 	/* Start at 912GiB. Size of 16 GiB. 16GB aligned to match RGX_CR_ISP_PIXEL_BASE */
-    #define RGX_TQ3DPARAMETERS_HEAP_BASE		IMG_UINT64_C(0xE400000000)
-    #define RGX_TQ3DPARAMETERS_HEAP_SIZE		IMG_UINT64_C(0x0400000000)
-#endif
+	#define RGX_TQ3DPARAMETERS_HEAP_BASE		IMG_UINT64_C(0xE400000000)
+	#define RGX_TQ3DPARAMETERS_HEAP_SIZE		IMG_UINT64_C(0x0400000000)
 
 	/* Size of 16 * 4 KB (think about large page systems .. */
-#if defined(FIX_HW_BRN_37200)
-    #define RGX_HWBRN37200_HEAP_BASE				IMG_UINT64_C(0xFFFFF00000)
-    #define RGX_HWBRN37200_HEAP_SIZE				IMG_UINT64_C(0x0000100000)
-#endif
+  	#define RGX_HWBRN37200_HEAP_BASE				IMG_UINT64_C(0xFFFFF00000)
+   	#define RGX_HWBRN37200_HEAP_SIZE				IMG_UINT64_C(0x0000100000)
 
 	/* Start at 928GiB. Size of 4 GiB */
 	#define RGX_DOPPLER_HEAP_BASE				IMG_UINT64_C(0xE800000000)
@@ -144,65 +140,18 @@
 	/* Start at 932GiB. Size of 4 GiB */
 	#define RGX_DOPPLER_OVERFLOW_HEAP_BASE		IMG_UINT64_C(0xE900000000)
 	#define RGX_DOPPLER_OVERFLOW_HEAP_SIZE		IMG_UINT64_C(0x0100000000)
-	
-	/* signal we've identified the core by the build */
-	#define RGX_CORE_IDENTIFIED
-#endif /* RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS == 40 */
 
-#if !defined(RGX_CORE_IDENTIFIED)
-	#error "rgxheapconfig.h: ERROR: unspecified RGX Core version"
-#endif
+	/* Start at 936GiB. Two groups of 128 KBytes that must follow each other in this order. */
+	#define RGX_SERVICES_SIGNALS_HEAP_BASE		IMG_UINT64_C(0xEA00000000)
+	#define RGX_SERVICES_SIGNALS_HEAP_SIZE		IMG_UINT64_C(0x0000020000)
 
-/* /\********************************************************************************* */
-/*  * */
-/*  * Heap overlap check */
-/*  * */
-/*  ********************************************************************************\/ */
-/* #if defined(SUPPORT_RGX_GENERAL_MAPPING_HEAP) */
-/* 	#if ((RGX_GENERAL_MAPPING_HEAP_BASE + RGX_GENERAL_MAPPING_HEAP_SIZE) >= RGX_GENERAL_HEAP_BASE) */
-/* 		#error "rgxheapconfig.h: ERROR: RGX_GENERAL_MAPPING_HEAP overlaps RGX_GENERAL_HEAP" */
-/* 	#endif */
-/* #endif */
+	#define RGX_SIGNALS_HEAP_BASE				IMG_UINT64_C(0xEA00020000)
+	#define RGX_SIGNALS_HEAP_SIZE				IMG_UINT64_C(0x0000020000)
 
-/* #if ((RGX_GENERAL_HEAP_BASE + RGX_GENERAL_HEAP_SIZE) >= RGX_3DPARAMETERS_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_GENERAL_HEAP overlaps RGX_3DPARAMETERS_HEAP" */
-/* #endif */
+	/* TDM TPU YUV coeffs - can be reduced to a single page */
+	#define RGX_TDM_TPU_YUV_COEFFS_HEAP_BASE	IMG_UINT64_C(0xEA00080000)
+	#define RGX_TDM_TPU_YUV_COEFFS_HEAP_SIZE	IMG_UINT64_C(0x0000040000)
 
-/* #if ((RGX_3DPARAMETERS_HEAP_BASE + RGX_3DPARAMETERS_HEAP_SIZE) >= RGX_TADATA_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_3DPARAMETERS_HEAP overlaps RGX_TADATA_HEAP" */
-/* #endif */
-
-/* #if ((RGX_TADATA_HEAP_BASE + RGX_TADATA_HEAP_SIZE) >= RGX_SYNCINFO_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_TADATA_HEAP overlaps RGX_SYNCINFO_HEAP" */
-/* #endif */
-
-/* #if ((RGX_SYNCINFO_HEAP_BASE + RGX_SYNCINFO_HEAP_SIZE) >= RGX_PDSPIXEL_CODEDATA_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_SYNCINFO_HEAP overlaps RGX_PDSPIXEL_CODEDATA_HEAP" */
-/* #endif */
-
-/* #if ((RGX_PDSPIXEL_CODEDATA_HEAP_BASE + RGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= RGX_KERNEL_CODE_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_PDSPIXEL_CODEDATA_HEAP overlaps RGX_KERNEL_CODE_HEAP" */
-/* #endif */
-
-/* #if ((RGX_KERNEL_CODE_HEAP_BASE + RGX_KERNEL_CODE_HEAP_SIZE) >= RGX_PDSVERTEX_CODEDATA_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_KERNEL_CODE_HEAP overlaps RGX_PDSVERTEX_CODEDATA_HEAP" */
-/* #endif */
-
-/* #if ((RGX_PDSVERTEX_CODEDATA_HEAP_BASE + RGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= RGX_KERNEL_DATA_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_PDSVERTEX_CODEDATA_HEAP overlaps RGX_KERNEL_DATA_HEAP" */
-/* #endif */
-
-/* #if ((RGX_KERNEL_DATA_HEAP_BASE + RGX_KERNEL_DATA_HEAP_SIZE) >= RGX_PIXELSHADER_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_KERNEL_DATA_HEAP overlaps RGX_PIXELSHADER_HEAP" */
-/* #endif */
-
-/* #if ((RGX_PIXELSHADER_HEAP_BASE + RGX_PIXELSHADER_HEAP_SIZE) >= RGX_VERTEXSHADER_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_PIXELSHADER_HEAP overlaps RGX_VERTEXSHADER_HEAP" */
-/* #endif */
-
-/* #if ((RGX_VERTEXSHADER_HEAP_BASE + RGX_VERTEXSHADER_HEAP_SIZE) < RGX_VERTEXSHADER_HEAP_BASE) */
-/* 	#error "rgxheapconfig.h: ERROR: RGX_VERTEXSHADER_HEAP_BASE size cause wraparound" */
-/* #endif */
 
 #endif /* __RGXHEAPCONFIG_H__ */
 
diff --git a/drivers/staging/imgtec/rogue/rgxhwperf.c b/drivers/staging/imgtec/rogue/rgxhwperf.c
index bd8a1f6..74e95da 100644
--- a/drivers/staging/imgtec/rogue/rgxhwperf.c
+++ b/drivers/staging/imgtec/rogue/rgxhwperf.c
@@ -46,35 +46,44 @@
 
 #include "pvr_debug.h"
 #include "pvr_hwperf.h"
+#include "pvr_notifier.h"
 #include "osfunc.h"
 #include "allocmem.h"
 
+#include "pvrsrv.h"
+#include "pvrsrv_tlstreams.h"
+#include "pvrsrv_tlcommon.h"
 #include "tlclient.h"
 #include "tlstream.h"
-#include "lists.h"
 
 #include "rgx_hwperf_km.h"
 #include "rgxhwperf.h"
 #include "rgxapi_km.h"
 #include "rgxfwutils.h"
+#include "rgxtimecorr.h"
+#include "devicemem.h"
 #include "devicemem_pdump.h"
 #include "pdump_km.h"
+#include "pvrsrv_apphint.h"
 
 #if defined(SUPPORT_GPUTRACE_EVENTS)
 #include "pvr_gputrace.h"
 #endif
 
-#define HWPERF_TL_STREAM_NAME  "hwperf"
-#define HWPERF_HOST_TL_STREAM_NAME "hwperf_host"
-#define HWPERF_HOST_TL_STREAM_SIZE 0x10000 /* 64KB */
+/* This is defined by default to enable producer callbacks.
+ * Clients of the TL interface can disable the use of the callback
+ * with PVRSRV_STREAM_FLAG_DISABLE_PRODUCER_CALLBACK. */
+#define SUPPORT_TL_PRODUCER_CALLBACK 1
 
-/* Defined to ensure HWPerf packets are not delayed */
-#define SUPPORT_TL_PROODUCER_CALLBACK 1
+/* Defines size of buffers returned from acquire/release calls */
+#define FW_STREAM_BUFFER_SIZE (0x80000)
+#define HOST_STREAM_BUFFER_SIZE (0x20000)
 
-
-/******************************************************************************
- *
- *****************************************************************************/
+/* Must be at least as large as two tl packets of maximum size */
+static_assert(HOST_STREAM_BUFFER_SIZE >= (PVRSRVTL_MAX_PACKET_SIZE<<1),
+			  "HOST_STREAM_BUFFER_SIZE is less than (PVRSRVTL_MAX_PACKET_SIZE<<1)");
+static_assert(FW_STREAM_BUFFER_SIZE >= (PVRSRVTL_MAX_PACKET_SIZE<<1),
+			  "FW_STREAM_BUFFER_SIZE is less than (PVRSRVTL_MAX_PACKET_SIZE<<1)");
 
 
 /*
@@ -147,7 +156,7 @@
 							   &ui32L2BufFree);
 	if ( eError == PVRSRV_OK )
 	{
-		OSMemCopy( pbL2Buffer, pbFwBuffer, (size_t)ui32BytesExp );
+		OSDeviceMemCopy( pbL2Buffer, pbFwBuffer, (size_t)ui32BytesExp );
 		eError = TLStreamCommit(hHWPerfStream, (size_t)ui32BytesExp);
 		if ( eError != PVRSRV_OK )
 		{
@@ -181,7 +190,7 @@
 
 			if ( eError == PVRSRV_OK )
 			{
-				OSMemCopy( pbL2Buffer, pbFwBuffer, (size_t)sizeSum );
+				OSDeviceMemCopy( pbL2Buffer, pbFwBuffer, (size_t)sizeSum );
 				eError = TLStreamCommit(hHWPerfStream, (size_t)sizeSum);
 				if ( eError != PVRSRV_OK )
 				{
@@ -270,7 +279,6 @@
 			ui32BytesCopied = RGXHWPerfCopyDataL1toL2(psDevInfo->hHWPerfStream,
 													  psHwPerfInfo + ui32SrcRIdx,
 													  ui32BytesExp);
-			ui32BytesCopiedSum += ui32BytesCopied;
 
 			/* Advance the read index and the free bytes counter by the number
 			 * of bytes transported. Items will be left in buffer if not all data
@@ -278,6 +286,8 @@
 			psRGXFWIfTraceBufCtl->ui32HWPerfRIdx = RGXHWPerfAdvanceRIdx(
 					psDevInfo->ui32RGXFWIfHWPerfBufSize, ui32SrcRIdx,
 					ui32BytesCopied);
+
+			ui32BytesCopiedSum += ui32BytesCopied;
 		}
 		/* No, buffer has wrapped and write position is behind read position */
 		else
@@ -294,7 +304,6 @@
 			ui32BytesCopied = RGXHWPerfCopyDataL1toL2(psDevInfo->hHWPerfStream,
 													  psHwPerfInfo + ui32SrcRIdx,
 													  ui32BytesExp);
-			ui32BytesCopiedSum += ui32BytesCopied;
 
 			/* Advance read index as before and Update the local copy of the
 			 * read index as it might be used in the last if branch*/
@@ -308,7 +317,9 @@
 				psRGXFWIfTraceBufCtl->ui32HWPerfWrapCount = psDevInfo->ui32RGXFWIfHWPerfBufSize;
 			}
 			psRGXFWIfTraceBufCtl->ui32HWPerfRIdx = ui32SrcRIdx;
-			
+
+			ui32BytesCopiedSum += ui32BytesCopied;
+
 			/* If all the data in the end of the array was copied, try copying
 			 * wrapped data in the beginning of the array, assuming there is
 			 * any and the RIdx was wrapped. */
@@ -323,11 +334,12 @@
 				ui32BytesCopied = RGXHWPerfCopyDataL1toL2(psDevInfo->hHWPerfStream,
 														  psHwPerfInfo,
 														  ui32BytesExp);
-				ui32BytesCopiedSum += ui32BytesCopied;
 				/* Advance the FW buffer read position. */
 				psRGXFWIfTraceBufCtl->ui32HWPerfRIdx = RGXHWPerfAdvanceRIdx(
 						psDevInfo->ui32RGXFWIfHWPerfBufSize, ui32SrcRIdx,
 						ui32BytesCopied);
+
+				ui32BytesCopiedSum += ui32BytesCopied;
 			}
 		}
 #ifdef HWPERF_MISR_FUNC_DEBUG
@@ -359,12 +371,14 @@
 	PVR_ASSERT(psDevInfo);
 	psRgxDevInfo = psDevInfo->pvDevice;
 
+	/* Keep HWPerf resource init check and use of
+	 * resources atomic, they may not be freed during use 
+	 */
+	OSLockAcquire(psRgxDevInfo->hHWPerfLock);
+	
 	if (psRgxDevInfo->hHWPerfStream != 0)
 	{
-		OSLockAcquire(psRgxDevInfo->hLockHWPerfModule);
 		ui32BytesCopied = RGXHWPerfDataStore(psRgxDevInfo);
-		OSLockRelease(psRgxDevInfo->hLockHWPerfModule);
-
 		if ( ui32BytesCopied )
 		{	/* Signal consumers that packets may be available to read when
 			 * running from a HW kick, not when called by client APP thread
@@ -375,17 +389,19 @@
 		}
 		else
 		{
-			PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfDataStoreCB: Zero bytes copied (IRQ: FW count %d)",
-					psRgxDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount));
+			PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfDataStoreCB: Zero bytes copied"));
+			RGXDEBUG_PRINT_IRQ_COUNT(psRgxDevInfo);
 		}
 	}
 
+	OSLockRelease(psRgxDevInfo->hHWPerfLock);
+
 	PVR_DPF_RETURN_OK;
 }
 
 
-/* Not currently supported by default */
-#if defined(SUPPORT_TL_PROODUCER_CALLBACK)
+/* Currently supported by default */
+#if defined(SUPPORT_TL_PRODUCER_CALLBACK)
 static PVRSRV_ERROR RGXHWPerfTLCB(IMG_HANDLE hStream,
 		IMG_UINT32 ui32ReqOp, IMG_UINT32* ui32Resp, void* pvUser)
 {
@@ -400,12 +416,15 @@
 	switch (ui32ReqOp)
 	{
 	case TL_SOURCECB_OP_CLIENT_EOS:
+		/* Keep HWPerf resource init check and use of
+		 * resources atomic, they may not be freed during use 
+		 */
+		OSLockAcquire(psRgxDevInfo->hHWPerfLock);
 		if (psRgxDevInfo->hHWPerfStream != 0)
 		{
-			OSLockAcquire(psRgxDevInfo->hLockHWPerfModule);
 			(void) RGXHWPerfDataStore(psRgxDevInfo);
-			OSLockRelease(psRgxDevInfo->hLockHWPerfModule);
 		}
+		OSLockRelease(psRgxDevInfo->hHWPerfLock);
 		break;
 
 	default:
@@ -432,7 +451,7 @@
 			DevmemReleaseCpuVirtAddr(gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc);
 			gpsRgxDevInfo->psRGXFWIfHWPerfBuf = NULL;
 		}
-		DevmemFwFree(gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc);
+		DevmemFwFree(gpsRgxDevInfo, gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc);
 		gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc = NULL;
 	}
 }
@@ -466,11 +485,11 @@
 	/* Create a lock for HWPerf server module used for serializing, L1 to L2
 	 * copy calls (e.g. in case of TL producer callback) and L1, L2 resource
 	 * allocation */
-	eError = OSLockCreate(&gpsRgxDevInfo->hLockHWPerfModule, LOCK_TYPE_PASSIVE);
+	eError = OSLockCreate(&gpsRgxDevInfo->hHWPerfLock, LOCK_TYPE_PASSIVE);
 	PVR_LOGR_IF_ERROR(eError, "OSLockCreate");
 
 	/* avoid uninitialised data */
-	gpsRgxDevInfo->hHWPerfStream = NULL;
+	gpsRgxDevInfo->hHWPerfStream = 0;
 	gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc = NULL;
 
 	PVR_DPF_RETURN_OK;
@@ -480,18 +499,21 @@
 @Function       RGXHWPerfIsInitRequired
 
 @Description    Returns true if the HWperf firmware buffer (L1 buffer) and host
-		driver TL buffer (L2 buffer) are not already allocated. Caller
-		should possess hLockHWPerfModule lock  before calling this
-		function.
+                driver TL buffer (L2 buffer) are not already allocated. Caller
+                must possess hHWPerfLock lock  before calling this
+                function so the state tested is not inconsistent.
 
-@Return		IMG_BOOL	Whether initialization (allocation) is required
+@Return         IMG_BOOL	Whether initialization (allocation) is required
 */ /**************************************************************************/
 static INLINE IMG_BOOL RGXHWPerfIsInitRequired(void)
 {
+	PVR_ASSERT(OSLockIsLocked(gpsRgxDevInfo->hHWPerfLock));
+
 #if !defined (NO_HARDWARE)
 	/* Both L1 and L2 buffers are required (for HWPerf functioning) on driver
-	 * built for actual hardware (TC, EMU, etc.) */
-	if (gpsRgxDevInfo->hHWPerfStream == NULL)
+	 * built for actual hardware (TC, EMU, etc.)
+	 */
+	if (gpsRgxDevInfo->hHWPerfStream == 0)
 	{
 		/* The allocation API (RGXHWPerfInitOnDemandResources) allocates
 		 * device memory for both L1 and L2 without any checks. Hence,
@@ -520,11 +542,14 @@
 @Function       RGXHWPerfInitOnDemandResources
 
 @Description    This function allocates the HWperf firmware buffer (L1 buffer)
-		and host driver TL buffer (L2 buffer) if HWPerf is enabled at
-		driver load time. Otherwise, these buffers are allocated
-		on-demand as and when required.
+                and host driver TL buffer (L2 buffer) if HWPerf is enabled at
+                driver load time. Otherwise, these buffers are allocated
+                on-demand as and when required. Caller
+                must possess hHWPerfLock lock  before calling this
+                function so the state tested is not inconsistent if called
+                outside of driver initialisation.
 
-@Return		PVRSRV_ERROR
+@Return         PVRSRV_ERROR
 */ /**************************************************************************/
 PVRSRV_ERROR RGXHWPerfInitOnDemandResources(void)
 {
@@ -546,7 +571,6 @@
 				#endif
 				;
 
-	PMRLock();
 	/* Allocate HWPerf FW L1 buffer */
 	eError = DevmemFwAllocate(gpsRgxDevInfo,
 							  gpsRgxDevInfo->ui32RGXFWIfHWPerfBufSize+RGXFW_HWPERF_L1_PADDING_DEFAULT,
@@ -562,11 +586,11 @@
 
 	/* Expecting the RuntimeCfg structure is mapped into CPU virtual memory.
 	 * Also, make sure the FW address is not already set */
-	PVR_ASSERT(gpsRgxDevInfo->psRGXFWIfRuntimeCfg && gpsRgxDevInfo->psRGXFWIfRuntimeCfg->pui8HWPerfBuf.ui32Addr == 0x0);
+	PVR_ASSERT(gpsRgxDevInfo->psRGXFWIfRuntimeCfg && gpsRgxDevInfo->psRGXFWIfRuntimeCfg->sHWPerfBuf.ui32Addr == 0x0);
 
 	/* Meta cached flag removed from this allocation as it was found
 	 * FW performance was better without it. */
-	RGXSetFirmwareAddress(&gpsRgxDevInfo->psRGXFWIfRuntimeCfg->pui8HWPerfBuf,
+	RGXSetFirmwareAddress(&gpsRgxDevInfo->psRGXFWIfRuntimeCfg->sHWPerfBuf,
 						  gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc,
 						  0, RFW_FWADDR_NOREF_FLAG);
 
@@ -578,13 +602,6 @@
 					 __FUNCTION__, eError));
 		goto e0;
 	}
-	
-	/* PDump the memory allocated */
-	PDUMPCOMMENT("Dump rgxfw HW Perf Info structure");
-	DevmemPDumpLoadMem (gpsRgxDevInfo->psRGXFWIfHWPerfBufMemDesc,
-						0,
-						gpsRgxDevInfo->ui32RGXFWIfHWPerfBufSize,
-						PDUMP_FLAGS_CONTINUOUS);
 
 	/* On NO-HW driver, there is no MISR installed to copy data from L1 to L2. Hence,
 	 * L2 buffer is not allocated */
@@ -599,10 +616,11 @@
 	 */
 	ui32L2BufferSize = gpsRgxDevInfo->ui32RGXFWIfHWPerfBufSize + 
 	                       (gpsRgxDevInfo->ui32RGXFWIfHWPerfBufSize>>1);
-	eError = TLStreamCreate(&gpsRgxDevInfo->hHWPerfStream, HWPERF_TL_STREAM_NAME,
-					ui32L2BufferSize+RGXFW_HWPERF_L1_PADDING_DEFAULT,
-					TL_FLAG_RESERVE_DROP_NEWER | TL_FLAG_NO_SIGNAL_ON_COMMIT, NULL, NULL,
-#if !defined(SUPPORT_TL_PROODUCER_CALLBACK)
+	eError = TLStreamCreate(&gpsRgxDevInfo->hHWPerfStream, PVRSRV_TL_HWPERF_RGX_FW_STREAM,
+					ui32L2BufferSize, 
+					TL_FLAG_RESERVE_DROP_NEWER | TL_FLAG_NO_SIGNAL_ON_COMMIT, 
+					NULL, NULL,
+#if !defined(SUPPORT_TL_PRODUCER_CALLBACK)
 					NULL, NULL
 #else
 					/* Not enabled  by default */
@@ -616,8 +634,6 @@
 ui32L2BufferSize = 0;
 #endif 
 
-	PMRUnlock();
-
 	PVR_DPF((PVR_DBG_MESSAGE, "HWPerf buffer size in bytes: L1: %d  L2: %d",
 			gpsRgxDevInfo->ui32RGXFWIfHWPerfBufSize, ui32L2BufferSize));
 
@@ -630,7 +646,6 @@
 e0: /* L1 buffer initialisation failures */
 	RGXHWPerfL1BufferDeinit();
 	
-	PMRUnlock();
 	PVR_DPF_RETURN_RC(eError);
 }
 
@@ -650,16 +665,12 @@
 	RGXHWPerfL1BufferDeinit();
 
 	/* Cleanup the HWPerf server module lock resource */
-	if (gpsRgxDevInfo && gpsRgxDevInfo->hLockHWPerfModule)
+	if (gpsRgxDevInfo && gpsRgxDevInfo->hHWPerfLock)
 	{
-		OSLockDestroy(gpsRgxDevInfo->hLockHWPerfModule);
-		gpsRgxDevInfo->hLockHWPerfModule = NULL;
+		OSLockDestroy(gpsRgxDevInfo->hHWPerfLock);
+		gpsRgxDevInfo->hHWPerfLock = NULL;
 	}
 
-	/* Clear global RGX device reference */
-	gpsRgxDevInfo = NULL;
-	gpsRgxDevNode = NULL;
-
 	PVR_DPF_RETURN;
 }
 
@@ -668,7 +679,7 @@
  * RGX HW Performance Profiling Server API(s)
  *****************************************************************************/
 
-static PVRSRV_ERROR RGXHWPerfCtrlFwBuffer(PVRSRV_DEVICE_NODE *psDeviceNode,
+static PVRSRV_ERROR RGXHWPerfCtrlFwBuffer(const PVRSRV_DEVICE_NODE *psDeviceNode,
                                           IMG_BOOL bToggle,
                                           IMG_UINT64 ui64Mask)
 {
@@ -676,7 +687,13 @@
 	PVRSRV_RGXDEV_INFO* psDevice = psDeviceNode->pvDevice;
 	RGXFWIF_KCCB_CMD sKccbCmd;
 
-	OSLockAcquire(psDevice->hLockHWPerfModule);
+	/* If this method is being used whether to enable or disable
+	 * then the hwperf buffers (host and FW) are likely to be needed
+	 * eventually so create them, also helps unit testing. Buffers
+	 * allocated on demand to reduce RAM foot print on systems not
+	 * needing HWPerf resources.
+	 * Obtain lock first, test and init if required. */
+	OSLockAcquire(psDevice->hHWPerfLock);
 
 	if (!psDevice->bFirmwareInitialised)
 	{
@@ -689,11 +706,6 @@
 		goto unlock_and_return;
 	}
 
-	/* If this method is being used whether to enable or disable
-	 * then the hwperf buffers (host and FW) are likely to be needed
-	 * eventually so create them, also helps unit testing. Buffers
-	 * allocated on demand to reduce RAM foot print on systems not
-	 * needing HWPerf resources. */
 	if (RGXHWPerfIsInitRequired())
 	{
 		eError = RGXHWPerfInitOnDemandResources();
@@ -705,9 +717,13 @@
 		}
 	}
 
+	/* Unlock here as no further HWPerf resources are used below that would be
+	 * affected if freed by another thread */
+	OSLockRelease(psDevice->hHWPerfLock);
+
 	/* Return if the filter is the same */
 	if (!bToggle && gpsRgxDevInfo->ui64HWPerfFilter == ui64Mask)
-		goto unlock_and_return;
+		goto return_;
 
 	/* Prepare command parameters ... */
 	sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_UPDATE_CONFIG;
@@ -716,33 +732,31 @@
 
 	/* Ask the FW to carry out the HWPerf configuration command */
 	eError = RGXScheduleCommand(psDeviceNode->pvDevice,	RGXFWIF_DM_GP, 
-								&sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+								&sKccbCmd, sizeof(sKccbCmd), 0, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set new HWPerfGpu filter in "
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set new HWPerfFW filter in "
 				"firmware (error = %d)", __func__, eError));
-		goto unlock_and_return;
+		goto return_;
 	}
 
 	gpsRgxDevInfo->ui64HWPerfFilter = bToggle ?
 	        gpsRgxDevInfo->ui64HWPerfFilter ^ ui64Mask : ui64Mask;
 
-	OSLockRelease(psDevice->hLockHWPerfModule);
-
 	/* Wait for FW to complete */
 	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP,
-	                        psDeviceNode->psSyncPrim, IMG_TRUE);
+	                        psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", return_);
 
 #if defined(DEBUG)
 	if (bToggle)
 	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfGpu events (%llx) have been TOGGLED",
+		PVR_DPF((PVR_DBG_WARNING, "HWPerfFW events (%llx) have been TOGGLED",
 		        ui64Mask));
 	}
 	else
 	{
-		PVR_DPF((PVR_DBG_WARNING, "HWPerfGpu mask has been SET to (%llx)",
+		PVR_DPF((PVR_DBG_WARNING, "HWPerfFW mask has been SET to (%llx)",
 		        ui64Mask));
 	}
 #endif
@@ -750,13 +764,13 @@
 	return PVRSRV_OK;
 
 unlock_and_return:
-	OSLockRelease(psDevice->hLockHWPerfModule);
+	OSLockRelease(psDevice->hHWPerfLock);
 
 return_:
 	return eError;
 }
 
-static PVRSRV_ERROR RGXHWPerfCtrlHostBuffer(PVRSRV_DEVICE_NODE *psDeviceNode,
+static PVRSRV_ERROR RGXHWPerfCtrlHostBuffer(const PVRSRV_DEVICE_NODE *psDeviceNode,
                                             IMG_BOOL bToggle,
                                             IMG_UINT32 ui32Mask)
 {
@@ -828,6 +842,78 @@
 	PVR_DPF_RETURN_OK;
 }
 
+/*
+	AppHint interfaces
+*/
+static
+PVRSRV_ERROR RGXHWPerfSetFwFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  const void *psPrivate,
+                                  IMG_UINT64 ui64Value)
+{
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+	return RGXHWPerfCtrlFwBuffer(psDeviceNode, IMG_FALSE, ui64Value);
+}
+
+static
+PVRSRV_ERROR RGXHWPerfReadFwFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const void *psPrivate,
+                                   IMG_UINT64 *pui64Value)
+{
+	PVRSRV_RGXDEV_INFO *psDevice;
+
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	if (!psDeviceNode || !psDeviceNode->pvDevice)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevice = psDeviceNode->pvDevice;
+	*pui64Value = psDevice->ui64HWPerfFilter;
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR RGXHWPerfSetHostFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    const void *psPrivate,
+                                    IMG_UINT32 ui32Value)
+{
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+	return RGXHWPerfCtrlHostBuffer(psDeviceNode, IMG_FALSE, ui32Value);
+}
+
+static
+PVRSRV_ERROR RGXHWPerfReadHostFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     const void *psPrivate,
+                                     IMG_UINT32 *pui32Value)
+{
+	PVRSRV_RGXDEV_INFO *psDevice;
+
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	if (!psDeviceNode || !psDeviceNode->pvDevice)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevice = psDeviceNode->pvDevice;
+	*pui32Value = psDevice->ui32HWPerfHostFilter;
+	return PVRSRV_OK;
+}
+
+void RGXHWPerfInitAppHintCallbacks(const PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRVAppHintRegisterHandlersUINT64(APPHINT_ID_HWPerfFWFilter,
+	                                    RGXHWPerfReadFwFilter,
+	                                    RGXHWPerfSetFwFilter,
+	                                    psDeviceNode,
+	                                    NULL);
+	PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_HWPerfHostFilter,
+	                                    RGXHWPerfReadHostFilter,
+	                                    RGXHWPerfSetHostFilter,
+	                                    psDeviceNode,
+	                                    NULL);
+}
 
 /*
 	PVRSRVRGXEnableHWPerfCountersKM
@@ -870,7 +956,7 @@
 	if (eError != PVRSRV_OK)
 		PVR_LOGR_IF_ERROR(eError, "DevmemFwAllocate");
 
-	RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.pasBlockConfigs,
+	RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.sBlockConfigs,
 			psFwBlkConfigsMemDesc, 0, 0);
 
 	eError = DevmemAcquireCpuVirtAddr(psFwBlkConfigsMemDesc, (void **)&psFwArray);
@@ -879,7 +965,7 @@
 		PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail1);
 	}
 
-	OSMemCopy(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen);
+	OSDeviceMemCopy(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen);
 	DevmemPDumpLoadMem(psFwBlkConfigsMemDesc,
 						0,
 						sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
@@ -890,7 +976,7 @@
 	/* Ask the FW to carry out the HWPerf configuration command
 	 */
 	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
-			RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+			RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), 0, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_LOGG_IF_ERROR(eError, "RGXScheduleCommand", fail2);
@@ -899,7 +985,7 @@
 	/* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM command scheduled for FW")); */
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", fail2);
@@ -909,7 +995,7 @@
 	 */
 	RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
 	DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
-	DevmemFwFree(psFwBlkConfigsMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, psFwBlkConfigsMemDesc);
 
 	/* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM firmware completed")); */
 
@@ -921,7 +1007,7 @@
 	DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
 fail1:
 	RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
-	DevmemFwFree(psFwBlkConfigsMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, psFwBlkConfigsMemDesc);
 
 	PVR_DPF_RETURN_RC(eError);
 }
@@ -973,7 +1059,7 @@
 		if (eError != PVRSRV_OK)
 			PVR_LOGR_IF_ERROR(eError, "DevmemFwAllocate");
 
-		RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfSelectCstmCntrs.pui32CustomCounterIDs,
+		RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfSelectCstmCntrs.sCustomCounterIDs,
 				psFwSelectCntrsMemDesc, 0, 0);
 
 		eError = DevmemAcquireCpuVirtAddr(psFwSelectCntrsMemDesc, (void **)&psFwArray);
@@ -982,7 +1068,7 @@
 			PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail1);
 		}
 
-		OSMemCopy(psFwArray, pui32CustomCounterIDs, sizeof(IMG_UINT32) * ui16NumCustomCounters);
+		OSDeviceMemCopy(psFwArray, pui32CustomCounterIDs, sizeof(IMG_UINT32) * ui16NumCustomCounters);
 		DevmemPDumpLoadMem(psFwSelectCntrsMemDesc,
 				0,
 				sizeof(IMG_UINT32) * ui16NumCustomCounters,
@@ -991,7 +1077,7 @@
 
 	/* Push in the KCCB the command to configure the custom counters block */
 	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
-			RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+			RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), 0, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_LOGG_IF_ERROR(eError, "RGXScheduleCommand", fail2);
@@ -999,7 +1085,7 @@
 	PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXSelectCustomCountersKM: Command scheduled"));
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", fail2);
@@ -1011,7 +1097,7 @@
 		/* Release temporary memory used for block configuration */
 		RGXUnsetFirmwareAddress(psFwSelectCntrsMemDesc);
 		DevmemReleaseCpuVirtAddr(psFwSelectCntrsMemDesc);
-		DevmemFwFree(psFwSelectCntrsMemDesc);
+		DevmemFwFree(psDeviceNode->pvDevice, psFwSelectCntrsMemDesc);
 	}
 
 	PVR_DPF((PVR_DBG_MESSAGE, "HWPerf custom counters %u reading will be sent with the next HW events", ui16NumCustomCounters));
@@ -1025,7 +1111,7 @@
 	if (psFwSelectCntrsMemDesc) 
 	{
 		RGXUnsetFirmwareAddress(psFwSelectCntrsMemDesc);
-		DevmemFwFree(psFwSelectCntrsMemDesc);
+		DevmemFwFree(psDeviceNode->pvDevice, psFwSelectCntrsMemDesc);
 	}
 	
 	PVR_DPF_RETURN_RC(eError);
@@ -1057,21 +1143,21 @@
 	sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CTRL_BLKS;
 	sKccbCmd.uCmdData.sHWPerfCtrlBlks.bEnable = bEnable;
 	sKccbCmd.uCmdData.sHWPerfCtrlBlks.ui32NumBlocks = ui32ArrayLen;
-	OSMemCopy(sKccbCmd.uCmdData.sHWPerfCtrlBlks.aeBlockIDs, psBlockIDs, sizeof(IMG_UINT16)*ui32ArrayLen);
+	OSDeviceMemCopy(sKccbCmd.uCmdData.sHWPerfCtrlBlks.aeBlockIDs, psBlockIDs, sizeof(IMG_UINT16)*ui32ArrayLen);
 
 	/* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfCountersKM parameters set, calling FW")); */
 
 	/* Ask the FW to carry out the HWPerf configuration command
 	 */
 	eError = RGXScheduleCommand(psDeviceNode->pvDevice,
-			RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+			RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), 0, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 		PVR_LOGR_IF_ERROR(eError, "RGXScheduleCommand");
 
 	/* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfCountersKM command scheduled for FW")); */
 
 	/* Wait for FW to complete */
-	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+	eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 		PVR_LOGR_IF_ERROR(eError, "RGXWaitForFWOp");
 
@@ -1087,6 +1173,36 @@
 	PVR_DPF_RETURN_OK;
 }
 
+static INLINE IMG_UINT32 _RGXHWPerfFixBufferSize(IMG_UINT32 ui32BufSizeKB)
+{
+	if (ui32BufSizeKB > HWPERF_HOST_TL_STREAM_SIZE_MAX)
+	{
+		/* Size specified as a AppHint but it is too big */
+		PVR_DPF((PVR_DBG_WARNING,"RGXHWPerfHostInit: HWPerf Host buffer size "
+				"value (%u) too big, using maximum (%u)", ui32BufSizeKB,
+		        HWPERF_HOST_TL_STREAM_SIZE_MAX));
+		return HWPERF_HOST_TL_STREAM_SIZE_MAX<<10;
+	}
+	else if (ui32BufSizeKB >= HWPERF_HOST_TL_STREAM_SIZE_MIN)
+	{
+		return ui32BufSizeKB<<10;
+	}
+	else if (ui32BufSizeKB > 0)
+	{
+		/* Size specified as a AppHint but it is too small */
+		PVR_DPF((PVR_DBG_WARNING,"RGXHWPerfHostInit: HWPerf Host buffer size "
+		        "value (%u) too small, using minimum (%u)", ui32BufSizeKB,
+		        HWPERF_HOST_TL_STREAM_SIZE_MIN));
+		return HWPERF_HOST_TL_STREAM_SIZE_MIN<<10;
+	}
+	else
+	{
+		/* 0 size implies AppHint not set or is set to zero,
+		 * use default size from driver constant. */
+		return HWPERF_HOST_TL_STREAM_SIZE_DEFAULT<<10;
+	}
+}
+
 /******************************************************************************
  * RGX HW Performance Host Stream API
  *****************************************************************************/
@@ -1101,18 +1217,18 @@
 
 @Return         PVRSRV_ERROR
 */ /**************************************************************************/
-PVRSRV_ERROR RGXHWPerfHostInit(void)
+PVRSRV_ERROR RGXHWPerfHostInit(IMG_UINT32 ui32BufSizeKB)
 {
 	PVRSRV_ERROR eError;
 	PVR_ASSERT(gpsRgxDevInfo != NULL);
-	
+
 	eError = OSLockCreate(&gpsRgxDevInfo->hLockHWPerfHostStream, LOCK_TYPE_PASSIVE);
 	PVR_LOGG_IF_ERROR(eError, "OSLockCreate", error);
 
 	gpsRgxDevInfo->hHWPerfHostStream = NULL;
-	gpsRgxDevInfo->bHWPerfHostEnabled = IMG_FALSE;
 	gpsRgxDevInfo->ui32HWPerfHostFilter = 0; /* disable all events */
 	gpsRgxDevInfo->ui32HWPerfHostNextOrdinal = 0;
+	gpsRgxDevInfo->ui32HWPerfHostBufSize = _RGXHWPerfFixBufferSize(ui32BufSizeKB);
 
 error:
 	return eError;
@@ -1139,12 +1255,13 @@
 	PVRSRV_ERROR eError;
 
 	eError = TLStreamCreate(&gpsRgxDevInfo->hHWPerfHostStream,
-	        HWPERF_HOST_TL_STREAM_NAME, HWPERF_HOST_TL_STREAM_SIZE,
+	        PVRSRV_TL_HWPERF_HOST_SERVER_STREAM, gpsRgxDevInfo->ui32HWPerfHostBufSize,
 	        TL_FLAG_RESERVE_DROP_NEWER, _HWPerfHostOnConnectCB, NULL, NULL,
 	        NULL);
 	PVR_LOGG_IF_ERROR(eError, "TLStreamCreate", error_stream_create);
-
-	gpsRgxDevInfo->bHWPerfHostEnabled = IMG_TRUE;
+	
+	PVR_DPF((DBGPRIV_MESSAGE, "HWPerf Host buffer size is %uKB",
+	        gpsRgxDevInfo->ui32HWPerfHostBufSize));
 
 	return PVRSRV_OK;
 
@@ -1169,10 +1286,9 @@
 		gpsRgxDevInfo->hLockHWPerfHostStream = NULL;
 	}
 
-	if (gpsRgxDevInfo)
-	{
-		gpsRgxDevInfo->bHWPerfHostEnabled = IMG_FALSE;
-	}
+	/* Clear global RGX device reference */
+	gpsRgxDevInfo = NULL;
+	gpsRgxDevNode = NULL;
 }
 
 void RGXHWPerfHostSetEventFilter(IMG_UINT32 ui32Filter)
@@ -1212,7 +1328,7 @@
 	{
 		PVR_DPF((PVR_DBG_MESSAGE, "%s: Could not reserve space in %s buffer"
 		        " (%d). Dropping packet.",
-		        __func__, HWPERF_HOST_TL_STREAM_NAME, eError));
+		        __func__, PVRSRV_TL_HWPERF_HOST_SERVER_STREAM, eError));
 		return NULL;
 	}
 	PVR_ASSERT(pui8Dest != NULL);
@@ -1227,7 +1343,7 @@
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_MESSAGE, "%s: Could not commit data to %s"
-	            " (%d)", __func__, HWPERF_HOST_TL_STREAM_NAME, eError));
+	            " (%d)", __func__, PVRSRV_TL_HWPERF_HOST_SERVER_STREAM, eError));
 	}
 }
 
@@ -1236,18 +1352,76 @@
                                           IMG_UINT32 ui32Size)
 {
 	RGX_HWPERF_V2_PACKET_HDR *psHeader = (RGX_HWPERF_V2_PACKET_HDR *) pui8Dest;
+
+	PVR_ASSERT(ui32Size<=RGX_HWPERF_MAX_PACKET_SIZE);
+
 	psHeader->ui32Ordinal = gpsRgxDevInfo->ui32HWPerfHostNextOrdinal;
-	psHeader->ui64Timestamp = OSClockus64();
+	psHeader->ui64Timestamp = RGXGPUFreqCalibrateClockus64();
 	psHeader->ui32Sig = HWPERF_PACKET_V2B_SIG;
 	psHeader->eTypeId = RGX_HWPERF_MAKE_TYPEID(RGX_HWPERF_STREAM_ID1_HOST,
-	        eEvType, 0);
+	        eEvType, 0, 0);
 	psHeader->ui32Size = ui32Size;
 }
 
+static inline IMG_UINT32 _CalculateHostCtrlPacketSize(
+                                            RGX_HWPERF_HOST_CTRL_TYPE eCtrlType)
+{
+	RGX_HWPERF_HOST_CTRL_DATA *psData;
+	IMG_UINT32 ui32Size = sizeof(psData->eEvType);
+
+	switch (eCtrlType)
+	{
+		case RGX_HWPERF_CTRL_TYPE_CLIENT_STREAM_OPEN:
+		case RGX_HWPERF_CTRL_TYPE_CLIENT_STREAM_CLOSE:
+			ui32Size += sizeof(psData->uData.ui32Pid);
+			break;
+		default:
+			// unknown type - this should never happen
+			PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfHostPostCtrlEvent: Invalid alloc"
+			        " event type"));
+			PVR_ASSERT(IMG_FALSE);
+			break;
+	}
+
+	return RGX_HWPERF_MAKE_SIZE_VARIABLE(ui32Size);
+}
+
+static inline void _SetupHostCtrlPacketData(IMG_UINT8 *pui8Dest,
+                                            RGX_HWPERF_HOST_CTRL_TYPE eEvType,
+											IMG_UINT32 ui32Pid)
+{
+	RGX_HWPERF_HOST_CTRL_DATA *psData = (RGX_HWPERF_HOST_CTRL_DATA *)
+	        (pui8Dest + sizeof(RGX_HWPERF_V2_PACKET_HDR));
+	psData->eEvType = eEvType;
+	psData->uData.ui32Pid = ui32Pid;
+}
+
+void RGXHWPerfHostPostCtrlEvent(RGX_HWPERF_HOST_CTRL_TYPE eEvType,
+                                IMG_UINT32 ui32Pid)
+{
+	IMG_UINT8 *pui8Dest;
+	IMG_UINT32 ui32Size = _CalculateHostCtrlPacketSize(eEvType);
+
+	_PostFunctionPrologue();
+
+	if ((pui8Dest = _ReserveHWPerfStream(ui32Size)) == NULL)
+	{
+		goto cleanup;
+	}
+
+	_SetupHostPacketHeader(pui8Dest, RGX_HWPERF_HOST_CTRL, ui32Size);
+	_SetupHostCtrlPacketData(pui8Dest, eEvType, ui32Pid);
+
+	_CommitHWPerfStream(ui32Size);
+
+cleanup:
+	_PostFunctionEpilogue();
+}
+
 static inline void _SetupHostEnqPacketData(IMG_UINT8 *pui8Dest,
                                            RGX_HWPERF_KICK_TYPE eEnqType,
                                            IMG_UINT32 ui32Pid,
-                                           IMG_UINT32 ui32FWCtx,
+                                           IMG_UINT32 ui32FWDMContext,
                                            IMG_UINT32 ui32ExtJobRef,
                                            IMG_UINT32 ui32IntJobRef)
 {
@@ -1255,14 +1429,15 @@
 	        (pui8Dest + sizeof(RGX_HWPERF_V2_PACKET_HDR));
 	psData->ui32EnqType = eEnqType;
 	psData->ui32PID = ui32Pid;
-	psData->ui32FWCtx = ui32FWCtx;
 	psData->ui32ExtJobRef = ui32ExtJobRef;
 	psData->ui32IntJobRef = ui32IntJobRef;
+	psData->ui32DMContext = ui32FWDMContext;
+	psData->ui32Padding = 0;       /* Set to zero for future compatibility */
 }
 
 void RGXHWPerfHostPostEnqEvent(RGX_HWPERF_KICK_TYPE eEnqType,
                                IMG_UINT32 ui32Pid,
-                               IMG_UINT32 ui32FWCtx,
+                               IMG_UINT32 ui32FWDMContext,
                                IMG_UINT32 ui32ExtJobRef,
                                IMG_UINT32 ui32IntJobRef)
 {
@@ -1277,7 +1452,7 @@
 	}
 
 	_SetupHostPacketHeader(pui8Dest, RGX_HWPERF_HOST_ENQ, ui32Size);
-	_SetupHostEnqPacketData(pui8Dest, eEnqType, ui32Pid, ui32FWCtx,
+	_SetupHostEnqPacketData(pui8Dest, eEnqType, ui32Pid, ui32FWDMContext,
 	        ui32ExtJobRef, ui32IntJobRef);
 
 	_CommitHWPerfStream(ui32Size);
@@ -1289,27 +1464,22 @@
 static inline IMG_UINT32 _CalculateHostUfoPacketSize(RGX_HWPERF_UFO_EV eUfoType,
                                                      IMG_UINT uiNoOfUFOs)
 {
-	IMG_UINT32 ui32Size = 0;
+	IMG_UINT32 ui32Size =
+		(IMG_UINT32) offsetof(RGX_HWPERF_UFO_DATA, aui32StreamData);
 	RGX_HWPERF_UFO_DATA_ELEMENT *puData;
 
 	switch (eUfoType)
 	{
 		case RGX_HWPERF_UFO_EV_CHECK_SUCCESS:
 		case RGX_HWPERF_UFO_EV_PRCHECK_SUCCESS:
-			ui32Size = sizeof(RGX_HWPERF_HOST_UFO_DATA)
-			        + (uiNoOfUFOs ? uiNoOfUFOs - 1 : 0)
-			        * sizeof(puData->sCheckSuccess);
+			ui32Size += uiNoOfUFOs * sizeof(puData->sCheckSuccess);
 			break;
 		case RGX_HWPERF_UFO_EV_CHECK_FAIL:
 		case RGX_HWPERF_UFO_EV_PRCHECK_FAIL:
-			ui32Size = sizeof(RGX_HWPERF_HOST_UFO_DATA)
-			        + (uiNoOfUFOs ? uiNoOfUFOs - 1 : 0)
-			        * sizeof(puData->sCheckFail);
+			ui32Size += uiNoOfUFOs * sizeof(puData->sCheckFail);
 			break;
 		case RGX_HWPERF_UFO_EV_UPDATE:
-			ui32Size = sizeof(RGX_HWPERF_HOST_UFO_DATA)
-			        + (uiNoOfUFOs ? uiNoOfUFOs - 1 : 0)
-			        * sizeof(puData->sUpdate);
+			ui32Size += uiNoOfUFOs * sizeof(puData->sUpdate);
 			break;
 		default:
 			// unknown type - this should never happen
@@ -1413,6 +1583,135 @@
 	_PostFunctionEpilogue();
 }
 
+#define UNKNOWN_SYNC_NAME "UnknownSync"
+
+static inline IMG_UINT32 _FixNameAndCalculateHostAllocPacketSize(
+                                       RGX_HWPERF_HOST_RESOURCE_TYPE eAllocType,
+                                       const IMG_CHAR **ppsName,
+                                       IMG_UINT32 *ui32NameSize)
+{
+	RGX_HWPERF_HOST_ALLOC_DATA *psData;
+	RGX_HWPERF_HOST_ALLOC_DETAIL *puData;
+	IMG_UINT32 ui32Size = sizeof(psData->ui32AllocType);
+
+	if (*ppsName != NULL && *ui32NameSize > 0)
+	{
+		/* first strip the terminator */
+		if ((*ppsName)[*ui32NameSize - 1] == '\0')
+			*ui32NameSize -= 1;
+		/* if string longer than maximum cut it (leave space for '\0') */
+		if (*ui32NameSize >= SYNC_MAX_CLASS_NAME_LEN)
+			*ui32NameSize = SYNC_MAX_CLASS_NAME_LEN - 1;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_WARNING, "RGXHWPerfHostPostAllocEvent: Invalid"
+		        " resource name given."));
+		*ppsName = UNKNOWN_SYNC_NAME;
+		*ui32NameSize = sizeof(UNKNOWN_SYNC_NAME) - 1;
+	}
+
+	switch (eAllocType)
+	{
+		case RGX_HWPERF_HOST_RESOURCE_TYPE_SYNC:
+			ui32Size += sizeof(puData->sSyncAlloc) - SYNC_MAX_CLASS_NAME_LEN +
+			        *ui32NameSize + 1; /* +1 for '\0' */
+			break;
+		default:
+			// unknown type - this should never happen
+			PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfHostPostAllocEvent: Invalid alloc"
+			        " event type"));
+			PVR_ASSERT(IMG_FALSE);
+			break;
+	}
+
+	return RGX_HWPERF_MAKE_SIZE_VARIABLE(ui32Size);
+}
+
+static inline void _SetupHostAllocPacketData(IMG_UINT8 *pui8Dest,
+                                       RGX_HWPERF_HOST_RESOURCE_TYPE eAllocType,
+                                       IMG_UINT32 ui32FWAddr,
+                                       const IMG_CHAR *psName,
+                                       IMG_UINT32 ui32NameSize)
+{
+	RGX_HWPERF_HOST_ALLOC_DATA *psData = (RGX_HWPERF_HOST_ALLOC_DATA *)
+	        (pui8Dest + sizeof(RGX_HWPERF_V2_PACKET_HDR));
+	psData->ui32AllocType = eAllocType;
+
+	if (ui32NameSize)
+	{
+		OSStringNCopy(psData->uAllocDetail.sSyncAlloc.acName, psName,
+		              ui32NameSize);
+		/* we know here that string is not null terminated and that we have
+		 *enough space for the terminator */
+		psData->uAllocDetail.sSyncAlloc.acName[ui32NameSize] = '\0';
+	}
+	else
+	{
+		/* In case no name was given make sure we don't access random memory */
+		psData->uAllocDetail.sSyncAlloc.acName[0] = '\0';
+	}
+}
+
+void RGXHWPerfHostPostAllocEvent(RGX_HWPERF_HOST_RESOURCE_TYPE eAllocType,
+                                 IMG_UINT32 ui32FWAddr,
+                                 const IMG_CHAR *psName,
+                                 IMG_UINT32 ui32NameSize)
+{
+	IMG_UINT8 *pui8Dest;
+	IMG_UINT32 ui32Size = _FixNameAndCalculateHostAllocPacketSize(eAllocType,
+	                                                             &psName,
+	                                                             &ui32NameSize);
+
+	_PostFunctionPrologue();
+
+	if ((pui8Dest = _ReserveHWPerfStream(ui32Size)) == NULL)
+	{
+		goto cleanup;
+	}
+
+	_SetupHostPacketHeader(pui8Dest, RGX_HWPERF_HOST_ALLOC, ui32Size);
+	_SetupHostAllocPacketData(pui8Dest, eAllocType, ui32FWAddr, psName,
+	                          ui32NameSize);
+
+	_CommitHWPerfStream(ui32Size);
+
+cleanup:
+	_PostFunctionEpilogue();
+}
+
+static inline void _SetupHostFreePacketData(IMG_UINT8 *pui8Dest,
+                                          RGX_HWPERF_HOST_RESOURCE_TYPE eFreeType,
+                                          IMG_UINT32 ui32FWAddr)
+{
+	RGX_HWPERF_HOST_FREE_DATA *psData = (RGX_HWPERF_HOST_FREE_DATA *)
+	        (pui8Dest + sizeof(RGX_HWPERF_V2_PACKET_HDR));
+	psData->ui32FreeType = eFreeType;
+	psData->uFreeDetail.sSyncFree.ui32FWAddr = ui32FWAddr;
+}
+
+void RGXHWPerfHostPostFreeEvent(RGX_HWPERF_HOST_RESOURCE_TYPE eFreeType,
+                                IMG_UINT32 ui32FWAddr)
+{
+	IMG_UINT8 *pui8Dest;
+	IMG_UINT32 ui32Size = RGX_HWPERF_MAKE_SIZE_FIXED(RGX_HWPERF_HOST_FREE_DATA);
+
+	_PostFunctionPrologue();
+
+	if ((pui8Dest = _ReserveHWPerfStream(ui32Size)) == NULL)
+	{
+		goto cleanup;
+	}
+
+	_SetupHostPacketHeader(pui8Dest, RGX_HWPERF_HOST_FREE, ui32Size);
+	_SetupHostFreePacketData(pui8Dest, eFreeType, ui32FWAddr);
+
+	_CommitHWPerfStream(ui32Size);
+
+cleanup:
+	_PostFunctionEpilogue();
+}
+
 static inline void _SetupHostClkSyncPacketData(IMG_UINT8 *pui8Dest)
 {
 	RGX_HWPERF_HOST_CLK_SYNC_DATA *psData = (RGX_HWPERF_HOST_CLK_SYNC_DATA *)
@@ -1458,33 +1757,39 @@
  *****************************************************************************/
 #if defined(SUPPORT_GPUTRACE_EVENTS)
 
-static POS_LOCK g_hFTraceLock = NULL;
-
-/* This lock ensures that the reference counting operation on the FTrace UFO
- * events and enable/disable operation on firmware event are performed as
- * one atomic operation. This should ensure that there are no race conditions
- * between reference counting and firmware event state change.
- * See below comment for g_uiUfoEventRef.
- */
-static POS_LOCK g_hLockFTraceEventLock = NULL;
-
-/* Multiple FTrace UFO events are reflected in the firmware as only one event. When
- * we enable FTrace UFO event we want to also at the same time enable it in
- * the firmware. Since there is a multiple-to-one relation between those events
- * we count how many FTrace UFO events is enabled. If at least one event is
- * enabled we enabled the firmware event. When all FTrace UFO events are disabled
- * we disable firmware event. */
-static IMG_INT g_uiUfoEventRef = 0;
-
 static void RGXHWPerfFTraceCmdCompleteNotify(PVRSRV_CMDCOMP_HANDLE);
 
 typedef struct RGX_HWPERF_FTRACE_DATA {
+	/* This lock ensures the HWPerf TL stream reading resources are not destroyed
+	 * by one thread disabling it while another is reading from it in. Keeps the
+	 * state and resource create/destroy atomic and consistent. */
+	POS_LOCK    hFTraceLock;
 	IMG_HANDLE  hGPUTraceCmdCompleteHandle;
 	IMG_HANDLE  hGPUTraceTLStream;
 	IMG_UINT64  ui64LastSampledTimeCorrOSTimeStamp;
 	IMG_UINT32  ui32FTraceLastOrdinal;
+	/* This lock ensures that the reference counting operation on the FTrace UFO
+	 * events and enable/disable operation on firmware event are performed as
+	 * one atomic operation. This should ensure that there are no race conditions
+	 * between reference counting and firmware event state change.
+	 * See below comment for g_uiUfoEventRef.
+	 */
+	POS_LOCK    hLockFTraceEventLock;
+	/* Multiple FTrace UFO events are reflected in the firmware as only one event. When
+	 * we enable FTrace UFO event we want to also at the same time enable it in
+	 * the firmware. Since there is a multiple-to-one relation between those events
+	 * we count how many FTrace UFO events is enabled. If at least one event is
+	 * enabled we enabled the firmware event. When all FTrace UFO events are disabled
+	 * we disable firmware event. */
+	IMG_UINT    uiUfoEventRef;
+	/* Saved value of the clock source before the trace was enabled. We're keeping
+	 * it here so that know we which clock should be selected after we disable the
+	 * gpu ftrace. */
+	IMG_UINT64  ui64LastTimeCorrClock;
 } RGX_HWPERF_FTRACE_DATA;
 
+/* Caller must now hold hFTraceLock before calling this method.
+ */
 static PVRSRV_ERROR RGXHWPerfFTraceGPUEnable(void)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -1496,6 +1801,8 @@
 
 	psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
 
+	PVR_ASSERT(OSLockIsLocked(psFtraceData->hFTraceLock));
+
 	/* In the case where the AppHint has not been set we need to
 	 * initialise the host driver HWPerf resources here. Allocated on
 	 * demand to reduce RAM foot print on systems not needing HWPerf.
@@ -1504,10 +1811,10 @@
 	if (gpsRgxDevInfo->bFirmwareInitialised)
 	{
 		IMG_UINT64 ui64UFOFilter = RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_UFO) &
-		        gpsRgxDevInfo->ui64HWPerfFilter;
+								   gpsRgxDevInfo->ui64HWPerfFilter;
 
-		eError = PVRSRVRGXCtrlHWPerfKM(NULL, gpsRgxDevNode, IMG_FALSE,
-		                               RGX_HWPERF_STREAM_ID0_FW,
+		eError = PVRSRVRGXCtrlHWPerfKM(NULL, gpsRgxDevNode,
+		                               RGX_HWPERF_STREAM_ID0_FW, IMG_FALSE,
 		                               RGX_HWPERF_EVENT_MASK_HW_KICKFINISH |
 		                               ui64UFOFilter);
 		PVR_LOGG_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM", err_out);
@@ -1528,11 +1835,22 @@
 
 	/* Open the TL Stream for HWPerf data consumption */
 	eError = TLClientOpenStream(DIRECT_BRIDGE_HANDLE,
-								HWPERF_TL_STREAM_NAME,
+								PVRSRV_TL_HWPERF_RGX_FW_STREAM,
 								PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING,
 								&psFtraceData->hGPUTraceTLStream);
 	PVR_LOGG_IF_ERROR(eError, "TLClientOpenStream", err_out);
 
+	/* Set clock source for timer correlation data to sched_clock */
+	psFtraceData->ui64LastTimeCorrClock = RGXGPUFreqCalibrateGetClockSource();
+	RGXGPUFreqCalibrateSetClockSource(gpsRgxDevNode, RGXTIMECORR_CLOCK_SCHED);
+
+	/* Reset the OS timestamp coming from the timer correlation data
+	 * associated with the latest HWPerf event we processed.
+	 */
+	psFtraceData->ui64LastSampledTimeCorrOSTimeStamp = 0;
+
+	PVRGpuTraceSetEnabled(IMG_TRUE);
+
 	/* Register a notifier to collect HWPerf data whenever the HW completes
 	 * an operation.
 	 */
@@ -1542,13 +1860,6 @@
 		gpsRgxDevInfo);
 	PVR_LOGG_IF_ERROR(eError, "PVRSRVRegisterCmdCompleteNotify", err_close_stream);
 
-	/* Reset the OS timestamp coming from the timer correlation data
-	 * associated with the latest HWPerf event we processed.
-	 */
-	psFtraceData->ui64LastSampledTimeCorrOSTimeStamp = 0;
-
-	PVRGpuTraceSetEnabled(IMG_TRUE);
-
 err_out:
 	PVR_DPF_RETURN_RC(eError);
 
@@ -1557,26 +1868,30 @@
 
 	TLClientCloseStream(DIRECT_BRIDGE_HANDLE,
 						psFtraceData->hGPUTraceTLStream);
-	psFtraceData->hGPUTraceTLStream = NULL;
+	psFtraceData->hGPUTraceTLStream = 0;
 	goto err_out;
 }
 
+/* Caller must now hold hFTraceLock before calling this method.
+ */
 static PVRSRV_ERROR RGXHWPerfFTraceGPUDisable(IMG_BOOL bDeInit)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
-	RGX_HWPERF_FTRACE_DATA *psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
+	RGX_HWPERF_FTRACE_DATA *psFtraceData;
 
 	PVR_DPF_ENTERED;
 
 	PVR_ASSERT(gpsRgxDevNode && gpsRgxDevInfo);
 
+	psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
+
 	PVRGpuTraceSetEnabled(IMG_FALSE);
 	PVRGpuTraceSetPreEnabled(IMG_FALSE);
 
-	OSLockAcquire(g_hFTraceLock);
-
 	if (!bDeInit)
 	{
+		PVR_ASSERT(OSLockIsLocked(psFtraceData->hFTraceLock));
+
 		eError = PVRSRVRGXCtrlHWPerfKM(NULL, gpsRgxDevNode, RGX_HWPERF_STREAM_ID0_FW, IMG_FALSE, (RGX_HWPERF_EVENT_MASK_NONE));
 		PVR_LOG_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM");
 	}
@@ -1617,9 +1932,11 @@
 		psFtraceData->hGPUTraceTLStream = NULL;
 	}
 
-	PVRGpuTraceSetEnabled(IMG_FALSE);
-
-	OSLockRelease(g_hFTraceLock);
+	if (psFtraceData->ui64LastTimeCorrClock != RGXTIMECORR_CLOCK_SCHED)
+	{
+		RGXGPUFreqCalibrateSetClockSource(gpsRgxDevNode,
+		                                  psFtraceData->ui64LastTimeCorrClock);
+	}
 
 	PVR_DPF_RETURN_RC(eError);
 }
@@ -1628,11 +1945,19 @@
 {
 	IMG_BOOL bOldValue;
 	PVRSRV_ERROR eError = PVRSRV_OK;
+	RGX_HWPERF_FTRACE_DATA *psFtraceData;
 
 	PVR_DPF_ENTERED;
 
 	PVR_ASSERT(gpsRgxDevNode && gpsRgxDevInfo);
 
+	psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
+
+	/* About to create/destroy FTrace resources, lock critical section
+	 * to avoid HWPerf MISR thread contention.
+	 */
+	OSLockAcquire(psFtraceData->hFTraceLock);
+
 	bOldValue = PVRGpuTraceEnabled();
 
 	if (bOldValue != bNewValue)
@@ -1647,6 +1972,8 @@
 		}
 	}
 
+	OSLockRelease(psFtraceData->hFTraceLock);
+
 	PVR_DPF_RETURN_RC(eError);
 }
 
@@ -1654,8 +1981,11 @@
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
 
-	/* Lock down because we need to protect
-	 * RGXHWPerfFTraceGPUDisable()/RGXHWPerfFTraceGPUEnable()
+	/* This entry point from DebugFS must take the global 
+	 * bridge lock at this outer level of the stack before calling
+	 * into the RGX part of the driver which can lead to RGX
+	 * device data changes and communication with the FW which
+	 * all requires the bridge lock.
 	 */
 	OSAcquireBridgeLock();
 	eError = RGXHWPerfFTraceGPUEventsEnabledSet(bNewValue);
@@ -1664,17 +1994,60 @@
 	PVR_DPF_RETURN_RC(eError);
 }
 
+/* Calculate the OS timestamp given an RGX timestamp in the HWPerf event. */
+static uint64_t
+CalculateEventTimestamp(PVRSRV_RGXDEV_INFO *psDevInfo,
+						uint32_t ui32TimeCorrIndex,
+						uint64_t ui64EventTimestamp)
+{
+	RGXFWIF_GPU_UTIL_FWCB *psGpuUtilFWCB = psDevInfo->psRGXFWIfGpuUtilFWCb;
+	RGX_HWPERF_FTRACE_DATA *psFtraceData = psDevInfo->pvGpuFtraceData;
+	RGXFWIF_TIME_CORR *psTimeCorr = &psGpuUtilFWCB->sTimeCorr[ui32TimeCorrIndex];
+	uint64_t ui64CRTimeStamp = psTimeCorr->ui64CRTimeStamp;
+	uint64_t ui64OSTimeStamp = psTimeCorr->ui64OSTimeStamp;
+	uint32_t ui32CRDeltaToOSDeltaKNs = psTimeCorr->ui32CRDeltaToOSDeltaKNs;
+	uint64_t ui64EventOSTimestamp, deltaRgxTimer, delta_ns;
+
+	if (psFtraceData->ui64LastSampledTimeCorrOSTimeStamp > ui64OSTimeStamp)
+	{
+		/* The previous packet had a time reference (time correlation data) more
+		 * recent than the one in the current packet, it means the timer
+		 * correlation array wrapped too quickly (buffer too small) and in the
+		 * previous call to RGXHWPerfFTraceGPUUfoEvent we read one of the
+		 * newest timer correlations rather than one of the oldest ones.
+		 */
+		PVR_DPF((PVR_DBG_ERROR, "%s: The timestamps computed so far could be "
+				 "wrong! The time correlation array size should be increased "
+				 "to avoid this.", __func__));
+	}
+
+	psFtraceData->ui64LastSampledTimeCorrOSTimeStamp = ui64OSTimeStamp;
+
+	/* RGX CR timer ticks delta */
+	deltaRgxTimer = ui64EventTimestamp - ui64CRTimeStamp;
+	/* RGX time delta in nanoseconds */
+	delta_ns = RGXFWIF_GET_DELTA_OSTIME_NS(deltaRgxTimer, ui32CRDeltaToOSDeltaKNs);
+	/* Calculate OS time of HWPerf event */
+	ui64EventOSTimestamp = ui64OSTimeStamp + delta_ns;
+
+	PVR_DPF((PVR_DBG_VERBOSE, "%s: psCurrentDvfs RGX %llu, OS %llu, DVFSCLK %u",
+			 __func__, ui64CRTimeStamp, ui64OSTimeStamp,
+			 psTimeCorr->ui32CoreClockSpeed));
+
+	return ui64EventOSTimestamp;
+}
+
 void RGXHWPerfFTraceGPUEnqueueEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
-		IMG_UINT32 ui32ExternalJobRef, IMG_UINT32 ui32InternalJobRef,
+		IMG_UINT32 ui32CtxId, IMG_UINT32 ui32JobId,
 		RGX_HWPERF_KICK_TYPE eKickType)
 {
 	PVR_DPF_ENTERED;
 
-	PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUEnqueueEvent: ExtJobRef %u, "
-	        "IntJobRef %u", ui32ExternalJobRef, ui32InternalJobRef));
+	PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUEnqueueEvent: ui32CtxId %u, "
+	        "ui32JobId %u", ui32CtxId, ui32JobId));
 
-	PVRGpuTraceClientWork(ui32ExternalJobRef, ui32InternalJobRef,
-	                      RGXHWPerfKickTypeToStr(eKickType));
+	PVRGpuTraceClientWork(ui32CtxId, ui32JobId,
+	    RGXHWPerfKickTypeToStr(eKickType));
 
 	PVR_DPF_RETURN;
 }
@@ -1686,12 +2059,6 @@
 {
 	IMG_UINT64 ui64Timestamp;
 	RGX_HWPERF_HW_DATA_FIELDS* psHWPerfPktData;
-	RGXFWIF_GPU_UTIL_FWCB *psGpuUtilFWCB = psDevInfo->psRGXFWIfGpuUtilFWCb;
-	RGX_HWPERF_FTRACE_DATA *psFtraceData = psDevInfo->pvGpuFtraceData;
-	RGXFWIF_TIME_CORR *psTimeCorr;
-	IMG_UINT32 ui32CRDeltaToOSDeltaKNs;
-	IMG_UINT64 ui64CRTimeStamp;
-	IMG_UINT64 ui64OSTimeStamp;
 
 	PVR_DPF_ENTERED;
 
@@ -1700,41 +2067,13 @@
 
 	psHWPerfPktData = (RGX_HWPERF_HW_DATA_FIELDS*) RGX_HWPERF_GET_PACKET_DATA_BYTES(psHWPerfPkt);
 
-	/* Filter out 3DFINISH events for 3DTQKICKs which have already been
-	 * filtered by ValidAndEmitFTraceEvent() */
-
-	/* Calculate the OS timestamp given an RGX timestamp in the HWPerf event */
-	psTimeCorr              = &psGpuUtilFWCB->sTimeCorr[psHWPerfPktData->ui32TimeCorrIndex];
-	ui64CRTimeStamp         = psTimeCorr->ui64CRTimeStamp;
-	ui64OSTimeStamp         = psTimeCorr->ui64OSTimeStamp;
-	ui32CRDeltaToOSDeltaKNs = psTimeCorr->ui32CRDeltaToOSDeltaKNs;
-
-	if(psFtraceData->ui64LastSampledTimeCorrOSTimeStamp > ui64OSTimeStamp)
-	{
-		/* The previous packet had a time reference (time correlation data) more recent
-		 * than the one in the current packet, it means the timer correlation array wrapped
-		 * too quickly (buffer too small) and in the previous call to RGXHWPerfFTraceGPUSwitchEvent
-		 * we read one of the newest timer correlations rather than one of the oldest ones.
-		 */
-		PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfFTraceGPUSwitchEvent: The timestamps computed so far could be wrong! "
-		                        "The time correlation array size should be increased to avoid this."));
-	}
-	psFtraceData->ui64LastSampledTimeCorrOSTimeStamp = ui64OSTimeStamp;
-
-	{
-		IMG_UINT64 deltaRgxTimer = psHWPerfPkt->ui64Timestamp - ui64CRTimeStamp;  /* RGX CR timer ticks delta */
-		IMG_UINT64 delta_nS =
-		    RGXFWIF_GET_DELTA_OSTIME_NS(deltaRgxTimer, ui32CRDeltaToOSDeltaKNs); /* RGX time delta in nS */
-		ui64Timestamp = ui64OSTimeStamp + delta_nS;                              /* Calculate OS time of HWPerf event */
-
-		PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUSwitchEvent: psCurrentDvfs RGX %llu, OS %llu, DVFSCLK %u",
-		         ui64CRTimeStamp, ui64OSTimeStamp, psTimeCorr->ui32CoreClockSpeed ));
-	}
+	ui64Timestamp = CalculateEventTimestamp(psDevInfo, psHWPerfPktData->ui32TimeCorrIndex,
+											psHWPerfPkt->ui64Timestamp);
 
 	PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUSwitchEvent: %s ui32ExtJobRef=%d, ui32IntJobRef=%d, eSwType=%d",
 			pszWorkName, psHWPerfPktData->ui32DMContext, psHWPerfPktData->ui32IntJobRef, eSwType));
 
-	PVRGpuTraceWorkSwitch(ui64Timestamp, psHWPerfPktData->ui32DMContext,
+	PVRGpuTraceWorkSwitch(ui64Timestamp, psHWPerfPktData->ui32DMContext, psHWPerfPktData->ui32CtxPriority,
 	                      psHWPerfPktData->ui32IntJobRef, pszWorkName, eSwType);
 
 	PVR_DPF_RETURN;
@@ -1745,12 +2084,6 @@
 {
 	IMG_UINT64 ui64Timestamp;
 	RGX_HWPERF_UFO_DATA *psHWPerfPktData;
-	RGXFWIF_GPU_UTIL_FWCB *psGpuUtilFWCB = psDevInfo->psRGXFWIfGpuUtilFWCb;
-	RGX_HWPERF_FTRACE_DATA *psFtraceData = psDevInfo->pvGpuFtraceData;
-	RGXFWIF_TIME_CORR *psTimeCorr;
-	IMG_UINT32 ui32CRDeltaToOSDeltaKNs;
-	IMG_UINT64 ui64CRTimeStamp;
-	IMG_UINT64 ui64OSTimeStamp;
 	IMG_UINT32 ui32UFOCount;
 	RGX_HWPERF_UFO_DATA_ELEMENT *puData;
 
@@ -1761,60 +2094,50 @@
 	puData = (RGX_HWPERF_UFO_DATA_ELEMENT *) (((IMG_BYTE *) psHWPerfPktData)
 	        + RGX_HWPERF_GET_UFO_STREAMOFFSET(psHWPerfPktData->ui32StreamInfo));
 
-	/* Calculate the OS timestamp given an RGX timestamp in the HWPerf event */
-	psTimeCorr = &psGpuUtilFWCB->sTimeCorr[psHWPerfPktData->ui32TimeCorrIndex];
-	ui64CRTimeStamp = psTimeCorr->ui64CRTimeStamp;
-	ui64OSTimeStamp = psTimeCorr->ui64OSTimeStamp;
-	ui32CRDeltaToOSDeltaKNs = psTimeCorr->ui32CRDeltaToOSDeltaKNs;
-
-	if(psFtraceData->ui64LastSampledTimeCorrOSTimeStamp > ui64OSTimeStamp)
-	{
-		/* The previous packet had a time reference (time correlation data) more
-		 * recent than the one in the current packet, it means the timer
-		 * correlation array wrapped too quickly (buffer too small) and in the
-		 * previous call to RGXHWPerfFTraceGPUUfoEvent we read one of the
-		 * newest timer correlations rather than one of the oldest ones.
-		 */
-		PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfFTraceGPUUfoEvent: The timestamps "
-		        "computed so far could be wrong! The time correlation array "
-		        "size should be increased to avoid this."));
-	}
-	psFtraceData->ui64LastSampledTimeCorrOSTimeStamp = ui64OSTimeStamp;
-
-	{
-		/* RGX CR timer ticks delta */
-		IMG_UINT64 deltaRgxTimer = psHWPerfPkt->ui64Timestamp - ui64CRTimeStamp;
-		/* RGX time delta in nS */
-		IMG_UINT64 delta_ns =
-		        RGXFWIF_GET_DELTA_OSTIME_NS(deltaRgxTimer, ui32CRDeltaToOSDeltaKNs);
-		/* Calculate OS time of HWPerf event */
-		ui64Timestamp = ui64OSTimeStamp + delta_ns;
-
-		PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUUfoEvent: psCurrentDvfs "
-		        "RGX %llu, OS %llu, DVFSCLK %u", ui64CRTimeStamp,
-		        ui64OSTimeStamp, psTimeCorr->ui32CoreClockSpeed));
-	}
+	ui64Timestamp = CalculateEventTimestamp(psDevInfo, psHWPerfPktData->ui32TimeCorrIndex,
+											psHWPerfPkt->ui64Timestamp);
 
 	PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUUfoEvent: ui32ExtJobRef=%d, "
 	        "ui32IntJobRef=%d", psHWPerfPktData->ui32ExtJobRef,
 	        psHWPerfPktData->ui32IntJobRef));
 
 	PVRGpuTraceUfo(ui64Timestamp, psHWPerfPktData->eEvType,
-	        psHWPerfPktData->ui32ExtJobRef, psHWPerfPktData->ui32FWCtx,
+	        psHWPerfPktData->ui32ExtJobRef, psHWPerfPktData->ui32DMContext,
 	        psHWPerfPktData->ui32IntJobRef, ui32UFOCount, puData);
 }
 
+static void RGXHWPerfFTraceGPUFirmwareEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
+		RGX_HWPERF_V2_PACKET_HDR* psHWPerfPkt, const IMG_CHAR* pszWorkName,
+		PVR_GPUTRACE_SWITCH_TYPE eSwType)
+
+{
+	uint64_t ui64Timestamp;
+	RGX_HWPERF_FW_DATA *psHWPerfPktData = (RGX_HWPERF_FW_DATA *)
+		RGX_HWPERF_GET_PACKET_DATA_BYTES(psHWPerfPkt);
+
+	ui64Timestamp = CalculateEventTimestamp(psDevInfo, psHWPerfPktData->ui32TimeCorrIndex,
+											psHWPerfPkt->ui64Timestamp);
+
+	PVRGpuTraceFirmware(ui64Timestamp, pszWorkName, eSwType);
+}
+
 static IMG_BOOL ValidAndEmitFTraceEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
 		RGX_HWPERF_V2_PACKET_HDR* psHWPerfPkt)
 {
 	RGX_HWPERF_EVENT_TYPE eType;
 	RGX_HWPERF_FTRACE_DATA *psFtraceData = psDevInfo->pvGpuFtraceData;
-	const IMG_CHAR* pszWorkName;
-	PVR_GPUTRACE_SWITCH_TYPE eSwType;
+	IMG_UINT32 ui32HwEventTypeIndex;
 	static const struct {
 		IMG_CHAR* pszName;
 		PVR_GPUTRACE_SWITCH_TYPE eSwType;
 	} aszHwEventTypeMap[] = {
+			{ /* RGX_HWPERF_FW_BGSTART */      "BG",     PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+			{ /* RGX_HWPERF_FW_BGEND */        "BG",     PVR_GPUTRACE_SWITCH_TYPE_END },
+			{ /* RGX_HWPERF_FW_IRQSTART */     "IRQ",     PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+			{ /* RGX_HWPERF_FW_IRQEND */       "IRQ",     PVR_GPUTRACE_SWITCH_TYPE_END },
+			{ /* RGX_HWPERF_FW_DBGSTART */     "DBG",     PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+			{ /* RGX_HWPERF_FW_DBGEND */       "DBG",     PVR_GPUTRACE_SWITCH_TYPE_END },
+			{ /* RGX_HWPERF_HW_PMOOM_TAPAUSE */	"PMOOM_TAPAUSE",  PVR_GPUTRACE_SWITCH_TYPE_END },
 			{ /* RGX_HWPERF_HW_TAKICK */       "TA",     PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
 			{ /* RGX_HWPERF_HW_TAFINISHED */   "TA",     PVR_GPUTRACE_SWITCH_TYPE_END },
 			{ /* RGX_HWPERF_HW_3DTQKICK */     "TQ3D",   PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
@@ -1832,7 +2155,12 @@
 			{ /* RGX_HWPERF_HW_SHGFINISHED */  "SHG",    PVR_GPUTRACE_SWITCH_TYPE_END },
 			{ /* RGX_HWPERF_HW_3DTQFINISHED */ "TQ3D",   PVR_GPUTRACE_SWITCH_TYPE_END },
 			{ /* RGX_HWPERF_HW_3DSPMFINISHED */ "3DSPM", PVR_GPUTRACE_SWITCH_TYPE_END },
+			{ /* RGX_HWPERF_HW_PMOOM_TARESUME */	"PMOOM_TARESUME",  PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+			{ /* RGX_HWPERF_HW_TDMKICK */      "TDM",   PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+			{ /* RGX_HWPERF_HW_TDMFINISHED */  "TDM",   PVR_GPUTRACE_SWITCH_TYPE_END },
 	};
+	static_assert(RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE == RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE + 1,
+				  "FW and HW events are not contiguous in RGX_HWPERF_EVENT_TYPE");
 
 	PVR_ASSERT(psHWPerfPkt);
 	eType = RGX_HWPERF_GET_TYPE(psHWPerfPkt);
@@ -1856,30 +2184,49 @@
 		return IMG_TRUE;
 	}
 
-	/* Process HW packets */
-	if (((eType < RGX_HWPERF_HW_TAKICK) || (eType > RGX_HWPERF_HW_3DSPMFINISHED)))
+	if (eType <= RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE)
 	{
-		/* No map entry, ignore event */
-		PVR_DPF((PVR_DBG_VERBOSE, "ValidAndEmitFTraceEvent: Unsupported event type %d %02d",
-			eType, eType+RGX_HWPERF_HW_TAKICK)); 
-		return IMG_FALSE;
+		/* this ID belongs to range 0, so index directly in range 0 */
+		ui32HwEventTypeIndex = eType - RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE;
 	}
-	eType-=RGX_HWPERF_HW_TAKICK;
+	else
+	{
+		/* this ID belongs to range 1, so first index in range 1 and skip number of slots used up for range 0 */
+		ui32HwEventTypeIndex = (eType - RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE) + 
+		                       (RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE - RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE + 1);
+	}
 
-	if (aszHwEventTypeMap[eType].pszName == NULL)
+	if (ui32HwEventTypeIndex >= IMG_ARR_NUM_ELEMS(aszHwEventTypeMap))
+		goto err_unsupported;
+
+	if (aszHwEventTypeMap[ui32HwEventTypeIndex].pszName == NULL)
 	{
 		/* Not supported map entry, ignore event */
-		PVR_DPF((PVR_DBG_VERBOSE, "ValidAndEmitFTraceEventl: Unsupported event type %d %02d",
-			eType, eType+RGX_HWPERF_HW_TAKICK)); 
-		return IMG_FALSE;
+		goto err_unsupported;
 	}
 
-	pszWorkName = aszHwEventTypeMap[eType].pszName;
-	eSwType = aszHwEventTypeMap[eType].eSwType;
-
-	RGXHWPerfFTraceGPUSwitchEvent(psDevInfo, psHWPerfPkt, pszWorkName, eSwType);
+	if (HWPERF_PACKET_IS_HW_TYPE(eType))
+	{
+		RGXHWPerfFTraceGPUSwitchEvent(psDevInfo, psHWPerfPkt,
+									  aszHwEventTypeMap[ui32HwEventTypeIndex].pszName,
+									  aszHwEventTypeMap[ui32HwEventTypeIndex].eSwType);
+	}
+	else if (HWPERF_PACKET_IS_FW_TYPE(eType))
+	{
+		RGXHWPerfFTraceGPUFirmwareEvent(psDevInfo, psHWPerfPkt,
+										aszHwEventTypeMap[ui32HwEventTypeIndex].pszName,
+										aszHwEventTypeMap[ui32HwEventTypeIndex].eSwType);
+	}
+	else
+	{
+		goto err_unsupported;
+	}
 
 	return IMG_TRUE;
+
+err_unsupported:
+	PVR_DPF((PVR_DBG_VERBOSE, "%s: Unsupported event type %d", __func__, eType));
+	return IMG_FALSE;
 }
 
 
@@ -1960,139 +2307,126 @@
 {
 	PVRSRV_DATA*		psPVRSRVData = PVRSRVGetPVRSRVData();
 	PVRSRV_RGXDEV_INFO* psDeviceInfo = hCmdCompHandle;
-	RGX_HWPERF_FTRACE_DATA* psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
+	RGX_HWPERF_FTRACE_DATA* psFtraceData;
 	PVRSRV_ERROR		eError;
-	IMG_HANDLE			hStream;
 	IMG_PBYTE			pBuffer;
 	IMG_UINT32			ui32ReadLen;
 
 	PVR_DPF_ENTERED;
 
-	/* Command-complete notifiers can run concurrently. If this is
-	 * happening, just bail out and let the previous call finish.
-	 * This is ok because we can process the queued packets on the next call.
-	 */
-	if (!(OSTryLockAcquire(g_hFTraceLock)))
-	{
-		PVR_DPF_RETURN;
-	}
-
 	/* Exit if no HWPerf enabled device exits */
 	PVR_ASSERT(psDeviceInfo != NULL &&
 			   psPVRSRVData != NULL &&
 			   gpsRgxDevInfo != NULL);
 
-	hStream = psFtraceData->hGPUTraceTLStream;
+	psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
 
-	if (hStream)
+	/* Command-complete notifiers can run concurrently. If this is
+	 * happening, just bail out and let the previous call finish.
+	 * This is ok because we can process the queued packets on the next call.
+	 */
+	if (!PVRGpuTraceEnabled() || !(OSTryLockAcquire(psFtraceData->hFTraceLock)))
 	{
-		/* If we have a valid stream attempt to acquire some data */
-		eError = TLClientAcquireData(DIRECT_BRIDGE_HANDLE, hStream, &pBuffer, &ui32ReadLen);
-		if (eError == PVRSRV_OK)
-		{
-			/* Process the HWPerf packets and release the data */
-			if (ui32ReadLen > 0)
-			{
-				PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUThread: DATA AVAILABLE offset=%p, length=%d", pBuffer, ui32ReadLen));
-
-				/* Process the transport layer data for HWPerf packets... */
-				RGXHWPerfFTraceGPUProcessPackets(psDeviceInfo, pBuffer, ui32ReadLen);
-
-				eError = TLClientReleaseData(DIRECT_BRIDGE_HANDLE, hStream);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_LOG_ERROR(eError, "TLClientReleaseData");
-
-					/* Serious error, disable FTrace GPU events */
-
-					/* Release TraceLock so we always have the locking
-					 * order BridgeLock->TraceLock to prevent AB-BA deadlocks*/
-					OSLockRelease(g_hFTraceLock);
-					OSAcquireBridgeLock();
-					RGXHWPerfFTraceGPUDisable(IMG_FALSE);
-					OSReleaseBridgeLock();
-					goto out;
-
-				}
-			} /* else no data, ignore */
-		}
-		else if (eError != PVRSRV_ERROR_TIMEOUT)
-		{
-			PVR_LOG_ERROR(eError, "TLClientAcquireData");
-		}
+		PVR_DPF_RETURN;
 	}
 
-	OSLockRelease(g_hFTraceLock);
+	/* PVRGpuTraceSetEnabled() and hGPUTraceTLStream are now
+	 * called / atomically set inside the hFTraceLock so just assert here.
+	 */
+	PVR_ASSERT(psFtraceData->hGPUTraceTLStream);
+
+	/* If we have a valid stream attempt to acquire some data */
+	eError = TLClientAcquireData(DIRECT_BRIDGE_HANDLE, psFtraceData->hGPUTraceTLStream, &pBuffer, &ui32ReadLen);
+	if (eError == PVRSRV_OK)
+	{
+		/* Process the HWPerf packets and release the data */
+		if (ui32ReadLen > 0)
+		{
+			PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUThread: DATA AVAILABLE offset=%p, length=%d", pBuffer, ui32ReadLen));
+
+			/* Process the transport layer data for HWPerf packets... */
+			RGXHWPerfFTraceGPUProcessPackets(psDeviceInfo, pBuffer, ui32ReadLen);
+
+			eError = TLClientReleaseData(DIRECT_BRIDGE_HANDLE, psFtraceData->hGPUTraceTLStream);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_LOG_ERROR(eError, "TLClientReleaseData");
+
+				/* Serious error, disable FTrace GPU events */
+
+				/* Release TraceLock so we always have the locking
+				 * order BridgeLock->TraceLock to prevent AB-BA deadlocks*/
+				OSLockRelease(psFtraceData->hFTraceLock);
+				OSAcquireBridgeLock();
+				OSLockAcquire(psFtraceData->hFTraceLock);
+				RGXHWPerfFTraceGPUDisable(IMG_FALSE);
+				OSLockRelease(psFtraceData->hFTraceLock);
+				OSReleaseBridgeLock();
+				goto out;
+
+			}
+		} /* else no data, ignore */
+	}
+	else if (eError != PVRSRV_ERROR_TIMEOUT)
+	{
+		PVR_LOG_ERROR(eError, "TLClientAcquireData");
+	}
+
+	OSLockRelease(psFtraceData->hFTraceLock);
 out:
 	PVR_DPF_RETURN;
 }
 
-PVRSRV_ERROR RGXHWPerfFTraceGPUInit(PVRSRV_RGXDEV_INFO *psDevInfo)
+PVRSRV_ERROR RGXHWPerfFTraceGPUInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 	PVRSRV_ERROR eError;
-
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 	RGX_HWPERF_FTRACE_DATA *psData = OSAllocMem(sizeof(RGX_HWPERF_FTRACE_DATA));
 	if (psData == NULL)
-	{
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto e0;
-	}
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
 
 	/* We initialise it only once because we want to track if any
 	 * packets were dropped. */
 	psData->ui32FTraceLastOrdinal = IMG_UINT32_MAX - 1;
-	psData->hGPUTraceCmdCompleteHandle = NULL;
-	psData->hGPUTraceTLStream = NULL;
-	psData->ui64LastSampledTimeCorrOSTimeStamp = 0;
+
+	eError = OSLockCreate(&psData->hFTraceLock, LOCK_TYPE_DISPATCH);
+	PVR_LOGG_IF_ERROR(eError, "OSLockCreate", e0);
+
+	eError = OSLockCreate(&psData->hLockFTraceEventLock, LOCK_TYPE_PASSIVE);
+	PVR_LOGG_IF_ERROR(eError, "OSLockCreate", e1);
+
+	psData->uiUfoEventRef = 0;
 
 	psDevInfo->pvGpuFtraceData = psData;
 
-	eError = OSLockCreate(&g_hFTraceLock, LOCK_TYPE_DISPATCH);
-	PVR_LOGG_IF_ERROR(eError, "OSLockCreate", e1);
-
-	eError = OSLockCreate(&g_hLockFTraceEventLock, LOCK_TYPE_PASSIVE);
-	PVR_LOGG_IF_ERROR(eError, "OSLockCreate", e2);
-
-	g_uiUfoEventRef = 0;
-
 	return PVRSRV_OK;
 
-e2:
-	OSLockDestroy(g_hFTraceLock);
 e1:
-	OSFREEMEM(psDevInfo->pvGpuFtraceData);
+	OSLockDestroy(psData->hFTraceLock);
 e0:
+	OSFreeMem(psData);
+
 	return eError;
 }
 
-void RGXHWPerfFTraceGPUDeInit()
+void RGXHWPerfFTraceGPUDeInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	/* gbFTraceGPUEventsEnabled and gbFTraceGPUEventsPreEnabled are cleared
-	 * in this function. */
-	PVRGpuTraceEnabledSet(IMG_FALSE);
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	RGX_HWPERF_FTRACE_DATA *psData = psDevInfo->pvGpuFtraceData;
 
-	OSFREEMEM(gpsRgxDevInfo->pvGpuFtraceData);
-
-	if (g_hLockFTraceEventLock != NULL)
-	{
-		OSLockDestroy(g_hLockFTraceEventLock);
-		g_hLockFTraceEventLock = NULL;
-	}
-
-	if (g_hFTraceLock != NULL)
-	{
-		OSLockDestroy(g_hFTraceLock);
-		g_hFTraceLock = NULL;
-	}
+	OSLockDestroy(psData->hFTraceLock);
+	OSLockDestroy(psData->hLockFTraceEventLock);
+	OSFreeMem(psDevInfo->pvGpuFtraceData);
 }
 
 void PVRGpuTraceEnableUfoCallback(void)
 {
 	PVRSRV_ERROR eError;
+	RGX_HWPERF_FTRACE_DATA *psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
 
-	OSLockAcquire(g_hLockFTraceEventLock);
+	OSLockAcquire(psFtraceData->hLockFTraceEventLock);
 
-	if (g_uiUfoEventRef++ == 0)
+	if (psFtraceData->uiUfoEventRef++ == 0)
 	{
 		IMG_UINT64 ui64Filter = RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_UFO) |
 		        gpsRgxDevInfo->ui64HWPerfFilter;
@@ -2114,7 +2448,7 @@
 		}
 	}
 
-	OSLockRelease(g_hLockFTraceEventLock);
+	OSLockRelease(psFtraceData->hLockFTraceEventLock);
 }
 
 void PVRGpuTraceDisableUfoCallback(void)
@@ -2133,9 +2467,9 @@
 
 	psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
 
-	OSLockAcquire(g_hLockFTraceEventLock);
+	OSLockAcquire(psFtraceData->hLockFTraceEventLock);
 
-	if (--g_uiUfoEventRef == 0)
+	if (--psFtraceData->uiUfoEventRef == 0)
 	{
 		IMG_UINT64 ui64Filter = ~(RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_UFO)) &
 		        gpsRgxDevInfo->ui64HWPerfFilter;
@@ -2157,7 +2491,64 @@
 		}
 	}
 
-	OSLockRelease(g_hLockFTraceEventLock);
+	OSLockRelease(psFtraceData->hLockFTraceEventLock);
+}
+
+void PVRGpuTraceEnableFirmwareActivityCallback(void)
+{
+	RGX_HWPERF_FTRACE_DATA *psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
+	uint64_t ui64Filter;
+	int i;
+
+	OSLockAcquire(psFtraceData->hLockFTraceEventLock);
+
+	ui64Filter = gpsRgxDevInfo->ui64HWPerfFilter;
+
+	/* Enable all FW events. */
+	for (i = RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE;
+		 i <= RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE;
+		 i++)
+	{
+		ui64Filter |= RGX_HWPERF_EVENT_MASK_VALUE(i);
+	}
+
+	if (PVRSRVRGXCtrlHWPerfKM(NULL, gpsRgxDevNode, RGX_HWPERF_STREAM_ID0_FW,
+							  IMG_FALSE, ui64Filter) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Could not enable HWPerf event for firmware task timings."));
+	}
+
+	OSLockRelease(psFtraceData->hLockFTraceEventLock);
+}
+
+void PVRGpuTraceDisableFirmwareActivityCallback(void)
+{
+	RGX_HWPERF_FTRACE_DATA *psFtraceData = gpsRgxDevInfo->pvGpuFtraceData;
+	uint64_t ui64Filter;
+	int i;
+
+	if (!psFtraceData)
+		return;
+
+	OSLockAcquire(psFtraceData->hLockFTraceEventLock);
+
+	ui64Filter = gpsRgxDevInfo->ui64HWPerfFilter;
+
+	/* Disable all FW events. */
+	for (i = RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE;
+		 i <= RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE;
+		 i++)
+	{
+		ui64Filter &= ~RGX_HWPERF_EVENT_MASK_VALUE(i);
+	}
+
+	if (PVRSRVRGXCtrlHWPerfKM(NULL, gpsRgxDevNode, RGX_HWPERF_STREAM_ID0_FW,
+							  IMG_FALSE, ui64Filter) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Could not disable HWPerf event for firmware task timings."));
+	}
+
+	OSLockRelease(psFtraceData->hLockFTraceEventLock);
 }
 
 #endif /* SUPPORT_GPUTRACE_EVENTS */
@@ -2181,8 +2572,14 @@
 	IMG_HANDLE          hSD[RGX_HWPERF_STREAM_ID_LAST];
 
 	/* TL Acquire/release state */
-	IMG_PBYTE			pHwpBuf[RGX_HWPERF_STREAM_ID_LAST];
-	IMG_UINT32			ui32HwpBufLen[RGX_HWPERF_STREAM_ID_LAST];
+	IMG_PBYTE			pHwpBuf[RGX_HWPERF_STREAM_ID_LAST];			/*!< buffer returned to user in acquire call */
+	IMG_PBYTE			pHwpBufEnd[RGX_HWPERF_STREAM_ID_LAST];		/*!< pointer to end of HwpBuf */
+	IMG_PBYTE			pTlBuf[RGX_HWPERF_STREAM_ID_LAST];			/*!< buffer obtained via TlAcquireData */
+	IMG_PBYTE			pTlBufPos[RGX_HWPERF_STREAM_ID_LAST];		/*!< initial position in TlBuf to acquire packets */
+	IMG_PBYTE			pTlBufRead[RGX_HWPERF_STREAM_ID_LAST];		/*!< pointer to the last packet read */
+	IMG_UINT32			ui32AcqDataLen[RGX_HWPERF_STREAM_ID_LAST];	/*!< length of acquired TlBuf */
+	IMG_BOOL			bRelease[RGX_HWPERF_STREAM_ID_LAST];		/*!< used to determine whether or not to release currently held TlBuf */
+
 
 } RGX_KM_HWPERF_DEVDATA;
 
@@ -2226,6 +2623,11 @@
 {
 	PVRSRV_ERROR eError;
 	RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*) hDevData;
+	IMG_UINT32 ui32BufSize;
+
+	/* Disable producer callback by default for the Kernel API. */
+	IMG_UINT32 ui32StreamFlags = PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING |
+			                     PVRSRV_STREAM_FLAG_DISABLE_PRODUCER_CALLBACK;
 
 	/* Valid input argument values supplied by the caller */
 	if (!psDevData)
@@ -2243,19 +2645,19 @@
 	 * initialise the HWPerf resources here. Allocated on-demand
 	 * to reduce RAM foot print on systems not needing HWPerf.
 	 */
-	OSLockAcquire(gpsRgxDevInfo->hLockHWPerfModule);
+	OSLockAcquire(gpsRgxDevInfo->hHWPerfLock);
 	if (RGXHWPerfIsInitRequired())
 	{
 		eError = RGXHWPerfInitOnDemandResources();
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Initialization of on-demand HWPerfGpu"
+			PVR_DPF((PVR_DBG_ERROR, "%s: Initialization of on-demand HWPerfFW"
 			        " resources failed", __FUNCTION__));
-			OSLockRelease(gpsRgxDevInfo->hLockHWPerfModule);
+			OSLockRelease(gpsRgxDevInfo->hHWPerfLock);
 			goto e0;
 		}
 	}
-	OSLockRelease(gpsRgxDevInfo->hLockHWPerfModule);
+	OSLockRelease(gpsRgxDevInfo->hHWPerfLock);
 
 	OSLockAcquire(gpsRgxDevInfo->hLockHWPerfHostStream);
 	if (gpsRgxDevInfo->hHWPerfHostStream == NULL)
@@ -2271,19 +2673,19 @@
 	}
 	OSLockRelease(gpsRgxDevInfo->hLockHWPerfHostStream);
 
-	/* Open the 'hwperf_gpu' TL stream for reading in this session */
+	/* Open the RGX TL stream for reading in this session */
 	eError = TLClientOpenStream(DIRECT_BRIDGE_HANDLE,
-								HWPERF_TL_STREAM_NAME,
-								PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING,
+								PVRSRV_TL_HWPERF_RGX_FW_STREAM,
+								ui32StreamFlags,
 								&psDevData->hSD[RGX_HWPERF_STREAM_ID0_FW]);
 	if (eError != PVRSRV_OK)
 	{
 		goto e1;
 	}
 
-	/* Open the 'hwperf_host' TL stream for reading in this session */
+	/* Open the host TL stream for reading in this session */
 	eError = TLClientOpenStream(DIRECT_BRIDGE_HANDLE,
-								HWPERF_HOST_TL_STREAM_NAME,
+								PVRSRV_TL_HWPERF_HOST_SERVER_STREAM,
 								PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING,
 								&psDevData->hSD[RGX_HWPERF_STREAM_ID1_HOST]);
 	if (eError != PVRSRV_OK)
@@ -2291,8 +2693,34 @@
 		goto e1;
 	}
 
+	/* Allocate a large enough buffer for use during the entire session to
+	 * avoid the need to resize in the Acquire call as this might be in an ISR
+	 * Choose size that can contain at least one packet.
+	 */
+	/* Allocate buffer for FW Stream */
+	ui32BufSize = FW_STREAM_BUFFER_SIZE;
+	psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID0_FW] = OSAllocMem(ui32BufSize);
+	if (psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID0_FW] == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e1;
+	}
+	psDevData->pHwpBufEnd[RGX_HWPERF_STREAM_ID0_FW] = psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID0_FW]+ui32BufSize;
+
+	/* Allocate buffer for Host Stream */
+	ui32BufSize = HOST_STREAM_BUFFER_SIZE;
+	psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID1_HOST] = OSAllocMem(ui32BufSize);
+	if (psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID1_HOST] == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e2;
+	}
+	psDevData->pHwpBufEnd[RGX_HWPERF_STREAM_ID1_HOST] = psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID1_HOST]+ui32BufSize;
+
 	return PVRSRV_OK;
 
+e2:
+	OSFreeMem(psDevData->pHwpBuf[RGX_HWPERF_STREAM_ID0_FW]);
 e1:
 	RGXHWPerfHostDeInit();
 e0:
@@ -2316,7 +2744,7 @@
 	return PVRSRV_OK;
 
 e1:
-	RGXHWPerfFreeConnection(phDevData);
+	RGXHWPerfFreeConnection(*phDevData);
 e0:
 	*phDevData = NULL;
 	return eError;
@@ -2414,7 +2842,7 @@
 }
 
 
-PVRSRV_ERROR RGXHWPerfAcquireData(
+PVRSRV_ERROR RGXHWPerfAcquireEvents(
 		IMG_HANDLE  hDevData,
 		RGX_HWPERF_STREAM_ID eStreamId,
 		IMG_PBYTE*  ppBuf,
@@ -2422,8 +2850,6 @@
 {
 	PVRSRV_ERROR			eError;
 	RGX_KM_HWPERF_DEVDATA*	psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
-	IMG_PBYTE				pTlBuf = NULL;
-	IMG_UINT32				ui32TlBufLen = 0;
 	IMG_PBYTE				pDataDest;
 	IMG_UINT32			ui32TlPackets = 0;
 	IMG_PBYTE			pBufferEnd;
@@ -2440,41 +2866,29 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	/* Acquire some data to read from the HWPerf TL stream */
-	eError = TLClientAcquireData(DIRECT_BRIDGE_HANDLE,
-								 psDevData->hSD,
-								 &pTlBuf,
-								 &ui32TlBufLen);
-	PVR_LOGR_IF_ERROR(eError, "TLClientAcquireData");
+	if (psDevData->pTlBuf[eStreamId] == NULL)
+	{
+		/* Acquire some data to read from the HWPerf TL stream */
+		eError = TLClientAcquireData(DIRECT_BRIDGE_HANDLE,
+								 	 psDevData->hSD[eStreamId],
+									 &psDevData->pTlBuf[eStreamId],
+									 &psDevData->ui32AcqDataLen[eStreamId]);
+		PVR_LOGR_IF_ERROR(eError, "TLClientAcquireData");
+
+		psDevData->pTlBufPos[eStreamId] = psDevData->pTlBuf[eStreamId];
+	}
 
 	/* TL indicates no data exists so return OK and zero. */
-	if ((pTlBuf == NULL) || (ui32TlBufLen == 0))
+	if ((psDevData->pTlBufPos[eStreamId] == NULL) || (psDevData->ui32AcqDataLen[eStreamId] == 0))
 	{
 		return PVRSRV_OK;
 	}
 
-	/* Is the client buffer allocated and too small? */
-	if (psDevData->pHwpBuf[eStreamId] && (psDevData->ui32HwpBufLen[eStreamId] < ui32TlBufLen))
-	{
-		OSFREEMEM(psDevData->pHwpBuf[eStreamId]);
-	}
-
-	/* Do we need to allocate a new client buffer? */
-	if (!psDevData->pHwpBuf[eStreamId])
-	{
-		psDevData->pHwpBuf[eStreamId] = OSAllocMem(ui32TlBufLen);
-		if (psDevData->pHwpBuf[eStreamId]  == NULL)
-		{
-			(void) TLClientReleaseData(DIRECT_BRIDGE_HANDLE, psDevData->hSD[eStreamId]);
-			return PVRSRV_ERROR_OUT_OF_MEMORY;
-		}
-		psDevData->ui32HwpBufLen[eStreamId] = ui32TlBufLen;
-	}
-
 	/* Process each TL packet in the data buffer we have acquired */
-	pBufferEnd = pTlBuf+ui32TlBufLen;
+	pBufferEnd = psDevData->pTlBuf[eStreamId]+psDevData->ui32AcqDataLen[eStreamId];
 	pDataDest = psDevData->pHwpBuf[eStreamId];
-	psHDRptr = GET_PACKET_HDR(pTlBuf);
+	psHDRptr = GET_PACKET_HDR(psDevData->pTlBufPos[eStreamId]);
+	psDevData->pTlBufRead[eStreamId] = psDevData->pTlBufPos[eStreamId];
 	while ( psHDRptr < (PVRSRVTL_PPACKETHDR)pBufferEnd )
 	{
 		ui16TlType = GET_PACKET_TYPE(psHDRptr);
@@ -2483,32 +2897,46 @@
 			IMG_UINT16 ui16DataLen = GET_PACKET_DATA_LEN(psHDRptr);
 			if (0 == ui16DataLen)
 			{
-				PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfAcquireData: ZERO Data in TL data packet: %p", psHDRptr));
+				PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfAcquireEvents: ZERO Data in TL data packet: %p", psHDRptr));
 			}
 			else
 			{
+				/* Check next packet does not fill buffer */
+				if (pDataDest + ui16DataLen > psDevData->pHwpBufEnd[eStreamId])
+				{
+					break;
+				}
+
 				/* For valid data copy it into the client buffer and move
 				 * the write position on */
-				OSMemCopy(pDataDest, GET_PACKET_DATA_PTR(psHDRptr), ui16DataLen);
+				OSDeviceMemCopy(pDataDest, GET_PACKET_DATA_PTR(psHDRptr), ui16DataLen);
 				pDataDest += ui16DataLen;
 			}
 		}
 		else if (ui16TlType == PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED)
 		{
-			PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfAcquireData: Indication that the transport buffer was full"));
+			PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfAcquireEvents: Indication that the transport buffer was full"));
 		}
 		else
 		{
 			/* else Ignore padding packet type and others */
-			PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfAcquireData: Ignoring TL packet, type %d", ui16TlType ));
+			PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfAcquireEvents: Ignoring TL packet, type %d", ui16TlType ));
 		}
 
 		/* Update loop variable to the next packet and increment counts */
 		psHDRptr = GET_NEXT_PACKET_ADDR(psHDRptr);
+		/* Updated to keep track of the next packet to be read. */
+		psDevData->pTlBufRead[eStreamId] = (IMG_PBYTE) psHDRptr;
 		ui32TlPackets++;
 	}
 
-	PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfAcquireData: TL Packets processed %03d", ui32TlPackets));
+	PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfAcquireEvents: TL Packets processed %03d", ui32TlPackets));
+
+	psDevData->bRelease[eStreamId] = IMG_FALSE;
+	if (psHDRptr >= (PVRSRVTL_PPACKETHDR) pBufferEnd)
+	{
+		psDevData->bRelease[eStreamId] = IMG_TRUE;
+	}
 
 	/* Update output arguments with client buffer details and true length */
 	*ppBuf = psDevData->pHwpBuf[eStreamId];
@@ -2518,11 +2946,11 @@
 }
 
 
-PVRSRV_ERROR RGXHWPerfReleaseData(
+PVRSRV_ERROR RGXHWPerfReleaseEvents(
 		IMG_HANDLE hDevData,
 		RGX_HWPERF_STREAM_ID eStreamId)
 {
-	PVRSRV_ERROR			eError;
+	PVRSRV_ERROR			eError = PVRSRV_OK;
 	RGX_KM_HWPERF_DEVDATA*	psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
 
 	/* Valid input argument values supplied by the caller */
@@ -2531,16 +2959,17 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	/* Free the client buffer if allocated and reset length */
-	if (psDevData->pHwpBuf[eStreamId])
+	if (psDevData->bRelease[eStreamId])
 	{
-		OSFREEMEM(psDevData->pHwpBuf[eStreamId]);
+		/* Inform the TL that we are done with reading the data. */
+		eError = TLClientReleaseData(DIRECT_BRIDGE_HANDLE, psDevData->hSD[eStreamId]);
+		psDevData->ui32AcqDataLen[eStreamId] = 0;
+		psDevData->pTlBuf[eStreamId] = NULL;
 	}
-	psDevData->ui32HwpBufLen[eStreamId] = 0;
-
-	/* Inform the TL that we are done with reading the data. Could perform this
-	 * in the acquire call but felt it worth keeping it symmetrical */
-	eError = TLClientReleaseData(DIRECT_BRIDGE_HANDLE, psDevData->hSD);
+	else
+	{
+		psDevData->pTlBufPos[eStreamId] = psDevData->pTlBufRead[eStreamId];
+	}
 	return eError;
 }
 
@@ -2550,7 +2979,6 @@
 		RGX_HWPERF_STREAM_ID eStreamId,
 		IMG_UINT64 *ui64Filter)
 {
-#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	PVRSRV_RGXDEV_INFO* psRgxDevInfo =
 			hDevData ? ((RGX_KM_HWPERF_DEVDATA*) hDevData)->psRgxDevInfo : NULL;
 
@@ -2562,23 +2990,22 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
+	/* No need to take hHWPerfLock here since we are only reading data
+	 * from always existing integers to return to debugfs which is an
+	 * atomic operation. 
+	 */
 	switch (eStreamId) {
 		case RGX_HWPERF_STREAM_ID0_FW:
-			OSLockAcquire(psRgxDevInfo->hLockHWPerfModule);
 			*ui64Filter = psRgxDevInfo->ui64HWPerfFilter;
-			OSLockRelease(psRgxDevInfo->hLockHWPerfModule);
 			break;
 		case RGX_HWPERF_STREAM_ID1_HOST:
-			OSLockAcquire(psRgxDevInfo->hLockHWPerfHostStream);
 			*ui64Filter = psRgxDevInfo->ui32HWPerfHostFilter;
-			OSLockRelease(psRgxDevInfo->hLockHWPerfHostStream);
 			break;
 		default:
 			PVR_DPF((PVR_DBG_ERROR, "%s: Invalid stream ID",
 			        __func__));
 			return PVRSRV_ERROR_INVALID_PARAMS;
 	}
-#endif
 
 	return PVRSRV_OK;
 }
@@ -2598,7 +3025,7 @@
 	/* Free the session memory */
 	psDevData->psRgxDevNode = NULL;
 	psDevData->psRgxDevInfo = NULL;
-	OSFREEMEM(psDevData);
+	OSFreeMem(psDevData);
 
 	return PVRSRV_OK;
 }
@@ -2619,14 +3046,21 @@
 
 	for (uiStreamId = 0; uiStreamId < RGX_HWPERF_STREAM_ID_LAST; uiStreamId++)
 	{
-		/* If the client buffer exists they have not called ReleaseData
+		/* If the TL buffer exists they have not called ReleaseData
 		 * before disconnecting so clean it up */
-		if (psDevData->pHwpBuf[uiStreamId])
+		if (psDevData->pTlBuf[uiStreamId])
 		{
-			/* RGXHWPerfReleaseData call will null out the buffer fields
+			/* TLClientReleaseData call and null out the buffer fields
 			 * and length */
-			eError = RGXHWPerfReleaseData(hDevData, uiStreamId);
-			PVR_LOG_ERROR(eError, "RGXHWPerfReleaseData");
+			eError = TLClientReleaseData(DIRECT_BRIDGE_HANDLE, psDevData->hSD[uiStreamId]);
+			psDevData->ui32AcqDataLen[uiStreamId] = 0;
+			psDevData->pTlBuf[uiStreamId] = NULL;
+			PVR_LOG_IF_ERROR(eError, "TLClientReleaseData");
+			/* Packets may be lost if release was not required */
+			if (!psDevData->bRelease[uiStreamId])
+			{
+				PVR_DPF((PVR_DBG_WARNING, "RGXHWPerfClose: Events in buffer waiting to be read, remaining events may be lost."));
+			}
 		}
 
 		/* Close the TL stream, ignore the error if it occurs as we
@@ -2635,9 +3069,12 @@
 		{
 			eError = TLClientCloseStream(DIRECT_BRIDGE_HANDLE,
 										 psDevData->hSD[uiStreamId]);
-			PVR_LOG_ERROR(eError, "TLClientCloseStream");
+			PVR_LOG_IF_ERROR(eError, "TLClientCloseStream");
 			psDevData->hSD[uiStreamId] = NULL;
 		}
+
+		/* Free the client buffers used in session */
+		OSFreeMem(psDevData->pHwpBuf[uiStreamId]);
 	}
 
 	return PVRSRV_OK;
@@ -2650,10 +3087,10 @@
 	PVRSRV_ERROR eError = PVRSRV_OK;
 
 	eError = RGXHWPerfClose(hDevData);
-	PVR_LOG_ERROR(eError, "RGXHWPerfClose");
+	PVR_LOG_IF_ERROR(eError, "RGXHWPerfClose");
 
 	eError = RGXHWPerfFreeConnection(hDevData);
-	PVR_LOG_ERROR(eError, "RGXHWPerfFreeConnection");
+	PVR_LOG_IF_ERROR(eError, "RGXHWPerfFreeConnection");
 
 	return eError;
 }
@@ -2662,7 +3099,7 @@
 const IMG_CHAR *RGXHWPerfKickTypeToStr(RGX_HWPERF_KICK_TYPE eKickType)
 {
 	static const IMG_CHAR *aszKickType[RGX_HWPERF_KICK_TYPE_LAST+1] = {
-		"TA3D", "TQ2D", "TQ3D", "CDM", "RS", "VRDM", "LAST"
+		"TA3D", "TQ2D", "TQ3D", "CDM", "RS", "VRDM", "TQTDM", "SYNC", "LAST"
 	};
 
 	/* cast in case of negative value */
@@ -2674,6 +3111,35 @@
 	return aszKickType[eKickType];
 }
 
+
+IMG_UINT64 RGXHWPerfConvertCRTimeStamp(
+		IMG_UINT32 ui32ClkSpeed,
+		IMG_UINT64 ui64CorrCRTimeStamp,
+		IMG_UINT64 ui64CorrOSTimeStamp,
+		IMG_UINT64 ui64CRTimeStamp)
+{
+	IMG_UINT32 ui32Remainder;
+	IMG_UINT64 ui64CRDeltaToOSDeltaKNs;
+	IMG_UINT64 ui64EventOSTimestamp, deltaRgxTimer, delta_ns;
+
+	if (!(ui64CRTimeStamp) || !(ui32ClkSpeed) || !(ui64CorrCRTimeStamp) || !(ui64CorrOSTimeStamp))
+	{
+		return 0;
+	}
+
+	ui64CRDeltaToOSDeltaKNs = RGXFWIF_GET_CRDELTA_TO_OSDELTA_K_NS(ui32ClkSpeed,
+																  ui32Remainder);
+
+	/* RGX CR timer ticks delta */
+	deltaRgxTimer = ui64CRTimeStamp - ui64CorrCRTimeStamp;
+	/* RGX time delta in nanoseconds */
+	delta_ns = RGXFWIF_GET_DELTA_OSTIME_NS(deltaRgxTimer, ui64CRDeltaToOSDeltaKNs);
+	/* Calculate OS time of HWPerf event */
+	ui64EventOSTimestamp = ui64CorrOSTimeStamp + delta_ns;
+
+	return ui64EventOSTimestamp;
+}
+
 /******************************************************************************
- End of file (rgxdebug.c)
+ End of file (rgxhwperf.c)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxhwperf.h b/drivers/staging/imgtec/rogue/rgxhwperf.h
index 10a5a4a..9053074 100644
--- a/drivers/staging/imgtec/rogue/rgxhwperf.h
+++ b/drivers/staging/imgtec/rogue/rgxhwperf.h
@@ -52,7 +52,6 @@
 #include "connection_server.h"
 #include "rgxdevice.h"
 #include "rgx_hwperf_km.h"
-#include "pvrsrv.h"
 
 
 /******************************************************************************
@@ -64,6 +63,7 @@
 PVRSRV_ERROR RGXHWPerfInit(PVRSRV_DEVICE_NODE *psRgxDevInfo);
 PVRSRV_ERROR RGXHWPerfInitOnDemandResources(void);
 void RGXHWPerfDeinit(void);
+void RGXHWPerfInitAppHintCallbacks(const PVRSRV_DEVICE_NODE *psDeviceNode);
 
 /******************************************************************************
  * RGX HW Performance Profiling API(s)
@@ -101,18 +101,29 @@
  * RGX HW Performance Host Stream API
  *****************************************************************************/
 
-PVRSRV_ERROR RGXHWPerfHostInit(void);
+PVRSRV_ERROR RGXHWPerfHostInit(IMG_UINT32 ui32BufSizeKB);
 PVRSRV_ERROR RGXHWPerfHostInitOnDemandResources(void);
 void RGXHWPerfHostDeInit(void);
 
 void RGXHWPerfHostSetEventFilter(IMG_UINT32 ui32Filter);
 
+void RGXHWPerfHostPostCtrlEvent(RGX_HWPERF_HOST_CTRL_TYPE eEvType,
+                                IMG_UINT32 ui32Pid);
+
 void RGXHWPerfHostPostEnqEvent(RGX_HWPERF_KICK_TYPE eEnqType,
                                IMG_UINT32 ui32Pid,
-                               IMG_UINT32 ui32FWCtx,
+                               IMG_UINT32 ui32FWDMContext,
                                IMG_UINT32 ui32ExtJobRef,
                                IMG_UINT32 ui32IntJobRef);
 
+void RGXHWPerfHostPostAllocEvent(RGX_HWPERF_HOST_RESOURCE_TYPE eAllocType,
+                                 IMG_UINT32 ui32FWAddr,
+                                 const IMG_CHAR *psName,
+                                 IMG_UINT32 ui32NameSize);
+
+void RGXHWPerfHostPostFreeEvent(RGX_HWPERF_HOST_RESOURCE_TYPE eFreeType,
+                                IMG_UINT32 ui32FWAddr);
+
 void RGXHWPerfHostPostUfoEvent(RGX_HWPERF_UFO_EV eUfoType,
                                RGX_HWPERF_UFO_DATA_ELEMENT psUFOData[],
                                IMG_UINT uiNoOfUFOs);
@@ -136,6 +147,54 @@
  * @param I IntJobRef
  * @param K kick type
  */
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+#define RGX_HWPERF_HOST_CTRL(E, P) \
+		do { \
+			PVR_UNREFERENCED_PARAMETER(P); \
+		} while (0)
+
+#define RGX_HWPERF_HOST_ENQ(C, P, X, E, I, K) \
+		do { \
+			PVR_UNREFERENCED_PARAMETER(X); \
+			PVR_UNREFERENCED_PARAMETER(E); \
+			PVR_UNREFERENCED_PARAMETER(I); \
+		} while (0)
+
+#define RGX_HWPERF_HOST_UFO(T, D, N) \
+		do { \
+			PVR_UNREFERENCED_PARAMETER(T); \
+			PVR_UNREFERENCED_PARAMETER(D); \
+			PVR_UNREFERENCED_PARAMETER(N); \
+		} while (0)
+
+#define RGX_HWPERF_HOST_ALLOC(T, F, N, Z) \
+		do { \
+			PVR_UNREFERENCED_PARAMETER(RGX_HWPERF_HOST_RESOURCE_TYPE_##T); \
+			PVR_UNREFERENCED_PARAMETER(F); \
+			PVR_UNREFERENCED_PARAMETER(N); \
+			PVR_UNREFERENCED_PARAMETER(Z); \
+		} while (0)
+
+#define RGX_HWPERF_HOST_FREE(T, F) \
+		do { \
+			PVR_UNREFERENCED_PARAMETER(RGX_HWPERF_HOST_RESOURCE_TYPE_##T); \
+			PVR_UNREFERENCED_PARAMETER(F); \
+		} while (0)
+
+#define RGX_HWPERF_HOST_CLK_SYNC()
+#else
+/**
+ * @param E event type
+ * @param P PID
+ */
+#define RGX_HWPERF_HOST_CTRL(E, P) \
+		do { \
+			if (RGXHWPerfHostIsEventEnabled(RGX_HWPERF_HOST_CTRL)) \
+			{ \
+				RGXHWPerfHostPostCtrlEvent(RGX_HWPERF_CTRL_TYPE_##E, (P)); \
+			} \
+		} while (0)
+
 #define RGX_HWPERF_HOST_ENQ(C, P, X, E, I, K) \
 		do { \
 			if (_RGX_HWPERF_HOST_FILTER(C, RGX_HWPERF_HOST_ENQ)) \
@@ -150,7 +209,7 @@
  *
  * @param T Host UFO event type
  * @param D UFO data array
- * @param N nomber of syncs in data array
+ * @param N number of syncs in data array
  */
 #define RGX_HWPERF_HOST_UFO(T, D, N) \
 		do { \
@@ -160,14 +219,60 @@
 			} \
 		} while (0)
 
+/**
+ * This macro checks if HWPerfHost and the event are enabled and if they are
+ * it posts event to the HWPerfHost stream.
+ *
+ * @param F sync firmware address
+ * @param S boolean value telling if this is a server sync
+ * @param N string containing sync name
+ * @param Z string size including null terminating character
+ */
+#define RGX_HWPERF_HOST_ALLOC(T, F, N, Z) \
+		do { \
+			if (RGXHWPerfHostIsEventEnabled(RGX_HWPERF_HOST_ALLOC)) \
+			{ \
+				RGXHWPerfHostPostAllocEvent(RGX_HWPERF_HOST_RESOURCE_TYPE_##T, \
+				                            (F), (N), (Z)); \
+			} \
+		} while (0)
+
+/**
+ * This macro checks if HWPerfHost and the event are enabled and if they are
+ * it posts event to the HWPerfHost stream.
+ *
+ * @param F sync firmware address
+ */
+#define RGX_HWPERF_HOST_FREE(T, F) \
+		do { \
+			if (RGXHWPerfHostIsEventEnabled(RGX_HWPERF_HOST_FREE)) \
+			{ \
+				RGXHWPerfHostPostFreeEvent(RGX_HWPERF_HOST_RESOURCE_TYPE_##T, \
+				                           (F)); \
+			} \
+		} while (0)
+
+/**
+ * This macro checks if HWPerfHost and the event are enabled and if they are
+ * it posts event to the HWPerfHost stream.
+ */
+#define RGX_HWPERF_HOST_CLK_SYNC() \
+		do { \
+			if (RGXHWPerfHostIsEventEnabled(RGX_HWPERF_HOST_CLK_SYNC)) \
+			{ \
+				RGXHWPerfHostPostClkSyncEvent(); \
+			} \
+		} while (0)
+#endif
+
 /******************************************************************************
  * RGX HW Performance To FTrace Profiling API(s)
  *****************************************************************************/
 
 #if defined(SUPPORT_GPUTRACE_EVENTS)
 
-PVRSRV_ERROR RGXHWPerfFTraceGPUInit(PVRSRV_RGXDEV_INFO *psDevInfo);
-void RGXHWPerfFTraceGPUDeInit(void);
+PVRSRV_ERROR RGXHWPerfFTraceGPUInit(PVRSRV_DEVICE_NODE *psDeviceNode);
+void RGXHWPerfFTraceGPUDeInit(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 void RGXHWPerfFTraceGPUEnqueueEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
 		IMG_UINT32 ui32ExternalJobRef, IMG_UINT32 ui32InternalJobRef,
@@ -179,22 +284,6 @@
 
 #endif
 
-/**
- * This macro checks if HWPerfHost and the event are enabled and if they are
- * it posts event to the HWPerfHost stream.
- */
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-#define RGX_HWPERF_HOST_CLK_SYNC()
-#else
-#define RGX_HWPERF_HOST_CLK_SYNC() \
-		do { \
-			if (RGXHWPerfHostIsEventEnabled(RGX_HWPERF_HOST_CLK_SYNC)) \
-			{ \
-				RGXHWPerfHostPostClkSyncEvent(); \
-			} \
-		} while (0)
-#endif
-
 /******************************************************************************
  * RGX HW utils functions
  *****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxinit.c b/drivers/staging/imgtec/rogue/rgxinit.c
index 6bdbefd..e928054 100644
--- a/drivers/staging/imgtec/rogue/rgxinit.c
+++ b/drivers/staging/imgtec/rogue/rgxinit.c
@@ -43,27 +43,37 @@
 
 #include <stddef.h>
 
+#include "img_defs.h"
+#include "pvr_notifier.h"
 #include "pvrsrv.h"
+#include "syscommon.h"
+#include "rgx_heaps.h"
 #include "rgxheapconfig.h"
 #include "rgxpower.h"
 
 #include "rgxinit.h"
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+#include "rgxinit_vz.h"
+#endif
 
 #include "pdump_km.h"
 #include "handle.h"
 #include "allocmem.h"
+#include "devicemem.h"
 #include "devicemem_pdump.h"
 #include "rgxmem.h"
 #include "sync_internal.h"
+#include "pvrsrv_apphint.h"
+#include "oskm_apphint.h"
+#include "debugmisc_server.h"
 
 #include "rgxutils.h"
 #include "rgxfwutils.h"
 #include "rgx_fwif_km.h"
 
 #include "rgxmmuinit.h"
-#if defined(RGX_FEATURE_MIPS)
 #include "rgxmipsmmuinit.h"
-#endif
+#include "physmem.h"
 #include "devicemem_utils.h"
 #include "devicemem_server.h"
 #include "physmem_osmem.h"
@@ -73,8 +83,9 @@
 #if defined(SUPPORT_GPUTRACE_EVENTS)
 #include "pvr_gputrace.h"
 #endif
+#include "htbserver.h"
 
-#include "rgx_options_km.h"
+#include "rgx_options.h"
 #include "pvrversion.h"
 
 #include "rgx_compat_bvnc.h"
@@ -82,10 +93,27 @@
 #include "rgx_heaps.h"
 
 #include "rgxta3d.h"
-#include "debug_request_ids.h"
 #include "rgxtimecorr.h"
 
-static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions);
+#include "rgx_bvnc_table_km.h"
+#include "rgx_bvnc_defs_km.h"
+#if defined(PDUMP)
+#include "rgxstartstop.h"
+#endif
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+#include "rgx_fwif_alignchecks.h"
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+#endif
+
+#if defined(SUPPORT_PDVFS)
+#include "rgxpdvfs.h"
+#endif
+
+static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
 static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_CHAR **ppszVersionString);
 static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_PUINT32  pui32RGXClockSpeed);
 static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64  ui64ResetValue1, IMG_UINT64  ui64ResetValue2);
@@ -108,13 +136,15 @@
 
 #define VAR(x) #x
 
-static IMG_BOOL g_bDevInit2Done = IMG_FALSE;
+#define MAX_BVNC_LEN (12)
+#define RGXBVNC_BUFFER_SIZE (((PVRSRV_MAX_DEVICES)*(MAX_BVNC_LEN))+1)
 
+/* List of BVNC strings given as module param & count*/
+IMG_PCHAR gazRGXBVNCList[PVRSRV_MAX_DEVICES];
+IMG_UINT32 gui32RGXLoadTimeDevCount;
 
 static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
 
-volatile IMG_UINT32 g_ui32HostSampleIRQCount = 0;
-
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
 
 /* bits used by the LISR to provide a trace of its last execution */
@@ -131,7 +161,7 @@
 	/* snapshot from the last LISR invocation, regardless of
 	 * whether an interrupt was handled
 	 */
-	IMG_UINT32 ui32InterruptCountSnapshot;
+	IMG_UINT32 aui32InterruptCountSnapshot[RGXFW_THREAD_NUM];
 	/* time of the last LISR invocation */
 	IMG_UINT64 ui64Clockns;
 } LISR_EXECUTION_INFO;
@@ -142,39 +172,104 @@
 #endif
 
 #if !defined(NO_HARDWARE)
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+void RGX_WaitForInterruptsTimeout(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	OSScheduleMISR(psDevInfo->pvMISRData);
+}
+
+/*
+	Guest Driver RGX LISR Handler
+*/
+static IMG_BOOL RGX_LISRHandler (void *pvData)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+	if (psDevInfo->bRGXPowered == IMG_FALSE)
+	{
+		return IMG_FALSE;
+	}
+
+	OSScheduleMISR(psDevInfo->pvMISRData);
+	return IMG_TRUE;
+}
+#else
+
+/*************************************************************************/ /*! 
+@Function       SampleIRQCount
+@Description    Utility function taking snapshots of RGX FW interrupt count.
+@Input          paui32Input  A pointer to RGX FW IRQ count array.
+                             Size of the array should be equal to RGX FW thread
+                             count.
+@Input          paui32Output A pointer to array containing sampled RGX FW
+                             IRQ counts
+@Return         IMG_BOOL     Returns IMG_TRUE, if RGX FW IRQ is not equal to
+                             sampled RGX FW IRQ count for any RGX FW thread.
+*/ /**************************************************************************/ 
+static INLINE IMG_BOOL SampleIRQCount(volatile IMG_UINT32 *paui32Input,
+									  volatile IMG_UINT32 *paui32Output)
+{
+	IMG_UINT32 ui32TID;
+	IMG_BOOL bReturnVal = IMG_FALSE;
+
+	for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+	{
+		if (paui32Output[ui32TID] != paui32Input[ui32TID])
+		{
+			/**
+			 * we are handling any unhandled interrupts here so align the host
+			 * count with the FW count
+			 */
+
+			/* Sample the current count from the FW _after_ we've cleared the interrupt. */
+			paui32Output[ui32TID] = paui32Input[ui32TID];
+			bReturnVal = IMG_TRUE;
+		}
+	}
+
+	return bReturnVal;
+}
 
 void RGX_WaitForInterruptsTimeout(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-	PVR_DPF((PVR_DBG_ERROR, "_WaitForInterruptsTimeout: FW Count: 0x%X Host Count: 0x%X",
-						psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount,
-									g_ui32HostSampleIRQCount));
+	RGXFWIF_TRACEBUF *psRGXFWIfTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+	IMG_BOOL bScheduleMISR = IMG_FALSE;
+#if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+	IMG_UINT32 ui32TID;
+#endif
+
+	RGXDEBUG_PRINT_IRQ_COUNT(psDevInfo);
 
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+	PVR_DPF((PVR_DBG_ERROR, "Last RGX_LISRHandler State: 0x%08X Clock: %llu",
+							g_sLISRExecutionInfo.ui32State,
+							g_sLISRExecutionInfo.ui64Clockns));
 
-	PVR_DPF((PVR_DBG_ERROR, "Last RGX_LISRHandler State: 0x%08X InterruptCountSnapshot: 0x%X Clock: %llu",
-									g_sLISRExecutionInfo.ui32State,
-									g_sLISRExecutionInfo.ui32InterruptCountSnapshot,
-									g_sLISRExecutionInfo.ui64Clockns));
+	for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+	{
+		PVR_DPF((PVR_DBG_ERROR, \
+				"RGX FW thread %u: InterruptCountSnapshot: 0x%X", \
+				ui32TID, g_sLISRExecutionInfo.aui32InterruptCountSnapshot[ui32TID]));
+	}
 #else
 	PVR_DPF((PVR_DBG_ERROR, "No further information available. Please enable PVRSRV_DEBUG_LISR_EXECUTION"));
 #endif
 
 
-	if(psDevInfo->psRGXFWIfTraceBuf->ePowState != RGXFWIF_POW_OFF)
+	if(psRGXFWIfTraceBuf->ePowState != RGXFWIF_POW_OFF)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "_WaitForInterruptsTimeout: FW pow state is not OFF (is %u)",
-						(unsigned int) psDevInfo->psRGXFWIfTraceBuf->ePowState));
+						(unsigned int) psRGXFWIfTraceBuf->ePowState));
 	}
 
-	if(g_ui32HostSampleIRQCount != psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount)
+	bScheduleMISR = SampleIRQCount(psRGXFWIfTraceBuf->aui32InterruptCount, 
+								   psDevInfo->aui32SampleIRQCount);
+
+	if (bScheduleMISR)
 	{
-		/* we are handling any unhandled interrupts here so align the host
-		 * count with the FW count
-		 */
-		g_ui32HostSampleIRQCount = psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount;
-
 		OSScheduleMISR(psDevInfo->pvMISRData);
-
+		
 		if(psDevInfo->pvAPMISRData != NULL)
 		{
 			OSScheduleMISR(psDevInfo->pvAPMISRData);
@@ -188,13 +283,33 @@
 static IMG_BOOL RGX_LISRHandler (void *pvData)
 {
 	PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
-	PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
 	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 	IMG_BOOL bInterruptProcessed = IMG_FALSE;
-	IMG_UINT32 ui32IRQStatus;
+	RGXFWIF_TRACEBUF *psRGXFWIfTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+	IMG_UINT32 ui32IRQStatus, ui32IRQStatusReg, ui32IRQStatusEventMsk, ui32IRQClearReg, ui32IRQClearMask;
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		ui32IRQStatusReg = RGX_CR_MIPS_WRAPPER_IRQ_STATUS;
+		ui32IRQStatusEventMsk = RGX_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN;
+		ui32IRQClearReg = RGX_CR_MIPS_WRAPPER_IRQ_CLEAR;
+		ui32IRQClearMask = RGX_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN;
+	}else
+	{
+		ui32IRQStatusReg = RGX_CR_META_SP_MSLVIRQSTATUS;
+		ui32IRQStatusEventMsk = RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN;
+		ui32IRQClearReg = RGX_CR_META_SP_MSLVIRQSTATUS;
+		ui32IRQClearMask = RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK;
+	}
 
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
-	g_sLISRExecutionInfo.ui32InterruptCountSnapshot = psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount;
+	IMG_UINT32 ui32TID;
+
+	for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+	{
+		g_sLISRExecutionInfo.aui32InterruptCountSnapshot[ui32TID ] = 
+			psRGXFWIfTraceBuf->aui32InterruptCount[ui32TID];
+	}
 	g_sLISRExecutionInfo.ui32State = 0;
 	g_sLISRExecutionInfo.ui64Clockns = OSClockns64();
 #endif
@@ -204,35 +319,32 @@
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
 		g_sLISRExecutionInfo.ui32State |= RGX_LISR_DEVICE_NOT_POWERED;
 #endif
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-		/* Guest driver do not support FW trace */
-		return bInterruptProcessed;
-#else
-		if (psDevInfo->psRGXFWIfTraceBuf->ePowState == RGXFWIF_POW_OFF)
+		if (psRGXFWIfTraceBuf->ePowState == RGXFWIF_POW_OFF)
 		{
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
 			g_sLISRExecutionInfo.ui32State |= RGX_LISR_FWIF_POW_OFF;
 #endif
 			return bInterruptProcessed;
 		}
-#endif
 	}
 
-	ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGXFW_CR_IRQ_STATUS);
-	if (ui32IRQStatus & RGXFW_CR_IRQ_STATUS_EVENT_EN)
+	ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32IRQStatusReg);
+	if (ui32IRQStatus & ui32IRQStatusEventMsk)
 	{
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
 		g_sLISRExecutionInfo.ui32State |= RGX_LISR_EVENT_EN;
 #endif
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-		/* Guest driver do not support FW trace or device management */
-#else
-		OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGXFW_CR_IRQ_CLEAR, RGXFW_CR_IRQ_CLEAR_MASK);
-		
+
+		OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32IRQClearReg, ui32IRQClearMask);
+
 #if defined(RGX_FEATURE_OCPBUS)
 		OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OCP_IRQSTATUS_2, RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN);
 #endif
-		if (g_ui32HostSampleIRQCount == psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount)
+
+		bInterruptProcessed = SampleIRQCount(psRGXFWIfTraceBuf->aui32InterruptCount, 
+											 psDevInfo->aui32SampleIRQCount);
+
+		if (!bInterruptProcessed)
 		{
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
 			g_sLISRExecutionInfo.ui32State |= RGX_LISR_COUNTS_EQUAL;
@@ -240,15 +352,6 @@
 			return bInterruptProcessed;
 		}
 
-		/* Sample the current count from the FW _after_ we've cleared the interrupt. */
-		g_ui32HostSampleIRQCount = psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount;
-#endif
-
-		if (psDevConfig->pfnInterruptHandled)
-		{
-			psDevConfig->pfnInterruptHandled(psDevConfig);
-		}
-
 		bInterruptProcessed = IMG_TRUE;
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
 		g_sLISRExecutionInfo.ui32State |= RGX_LISR_PROCESSED;
@@ -261,11 +364,10 @@
 			OSScheduleMISR(psDevInfo->pvAPMISRData);
 		}
 	}
+
 	return bInterruptProcessed;
 }
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-#else
 static void RGXCheckFWActivePowerState(void *psDevice)
 {
 	PVRSRV_DEVICE_NODE	*psDeviceNode = psDevice;
@@ -280,56 +382,16 @@
 
 		if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED))
 		{
-			PVR_DPF((PVR_DBG_WARNING,"RGXCheckFWActivePowerState: Failed RGXActivePowerRequest call (device index: %d) with %s", 
-						psDeviceNode->sDevId.ui32DeviceIndex,
-						PVRSRVGetErrorStringKM(eError)));
+			PVR_DPF((PVR_DBG_WARNING,
+					 "%s: Failed RGXActivePowerRequest call (device: %p) with %s",
+					 __func__, psDeviceNode, PVRSRVGetErrorStringKM(eError)));
 			
-			PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+			PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
 		}
 	}
 
 }
 
-
-PVRSRV_ERROR RGXRegisterGpuUtilStats(IMG_HANDLE *phGpuUtilUser)
-{
-	RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
-
-	psAggregateStats = OSAllocMem(sizeof(RGXFWIF_GPU_UTIL_STATS));
-	if(psAggregateStats == NULL)
-	{
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
-	}
-
-	psAggregateStats->ui64GpuStatActiveLow  = 0;
-	psAggregateStats->ui64GpuStatIdle       = 0;
-	psAggregateStats->ui64GpuStatActiveHigh = 0;
-	psAggregateStats->ui64GpuStatBlocked    = 0;
-
-	/* Not used */
-	psAggregateStats->bValid = IMG_FALSE;
-	psAggregateStats->ui64GpuStatCumulative = 0;
-
-	*phGpuUtilUser = psAggregateStats;
-
-	return PVRSRV_OK;
-}
-
-PVRSRV_ERROR RGXUnregisterGpuUtilStats(IMG_HANDLE hGpuUtilUser)
-{
-	RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
-
-	if(hGpuUtilUser == NULL)
-	{
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-	psAggregateStats = hGpuUtilUser;
-	OSFreeMem(psAggregateStats);
-
-	return PVRSRV_OK;
-}
-
 /* Shorter defines to keep the code a bit shorter */
 #define GPU_ACTIVE_LOW   RGXFWIF_GPU_UTIL_STATE_ACTIVE_LOW
 #define GPU_IDLE         RGXFWIF_GPU_UTIL_STATE_IDLE
@@ -455,7 +517,46 @@
 
 	return PVRSRV_OK;
 }
-#endif
+#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
+
+PVRSRV_ERROR RGXRegisterGpuUtilStats(IMG_HANDLE *phGpuUtilUser)
+{
+	RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
+
+	psAggregateStats = OSAllocMem(sizeof(RGXFWIF_GPU_UTIL_STATS));
+	if(psAggregateStats == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psAggregateStats->ui64GpuStatActiveLow  = 0;
+	psAggregateStats->ui64GpuStatIdle       = 0;
+	psAggregateStats->ui64GpuStatActiveHigh = 0;
+	psAggregateStats->ui64GpuStatBlocked    = 0;
+
+	/* Not used */
+	psAggregateStats->bValid = IMG_FALSE;
+	psAggregateStats->ui64GpuStatCumulative = 0;
+
+	*phGpuUtilUser = psAggregateStats;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXUnregisterGpuUtilStats(IMG_HANDLE hGpuUtilUser)
+{
+	RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
+
+	if(hGpuUtilUser == NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psAggregateStats = hGpuUtilUser;
+	OSFreeMem(psAggregateStats);
+
+	return PVRSRV_OK;
+}
 
 /*
 	RGX MISR Handler
@@ -472,82 +573,163 @@
 	/* Inform other services devices that we have finished an operation */
 	PVRSRVCheckStatus(psDeviceNode);
 
+#if defined(SUPPORT_PDVFS) && defined(RGXFW_META_SUPPORT_2ND_THREAD)
+	/*
+	 * Firmware CCB only exists for primary FW thread. Only requirement for
+	 * non primary FW thread(s) to communicate with host driver is in the case
+	 * of PDVFS running on non primary FW thread.
+	 * This requirement is directly handled by the below
+	 */
+	RGXPDVFSCheckCoreClkRateChange(psDeviceNode->pvDevice);
+#endif
+
 	/* Process the Firmware CCB for pending commands */
 	RGXCheckFirmwareCCB(psDeviceNode->pvDevice);
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers do not perform general device management */
-#else
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	/* Calibrate the GPU frequency and recorrelate Host and FW timers (done every few seconds) */
 	RGXGPUFreqCalibrateCorrelatePeriodic(psDeviceNode);
 #endif
-}
-#endif
 
-#if defined(RGX_FEATURE_MIPS)
-/* This function puts into the firmware image some parameters for the initial boot*/
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	/* Process Workload Estimation Specific commands from the FW */
+	WorkEstCheckFirmwareCCB(psDeviceNode->pvDevice);
+#endif
+}
+#endif /* !defined(NO_HARDWARE) */
+
+
+/* This function puts into the firmware image some parameters for the initial boot */
 static PVRSRV_ERROR RGXBootldrDataInit(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                       void *pvFWImage,
-                                       PMR *psFWImagePMR,
-                                       IMG_UINT32 ui32BootLdrConfOffset,
-                                       IMG_UINT32 ui32BootCodeBaseAddress,
-                                       IMG_UINT32 ui32ExceptionVectorsBaseAddress)
+                                       void *pvFWImage)
 {
 	PVRSRV_ERROR eError;
 	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*) psDeviceNode->pvDevice;
+	IMG_UINT64 *pui64BootConfig;
 	IMG_DEV_PHYADDR sPhyAddr;
 	IMG_BOOL bValid;
 
-	IMG_UINT64 *pui64BootConfig = ((IMG_UINT64 *)(pvFWImage)) +
-	                              (ui32BootLdrConfOffset / 2) +
-	                              (ui32BootCodeBaseAddress / (2 * sizeof(IMG_UINT32)));
+	/* To get a pointer to the bootloader configuration data start from a pointer to the FW image... */
+	pui64BootConfig =  (IMG_UINT64 *) pvFWImage;
+
+	/* ... jump to the boot/NMI data page... */
+	pui64BootConfig += RGXMIPSFW_GET_OFFSET_IN_QWORDS(RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * RGXMIPSFW_PAGE_SIZE);
+
+	/* ... and then jump to the bootloader data offset within the page */
+	pui64BootConfig += RGXMIPSFW_GET_OFFSET_IN_QWORDS(RGXMIPSFW_BOOTLDR_CONF_OFFSET);
 
 
 	/* Rogue Registers physical address */
-	*pui64BootConfig++ = psDeviceNode->psDevConfig->sRegsCpuPBase.uiAddr;
+	PhysHeapCpuPAddrToDevPAddr(psDevInfo->psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL],
+							   1, &sPhyAddr, &(psDeviceNode->psDevConfig->sRegsCpuPBase));
+	pui64BootConfig[RGXMIPSFW_ROGUE_REGS_BASE_PHYADDR_OFFSET] = sPhyAddr.uiAddr;
 
-
-	/* MIPS Page Table physical address. There are 16 pages for a firmware heap of 32 MB*/
+	/* MIPS Page Table physical address. There are 16 pages for a firmware heap of 32 MB */
 	MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx, &sPhyAddr);
-	*pui64BootConfig++ = sPhyAddr.uiAddr;
+	pui64BootConfig[RGXMIPSFW_PAGE_TABLE_BASE_PHYADDR_OFFSET] = sPhyAddr.uiAddr;
 
-	/* MIPS exception vectors page physical address */
-	eError = RGXGetPhyAddr(psFWImagePMR, &sPhyAddr ,ui32ExceptionVectorsBaseAddress, (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE, 1, &bValid);
-
-
+	/* MIPS Stack Pointer Physical Address */
+	eError = RGXGetPhyAddr(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR,
+						   &sPhyAddr,
+						   RGXMIPSFW_STACK_OFFSET,
+						   RGXMIPSFW_LOG2_PAGE_SIZE,
+						   1,
+						   &bValid);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXBootldrDataInit: RGXGetPhyAddr failed (%u)",
 				eError));
 		return eError;
 	}
-	*pui64BootConfig++ = sPhyAddr.uiAddr;
+	pui64BootConfig[RGXMIPSFW_STACKPOINTER_PHYADDR_OFFSET] = sPhyAddr.uiAddr;
 
-
-	/*The MIPS Stack Pointer Physical Address*/
-	eError = RGXGetPhyAddr(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR, &sPhyAddr, 0, (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE, 1, &bValid);
-
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXBootldrDataInit: RGXGetPhyAddr failed (%u)",
-				eError));
-		return eError;
-	}
-	*pui64BootConfig++ = sPhyAddr.uiAddr;
 	/* Reserved for future use */
-	*pui64BootConfig++ = 0;
-	/*The FW Init Data Structure  Virtual Address*/
-	*pui64BootConfig++ = psDevInfo->psRGXFWIfInitMemDesc->sDeviceMemDesc.sDevVAddr.uiAddr;
+	pui64BootConfig[RGXMIPSFW_RESERVED_FUTURE_OFFSET] = 0;
+
+	/* FW Init Data Structure Virtual Address */
+	pui64BootConfig[RGXMIPSFW_FWINIT_VIRTADDR_OFFSET] = psDevInfo->psRGXFWIfInitMemDesc->sDeviceMemDesc.sDevVAddr.uiAddr;
 
 	return PVRSRV_OK;
 }
-#endif
+
+#if defined(PDUMP) && !defined(PVRSRV_GPUVIRT_GUESTDRV)
+static PVRSRV_ERROR RGXPDumpBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	PMR *psFWDataPMR = (PMR *)(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR);
+	IMG_DEV_PHYADDR sTmpAddr;
+	IMG_UINT32 ui32BootConfOffset, ui32ParamOffset;
+	PVRSRV_ERROR eError;
+
+	ui32BootConfOffset = (RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * RGXMIPSFW_PAGE_SIZE);
+	ui32BootConfOffset += RGXMIPSFW_BOOTLDR_CONF_OFFSET;
+
+	/* The physical addresses used by a pdump player will be different
+	 * than the ones we have put in the MIPS bootloader configuration data.
+	 * We have to tell the pdump player to replace the original values with the real ones.
+	 */
+	PDUMPCOMMENT("Pass new boot parameters to the FW");
+
+	/* Rogue Registers physical address */
+	ui32ParamOffset = ui32BootConfOffset + (RGXMIPSFW_ROGUE_REGS_BASE_PHYADDR_OFFSET * sizeof(IMG_UINT64));
+
+	eError = PDumpRegLabelToMem64(RGX_PDUMPREG_NAME,
+	                              0x0,
+	                              psFWDataPMR,
+	                              ui32ParamOffset,
+	                              PDUMP_FLAGS_CONTINUOUS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXPDumpBootldrData: Dump of Rogue registers phy address failed (%u)", eError));
+		return eError;
+	}
+
+	/* Page Table physical Address */
+	ui32ParamOffset = ui32BootConfOffset + (RGXMIPSFW_PAGE_TABLE_BASE_PHYADDR_OFFSET * sizeof(IMG_UINT64));
+
+	MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx, &sTmpAddr);
+
+	eError = PDumpPTBaseObjectToMem64(psDeviceNode->psFirmwareMMUDevAttrs->pszMMUPxPDumpMemSpaceName,
+	                                  psFWDataPMR,
+	                                  0,
+	                                  ui32ParamOffset,
+	                                  PDUMP_FLAGS_CONTINUOUS,
+	                                  MMU_LEVEL_1,
+	                                  sTmpAddr.uiAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXPDumpBootldrData: Dump of page tables phy address failed (%u)", eError));
+		return eError;
+	}
+
+	/* Stack physical address */
+	ui32ParamOffset = ui32BootConfOffset + (RGXMIPSFW_STACKPOINTER_PHYADDR_OFFSET * sizeof(IMG_UINT64));
+
+	eError = PDumpMemLabelToMem64(psFWDataPMR,
+	                              psFWDataPMR,
+	                              RGXMIPSFW_STACK_OFFSET,
+	                              ui32ParamOffset,
+	                              PDUMP_FLAGS_CONTINUOUS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXPDumpBootldrData: Dump of stack phy address failed (%u)", eError));
+		return eError;
+	}
+
+	return eError;
+}
+#endif /* PDUMP */
+
 
 PVRSRV_ERROR PVRSRVGPUVIRTPopulateLMASubArenasKM(CONNECTION_DATA    * psConnection,
                                                  PVRSRV_DEVICE_NODE	* psDeviceNode,
                                                  IMG_UINT32         ui32NumElements,
-                                                 IMG_UINT32         aui32Elements[])
+                                                 IMG_UINT32         aui32Elements[],
+                                                 IMG_BOOL         bEnableTrustedDeviceAceConfig)
 {
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 {
 	IMG_UINT32	ui32OS, ui32Region, ui32Counter=0;
@@ -568,41 +750,119 @@
 	}
 
 	PopulateLMASubArenas(psDeviceNode, aui32OSidMin, aui32OSidMax);
-}
+
+    #if defined(EMULATOR)
+    if ((bEnableTrustedDeviceAceConfig) && (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_AXI_ACELITE_BIT_MASK))
+    {
+        SetTrustedDeviceAceEnabled();
+    }
+    #else
+    {
+        PVR_UNREFERENCED_PARAMETER(bEnableTrustedDeviceAceConfig);
+    }
+    #endif
+    }
 #else
 {
 	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 	PVR_UNREFERENCED_PARAMETER(ui32NumElements);
 	PVR_UNREFERENCED_PARAMETER(aui32Elements);
+    PVR_UNREFERENCED_PARAMETER(bEnableTrustedDeviceAceConfig);
 }
 #endif
 
 	return PVRSRV_OK;
 }
 
-
 static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
                                       PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
-	IMG_DEV_PHYADDR sKernelMMUCtxPCAddr;
 	PVRSRV_ERROR eError;
 
-	eError = MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx,
-	                             &sKernelMMUCtxPCAddr);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: Failed to acquire Kernel MMU Ctx page catalog"));
-		return eError;
-	}
-
 	/* Save information used on power transitions for later
 	 * (when RGXStart and RGXStop are executed)
 	 */
 	psDevInfo->sPowerParams.psDevInfo = psDevInfo;
 	psDevInfo->sPowerParams.psDevConfig = psDevConfig;
-	psDevInfo->sPowerParams.sPCAddr = sKernelMMUCtxPCAddr;
+#if defined(PDUMP)
+	psDevInfo->sPowerParams.ui32PdumpFlags = PDUMP_FLAGS_CONTINUOUS;
+#endif
+	if(psDevInfo->sDevFeatureCfg.ui32META)
+	{
+		IMG_DEV_PHYADDR sKernelMMUCtxPCAddr;
 
-#if defined(SUPPORT_TRUSTED_DEVICE)
+		eError = MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx,
+		                             &sKernelMMUCtxPCAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: Failed to acquire Kernel MMU Ctx page catalog"));
+			return eError;
+		}
+
+		psDevInfo->sPowerParams.sPCAddr = sKernelMMUCtxPCAddr;
+	}else
+	{
+		PMR *psFWCodePMR = (PMR *)(psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR);
+		PMR *psFWDataPMR = (PMR *)(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR);
+		IMG_DEV_PHYADDR sPhyAddr;
+		IMG_BOOL bValid;
+
+		/* The physical address of the GPU registers needs to be translated
+		 * in case we are in a LMA scenario
+		 */
+		PhysHeapCpuPAddrToDevPAddr(psDevInfo->psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL],
+		                           1,
+		                           &sPhyAddr,
+		                           &(psDevConfig->sRegsCpuPBase));
+
+		psDevInfo->sPowerParams.sGPURegAddr = sPhyAddr;
+
+		eError = RGXGetPhyAddr(psFWCodePMR,
+		                       &sPhyAddr,
+		                       RGXMIPSFW_BOOT_NMI_CODE_BASE_PAGE * RGXMIPSFW_PAGE_SIZE,
+		                       RGXMIPSFW_LOG2_PAGE_SIZE,
+		                       1,
+		                       &bValid);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: Failed to acquire FW boot/NMI code address"));
+			return eError;
+		}
+
+		psDevInfo->sPowerParams.sBootRemapAddr = sPhyAddr;
+
+		eError = RGXGetPhyAddr(psFWDataPMR,
+		                       &sPhyAddr,
+		                       RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * RGXMIPSFW_PAGE_SIZE,
+		                       RGXMIPSFW_LOG2_PAGE_SIZE,
+		                       1,
+		                       &bValid);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: Failed to acquire FW boot/NMI data address"));
+			return eError;
+		}
+
+		psDevInfo->sPowerParams.sDataRemapAddr = sPhyAddr;
+
+		eError = RGXGetPhyAddr(psFWCodePMR,
+		                       &sPhyAddr,
+		                       RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * RGXMIPSFW_PAGE_SIZE,
+		                       RGXMIPSFW_LOG2_PAGE_SIZE,
+		                       1,
+		                       &bValid);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: Failed to acquire FW exceptions address"));
+			return eError;
+		}
+
+		psDevInfo->sPowerParams.sCodeRemapAddr = sPhyAddr;
+
+		psDevInfo->sPowerParams.sTrampolineRemapAddr.uiAddr = psDevInfo->sTrampoline.sPhysAddr.uiAddr;
+	}
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
 	/* Send information used on power transitions to the trusted device as
 	 * in this setup the driver cannot start/stop the GPU and perform resets
 	 */
@@ -610,8 +870,18 @@
 	{
 		PVRSRV_TD_POWER_PARAMS sTDPowerParams;
 
-		sTDPowerParams.sPCAddr = psDevInfo->sPowerParams.sPCAddr;
-		eError = psDevConfig->pfnTDSetPowerParams(&sTDPowerParams);
+		if(psDevInfo->sDevFeatureCfg.ui32META)
+		{
+			sTDPowerParams.sPCAddr = psDevInfo->sPowerParams.sPCAddr;
+		}else
+		{
+			sTDPowerParams.sGPURegAddr      = psDevInfo->sPowerParams.sGPURegAddr;
+			sTDPowerParams.sBootRemapAddr = psDevInfo->sPowerParams.sBootRemapAddr;
+			sTDPowerParams.sCodeRemapAddr = psDevInfo->sPowerParams.sCodeRemapAddr;
+			sTDPowerParams.sDataRemapAddr = psDevInfo->sPowerParams.sDataRemapAddr;
+		}
+		eError = psDevConfig->pfnTDSetPowerParams(psDevConfig->hSysData,
+												  &sTDPowerParams);
 	}
 	else
 	{
@@ -630,9 +900,8 @@
 PVRSRV_ERROR PVRSRVRGXInitDevPart2KM (CONNECTION_DATA       *psConnection,
                                       PVRSRV_DEVICE_NODE	*psDeviceNode,
 									  RGX_INIT_COMMAND		*psDbgScript,
-									  RGX_INIT_COMMAND		*psDbgBusScript,
-									  RGX_INIT_COMMAND		*psDeinitScript,
 									  IMG_UINT32			ui32DeviceFlags,
+									  IMG_UINT32			ui32HWPerfHostBufSizeKB,
 									  IMG_UINT32			ui32HWPerfHostFilter,
 									  RGX_ACTIVEPM_CONF		eActivePMConf,
 									  PMR					*psFWCodePMR,
@@ -645,78 +914,18 @@
 	PVRSRV_DEV_POWER_STATE	eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
 	PVRSRV_DEVICE_CONFIG	*psDevConfig = psDeviceNode->psDevConfig;
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers do not perform pdump(ing) of fw initialization */
-#else
-#if defined(PDUMP) && defined (RGX_FEATURE_MIPS)
-	IMG_DEV_PHYADDR ui64TempAddr;
-	IMG_UINT32 ui32BootConfOffset = RGXMIPSFW_BOOTLDR_CONF_OFFSET_KERNEL + (RGXMIPSFW_BOOTCODE_BASE_PAGE * RGXMIPSFW_PAGE_SIZE)/sizeof(IMG_UINT32);
-	IMG_UINT32 ui32ExceptionVectorsBaseAddress = RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * RGXMIPSFW_PAGE_SIZE;
-
-	/* Fixing the pdump with the proper labels in the boot configuration areas */
-	PDUMPCOMMENT("Pass parameters to the FW into the ELF file, registers and page table physical locations");
-
-	/* Rogue Registers physical address. Here the pdump label containing the registers address is
-		copied to the memory location containing that information (that is the first configuration word
-		in the MIPS boot code) */
-	eError = PDumpRegLabelToMem64(RGX_PDUMPREG_NAME,
-                                      0x0,
-                                      psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
-                                      (ui32BootConfOffset/2) * sizeof(IMG_UINT64),
-                                      PDUMP_FLAGS_CONTINUOUS);
-
-	if (eError != PVRSRV_OK)
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+#if defined(PDUMP)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXPdumpBootldrDataInitKM: First PDumpSymbolicPhyReg failed %u", eError));
-		return eError;
-	}
-	/* Page Table Phy Addresses */
-	MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx, &ui64TempAddr);
-
-	eError = PDumpPTBaseObjectToMem64(psDeviceNode->pszMMUPxPDumpMemSpaceName,
-                                          psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
-                                          0,
-                                          (ui32BootConfOffset/2 + 1) * sizeof(IMG_UINT64),
-                                          PDUMP_FLAGS_CONTINUOUS,
-                                          MMU_LEVEL_1,
-                                          ui64TempAddr.uiAddr);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXPdumpBootldrDataInitKM: PDumpSymbolicPhySymbolicPhy failed %u", eError));
-		return eError;
-	}
-
-
-	/* Exception vectors */
-	eError = PDumpMemLabelToMem64(psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
-                                      psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
-                                      ui32ExceptionVectorsBaseAddress,
-                                      (ui32BootConfOffset/2 + 1 + 1) * sizeof(IMG_UINT64),
-                                      PDUMP_FLAGS_CONTINUOUS);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXPdumpBootldrDataInitKM: PDumpSymbolicPhySymbolicPhy failed %u", eError));
-		return eError;
-	}
-
-	/* Stack Physical address */
-	eError = PDumpMemLabelToMem64(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR,
-                                      psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
-                                      0,
-                                      (ui32BootConfOffset/2 + 1 + 1 + 1) * sizeof(IMG_UINT64),
-                                      PDUMP_FLAGS_CONTINUOUS);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXPdumpBootldrDataInitKM: PDumpSymbolicPhySymbolicPhy failed %u", eError));
-		return eError;
+		RGXPDumpBootldrData(psDeviceNode, psDevInfo);
 	}
 #endif
 
 #if defined(TIMING) || defined(DEBUG)
 	OSUserModeAccessToPerfCountersEn();
 #endif
-
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
+#endif
 
 	/* Passing down the PMRs to destroy their handles */
 	PVR_UNREFERENCED_PARAMETER(psFWCodePMR);
@@ -726,73 +935,30 @@
 
 	PDUMPCOMMENT("RGX Initialisation Part 2");
 
-	/*
-	 * Map RGX Registers
-	 */
-#if !defined(NO_HARDWARE)
-	psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psDevConfig->sRegsCpuPBase,
-										     psDevConfig->ui32RegsSize,
-										     0);
-
-	if (psDevInfo->pvRegsBaseKM == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: Failed to create RGX register mapping"));
-		return PVRSRV_ERROR_BAD_MAPPING;
-	}
-#else
-	psDevInfo->pvRegsBaseKM = NULL;
-#endif /* !NO_HARDWARE */
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers do not perform actual on-chip fw 
-	 *	- Loading, Initialization, Management
-	 */	
-	PVR_UNREFERENCED_PARAMETER(psDbgScript);
-	PVR_UNREFERENCED_PARAMETER(psDbgBusScript);
-	PVR_UNREFERENCED_PARAMETER(psDeinitScript);
-	PVR_UNREFERENCED_PARAMETER(eActivePMConf);
-#else
-	/*
-	 * Copy scripts
-	 */
-	OSMemCopy(psDevInfo->psScripts->asDbgCommands, psDbgScript,
-			  RGX_MAX_DEBUG_COMMANDS * sizeof(*psDbgScript));
-
-	OSMemCopy(psDevInfo->psScripts->asDbgBusCommands, psDbgBusScript,
-			  RGX_MAX_DBGBUS_COMMANDS * sizeof(*psDbgBusScript));
-
-	OSMemCopy(psDevInfo->psScripts->asDeinitCommands, psDeinitScript,
-			  RGX_MAX_DEINIT_COMMANDS * sizeof(*psDeinitScript));
-
-#if defined(PDUMP)
-	/* Run the deinit script to feed the last-frame deinit buffer */
-	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "RGX deinitialisation script");
-	RGXRunScript(psDevInfo, psDevInfo->psScripts->asDeinitCommands, RGX_MAX_DEINIT_COMMANDS, PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW, NULL, NULL);
-#endif
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
-
 	psDevInfo->ui32RegSize = psDevConfig->ui32RegsSize;
 	psDevInfo->sRegsPhysBase = psDevConfig->sRegsCpuPBase;
 
 	/* Initialise Device Flags */
 	psDevInfo->ui32DeviceFlags = 0;
-	if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_ZERO_FREELIST)
+	RGXSetDeviceFlags(psDevInfo, ui32DeviceFlags, IMG_TRUE);
+
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/* Allocate DVFS Table (needs to be allocated before SUPPORT_GPUTRACE_EVENTS
+	 * is initialised because there is a dependency between them) */
+	psDevInfo->psGpuDVFSTable = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSTable)));
+	if (psDevInfo->psGpuDVFSTable == NULL)
 	{
-		psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_ZERO_FREELIST;
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to allocate gpu dvfs table storage"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN)
-	{
-		psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN;
-	}
-
-	if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_DUST_REQUEST_INJECT_EN)
-	{
-		psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_DUST_REQUEST_INJECT_EN;
-	}
+	/* Reset DVFS Table */
+	psDevInfo->psGpuDVFSTable->ui32CurrentDVFSId = 0;
+	psDevInfo->psGpuDVFSTable->aui32DVFSClock[0] = 0;
+#endif /* !defined(PVRSRV_GPUVIRT_GUESTDRV) */
 
 	/* Initialise HWPerfHost buffer. */
-	if (RGXHWPerfHostInit() == PVRSRV_OK)
+	if (RGXHWPerfHostInit(ui32HWPerfHostBufSizeKB) == PVRSRV_OK)
 	{
 		/* If HWPerf enabled allocate all resources for the host side buffer. */
 		if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_HWPERF_HOST_EN)
@@ -848,6 +1014,15 @@
 	dllist_init(&psDevInfo->sFreeListHead);
 	psDevInfo->ui32FreelistCurrID = 1;
 
+#if 1//defined(SUPPORT_RAY_TRACING)
+	eError = OSLockCreate(&psDevInfo->hLockRPMFreeList,LOCK_TYPE_PASSIVE);
+	PVR_ASSERT(eError == PVRSRV_OK);
+	dllist_init(&psDevInfo->sRPMFreeListHead);
+	psDevInfo->ui32RPMFreelistCurrID = 1;
+	eError = OSLockCreate(&psDevInfo->hLockRPMContext,LOCK_TYPE_PASSIVE);
+	PVR_ASSERT(eError == PVRSRV_OK);
+#endif
+
 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
 	eError = OSLockCreate(&psDevInfo->hDebugFaultInfoLock, LOCK_TYPE_PASSIVE);
 
@@ -863,30 +1038,18 @@
 		return eError;
 	}
 #endif
-#if defined(RGX_FEATURE_MIPS)
-	eError = OSLockCreate(&psDevInfo->hNMILock, LOCK_TYPE_DISPATCH);
 
-	if(eError != PVRSRV_OK)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
 	{
-		return eError;
-	}
-#endif
+		eError = OSLockCreate(&psDevInfo->hNMILock, LOCK_TYPE_DISPATCH);
 
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest driver do not support HwPerf & Dvfs */
-#else
-	/* Allocate DVFS Table */
-	psDevInfo->psGpuDVFSTable = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSTable)));
-	if (psDevInfo->psGpuDVFSTable == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to allocate gpu dvfs table storage"));
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
+		if(eError != PVRSRV_OK)
+		{
+			return eError;
+		}
 	}
 
-	/* Reset DVFS Table */
-	psDevInfo->psGpuDVFSTable->ui32CurrentDVFSId = 0;
-	psDevInfo->psGpuDVFSTable->aui32DVFSClock[0] = 0;
-
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
 	/* Setup GPU utilisation stats update callback */
 #if !defined(NO_HARDWARE)
 	psDevInfo->pfnGetGpuUtilStats = RGXGetGpuUtilStats;
@@ -896,6 +1059,7 @@
 	PVR_ASSERT(eError == PVRSRV_OK);
 
 	eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
+	psDevInfo->eActivePMConf = eActivePMConf;
 
 	/* set-up the Active Power Mgmt callback */
 #if !defined(NO_HARDWARE)
@@ -904,7 +1068,10 @@
 		IMG_BOOL bSysEnableAPM = psRGXData->psRGXTimingInfo->bEnableActivePM;
 		IMG_BOOL bEnableAPM = ((eActivePMConf == RGX_ACTIVEPM_DEFAULT) && bSysEnableAPM) ||
 							   (eActivePMConf == RGX_ACTIVEPM_FORCE_ON);
-
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+		/* Disable APM for now */
+		bEnableAPM = IMG_FALSE;
+#endif
 		if (bEnableAPM)
 		{
 			eError = OSInstallMISR(&psDevInfo->pvAPMISRData, RGXCheckFWActivePowerState, psDeviceNode);
@@ -918,22 +1085,30 @@
 		}
 	}
 #endif
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
+#endif
+
+	PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableAPM,
+	                                    RGXQueryAPMState,
+	                                    RGXSetAPMState,
+	                                    psDeviceNode,
+	                                    NULL);
+
+	RGXGPUFreqCalibrationInitAppHintCallbacks(psDeviceNode);
 
 	/* 
 		Register the device with the power manager.
 			Normal/Hyperv Drivers: Supports power management
 			Guest Drivers: Do not currently support power management
 	*/
-	eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
-										&RGXPrePowerState, &RGXPostPowerState,
-										psDevConfig->pfnPrePowerState, psDevConfig->pfnPostPowerState,
-										&RGXPreClockSpeedChange, &RGXPostClockSpeedChange,
-										&RGXForcedIdleRequest, &RGXCancelForcedIdleRequest,
-										&RGXDustCountChange,
-										(IMG_HANDLE)psDeviceNode,
-										PVRSRV_DEV_POWER_STATE_OFF,
-										eDefaultPowerState);
+	eError = PVRSRVRegisterPowerDevice(psDeviceNode,
+									   &RGXPrePowerState, &RGXPostPowerState,
+									   psDevConfig->pfnPrePowerState, psDevConfig->pfnPostPowerState,
+									   &RGXPreClockSpeedChange, &RGXPostClockSpeedChange,
+									   &RGXForcedIdleRequest, &RGXCancelForcedIdleRequest,
+									   &RGXDustCountChange,
+									   (IMG_HANDLE)psDeviceNode,
+									   PVRSRV_DEV_POWER_STATE_OFF,
+									   eDefaultPowerState);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to register device with power manager"));
@@ -943,6 +1118,33 @@
 	eError = RGXSetPowerParams(psDevInfo, psDevConfig);
 	if (eError != PVRSRV_OK) return eError;
 
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/* 
+	 * Guest drivers do not perform on-chip firmware
+	 *  - Loading, Initialization and Management
+	 */
+	PVR_UNREFERENCED_PARAMETER(psDbgScript);
+	PVR_UNREFERENCED_PARAMETER(eActivePMConf);
+#else
+	/*
+	 * Copy scripts
+	 */
+	OSCachedMemCopy(psDevInfo->psScripts->asDbgCommands, psDbgScript,
+			  RGX_MAX_DEBUG_COMMANDS * sizeof(*psDbgScript));
+
+#if defined(PDUMP)
+	/* Run RGXStop with the correct PDump flags to feed the last-frame deinit buffer */
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "RGX deinitialisation commands");
+
+	psDevInfo->sPowerParams.ui32PdumpFlags |= PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW;
+
+	eError = RGXStop(&psDevInfo->sPowerParams);
+	if (eError != PVRSRV_OK) return eError;
+
+	psDevInfo->sPowerParams.ui32PdumpFlags &= ~(PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW);
+#endif
+#endif
+
 #if !defined(NO_HARDWARE)
 	eError = RGXInstallProcessQueuesMISR(&psDevInfo->hProcessQueuesMISR, psDeviceNode);
 	if (eError != PVRSRV_OK)
@@ -967,8 +1169,12 @@
 		return eError;
 	}
 
-	eError = OSInstallDeviceLISR(psDevConfig, &psDevInfo->pvLISRData,
-								 RGX_LISRHandler, psDeviceNode);
+	eError = SysInstallDeviceLISR(psDevConfig->hSysData,
+								  psDevConfig->ui32IRQ,
+								  PVRSRV_MODNAME,
+								  RGX_LISRHandler,
+								  psDeviceNode,
+								  &psDevInfo->pvLISRData);
 	if (eError != PVRSRV_OK)
 	{
 		if (psDevInfo->pvAPMISRData != NULL)
@@ -979,28 +1185,40 @@
 		(void) OSUninstallMISR(psDevInfo->pvMISRData);
 		return eError;
 	}
-
 #endif
 
-#if defined(PDUMP) && !defined(RGX_FEATURE_S7_CACHE_HIERARCHY)
-	if (!PVRSRVSystemSnoopingOfCPUCache() && !PVRSRVSystemSnoopingOfDeviceCache())
+#if defined(SUPPORT_PDVFS) && !defined(RGXFW_META_SUPPORT_2ND_THREAD)
+	psDeviceNode->psDevConfig->sDVFS.sPDVFSData.hReactiveTimer =
+		OSAddTimer((PFN_TIMER_FUNC)PDVFSRequestReactiveUpdate,
+		           psDevInfo,
+		           PDVFS_REACTIVE_INTERVAL_MS);
+
+	OSEnableTimer(psDeviceNode->psDevConfig->sDVFS.sPDVFSData.hReactiveTimer);
+#endif
+
+#if defined(PDUMP)
+	if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK))
 	{
-		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has NO cache snooping");
-	}
-	else
-	{
-		if (PVRSRVSystemSnoopingOfCPUCache())
+		if (!PVRSRVSystemSnoopingOfCPUCache(psDevConfig) &&
+			!PVRSRVSystemSnoopingOfDeviceCache(psDevConfig))
 		{
-			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has CPU cache snooping");
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has NO cache snooping");
 		}
-		if (PVRSRVSystemSnoopingOfDeviceCache())
+		else
 		{
-			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has DEVICE cache snooping");
+			if (PVRSRVSystemSnoopingOfCPUCache(psDevConfig))
+			{
+				PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has CPU cache snooping");
+			}
+			if (PVRSRVSystemSnoopingOfDeviceCache(psDevConfig))
+			{
+				PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has DEVICE cache snooping");
+			}
 		}
 	}
 #endif
 
-	g_bDevInit2Done = IMG_TRUE;
+	psDevInfo->bDevInit2Done = IMG_TRUE;
 
 	return PVRSRV_OK;
 }
@@ -1016,19 +1234,11 @@
 	 */
 	sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS_DIRECT;
 
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRLock();
-#endif
-
 	eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
 											RGXFWIF_DM_GP,
 											&sKccbCmd,
 											sizeof(sKccbCmd),
-											IMG_TRUE);
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRUnlock();
-#endif
+											PDUMP_FLAGS_CONTINUOUS);
 
 	return PVRSRV_OK;
 
@@ -1054,7 +1264,8 @@
 	}
 
 	eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
-								  "Firmware",
+								  "Firmware", /* FIXME: We need to create an IDENT macro for this string.
+								                 Make sure the IDENT macro is not accessible to userland */
 								  &psDevInfo->psFirmwareHeap);
 	if (eError != PVRSRV_OK)
 	{
@@ -1063,7 +1274,14 @@
 	}
 
 #if defined(SUPPORT_PVRSRV_GPUVIRT)
-	eError = RGXVirtInitCreateFWKernelMemoryContext(psDeviceNode);
+	eError = RGXVzInitCreateFWKernelMemoryContext(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "RGXInitCreateFWKernelMemoryContext: Failed RGXVzInitCreateFWKernelMemoryContext (%u)",
+				 eError));
+		goto failed_to_find_heap;
+	}
 #endif
 
 	return eError;
@@ -1086,1189 +1304,192 @@
 	PVRSRV_RGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
 	PVRSRV_ERROR        eError;
 
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	RGXVzDeInitDestroyFWKernelMemoryContext(psDeviceNode);
+#endif
+
 	/*
 	 * Clear the mem context create callbacks before destroying the RGX firmware
 	 * context to avoid a spurious callback.
 	 */
 	psDeviceNode->pfnRegisterMemoryContext = NULL;
-	psDeviceNode->pfnUnregisterMemoryContext = NULL;	
+	psDeviceNode->pfnUnregisterMemoryContext = NULL;
 
 	if (psDevInfo->psKernelDevmemCtx)
 	{
 		eError = DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
+		/* FIXME - this should return void */
 		PVR_ASSERT(eError == PVRSRV_OK);
 	}
 }
 
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(RGXFW_ALIGNCHECKS)
+static PVRSRV_ERROR RGXAlignmentCheck(PVRSRV_DEVICE_NODE *psDevNode,
+                                      IMG_UINT32 ui32AlignChecksSize,
+                                      IMG_UINT32 aui32AlignChecks[])
+{
+	static IMG_UINT32 aui32AlignChecksKM[] = {RGXFW_ALIGN_CHECKS_INIT_KM};
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice;
+	IMG_UINT32 i, *paui32FWAlignChecks;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (psDevInfo->psRGXFWAlignChecksMemDesc == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAlignmentCheckKM: FW Alignment Check"
+		        " Mem Descriptor is NULL"));
+		return PVRSRV_ERROR_ALIGNMENT_ARRAY_NOT_AVAILABLE;
+	}
+
+	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc,
+	                                  (void **) &paui32FWAlignChecks);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAlignmentCheckKM: Failed to acquire"
+		        " kernel address for alignment checks (%u)", eError));
+		return eError;
+	}
+
+	paui32FWAlignChecks += IMG_ARR_NUM_ELEMS(aui32AlignChecksKM) + 1;
+	if (*paui32FWAlignChecks++ != ui32AlignChecksSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAlignmentCheckKM: Mismatch"
+					" in number of structures to check."));
+		eError = PVRSRV_ERROR_INVALID_ALIGNMENT;
+		goto return_;
+	}
+
+	for (i = 0; i < ui32AlignChecksSize; i++)
+	{
+		if (aui32AlignChecks[i] != paui32FWAlignChecks[i])
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVAlignmentCheckKM: Check for"
+					" structured alignment failed."));
+			eError = PVRSRV_ERROR_INVALID_ALIGNMENT;
+			goto return_;
+		}
+	}
+
+return_:
+
+	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc);
+
+	return eError;
+}
+#endif /* defined(SUPPORT_KERNEL_SRVINIT) */
+
 #if defined(PVRSRV_GPUVIRT_GUESTDRV)
-/* Guest driver do not perform actual on-chip FW loading/initialization */
+static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/* FW compatibility checks are ignored in guest drivers */
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
+								 IMG_UINT64  ui64ResetValue1,
+								 IMG_UINT64  ui64ResetValue2)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(ui64ResetValue1);
+	PVR_UNREFERENCED_PARAMETER(ui64ResetValue2);
+	return PVRSRV_OK;
+}
+
+static void RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgReqestHandle,
+					IMG_UINT32 ui32VerbLevel,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	PVR_UNREFERENCED_PARAMETER(hDbgReqestHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32VerbLevel);
+	PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
+	PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitAllocFWImgMemKM(CONNECTION_DATA      *psConnection,
+										  PVRSRV_DEVICE_NODE   *psDeviceNode,
+										  IMG_DEVMEM_SIZE_T    uiFWCodeLen,
+										  IMG_DEVMEM_SIZE_T    uiFWDataLen,
+										  IMG_DEVMEM_SIZE_T    uiFWCorememLen,
+										  PMR                  **ppsFWCodePMR,
+										  IMG_DEV_VIRTADDR     *psFWCodeDevVAddrBase,
+										  PMR                  **ppsFWDataPMR,
+										  IMG_DEV_VIRTADDR     *psFWDataDevVAddrBase,
+										  PMR                  **ppsFWCorememPMR,
+										  IMG_DEV_VIRTADDR     *psFWCorememDevVAddrBase,
+										  RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase)
+{
+	DEVMEM_FLAGS_T uiMemAllocFlags;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	PVRSRV_ERROR eError;
+
+	/* Guest driver do not perform actual on-chip FW loading/initialization */
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(uiMemAllocFlags);
+
+	eError = RGXInitCreateFWKernelMemoryContext(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXInitCreateFWKernelMemoryContext: Failed (%u)", eError));
+		goto failFWMemoryContextAlloc;
+	}
+
+failFWMemoryContextAlloc:
+	return eError;
+}
 #else
 static
 PVRSRV_ERROR RGXAllocateFWCodeRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
                                      IMG_DEVMEM_SIZE_T ui32FWCodeAllocSize,
-                                     IMG_UINT32 uiMemAllocFlags)
+                                     IMG_UINT32 uiMemAllocFlags,
+                                     IMG_BOOL bFWCorememCode,
+                                     const IMG_PCHAR pszText,
+                                     DEVMEM_MEMDESC **ppsMemDescPtr)
 {
-	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 	PVRSRV_ERROR eError;
+	IMG_DEVMEM_LOG2ALIGN_T uiLog2Align = OSGetPageShift();
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		uiLog2Align = RGXMIPSFW_LOG2_PAGE_SIZE_64K;
+	}
+#endif
 
 #if !defined(SUPPORT_TRUSTED_DEVICE)
 	uiMemAllocFlags |= PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
 	                   PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
-	PDUMPCOMMENT("Allocate and export code memory for fw");
+	PVR_UNREFERENCED_PARAMETER(bFWCorememCode);
+
+	PDUMPCOMMENT("Allocate and export FW %s memory",
+	             bFWCorememCode? "coremem code" : "code");
 
 	eError = DevmemFwAllocateExportable(psDeviceNode,
 	                                    ui32FWCodeAllocSize,
+	                                    1 << uiLog2Align,
 	                                    uiMemAllocFlags,
-	                                    "FwExCodeRegion",
-	                                    &psDevInfo->psRGXFWCodeMemDesc);
+	                                    pszText,
+	                                    ppsMemDescPtr);
 	return eError;
 #else
-	PDUMPCOMMENT("Import TD META code memory for fw");
+	PDUMPCOMMENT("Import secure FW %s memory",
+	             bFWCorememCode? "coremem code" : "code");
 
-	eError = DevmemImportTDMetaCode(psDeviceNode,
-	                                uiMemAllocFlags,
-	                                &psDevInfo->psRGXFWCodeMemDesc);
+	eError = DevmemImportTDFWCode(psDeviceNode,
+	                              ui32FWCodeAllocSize,
+	                              uiLog2Align,
+	                              uiMemAllocFlags,
+	                              bFWCorememCode,
+	                              ppsMemDescPtr);
 	return eError;
 #endif
 }
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
-
-IMG_EXPORT
-PVRSRV_ERROR PVRSRVRGXInitAllocFWImgMemKM(CONNECTION_DATA      *psConnection,
-                                          PVRSRV_DEVICE_NODE   *psDeviceNode,
-                                          IMG_DEVMEM_SIZE_T    uiFWCodeLen,
-                                          IMG_DEVMEM_SIZE_T    uiFWDataLen,
-                                          IMG_DEVMEM_SIZE_T    uiFWCorememLen,
-                                          PMR                  **ppsFWCodePMR,
-                                          IMG_DEV_VIRTADDR     *psFWCodeDevVAddrBase,
-                                          PMR                  **ppsFWDataPMR,
-                                          IMG_DEV_VIRTADDR     *psFWDataDevVAddrBase,
-                                          PMR                  **ppsFWCorememPMR,
-                                          IMG_DEV_VIRTADDR     *psFWCorememDevVAddrBase,
-                                          RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase)
-{
-	DEVMEM_FLAGS_T		uiMemAllocFlags;
-	PVRSRV_RGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
-	PVRSRV_ERROR        eError;
-
-	PMRLock();
-
-	PVR_UNREFERENCED_PARAMETER(psConnection);
-
-	eError = RGXInitCreateFWKernelMemoryContext(psDeviceNode);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed RGXInitCreateFWKernelMemoryContext (%u)", eError));
-		goto failFWMemoryContextAlloc;
-	}
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest driver do not perform actual on-chip FW loading/initialization */
-	PVR_UNREFERENCED_PARAMETER(psDevInfo);
-	PVR_UNREFERENCED_PARAMETER(uiMemAllocFlags);
-#else
-	/* 
-	 * Set up Allocation for FW code section 
-	 */
-	uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-	                  PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
-	                  PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-                          PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
-	                  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
-
-
-	eError = RGXAllocateFWCodeRegion(psDeviceNode,
-                                     uiFWCodeLen,
-	                                 uiMemAllocFlags);
-
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw code mem (%u)",
-				eError));
-		goto failFWCodeMemDescAlloc;
-	}
-
-	eError = DevmemLocalGetImportHandle(psDevInfo->psRGXFWCodeMemDesc, (void**) ppsFWCodePMR);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"DevmemLocalGetImportHandle failed (%u)", eError));
-		goto failFWCodeMemDescAqDevVirt;
-	}
-
-	eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
-	                                  &psDevInfo->sFWCodeDevVAddrBase);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw code mem (%u)",
-				eError));
-		goto failFWCodeMemDescAqDevVirt;
-	}
-	*psFWCodeDevVAddrBase = psDevInfo->sFWCodeDevVAddrBase;
-
-	/*
-	* The FW code must be the first allocation in the firmware heap, otherwise
-	* the bootloader will not work (META will not be able to find the bootloader).
-	*/
-	PVR_ASSERT(psFWCodeDevVAddrBase->uiAddr == RGX_FIRMWARE_HEAP_BASE);
-
-	/* 
-	 * Set up Allocation for FW data section 
-	 */
-	uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-	                  PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
-	                  PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-                          PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
-	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-	                  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
-	                  PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
-
-	PDUMPCOMMENT("Allocate and export data memory for fw");
-
-	eError = DevmemFwAllocateExportable(psDeviceNode,
-										uiFWDataLen,
-										uiMemAllocFlags,
-										"FwExDataRegion",
-	                                    &psDevInfo->psRGXFWDataMemDesc);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw data mem (%u)",
-				eError));
-		goto failFWDataMemDescAlloc;
-	}
-
-	eError = DevmemLocalGetImportHandle(psDevInfo->psRGXFWDataMemDesc, (void **) ppsFWDataPMR);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"DevmemLocalGetImportHandle failed (%u)", eError));
-		goto failFWDataMemDescAqDevVirt;
-	}
-
-	eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
-	                                  &psDevInfo->sFWDataDevVAddrBase);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw data mem (%u)",
-				eError));
-		goto failFWDataMemDescAqDevVirt;
-	}
-	*psFWDataDevVAddrBase = psDevInfo->sFWDataDevVAddrBase;
-
-	if (uiFWCorememLen != 0)
-	{
-		/* 
-		 * Set up Allocation for FW coremem section 
-		 */
-		uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-			PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
-			PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
-			PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-			PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-			PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-			PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-			PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
-			PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
-
-		PDUMPCOMMENT("Allocate and export coremem memory for fw");
-
-		eError = DevmemFwAllocateExportable(psDeviceNode,
-				uiFWCorememLen,
-				uiMemAllocFlags,
-				"FwExCorememRegion",
-				&psDevInfo->psRGXFWCorememMemDesc);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw coremem mem, size: %lld, flags: %x (%u)",
-						uiFWCorememLen, uiMemAllocFlags, eError));
-			goto failFWCorememMemDescAlloc;
-		}
-
-		eError = DevmemLocalGetImportHandle(psDevInfo->psRGXFWCorememMemDesc, (void**) ppsFWCorememPMR);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"DevmemLocalGetImportHandle failed (%u)", eError));
-			goto failFWCorememMemDescAqDevVirt;
-		}
-
-		eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc,
-		                                  &psDevInfo->sFWCorememCodeDevVAddrBase);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw coremem mem (%u)",
-						eError));
-			goto failFWCorememMemDescAqDevVirt;
-		}
-
-		RGXSetFirmwareAddress(&psDevInfo->sFWCorememCodeFWAddr,
-		                      psDevInfo->psRGXFWCorememMemDesc,
-		                      0, RFW_FWADDR_NOREF_FLAG);
-
-#if defined(HW_ERN_45914)
-		/* temporarily make sure the coremem is init using the SLC */
-		psDevInfo->sFWCorememCodeFWAddr.ui32Addr &= ~RGXFW_SEGMMU_DMAP_ADDR_START;
-		psDevInfo->sFWCorememCodeFWAddr.ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
-#endif
-
-	}
-	else
-	{
-		psDevInfo->sFWCorememCodeDevVAddrBase.uiAddr = 0;
-		psDevInfo->sFWCorememCodeFWAddr.ui32Addr = 0;
-	}
-
-	*psFWCorememDevVAddrBase = psDevInfo->sFWCorememCodeDevVAddrBase;
-	*psFWCorememMetaVAddrBase = psDevInfo->sFWCorememCodeFWAddr;
-
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
-
-	PMRUnlock();
-	return PVRSRV_OK;
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Labels n/a to guest drivers */
-#else
-failFWCorememMemDescAqDevVirt:
-
-	if (uiFWCorememLen != 0)
-	{
-		DevmemFwFree(psDevInfo->psRGXFWCorememMemDesc);
-		psDevInfo->psRGXFWCorememMemDesc = NULL;
-	}
-failFWCorememMemDescAlloc:
-	DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
-failFWDataMemDescAqDevVirt:
-
-	DevmemFwFree(psDevInfo->psRGXFWDataMemDesc);
-	psDevInfo->psRGXFWDataMemDesc = NULL;
-failFWDataMemDescAlloc:
-
-	DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
-failFWCodeMemDescAqDevVirt:
-	DevmemFwFree(psDevInfo->psRGXFWCodeMemDesc);
-	psDevInfo->psRGXFWCodeMemDesc = NULL;
-failFWCodeMemDescAlloc:
-#endif
-
-failFWMemoryContextAlloc:
-	return eError;
-}
-
-/*
- * PVRSRVRGXInitFirmwareKM
- */ 
-IMG_EXPORT PVRSRV_ERROR
-PVRSRVRGXInitFirmwareKM(CONNECTION_DATA          *psConnection,
-                        PVRSRV_DEVICE_NODE       *psDeviceNode,
-                        RGXFWIF_DEV_VIRTADDR     *psRGXFwInit,
-                        IMG_BOOL                 bEnableSignatureChecks,
-                        IMG_UINT32               ui32SignatureChecksBufSize,
-                        IMG_UINT32               ui32HWPerfFWBufSizeKB,
-                        IMG_UINT64               ui64HWPerfFilter,
-                        IMG_UINT32               ui32RGXFWAlignChecksSize,
-                        IMG_UINT32               *pui32RGXFWAlignChecks,
-                        IMG_UINT32               ui32ConfigFlags,
-                        IMG_UINT32               ui32LogType,
-                        IMG_UINT32               ui32FilterFlags,
-                        IMG_UINT32               ui32JonesDisableMask,
-                        IMG_UINT32               ui32HWRDebugDumpLimit,
-                        RGXFWIF_COMPCHECKS_BVNC  *psClientBVNC,
-                        IMG_UINT32               ui32HWPerfCountersDataSize,
-                        PMR                      **ppsHWPerfPMR,
-                        RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
-                        FW_PERF_CONF             eFirmwarePerf)
-{
-	PVRSRV_ERROR eError;
-	RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
-	IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
-	IMG_UINT32 ui32NumBIFTilingConfigs, *pui32BIFTilingXStrides, i;
-
-
-	/* Check if BVNC numbers of client and driver are compatible */
-	rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
-
-	RGX_BVNC_EQUAL(sBVNC, *psClientBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
-
-	if (!bCompatibleAll)
-	{
-		if (!bCompatibleVersion)
-		{
-			PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and client (%d).",
-					__FUNCTION__, 
-					sBVNC.ui32LayoutVersion, 
-					psClientBVNC->ui32LayoutVersion));
-			eError = PVRSRV_ERROR_BVNC_MISMATCH;
-			PVR_DBG_BREAK;
-			goto failed_to_pass_compatibility_check;
-		}
-
-		if (!bCompatibleLenMax)
-		{
-			PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and client (%d).",
-					__FUNCTION__, 
-					sBVNC.ui32VLenMax, 
-					psClientBVNC->ui32VLenMax));
-			eError = PVRSRV_ERROR_BVNC_MISMATCH;
-			PVR_DBG_BREAK;
-			goto failed_to_pass_compatibility_check;
-		}
-
-		if (!bCompatibleBNC)
-		{
-			PVR_LOG(("(FAIL) %s: Incompatible driver BNC (%d._.%d.%d) / client BNC (%d._.%d.%d).",
-					__FUNCTION__, 
-					RGX_BVNC_PACKED_EXTR_B(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_N(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_C(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_B(*psClientBVNC), 
-					RGX_BVNC_PACKED_EXTR_N(*psClientBVNC), 
-					RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
-			eError = PVRSRV_ERROR_BVNC_MISMATCH;
-			PVR_DBG_BREAK;
-			goto failed_to_pass_compatibility_check;
-		}
-		
-		if (!bCompatibleV)
-		{
-			PVR_LOG(("(FAIL) %s: Incompatible driver BVNC (%d.%s.%d.%d) / client BVNC (%d.%s.%d.%d).",
-					__FUNCTION__, 
-					RGX_BVNC_PACKED_EXTR_B(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_V(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_N(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_C(sBVNC), 
-					RGX_BVNC_PACKED_EXTR_B(*psClientBVNC), 
-					RGX_BVNC_PACKED_EXTR_V(*psClientBVNC),
-					RGX_BVNC_PACKED_EXTR_N(*psClientBVNC), 
-					RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
-			eError = PVRSRV_ERROR_BVNC_MISMATCH;
-			PVR_DBG_BREAK;
-			goto failed_to_pass_compatibility_check;
-		}
-	}
-	else
-	{
-		PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver BVNC (%d.%s.%d.%d) and client BVNC (%d.%s.%d.%d) match. [ OK ]",
-				__FUNCTION__, 
-				RGX_BVNC_PACKED_EXTR_B(sBVNC), 
-				RGX_BVNC_PACKED_EXTR_V(sBVNC), 
-				RGX_BVNC_PACKED_EXTR_N(sBVNC), 
-				RGX_BVNC_PACKED_EXTR_C(sBVNC), 
-				RGX_BVNC_PACKED_EXTR_B(*psClientBVNC), 
-				RGX_BVNC_PACKED_EXTR_V(*psClientBVNC), 
-				RGX_BVNC_PACKED_EXTR_N(*psClientBVNC), 
-				RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
-	}
-
-	GetNumBifTilingHeapConfigs(&ui32NumBIFTilingConfigs);
-	pui32BIFTilingXStrides = OSAllocMem(sizeof(IMG_UINT32) * ui32NumBIFTilingConfigs);
-	if(pui32BIFTilingXStrides == NULL)
-	{
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: OSAllocMem failed (%u)", eError));
-		goto failed_BIF_tiling_alloc;
-	}
-	for(i = 0; i < ui32NumBIFTilingConfigs; i++)
-	{
-		eError = GetBIFTilingHeapXStride(i+1, &pui32BIFTilingXStrides[i]);
-		if(eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: GetBIFTilingHeapXStride for heap %u failed (%u)",
-			         i + 1, eError));
-			goto failed_BIF_heap_init;
-		}
-	}
-
-	eError = RGXSetupFirmware(psDeviceNode,
-	                          bEnableSignatureChecks,
-	                          ui32SignatureChecksBufSize,
-	                          ui32HWPerfFWBufSizeKB,
-	                          ui64HWPerfFilter,
-	                          ui32RGXFWAlignChecksSize,
-	                          pui32RGXFWAlignChecks,
-	                          ui32ConfigFlags,
-	                          ui32LogType,
-	                          ui32NumBIFTilingConfigs,
-	                          pui32BIFTilingXStrides,
-	                          ui32FilterFlags,
-	                          ui32JonesDisableMask,
-	                          ui32HWRDebugDumpLimit,
-	                          ui32HWPerfCountersDataSize,
-	                          ppsHWPerfPMR,
-	                          psRGXFwInit,
-	                          eRGXRDPowerIslandingConf,
-	                          eFirmwarePerf);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: RGXSetupFirmware failed (%u)", eError));
-		goto failed_init_firmware;
-	}
-	
-	OSFreeMem(pui32BIFTilingXStrides);
-
-	return PVRSRV_OK;
-
-failed_init_firmware:
-failed_BIF_heap_init:
-	OSFreeMem(pui32BIFTilingXStrides);
-failed_BIF_tiling_alloc:
-failed_to_pass_compatibility_check:
-	PVR_ASSERT(eError != PVRSRV_OK);
-	return eError;
-}
-
-/* See device.h for function declaration */
-static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
-									 DEVMEM_MEMDESC **psMemDesc,
-									 IMG_UINT32 *puiSyncPrimVAddr,
-									 IMG_UINT32 *puiSyncPrimBlockSize)
-{
-	PVRSRV_RGXDEV_INFO *psDevInfo;
-	PVRSRV_ERROR eError;
-	RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
-	IMG_DEVMEM_SIZE_T uiUFOBlockSize = sizeof(IMG_UINT32);
-	IMG_DEVMEM_ALIGN_T ui32UFOBlockAlign = sizeof(IMG_UINT32);
-
-	psDevInfo = psDeviceNode->pvDevice;
-
-	/* Size and align are 'expanded' because we request an Exportalign allocation */
-	DevmemExportalignAdjustSizeAndAlign(psDevInfo->psFirmwareHeap,
-										&uiUFOBlockSize,
-										&ui32UFOBlockAlign);
-
-	eError = DevmemFwAllocateExportable(psDeviceNode,
-										uiUFOBlockSize,
-										PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-										PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-										PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
-										PVRSRV_MEMALLOCFLAG_CACHE_COHERENT | 
-										PVRSRV_MEMALLOCFLAG_GPU_READABLE |
-										PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-										PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-										PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
-										"FwExUFOBlock",
-										psMemDesc);
-	if (eError != PVRSRV_OK)
-	{
-		goto e0;
-	}
-
-	DevmemPDumpLoadMem(*psMemDesc,
-					   0,
-					   uiUFOBlockSize,
-					   PDUMP_FLAGS_CONTINUOUS);
-
-	RGXSetFirmwareAddress(&pFirmwareAddr, *psMemDesc, 0, RFW_FWADDR_FLAG_NONE);
-	*puiSyncPrimVAddr = pFirmwareAddr.ui32Addr;
-	*puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
-
-	return PVRSRV_OK;
-
-e0:
-	return eError;
-}
-
-/* See device.h for function declaration */
-static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
-							DEVMEM_MEMDESC *psMemDesc)
-{
-	/*
-		If the system has snooping of the device cache then the UFO block
-		might be in the cache so we need to flush it out before freeing
-		the memory
-	*/
-	if (PVRSRVSystemSnoopingOfDeviceCache())
-	{
-		RGXFWIF_KCCB_CMD sFlushInvalCmd;
-		PVRSRV_ERROR eError;
-
-		/* Schedule the SLC flush command ... */
-#if defined(PDUMP)
-		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
-#endif
-		sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
-		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
-		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bDMContext = IMG_FALSE;
-		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = 0;
-		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
-
-		eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
-											RGXFWIF_DM_GP,
-											&sFlushInvalCmd,
-											sizeof(sFlushInvalCmd),
-											IMG_TRUE);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: Failed to schedule SLC flush command with error (%u)", eError));
-		}
-		else
-		{
-			/* Wait for the SLC flush to complete */
-			eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: SLC flush and invalidate aborted with error (%u)", eError));
-			}
-		}
-	}
-
-	RGXUnsetFirmwareAddress(psMemDesc);
-	DevmemFwFree(psMemDesc);
-}
-
-/*
-	DevDeInitRGX
-*/
-PVRSRV_ERROR DevDeInitRGX (PVRSRV_DEVICE_NODE *psDeviceNode)
-{
-	PVRSRV_RGXDEV_INFO			*psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
-	PVRSRV_ERROR				eError;
-	DEVICE_MEMORY_INFO		    *psDevMemoryInfo;
-	IMG_UINT32		ui32Temp=0;
-	if (!psDevInfo)
-	{
-		/* Can happen if DevInitRGX failed */
-		PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Null DevInfo"));
-		return PVRSRV_OK;
-	}
-
-	/*Delete the Dummy page related info */
-	ui32Temp = (IMG_UINT32)OSAtomicRead(&psDeviceNode->sDummyPage.atRefCounter);
-	if(0 != ui32Temp)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"%s: Dummy page reference counter is non zero", __func__));
-		PVR_ASSERT(0);
-	}
-#if defined(PDUMP)
-		if(NULL != psDeviceNode->sDummyPage.hPdumpDummyPg)
-		{
-			PDUMPCOMMENT("Error dummy page handle is still active");
-		}
-#endif
-
-	/*The lock type need to be dispatch type here because it can be acquired from MISR (Z-buffer) path */
-	OSLockDestroy(psDeviceNode->sDummyPage.psDummyPgLock);
-
-	/* Unregister debug request notifiers first as they could depend on anything. */
-	PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
-
-	/* Cancel notifications to this device */
-	PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
-	psDeviceNode->hCmdCompNotify = NULL;
-
-	/*
-	 *  De-initialise in reverse order, so stage 2 init is undone first.
-	 */
-	if (g_bDevInit2Done)
-	{
-		g_bDevInit2Done = IMG_FALSE;
-
-#if !defined(NO_HARDWARE)
-		(void) OSUninstallDeviceLISR(psDevInfo->pvLISRData);
-		(void) OSUninstallMISR(psDevInfo->pvMISRData);
-		(void) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
-		if (psDevInfo->pvAPMISRData != NULL)
-		{
-			(void) OSUninstallMISR(psDevInfo->pvAPMISRData);
-		}
-#endif /* !NO_HARDWARE */
-
-		/* Remove the device from the power manager */
-		eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
-		if (eError != PVRSRV_OK)
-		{
-			return eError;
-		}
-
-		OSLockDestroy(psDevInfo->hGPUUtilLock);
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-		/* Guest driver do not support dvfs */
-#else
-		/* Free DVFS Table */
-		if (psDevInfo->psGpuDVFSTable != NULL)
-		{
-			OSFreeMem(psDevInfo->psGpuDVFSTable);
-			psDevInfo->psGpuDVFSTable = NULL;
-		}
-#endif
-
-		/* De-init Freelists/ZBuffers... */
-		OSLockDestroy(psDevInfo->hLockFreeList);
-		OSLockDestroy(psDevInfo->hLockZSBuffer);
-
-		RGXHWPerfHostDeInit();
-
-		/* Unregister MMU related stuff */
-		eError = RGXMMUInit_Unregister(psDeviceNode);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)", eError));
-			return eError;
-		}
-
-#if defined(RGX_FEATURE_MIPS)
-		/* Unregister MMU related stuff */
-		eError = RGXMipsMMUInit_Unregister(psDeviceNode);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed RGXMipsMMUInit_Unregister (0x%x)", eError));
-			return eError;
-		}
-#endif
-
-
-		/* UnMap Regs */
-		if (psDevInfo->pvRegsBaseKM != NULL)
-		{
-#if !defined(NO_HARDWARE)
-			OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
-							 psDevInfo->ui32RegSize,
-							 0);
-#endif /* !NO_HARDWARE */
-			psDevInfo->pvRegsBaseKM = NULL;
-		}
-	}
-
-#if 0 /* not required at this time */
-	if (psDevInfo->hTimer)
-	{
-		eError = OSRemoveTimer(psDevInfo->hTimer);
-		if (eError != PVRSRV_OK)
-		{
-			PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed to remove timer"));
-			return 	eError;
-		}
-		psDevInfo->hTimer = NULL;
-	}
-#endif
-
-    psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
-
-	RGXDeInitHeaps(psDevMemoryInfo);
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest driver do not perform fw loading */
-#else
-	if (psDevInfo->psRGXFWCodeMemDesc)
-	{
-		/* Free fw code */
-		PDUMPCOMMENT("Freeing FW code memory");
-		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
-		DevmemFwFree(psDevInfo->psRGXFWCodeMemDesc);
-		psDevInfo->psRGXFWCodeMemDesc = NULL;
-	}
-	else
-	{
-		PVR_DPF((PVR_DBG_ERROR,"No firmware code memory to free!"));
-	}
-	if (psDevInfo->psRGXFWDataMemDesc)
-	{
-		/* Free fw data */
-		PDUMPCOMMENT("Freeing FW data memory");
-		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
-		DevmemFwFree(psDevInfo->psRGXFWDataMemDesc);
-		psDevInfo->psRGXFWDataMemDesc = NULL;
-	}
-	else
-	{
-		PVR_DPF((PVR_DBG_ERROR,"No firmware data memory to free!"));
-	}
-
-	if (psDevInfo->psRGXFWCorememMemDesc)
-	{
-		/* Free fw data */
-		PDUMPCOMMENT("Freeing FW coremem memory");
-		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc);
-		DevmemFwFree(psDevInfo->psRGXFWCorememMemDesc);
-		psDevInfo->psRGXFWCorememMemDesc = NULL;
-	}
-#endif
-
-	/*
-	   Free the firmware allocations.
-	 */
-	RGXFreeFirmware(psDevInfo);
-	RGXDeInitDestroyFWKernelMemoryContext(psDeviceNode);
-
-
-	/* destroy the context list locks */
-	OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
-	OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
-	OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
-	OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
-	OSWRLockDestroy(psDevInfo->hKickSyncCtxListLock);
-	OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
-
-#if defined(RGX_FEATURE_MIPS)
-	if (psDevInfo->hNMILock != NULL)
-	{
-		OSLockDestroy(psDevInfo->hNMILock);
-	}
-#endif
-
-#if defined(SUPPORT_PAGE_FAULT_DEBUG)
-	if (psDevInfo->hDebugFaultInfoLock != NULL)
-	{
-		OSLockDestroy(psDevInfo->hDebugFaultInfoLock);
-	}
-	if (psDevInfo->hMMUCtxUnregLock != NULL)
-	{
-		OSLockDestroy(psDevInfo->hMMUCtxUnregLock);
-	}
-#endif
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-#else
-	/* Free the init scripts. */
-	OSFreeMem(psDevInfo->psScripts);
-#endif
-
-	/* DeAllocate devinfo */
-	OSFreeMem(psDevInfo);
-
-	psDeviceNode->pvDevice = NULL;
-
-	return PVRSRV_OK;
-}
-
-/*!
-******************************************************************************
- 
- @Function	RGXDebugRequestNotify
-
- @Description Dump the debug data for RGX
-  
-******************************************************************************/
-static void RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgReqestHandle, IMG_UINT32 ui32VerbLevel,
-	DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile)
-{
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	PVR_UNREFERENCED_PARAMETER(hDbgReqestHandle);
-	PVR_UNREFERENCED_PARAMETER(ui32VerbLevel);
-#else
-	PVRSRV_DEVICE_NODE *psDeviceNode = hDbgReqestHandle;
-
-	/* Only action the request if we've fully init'ed */
-	if (g_bDevInit2Done)
-	{
-		RGXDebugRequestProcess(pfnDumpDebugPrintf, pvDumpDebugFile, psDeviceNode->pvDevice, ui32VerbLevel);
-	}
-#endif
-}
-
-#if defined(PDUMP)
-static
-PVRSRV_ERROR RGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
-{
-	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
-
-	psDevInfo->bDumpedKCCBCtlAlready = IMG_FALSE;
-
-	return PVRSRV_OK;
-}
-#endif /* PDUMP */
-
-static INLINE DEVMEM_HEAP_BLUEPRINT _blueprint_init(IMG_CHAR *name,
-	IMG_UINT64 heap_base,
-	IMG_DEVMEM_SIZE_T heap_length,
-	IMG_UINT32 log2_import_alignment)
-{
-	DEVMEM_HEAP_BLUEPRINT b = {
-		.pszName = name,
-		.sHeapBaseAddr.uiAddr = heap_base,
-		.uiHeapLength = heap_length,
-		.uiLog2DataPageSize = GET_LOG2_PAGESIZE(),
-		.uiLog2ImportAlignment = log2_import_alignment
-	};
-
-	return b;
-}
-
-#define INIT_HEAP(NAME) \
-do { \
-	*psDeviceMemoryHeapCursor = _blueprint_init( \
-			RGX_ ## NAME ## _HEAP_IDENT, \
-			RGX_ ## NAME ## _HEAP_BASE, \
-			RGX_ ## NAME ## _HEAP_SIZE, \
-			0); \
-	psDeviceMemoryHeapCursor++; \
-} while (0)
-
-#define INIT_HEAP_NAME(STR, NAME) \
-do { \
-	*psDeviceMemoryHeapCursor = _blueprint_init( \
-			STR, \
-			RGX_ ## NAME ## _HEAP_BASE, \
-			RGX_ ## NAME ## _HEAP_SIZE, \
-			0); \
-	psDeviceMemoryHeapCursor++; \
-} while (0)
-
-#define INIT_TILING_HEAP(N) \
-do { \
-	IMG_UINT32 xstride; \
-	GetBIFTilingHeapXStride(N, &xstride); \
-	*psDeviceMemoryHeapCursor = _blueprint_init( \
-			RGX_BIF_TILING_HEAP_ ## N ## _IDENT, \
-			RGX_BIF_TILING_HEAP_ ## N ## _BASE, \
-			RGX_BIF_TILING_HEAP_SIZE, \
-			RGX_BIF_TILING_HEAP_ALIGN_LOG2_FROM_XSTRIDE(xstride)); \
-	psDeviceMemoryHeapCursor++; \
-} while (0)
-
-static PVRSRV_ERROR RGXInitHeaps(DEVICE_MEMORY_INFO *psNewMemoryInfo, IMG_UINT32 *pui32DummyPgSize)
-{
-    DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor;
-
-	psNewMemoryInfo->psDeviceMemoryHeap = OSAllocMem(sizeof(DEVMEM_HEAP_BLUEPRINT) * RGX_MAX_HEAP_ID);
-    if(psNewMemoryInfo->psDeviceMemoryHeap == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_BLUEPRINT"));
-		goto e0;
-	}
-
-	/* Calculate the dummy page size which is the maximum page size supported
-	 * by heaps which can have sparse allocations
-	 *
-	 * The heaps that can have sparse allocations are general and Doppler for now.
-	 * As it was suggested the doppler allocations doesn't have to be backed by dummy
-	 * and taking into account its massize 2MB page size supported in future, we take
-	 * general heap page size as reference for now */
-	*pui32DummyPgSize =  GET_LOG2_PAGESIZE();
-
-	/* Initialise the heaps */
-	psDeviceMemoryHeapCursor = psNewMemoryInfo->psDeviceMemoryHeap;
-
-	INIT_HEAP(GENERAL);
-	INIT_HEAP(VISTEST);
-	INIT_HEAP(PDSCODEDATA);
-	INIT_HEAP(USCCODE);
-	INIT_HEAP(TQ3DPARAMETERS);
-	INIT_TILING_HEAP(1);
-	INIT_TILING_HEAP(2);
-	INIT_TILING_HEAP(3);
-	INIT_TILING_HEAP(4);
-	INIT_HEAP(DOPPLER);
-	INIT_HEAP(DOPPLER_OVERFLOW);
-#if defined(FIX_HW_BRN_37200)
-	INIT_HEAP_NAME("HWBRN37200", HWBRN37200);
-#endif
-	INIT_HEAP_NAME("Firmware", FIRMWARE);
-
-	/* set the heap count */
-	psNewMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeapCursor - psNewMemoryInfo->psDeviceMemoryHeap);
-
-	PVR_ASSERT(psNewMemoryInfo->ui32HeapCount <= RGX_MAX_HEAP_ID);
-
-    /* the new way: we'll set up 2 heap configs: one will be for Meta
-       only, and has only the firmware heap in it. 
-       The remaining one shall be for clients only, and shall have all
-       the other heaps in it */
-
-    psNewMemoryInfo->uiNumHeapConfigs = 2;
-	psNewMemoryInfo->psDeviceMemoryHeapConfigArray = OSAllocMem(sizeof(DEVMEM_HEAP_CONFIG) * psNewMemoryInfo->uiNumHeapConfigs);
-    if (psNewMemoryInfo->psDeviceMemoryHeapConfigArray == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_CONFIG"));
-		goto e1;
-	}
-    
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].pszName = "Default Heap Configuration";
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].uiNumHeaps = psNewMemoryInfo->ui32HeapCount-1;
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].psHeapBlueprintArray = psNewMemoryInfo->psDeviceMemoryHeap;
-
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].pszName = "Firmware Heap Configuration";
-#if defined(FIX_HW_BRN_37200)
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 2;
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-2;
-#else
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 1;
-    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-1;
-#endif
-
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	if (RGXVirtInitHeaps(psNewMemoryInfo, psDeviceMemoryHeapCursor) != PVRSRV_OK)
-	{
-		goto e1;
-	}
-#endif
-
-	return PVRSRV_OK;
-e1:
-	OSFreeMem(psNewMemoryInfo->psDeviceMemoryHeap);
-e0:
-	return PVRSRV_ERROR_OUT_OF_MEMORY;
-}
-
-#undef INIT_HEAP
-#undef INIT_HEAP_NAME
-#undef INIT_TILING_HEAP
-
-static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
-{
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-	RGXVirtDeInitHeaps(psDevMemoryInfo);
-#endif
-	OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeapConfigArray);
-	OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeap);
-}
-
-/*
-	RGXRegisterDevice
-*/
-PVRSRV_ERROR RGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
-{
-    PVRSRV_ERROR eError;
-	DEVICE_MEMORY_INFO *psDevMemoryInfo;
-	PVRSRV_RGXDEV_INFO	*psDevInfo;
-
-	/* pdump info about the core */
-	PDUMPCOMMENT("RGX Version Information (KM): %s", RGX_BVNC_KM);
-	
-	#if defined(RGX_FEATURE_SYSTEM_CACHE)
-	PDUMPCOMMENT("RGX System Level Cache is present");
-	#endif /* RGX_FEATURE_SYSTEM_CACHE */
-
-	PDUMPCOMMENT("RGX Initialisation (Part 1)");
-
-	/*********************
-	 * Device node setup *
-	 *********************/
-	/* Setup static data and callbacks on the device agnostic device node */
-	psDeviceNode->sDevId.eDeviceType		= DEV_DEVICE_TYPE;
-	psDeviceNode->sDevId.eDeviceClass		= DEV_DEVICE_CLASS;
-#if defined(PDUMP)
-	psDeviceNode->sDevId.pszPDumpRegName	= RGX_PDUMPREG_NAME;
-	psDeviceNode->sDevId.pszPDumpDevName	= PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
-	psDeviceNode->pfnPDumpInitDevice = &RGXResetPDump;
-#endif /* PDUMP */
-
-	psDeviceNode->eHealthStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
-	psDeviceNode->eHealthReason = PVRSRV_DEVICE_HEALTH_REASON_NONE;
-
-	/* Configure MMU specific stuff */
-	RGXMMUInit_Register(psDeviceNode);
-
-#if defined(RGX_FEATURE_MIPS)
-	RGXMipsMMUInit_Register(psDeviceNode);
-#endif
-
-	psDeviceNode->pfnMMUCacheInvalidate = RGXMMUCacheInvalidate;
-
-	psDeviceNode->pfnSLCCacheInvalidateRequest = RGXSLCCacheInvalidateRequest;
-
-	/* Register RGX to receive notifies when other devices complete some work */
-	PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
-
-	psDeviceNode->pfnInitDeviceCompatCheck	= &RGXDevInitCompatCheck;
-
-	/* Register callbacks for creation of device memory contexts */
-	psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
-	psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
-
-	/* Register callbacks for Unified Fence Objects */
-	psDeviceNode->pfnAllocUFOBlock = RGXAllocUFOBlock;
-	psDeviceNode->pfnFreeUFOBlock = RGXFreeUFOBlock;
-
-	/* Register callback for dumping debug info */
-	PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hDbgReqNotify, &RGXDebugRequestNotify, DEBUG_REQUEST_RGX, psDeviceNode);
-	
-	/* Register callback for checking the device's health */
-	psDeviceNode->pfnUpdateHealthStatus = RGXUpdateHealthStatus;
-
-	/* Register method to service the FW HWPerf buffer */
-	psDeviceNode->pfnServiceHWPerf = RGXHWPerfDataStoreCB;
-
-	/* Register callback for getting the device version information string */
-	psDeviceNode->pfnDeviceVersionString = RGXDevVersionString;
-
-	/* Register callback for getting the device clock speed */
-	psDeviceNode->pfnDeviceClockSpeed = RGXDevClockSpeed;
-
-	/* Register callback for soft resetting some device modules */
-	psDeviceNode->pfnSoftReset = RGXSoftReset;
-
-	/* Register callback for resetting the HWR logs */
-	psDeviceNode->pfnResetHWRLogs = RGXResetHWRLogs;
-
-	/*Set up required support for dummy page */
-	OSAtomicWrite(&(psDeviceNode->sDummyPage.atRefCounter), 0);
-
-	/*Set the order to 0 */
-	psDeviceNode->sDummyPage.sDummyPageHandle.ui32Order = 0;
-
-	/*Set the size of the Dummy page to zero */
-	psDeviceNode->sDummyPage.ui32Log2DummyPgSize = 0;
-
-	/*Set the Dummy page phys addr */
-	psDeviceNode->sDummyPage.ui64DummyPgPhysAddr = MMU_BAD_PHYS_ADDR;
-
-	/*The lock type need to be dispatch type here because it can be acquired from MISR (Z-buffer) path */
-	eError = OSLockCreate(&psDeviceNode->sDummyPage.psDummyPgLock ,LOCK_TYPE_DISPATCH);
-	if(PVRSRV_OK != eError)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create dummy page lock", __func__));
-		return eError;
-	}
-#if defined(PDUMP)
-	psDeviceNode->sDummyPage.hPdumpDummyPg = NULL;
-#endif
-
-	/*********************
-	 * Device info setup *
-	 *********************/
-	/* Allocate device control block */
-	psDevInfo = OSAllocMem(sizeof(*psDevInfo));
-	if (psDevInfo == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"DevInitRGXPart1 : Failed to alloc memory for DevInfo"));
-		return (PVRSRV_ERROR_OUT_OF_MEMORY);
-	}
-	OSMemSet (psDevInfo, 0, sizeof(*psDevInfo));
-
-	/* create locks for the context lists stored in the DevInfo structure.
-	 * these lists are modified on context create/destroy and read by the
-	 * watchdog thread
-	 */
-
-	eError = OSWRLockCreate(&(psDevInfo->hRenderCtxListLock));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create render context list lock", __func__));
-		goto e0;
-	}
-
-	eError = OSWRLockCreate(&(psDevInfo->hComputeCtxListLock));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create compute context list lock", __func__));
-		goto e1;
-	}
-
-	eError = OSWRLockCreate(&(psDevInfo->hTransferCtxListLock));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create transfer context list lock", __func__));
-		goto e2;
-	}
-
-	eError = OSWRLockCreate(&(psDevInfo->hRaytraceCtxListLock));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create raytrace context list lock", __func__));
-		goto e3;
-	}
-
-	eError = OSWRLockCreate(&(psDevInfo->hKickSyncCtxListLock));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create kick sync context list lock", __func__));
-		goto e4;
-	}
-
-	eError = OSWRLockCreate(&(psDevInfo->hMemoryCtxListLock));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create memory context list lock", __func__));
-		goto e5;
-	}
-
-	dllist_init(&(psDevInfo->sKCCBDeferredCommandsListHead));
-
-	dllist_init(&(psDevInfo->sRenderCtxtListHead));
-	dllist_init(&(psDevInfo->sComputeCtxtListHead));
-	dllist_init(&(psDevInfo->sTransferCtxtListHead));
-	dllist_init(&(psDevInfo->sRaytraceCtxtListHead));
-	dllist_init(&(psDevInfo->sKickSyncCtxtListHead));
-
-	dllist_init(&(psDevInfo->sCommonCtxtListHead));
-	psDevInfo->ui32CommonCtxtCurrentID = 1;
-
-	dllist_init(&psDevInfo->sMemoryContextList);
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest driver do not perform fw initialization */
-#else
-	/* Allocate space for scripts. */
-	psDevInfo->psScripts = OSAllocMem(sizeof(*psDevInfo->psScripts));
-	if (!psDevInfo->psScripts)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate memory for scripts", __func__));
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto e6;
-	}
-#endif
-
-	/* Setup static data and callbacks on the device specific device info */
-	psDevInfo->eDeviceType 		= DEV_DEVICE_TYPE;
-	psDevInfo->eDeviceClass 	= DEV_DEVICE_CLASS;
-	psDevInfo->psDeviceNode		= psDeviceNode;
-
-	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
-	psDevMemoryInfo->ui32AddressSpaceSizeLog2 = RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS;
-	psDevInfo->pvDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
-
-	/* flags, backing store details to be specified by system */
-	psDevMemoryInfo->ui32Flags = 0;
-
-	eError = RGXInitHeaps(psDevMemoryInfo, &psDeviceNode->sDummyPage.ui32Log2DummyPgSize);
-	if (eError != PVRSRV_OK)
-	{
-		goto e7;
-	}
-
-	psDeviceNode->pvDevice = psDevInfo;
-
-	eError = RGXHWPerfInit(psDeviceNode);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfInit failed"));
-	}
-
-#if defined(SUPPORT_GPUTRACE_EVENTS)
-	eError = PVRGpuTraceInit(psDeviceNode);
-	if (eError != 0)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "PVRCore_Init: failed to initialise PVR GPU"
-		        " Tracing (%d)", eError));
-	}
-#endif
-
-	return PVRSRV_OK;
-
-e7:
-#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
-	OSFreeMem(psDevInfo->psScripts);
-e6:
-#endif
-	OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
-e5:
-	OSWRLockDestroy(psDevInfo->hKickSyncCtxListLock);
-e4:
-	OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
-e3:
-	OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
-e2:
-	OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
-e1:
-	OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
-e0:
-	OSFreeMem(psDevInfo);
-
-	/*Destroy the dummy page lock created above */
-	OSLockDestroy(psDeviceNode->sDummyPage.psDummyPgLock);
-	PVR_ASSERT(eError != PVRSRV_OK);
-	return eError;
-}
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
 
-#else
 /*!
 *******************************************************************************
 
@@ -2278,7 +1499,7 @@
 
  Validate the FW build options against KM driver build options (KM build options only)
 
- Following check is reduntant, because next check checks the same bits.
+ Following check is redundant, because next check checks the same bits.
  Redundancy occurs because if client-server are build-compatible and client-firmware are 
  build-compatible then server-firmware are build-compatible as well.
  
@@ -2311,7 +1532,7 @@
 		if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
 		{
 			PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and KM driver build options; "
-				"extra options present in the KM driver: (0x%x). Please check rgx_options_km.h",
+				"extra options present in the KM driver: (0x%x). Please check rgx_options.h",
 				ui32BuildOptions & ui32BuildOptionsMismatch ));
 			return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
 		}
@@ -2319,7 +1540,7 @@
 		if ( (ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch) != 0)
 		{
 			PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware-side and KM driver build options; "
-				"extra options present in Firmware: (0x%x). Please check rgx_options_km.h",
+				"extra options present in Firmware: (0x%x). Please check rgx_options.h",
 				ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch ));
 			return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
 		}
@@ -2337,83 +1558,6 @@
 /*!
 *******************************************************************************
 
- @Function	RGXDevInitCompatCheck_BuildOptions_FWAgainstClient
-
- @Description
-
- Validate the FW build options against client build options (KM and non-KM)
-
- @Input psDevInfo - device info
- @Input psRGXFWInit - FW init data
- @Input ui32ClientBuildOptions - client build options flags
-
- @Return   PVRSRV_ERROR - depending on mismatch found
-
-******************************************************************************/
-static PVRSRV_ERROR RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(PVRSRV_RGXDEV_INFO 	*psDevInfo,
-																			RGXFWIF_INIT *psRGXFWInit,
-																			IMG_UINT32 ui32ClientBuildOptions)
-{
-#if !defined(NO_HARDWARE) && !defined(SUPPORT_KERNEL_SRVINIT)
-	IMG_UINT32			ui32BuildOptionsMismatch;
-	IMG_UINT32			ui32BuildOptionsFW;
-#endif
-#if defined(PDUMP)
-	PVRSRV_ERROR		eError;
-#endif
-
-#if defined(PDUMP)
-	PDUMPCOMMENT("Compatibility check: client and FW build options");
-	eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
-												offsetof(RGXFWIF_INIT, sRGXCompChecks) + 
-												offsetof(RGXFWIF_COMPCHECKS, ui32BuildOptions),
-												ui32ClientBuildOptions,
-												0xffffffff,
-												PDUMP_POLL_OPERATOR_EQUAL,
-												PDUMP_FLAGS_CONTINUOUS);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
-		return eError;
-	}
-#endif
-
-#if !defined(NO_HARDWARE) && !defined(SUPPORT_KERNEL_SRVINIT)
-	if (psRGXFWInit == NULL)
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	
-	ui32BuildOptionsFW = psRGXFWInit->sRGXCompChecks.ui32BuildOptions;
-	
-	if (ui32ClientBuildOptions != ui32BuildOptionsFW)
-	{
-		ui32BuildOptionsMismatch = ui32ClientBuildOptions ^ ui32BuildOptionsFW;
-		if ( (ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
-		{
-			PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
-				"extra options present in client: (0x%x). Please check rgx_options.h",
-				ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
-		}
-
-		if ( (ui32BuildOptionsFW & ui32BuildOptionsMismatch) != 0)
-		{
-			PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
-				"extra options present in Firmware: (0x%x). Please check rgx_options.h",
-				ui32BuildOptionsFW & ui32BuildOptionsMismatch ));
-		}
-		return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
-	}
-	else
-	{
-		PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and client build options match. [ OK ]"));
-	}
-#endif
-
-	return PVRSRV_OK;
-}
-
-/*!
-*******************************************************************************
-
  @Function	RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver
 
  @Description
@@ -2472,7 +1616,7 @@
 				PVRVERSION_MAJ, PVRVERSION_MIN, 
 				PVRVERSION_MAJ, PVRVERSION_MIN));
 	}
-#endif	
+#endif
 
 	return PVRSRV_OK;
 }
@@ -2526,11 +1670,11 @@
 	{
 		PVR_LOG(("(WARN) RGXDevInitCompatCheck: Incompatible driver DDK build version (%d) / Firmware DDK build version (%d).",
 				ui32DDKBuild, psRGXFWInit->sRGXCompChecks.ui32DDKBuild));
-#if defined(PVRSRV_STRICT_COMPAT_CHECK)				
+#if defined(PVRSRV_STRICT_COMPAT_CHECK)
 		eError = PVRSRV_ERROR_DDK_BUILD_MISMATCH;
 		PVR_DBG_BREAK;
 		return eError;
-#endif		
+#endif
 	}
 	else
 	{
@@ -2566,10 +1710,19 @@
 	IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
 #endif
 #if defined(PDUMP)||(!defined(NO_HARDWARE))
+	IMG_UINT32					ui32B, ui32V, ui32N, ui32C;
 	RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
 	PVRSRV_ERROR				eError;
+	IMG_CHAR	szV[8];
+
+	ui32B = psDevInfo->sDevFeatureCfg.ui32B;
+	ui32V = psDevInfo->sDevFeatureCfg.ui32V;
+	ui32N = psDevInfo->sDevFeatureCfg.ui32N;
+	ui32C = psDevInfo->sDevFeatureCfg.ui32C;
 	
-	rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+	OSSNPrintf(szV, sizeof(szV),"%d",ui32V);
+
+	rgx_bvnc_packed(&sBVNC.ui64BNC, sBVNC.aszV, sBVNC.ui32VLenMax, ui32B, szV, ui32N, ui32C);
 #endif
 
 #if defined(PDUMP)
@@ -2601,12 +1754,27 @@
 		PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
 	}
 
-	PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BNC part)");
+	PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BNC part - lower 32 bits)");
 	eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
 											offsetof(RGXFWIF_INIT, sRGXCompChecks) + 
 											offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
-											offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32BNC),
-											sBVNC.ui32BNC,
+											offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BNC),
+											(IMG_UINT32)sBVNC.ui64BNC,
+											0xffffffff,
+											PDUMP_POLL_OPERATOR_EQUAL,
+											PDUMP_FLAGS_CONTINUOUS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+	}
+
+	PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BNC part - Higher 32 bits)");
+	eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+											offsetof(RGXFWIF_INIT, sRGXCompChecks) + 
+											offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+											offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BNC) +
+											sizeof(IMG_UINT32),
+											(IMG_UINT32)(sBVNC.ui64BNC >> 32),
 											0xffffffff,
 											PDUMP_POLL_OPERATOR_EQUAL,
 											PDUMP_FLAGS_CONTINUOUS);
@@ -2717,16 +1885,11 @@
 #define TARGET_SILICON  /* definition for everything that is not emu and not nohw configuration */
 #endif
 
-#if defined(FIX_HW_BRN_38835)
-#define COMPAT_BVNC_MASK_B
-#define COMPAT_BVNC_MASK_V
-#endif
-
 static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
 																	RGXFWIF_INIT *psRGXFWInit)
 {
 #if defined(PDUMP) || defined(TARGET_SILICON)
-	IMG_UINT32 ui32MaskBNC = RGX_BVNC_PACK_MASK_B |
+	IMG_UINT64 ui64MaskBNC = RGX_BVNC_PACK_MASK_B |
 								RGX_BVNC_PACK_MASK_N |
 								RGX_BVNC_PACK_MASK_C;
 
@@ -2742,36 +1905,41 @@
 #endif
 
 #if defined(PDUMP) || defined(TARGET_SILICON)
+	IMG_UINT32 ui32B, ui32V, ui32N, ui32C;
+	IMG_CHAR szV[8];
 
-#if defined(COMPAT_BVNC_MASK_B)
-	ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_B;
-#endif
-#if defined(COMPAT_BVNC_MASK_V)
-	bMaskV = IMG_TRUE;
-#endif
+	/*if(psDevInfo->sDevFeatureCfg.ui64ErnsBrns & FIX_HW_BRN_38835_BIT_MASK)
+	{
+		ui64MaskBNC &= ~RGX_BVNC_PACK_MASK_B;
+		bMaskV = IMG_TRUE;
+	}*/
 #if defined(COMPAT_BVNC_MASK_N)
-	ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_N;
+	ui64MaskBNC &= ~RGX_BVNC_PACK_MASK_N;
 #endif
 #if defined(COMPAT_BVNC_MASK_C)
-	ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
+	ui64MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
 #endif
+	ui32B = psDevInfo->sDevFeatureCfg.ui32B;
+	ui32V = psDevInfo->sDevFeatureCfg.ui32V;
+	ui32N = psDevInfo->sDevFeatureCfg.ui32N;
+	ui32C = psDevInfo->sDevFeatureCfg.ui32C;
 	
-	rgx_bvnc_packed(&sSWBVNC.ui32BNC, sSWBVNC.aszV, sSWBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+	OSSNPrintf(szV, sizeof(szV),"%d",ui32V);
+	rgx_bvnc_packed(&sSWBVNC.ui64BNC, sSWBVNC.aszV, sSWBVNC.ui32VLenMax,  ui32B, szV, ui32N, ui32C);
 
-#if defined(FIX_HW_BRN_38344)
-	if (RGX_BVNC_KM_C >= 10)
+
+	if((psDevInfo->sDevFeatureCfg.ui64ErnsBrns & FIX_HW_BRN_38344_BIT_MASK) && (ui32C >= 10))
 	{
-		ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
+		ui64MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
 	}
-#endif
 
-	if ((ui32MaskBNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C)) || bMaskV)
+	if ((ui64MaskBNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C)) || bMaskV)
 	{
 		PVR_LOG(("Compatibility checks: Ignoring fields: '%s%s%s%s' of HW BVNC.",
-				((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_B))?("B"):("")), 
+				((!(ui64MaskBNC & RGX_BVNC_PACK_MASK_B))?("B"):("")), 
 				((bMaskV)?("V"):("")), 
-				((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_N))?("N"):("")), 
-				((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_C))?("C"):(""))));
+				((!(ui64MaskBNC & RGX_BVNC_PACK_MASK_N))?("N"):("")), 
+				((!(ui64MaskBNC & RGX_BVNC_PACK_MASK_C))?("C"):(""))));
 	}
 #endif
 
@@ -2810,17 +1978,17 @@
 		return eError;
 	}
 
-	if (ui32MaskBNC != 0)
+	if (ui64MaskBNC != 0)
 	{
 		PDUMPIF("DISABLE_HWBNC_CHECK");
 		PDUMPELSE("DISABLE_HWBNC_CHECK");
-		PDUMPCOMMENT("Compatibility check: HW BNC and FW BNC");
+		PDUMPCOMMENT("Compatibility check: HW BNC and FW BNC (Lower 32 bits)");
 		eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
 												offsetof(RGXFWIF_INIT, sRGXCompChecks) + 
 												offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
-												offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32BNC),
-												sSWBVNC.ui32BNC,
-												ui32MaskBNC,
+												offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BNC),
+												(IMG_UINT32)sSWBVNC.ui64BNC ,
+												(IMG_UINT32)ui64MaskBNC,
 												PDUMP_POLL_OPERATOR_EQUAL,
 												PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
@@ -2828,6 +1996,23 @@
 			PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
 			return eError;
 		}
+
+		PDUMPCOMMENT("Compatibility check: HW BNC and FW BNC (Higher 32 bits)");
+		eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+												offsetof(RGXFWIF_INIT, sRGXCompChecks) + 
+												offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+												offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BNC) +
+												sizeof(IMG_UINT32),
+												(IMG_UINT32)(sSWBVNC.ui64BNC >> 32),
+												(IMG_UINT32)(ui64MaskBNC >> 32),
+												PDUMP_POLL_OPERATOR_EQUAL,
+												PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+			return eError;
+		}
+
 		PDUMPFI("DISABLE_HWBNC_CHECK");
 	}
 	if (!bMaskV)
@@ -2865,8 +2050,8 @@
 	
 	sHWBVNC = psRGXFWInit->sRGXCompChecks.sHWBVNC;
 
-	sHWBVNC.ui32BNC &= ui32MaskBNC;
-	sSWBVNC.ui32BNC &= ui32MaskBNC;
+	sHWBVNC.ui64BNC &= ui64MaskBNC;
+	sSWBVNC.ui64BNC &= ui64MaskBNC;
 
 	if (bMaskV)
 	{
@@ -2876,27 +2061,28 @@
 
 	RGX_BVNC_EQUAL(sSWBVNC, sHWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
 
-#if defined(FIX_HW_BRN_42480)
-	if (!bCompatibleAll && bCompatibleVersion)
+	if(psDevInfo->sDevFeatureCfg.ui64ErnsBrns & FIX_HW_BRN_42480_BIT_MASK)
 	{
-		if ((RGX_BVNC_PACKED_EXTR_B(sSWBVNC) == 1) &&
-			!(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sSWBVNC),"76")) &&
-			(RGX_BVNC_PACKED_EXTR_N(sSWBVNC) == 4) &&
-			(RGX_BVNC_PACKED_EXTR_C(sSWBVNC) == 6))
+		if (!bCompatibleAll && bCompatibleVersion)
 		{
-			if ((RGX_BVNC_PACKED_EXTR_B(sHWBVNC) == 1) &&
-				!(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sHWBVNC),"69")) &&
-				(RGX_BVNC_PACKED_EXTR_N(sHWBVNC) == 4) &&
-				(RGX_BVNC_PACKED_EXTR_C(sHWBVNC) == 4))
+			if ((RGX_BVNC_PACKED_EXTR_B(sSWBVNC) == 1) &&
+				!(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sSWBVNC),"76")) &&
+				(RGX_BVNC_PACKED_EXTR_N(sSWBVNC) == 4) &&
+				(RGX_BVNC_PACKED_EXTR_C(sSWBVNC) == 6))
 			{
-				bCompatibleBNC = IMG_TRUE;
-				bCompatibleLenMax = IMG_TRUE;
-				bCompatibleV = IMG_TRUE;
-				bCompatibleAll = IMG_TRUE;
+				if ((RGX_BVNC_PACKED_EXTR_B(sHWBVNC) == 1) &&
+					!(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sHWBVNC),"69")) &&
+					(RGX_BVNC_PACKED_EXTR_N(sHWBVNC) == 4) &&
+					(RGX_BVNC_PACKED_EXTR_C(sHWBVNC) == 4))
+				{
+					bCompatibleBNC = IMG_TRUE;
+					bCompatibleLenMax = IMG_TRUE;
+					bCompatibleV = IMG_TRUE;
+					bCompatibleAll = IMG_TRUE;
+				}
 			}
 		}
 	}
-#endif
 
 	if (!bCompatibleAll)
 	{
@@ -2987,6 +2173,31 @@
 	PVRSRV_ERROR		eError;
 #endif
 
+	IMG_UINT32	ui32FWCoreIDValue = 0;
+	IMG_CHAR *pcRGXFW_PROCESSOR = NULL;
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		ui32FWCoreIDValue = RGXMIPSFW_CORE_ID_VALUE;
+		pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
+	}else if (psDevInfo->sDevFeatureCfg.ui32META)
+	{
+		switch(psDevInfo->sDevFeatureCfg.ui32META)
+		{
+		case MTP218: ui32FWCoreIDValue = RGX_CR_META_MTP218_CORE_ID_VALUE; break;
+		case MTP219: ui32FWCoreIDValue = RGX_CR_META_MTP219_CORE_ID_VALUE; break;
+		case LTP218: ui32FWCoreIDValue = RGX_CR_META_LTP218_CORE_ID_VALUE; break;
+		case LTP217: ui32FWCoreIDValue = RGX_CR_META_LTP217_CORE_ID_VALUE; break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,"%s: Undefined FW_CORE_ID_VALUE", __func__));
+			PVR_ASSERT(0);
+		}
+		pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
+	}else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Undefined FW_CORE_ID_VALUE", __func__));
+		PVR_ASSERT(0);
+	}
+
 #if defined(PDUMP)
 	PDUMPIF("DISABLE_HWMETA_CHECK");
 	PDUMPELSE("DISABLE_HWMETA_CHECK");
@@ -2994,7 +2205,7 @@
 	eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
 					offsetof(RGXFWIF_INIT, sRGXCompChecks) +
 					offsetof(RGXFWIF_COMPCHECKS, ui32FWProcessorVersion),
-					FW_CORE_ID_VALUE,
+					ui32FWCoreIDValue,
 					0xffffffff,
 					PDUMP_POLL_OPERATOR_EQUAL,
 					PDUMP_FLAGS_CONTINUOUS);
@@ -3010,12 +2221,12 @@
 	if (psRGXFWInit == NULL)
 		return PVRSRV_ERROR_INVALID_PARAMS;
 
-	if (psRGXFWInit->sRGXCompChecks.ui32FWProcessorVersion != FW_CORE_ID_VALUE)
+	if (psRGXFWInit->sRGXCompChecks.ui32FWProcessorVersion != ui32FWCoreIDValue)
 	{
 		PVR_LOG(("RGXDevInitCompatCheck: Incompatible driver %s version (%d) / HW %s version (%d).",
-				 RGXFW_PROCESSOR,
-				 FW_CORE_ID_VALUE,
-				 RGXFW_PROCESSOR,
+				pcRGXFW_PROCESSOR,
+				 ui32FWCoreIDValue,
+				 pcRGXFW_PROCESSOR,
 				 psRGXFWInit->sRGXCompChecks.ui32FWProcessorVersion));
 		eError = PVRSRV_ERROR_FWPROCESSOR_MISMATCH;
 		PVR_DBG_BREAK;
@@ -3024,15 +2235,14 @@
 	else
 	{
 		PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Compatible driver %s version (%d) / HW %s version (%d) [OK].",
-				 RGXFW_PROCESSOR,
-				 FW_CORE_ID_VALUE,
-				 RGXFW_PROCESSOR,
+				 pcRGXFW_PROCESSOR,
+				 ui32FWCoreIDValue,
+				 pcRGXFW_PROCESSOR,
 				 psRGXFWInit->sRGXCompChecks.ui32FWProcessorVersion));
 	}
 #endif
 	return PVRSRV_OK;
 }
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
 
 /*!
 *******************************************************************************
@@ -3049,36 +2259,15 @@
  @Return   PVRSRV_ERROR - depending on mismatch found
 
 ******************************************************************************/
-static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions)
+static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 	PVRSRV_ERROR		eError;
 	PVRSRV_RGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
 	RGXFWIF_INIT		*psRGXFWInit = NULL;
 #if !defined(NO_HARDWARE)
 	IMG_UINT32			ui32RegValue;
-#endif
 
-	/* Ensure it's a RGX device */
-	if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_RGX)
-	{
-		PVR_LOG(("(FAIL) %s: Device not of type RGX", __FUNCTION__));
-		eError = PVRSRV_ERROR_INVALID_PARAMS;
-		goto chk_exit;
-	}
-
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/*
-	 * For now, fw compatibility checks are ignored in guest drivers
-	 */
-	PVR_UNREFERENCED_PARAMETER(ui32RegValue);
-	PVR_UNREFERENCED_PARAMETER(psRGXFWInit);
-	PVR_UNREFERENCED_PARAMETER(psDevInfo);
-#else
-	/* 
-	 * Retrieve the FW information
-	 */
-	
-#if !defined(NO_HARDWARE)
+	/* Retrieve the FW information */
 	eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
 												(void **)&psRGXFWInit);
 	if (eError != PVRSRV_OK)
@@ -3100,24 +2289,25 @@
 
 	ui32RegValue = 0;
 
-#if defined(RGX_FEATURE_META)
-	eError = RGXReadMETAAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
-
-	if (eError != PVRSRV_OK)
+	if(psDevInfo->sDevFeatureCfg.ui32META)
 	{
-		PVR_LOG(("%s: Reading RGX META register failed. Is the GPU correctly powered up? (%u)",
-				__FUNCTION__, eError));
-		goto chk_exit;
-	}
+		eError = RGXReadMETAAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
 
-	if (!(ui32RegValue & META_CR_TXENABLE_ENABLE_BIT))
-	{
-		eError = PVRSRV_ERROR_META_THREAD0_NOT_ENABLED;
-		PVR_DPF((PVR_DBG_ERROR,"%s: RGX META is not running. Is the GPU correctly powered up? %d (%u)",
-				__FUNCTION__, psRGXFWInit->sRGXCompChecks.bUpdated, eError));
-		goto chk_exit;
+		if (eError != PVRSRV_OK)
+		{
+			PVR_LOG(("%s: Reading RGX META register failed. Is the GPU correctly powered up? (%u)",
+					__FUNCTION__, eError));
+			goto chk_exit;
+		}
+
+		if (!(ui32RegValue & META_CR_TXENABLE_ENABLE_BIT))
+		{
+			eError = PVRSRV_ERROR_META_THREAD0_NOT_ENABLED;
+			PVR_DPF((PVR_DBG_ERROR,"%s: RGX META is not running. Is the GPU correctly powered up? %d (%u)",
+					__FUNCTION__, psRGXFWInit->sRGXCompChecks.bUpdated, eError));
+			goto chk_exit;
+		}
 	}
-#endif
 	
 	if (!*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
 	{
@@ -3134,12 +2324,6 @@
 		goto chk_exit;
 	}
 
-	eError = RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(psDevInfo, psRGXFWInit, ui32ClientBuildOptions);
-	if (eError != PVRSRV_OK)
-	{
-		goto chk_exit;
-	}
-	
 	eError = RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(psDevInfo, psRGXFWInit);
 	if (eError != PVRSRV_OK)
 	{
@@ -3168,82 +2352,2589 @@
 	{
 		goto chk_exit;
 	}
-#endif
 
 	eError = PVRSRV_OK;
 chk_exit:
-#if !defined(NO_HARDWARE) && !defined(PVRSRV_GPUVIRT_GUESTDRV)
+#if !defined(NO_HARDWARE)
 	DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
 #endif
 	return eError;
 }
 
-IMG_EXPORT PVRSRV_ERROR
-PVRSRVRGXInitFinaliseFWImageKM(CONNECTION_DATA *psConnection,
-                               PVRSRV_DEVICE_NODE *psDeviceNode,
-                               PMR *psFWImagePMR,
-                               IMG_UINT64 ui64FWImgLen)
+/**************************************************************************/ /*!
+@Function       RGXSoftReset
+@Description    Resets some modules of the RGX device
+@Input          psDeviceNode		Device node
+@Input          ui64ResetValue1 A mask for which each bit set corresponds
+                                to a module to reset (via the SOFT_RESET
+                                register).
+@Input          ui64ResetValue2 A mask for which each bit set corresponds
+                                to a module to reset (via the SOFT_RESET2
+                                register).
+@Return         PVRSRV_ERROR
+*/ /***************************************************************************/
+static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 IMG_UINT64  ui64ResetValue1,
+                                 IMG_UINT64  ui64ResetValue2)
 {
-#if defined(RGX_FEATURE_MIPS)
-	void *pvFWImage;
-	IMG_HANDLE hFWImage;
-	size_t uiLen;
-	PVRSRV_ERROR eStatus;
+	PVRSRV_RGXDEV_INFO        *psDevInfo;
+	IMG_BOOL	bSoftReset = IMG_FALSE;
+	IMG_UINT64	ui64SoftResetMask = 0;
 
-	eStatus = PMRAcquireKernelMappingData(psFWImagePMR,
-	                                      0,
-	                                      0, /* Map whole PMR */
-	                                      &pvFWImage,
-	                                      &uiLen,
-	                                      &hFWImage);
-	if(eStatus != PVRSRV_OK)
+	PVR_ASSERT(psDeviceNode != NULL);
+	PVR_ASSERT(psDeviceNode->pvDevice != NULL);
+
+	/* the device info */
+	psDevInfo = psDeviceNode->pvDevice;
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_PBE2_IN_XE_BIT_MASK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXInitFinaliseFWImageKM: Acquire mapping for FW code failed (%u)", eStatus));
-		return eStatus;
+		ui64SoftResetMask = RGX_CR_SOFT_RESET__PBE2_XE__MASKFULL;
+	}else
+	{
+		ui64SoftResetMask = RGX_CR_SOFT_RESET_MASKFULL;
 	}
 
-	/* Sanity check whether the function mapped the whole FW image */
-	if(ui64FWImgLen > uiLen)
+	if((psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK) && \
+		((ui64ResetValue2 & RGX_CR_SOFT_RESET2_MASKFULL) != ui64ResetValue2))
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXInitFinaliseFWImageKM: PMR len (%llu) > mapped len (%llu)",
-		         ui64FWImgLen, (IMG_UINT64)uiLen));
-		return PVRSRV_ERROR_INVALID_MAP_REQUEST;
+		bSoftReset = IMG_TRUE;
 	}
 
-	eStatus = RGXBootldrDataInit(psDeviceNode,
-	                             pvFWImage,
-	                             psFWImagePMR,
-	                             (IMG_UINT32)RGXMIPSFW_BOOTLDR_CONF_OFFSET_KERNEL,
-	                             (IMG_UINT32)RGXMIPSFW_BOOTCODE_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE,
-	                             (IMG_UINT32)RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE);
-
-	if(eStatus != PVRSRV_OK)
+	if (((ui64ResetValue1 & ui64SoftResetMask) != ui64ResetValue1) || bSoftReset)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXInitLoadFWImageKM: ELF parameters injection failed (%u)", eStatus));
-		return eStatus;
+		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	eStatus = PMRReleaseKernelMappingData(psFWImagePMR,
-	                                      hFWImage);
-	if(eStatus != PVRSRV_OK)
+	/* Set in soft-reset */
+	OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue1);
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXInitLoadFWImageKM: Release mapping failed (%u)", eStatus));
-		return eStatus;
+		OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2, ui64ResetValue2);
 	}
 
-#endif /* defined(RGX_FEATURE_MIPS) */
 
-	PVR_UNREFERENCED_PARAMETER(psConnection);
-	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
-	PVR_UNREFERENCED_PARAMETER(psFWImagePMR);
-	PVR_UNREFERENCED_PARAMETER(ui64FWImgLen);
+	/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+	(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+	{
+		(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2);
+	}
+
+	/* Take the modules out of reset... */
+	OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, 0);
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+	{
+		OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2, 0);
+	}
+
+	/* ...and fence again */
+	(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+	{
+		(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2);
+	}
 
 	return PVRSRV_OK;
 }
 
+/*!
+******************************************************************************
 
-#define MAKESTRING(x) #x
-#define TOSTRING(x) MAKESTRING(x)
+ @Function	RGXDebugRequestNotify
+
+ @Description Dump the debug data for RGX
+
+******************************************************************************/
+static void RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgReqestHandle,
+					IMG_UINT32 ui32VerbLevel,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = hDbgReqestHandle;
+
+	/* Only action the request if we've fully init'ed */
+	if (psDevInfo->bDevInit2Done)
+	{
+		RGXDebugRequestProcess(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, ui32VerbLevel);
+	}
+}
+
+static const RGX_MIPS_ADDRESS_TRAMPOLINE sNullTrampoline =
+{
+#if defined(PDUMP)
+	.hPdumpPages = 0,
+#endif
+	.sPages = {{0}},
+	.sPhysAddr = {0}
+};
+
+static void RGXFreeTrampoline(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+	DevPhysMemFree(psDeviceNode,
+#if defined(PDUMP)
+	               psDevInfo->sTrampoline.hPdumpPages,
+#endif
+	               &psDevInfo->sTrampoline.sPages);
+	psDevInfo->sTrampoline = sNullTrampoline;
+}
+
+static PVRSRV_ERROR RGXAllocTrampoline(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+	IMG_INT32 i, j;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	RGX_MIPS_ADDRESS_TRAMPOLINE asTrampoline[RGXMIPSFW_TRAMPOLINE_NUMPAGES];
+
+	PDUMPCOMMENT("Allocate pages for trampoline");
+
+	/* Retry the allocation of the trampoline, retaining any allocations
+	 * overlapping with the target range until we get an allocation that
+	 * doesn't overlap with the target range. Any allocation like this
+	 * will require a maximum of 3 tries.
+	 * Free the unused allocations only after the desired range is obtained
+	 * to prevent the alloc function from returning the same bad range
+	 * repeatedly.
+	 */
+	#define RANGES_OVERLAP(x,y,size) (x < (y+size) && y < (x+size))
+	for (i = 0; i < 3; i++)
+	{
+		eError = DevPhysMemAlloc(psDeviceNode,
+					 RGXMIPSFW_TRAMPOLINE_SIZE,
+					 0,         // (init) u8Value
+					 IMG_FALSE, // bInitPage,
+#if defined(PDUMP)
+					 psDeviceNode->psFirmwareMMUDevAttrs->pszMMUPxPDumpMemSpaceName,
+					 "TrampolineRegion",
+					 &asTrampoline[i].hPdumpPages,
+#endif
+					 &asTrampoline[i].sPages,
+					 &asTrampoline[i].sPhysAddr);
+		if (PVRSRV_OK != eError)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"%s failed (%u)",
+				 __func__, eError));
+			goto fail;
+		}
+
+		if (!RANGES_OVERLAP(asTrampoline[i].sPhysAddr.uiAddr,
+		                    RGXMIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR,
+		                    RGXMIPSFW_TRAMPOLINE_SIZE))
+		{
+			break;
+		}
+	}
+	if (RGXMIPSFW_TRAMPOLINE_NUMPAGES == i)
+	{
+		eError = PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+		PVR_DPF((PVR_DBG_ERROR,
+		         "%s failed to allocate non-overlapping pages (%u)",
+			 __func__, eError));
+		goto fail;
+	}
+	#undef RANGES_OVERLAP
+
+	psDevInfo->sTrampoline = asTrampoline[i];
+
+fail:
+	/* free all unused allocations */
+	for (j = 0; j < i; j++)
+	{
+		DevPhysMemFree(psDeviceNode,
+#if defined(PDUMP)
+		               asTrampoline[j].hPdumpPages,
+#endif
+		               &asTrampoline[j].sPages);
+	}
+
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitAllocFWImgMemKM(CONNECTION_DATA      *psConnection,
+                                          PVRSRV_DEVICE_NODE   *psDeviceNode,
+                                          IMG_DEVMEM_SIZE_T    uiFWCodeLen,
+                                          IMG_DEVMEM_SIZE_T    uiFWDataLen,
+                                          IMG_DEVMEM_SIZE_T    uiFWCorememLen,
+                                          PMR                  **ppsFWCodePMR,
+                                          IMG_DEV_VIRTADDR     *psFWCodeDevVAddrBase,
+                                          PMR                  **ppsFWDataPMR,
+                                          IMG_DEV_VIRTADDR     *psFWDataDevVAddrBase,
+                                          PMR                  **ppsFWCorememPMR,
+                                          IMG_DEV_VIRTADDR     *psFWCorememDevVAddrBase,
+                                          RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase)
+{
+	DEVMEM_FLAGS_T		uiMemAllocFlags;
+	PVRSRV_RGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+	PVRSRV_ERROR        eError;
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	eError = RGXInitCreateFWKernelMemoryContext(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed RGXInitCreateFWKernelMemoryContext (%u)", eError));
+		goto failFWMemoryContextAlloc;
+	}
+
+	/* 
+	 * Set up Allocation for FW code section 
+	 */
+	uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+	                  PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
+	                  PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                          PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+	                  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
+
+
+	eError = RGXAllocateFWCodeRegion(psDeviceNode,
+	                                 uiFWCodeLen,
+	                                 uiMemAllocFlags,
+	                                 IMG_FALSE,
+	                                 "FwExCodeRegion",
+	                                 &psDevInfo->psRGXFWCodeMemDesc);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw code mem (%u)",
+				eError));
+		goto failFWCodeMemDescAlloc;
+	}
+
+	eError = DevmemLocalGetImportHandle(psDevInfo->psRGXFWCodeMemDesc, (void**) ppsFWCodePMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevmemLocalGetImportHandle failed (%u)", eError));
+		goto failFWCodeMemDescAqDevVirt;
+	}
+
+	eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
+	                                  &psDevInfo->sFWCodeDevVAddrBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw code mem (%u)",
+				eError));
+		goto failFWCodeMemDescAqDevVirt;
+	}
+	*psFWCodeDevVAddrBase = psDevInfo->sFWCodeDevVAddrBase;
+
+	if (0 == (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		/*
+		* The FW code must be the first allocation in the firmware heap, otherwise
+		* the bootloader will not work (META will not be able to find the bootloader).
+		*/
+		PVR_ASSERT(psFWCodeDevVAddrBase->uiAddr == RGX_FIRMWARE_HEAP_BASE);
+	}
+
+	/* 
+	 * Set up Allocation for FW data section 
+	 */
+	uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+	                  PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
+	                  PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                          PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+	                  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+	                  PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+	                  PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+	PDUMPCOMMENT("Allocate and export data memory for fw");
+
+	eError = DevmemFwAllocateExportable(psDeviceNode,
+										uiFWDataLen,
+										OSGetPageSize(),
+										uiMemAllocFlags,
+										"FwExDataRegion",
+	                                    &psDevInfo->psRGXFWDataMemDesc);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw data mem (%u)",
+				eError));
+		goto failFWDataMemDescAlloc;
+	}
+
+	eError = DevmemLocalGetImportHandle(psDevInfo->psRGXFWDataMemDesc, (void **) ppsFWDataPMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevmemLocalGetImportHandle failed (%u)", eError));
+		goto failFWDataMemDescAqDevVirt;
+	}
+
+	eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
+	                                  &psDevInfo->sFWDataDevVAddrBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw data mem (%u)",
+				eError));
+		goto failFWDataMemDescAqDevVirt;
+	}
+	*psFWDataDevVAddrBase = psDevInfo->sFWDataDevVAddrBase;
+
+	if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		eError = RGXAllocTrampoline(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "Failed to allocate trampoline region (%u)",
+					 eError));
+			goto failTrampolineMemDescAlloc;
+		}
+	}
+
+	if (uiFWCorememLen != 0)
+	{
+		/* 
+		 * Set up Allocation for FW coremem section 
+		 */
+		uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+			PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+			PVRSRV_MEMALLOCFLAG_GPU_READABLE | 
+			PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+			PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+			PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+			PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+			PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+			PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+		eError = RGXAllocateFWCodeRegion(psDeviceNode,
+		                                 uiFWCorememLen,
+		                                 uiMemAllocFlags,
+		                                 IMG_TRUE,
+		                                 "FwExCorememRegion",
+		                                 &psDevInfo->psRGXFWCorememMemDesc);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw coremem mem, size: %lld, flags: %x (%u)",
+						uiFWCorememLen, uiMemAllocFlags, eError));
+			goto failFWCorememMemDescAlloc;
+		}
+
+		eError = DevmemLocalGetImportHandle(psDevInfo->psRGXFWCorememMemDesc, (void**) ppsFWCorememPMR);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevmemLocalGetImportHandle failed (%u)", eError));
+			goto failFWCorememMemDescAqDevVirt;
+		}
+
+		eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc,
+		                                  &psDevInfo->sFWCorememCodeDevVAddrBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw coremem mem (%u)",
+						eError));
+			goto failFWCorememMemDescAqDevVirt;
+		}
+
+		RGXSetFirmwareAddress(&psDevInfo->sFWCorememCodeFWAddr,
+		                      psDevInfo->psRGXFWCorememMemDesc,
+		                      0, RFW_FWADDR_NOREF_FLAG);
+	}
+	else
+	{
+		psDevInfo->sFWCorememCodeDevVAddrBase.uiAddr = 0;
+		psDevInfo->sFWCorememCodeFWAddr.ui32Addr = 0;
+	}
+
+	*psFWCorememDevVAddrBase = psDevInfo->sFWCorememCodeDevVAddrBase;
+	*psFWCorememMetaVAddrBase = psDevInfo->sFWCorememCodeFWAddr;
+
+	return PVRSRV_OK;
+
+failFWCorememMemDescAqDevVirt:
+	if (uiFWCorememLen != 0)
+	{
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWCorememMemDesc);
+		psDevInfo->psRGXFWCorememMemDesc = NULL;
+	}
+failFWCorememMemDescAlloc:
+	if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		RGXFreeTrampoline(psDeviceNode);
+	}
+failTrampolineMemDescAlloc:
+	DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+failFWDataMemDescAqDevVirt:
+	DevmemFwFree(psDevInfo, psDevInfo->psRGXFWDataMemDesc);
+	psDevInfo->psRGXFWDataMemDesc = NULL;
+failFWDataMemDescAlloc:
+	DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+failFWCodeMemDescAqDevVirt:
+	DevmemFwFree(psDevInfo, psDevInfo->psRGXFWCodeMemDesc);
+	psDevInfo->psRGXFWCodeMemDesc = NULL;
+failFWCodeMemDescAlloc:
+failFWMemoryContextAlloc:
+	return eError;
+}
+#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
+
+/*
+	AppHint parameter interface
+*/
+static
+PVRSRV_ERROR RGXFWTraceQueryFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const void *psPrivate,
+                                   IMG_UINT32 *pui32Value)
+{
+	PVRSRV_ERROR eResult;
+
+	eResult = PVRSRVRGXDebugMiscQueryFWLogKM(NULL, psDeviceNode, pui32Value);
+	*pui32Value &= RGXFWIF_LOG_TYPE_GROUP_MASK;
+	return eResult;
+}
+
+static
+PVRSRV_ERROR RGXFWTraceQueryLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const void *psPrivate,
+                                   IMG_UINT32 *pui32Value)
+{
+	PVRSRV_ERROR eResult;
+
+	eResult = PVRSRVRGXDebugMiscQueryFWLogKM(NULL, psDeviceNode, pui32Value);
+	if (PVRSRV_OK == eResult)
+	{
+		if (*pui32Value & RGXFWIF_LOG_TYPE_TRACE)
+		{
+			*pui32Value = 2; /* Trace */
+		}
+		else if (*pui32Value & RGXFWIF_LOG_TYPE_GROUP_MASK)
+		{
+			*pui32Value = 1; /* TBI */
+		}
+		else
+		{
+			*pui32Value = 0; /* None */
+		}
+	}
+	return eResult;
+}
+
+static
+PVRSRV_ERROR RGXFWTraceSetFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  const void *psPrivate,
+                                  IMG_UINT32 ui32Value)
+{
+	PVRSRV_ERROR eResult;
+	IMG_UINT32 ui32RGXFWLogType;
+
+	eResult = RGXFWTraceQueryLogType(psDeviceNode, NULL, &ui32RGXFWLogType);
+	if (PVRSRV_OK == eResult)
+	{
+		if (ui32Value && 1 != ui32RGXFWLogType)
+		{
+			ui32Value |= RGXFWIF_LOG_TYPE_TRACE;
+		}
+		eResult = PVRSRVRGXDebugMiscSetFWLogKM(NULL, psDeviceNode, ui32Value);
+	}
+	return eResult;
+}
+
+static
+PVRSRV_ERROR RGXFWTraceSetLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    const void *psPrivate,
+                                    IMG_UINT32 ui32Value)
+{
+	PVRSRV_ERROR eResult;
+	IMG_UINT32 ui32RGXFWLogType = ui32Value;
+
+	/* 0 - none, 1 - tbi, 2 - trace */
+	if (ui32Value)
+	{
+		eResult = RGXFWTraceQueryFilter(psDeviceNode, NULL, &ui32RGXFWLogType);
+		if (PVRSRV_OK != eResult)
+		{
+			return eResult;
+		}
+		if (!ui32RGXFWLogType)
+		{
+			ui32RGXFWLogType = RGXFWIF_LOG_TYPE_GROUP_MAIN;
+		}
+		if (2 == ui32Value)
+		{
+			ui32RGXFWLogType |= RGXFWIF_LOG_TYPE_TRACE;
+		}
+	}
+
+	eResult = PVRSRVRGXDebugMiscSetFWLogKM(NULL, psDeviceNode, ui32RGXFWLogType);
+	return eResult;
+}
+
+static
+PVRSRV_ERROR RGXQueryFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
+									const void *psPrivate,
+									IMG_BOOL *pbValue)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+
+	*pbValue = psDevInfo->bEnableFWPoisonOnFree;
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR RGXSetFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
+									const void *psPrivate,
+									IMG_BOOL bValue)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+
+	psDevInfo->bEnableFWPoisonOnFree = bValue;
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR RGXQueryFWPoisonOnFreeValue(const PVRSRV_DEVICE_NODE *psDeviceNode,
+									const void *psPrivate,
+									IMG_UINT32 *pui32Value)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+	*pui32Value = psDevInfo->ubFWPoisonOnFreeValue;
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR RGXSetFWPoisonOnFreeValue(const PVRSRV_DEVICE_NODE *psDeviceNode,
+									const void *psPrivate,
+									IMG_UINT32 ui32Value)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+	psDevInfo->ubFWPoisonOnFreeValue = (IMG_BYTE) ui32Value;
+	return PVRSRV_OK;
+}
+
+/*
+ * PVRSRVRGXInitFirmwareKM
+ */ 
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXInitFirmwareKM(CONNECTION_DATA          *psConnection,
+                        PVRSRV_DEVICE_NODE       *psDeviceNode,
+                        RGXFWIF_DEV_VIRTADDR     *psRGXFwInit,
+                        IMG_BOOL                 bEnableSignatureChecks,
+                        IMG_UINT32               ui32SignatureChecksBufSize,
+                        IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                        IMG_UINT64               ui64HWPerfFilter,
+                        IMG_UINT32               ui32RGXFWAlignChecksArrLength,
+                        IMG_UINT32               *pui32RGXFWAlignChecks,
+                        IMG_UINT32               ui32ConfigFlags,
+                        IMG_UINT32               ui32LogType,
+                        IMG_UINT32               ui32FilterFlags,
+                        IMG_UINT32               ui32JonesDisableMask,
+                        IMG_UINT32               ui32HWRDebugDumpLimit,
+                        RGXFWIF_COMPCHECKS_BVNC  *psClientBVNC,
+                        IMG_UINT32               ui32HWPerfCountersDataSize,
+                        PMR                      **ppsHWPerfPMR,
+                        RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
+                        FW_PERF_CONF             eFirmwarePerf)
+{
+	PVRSRV_ERROR eError;
+	void *pvAppHintState = NULL;
+	IMG_UINT32 ui32AppHintDefault;
+	RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
+	IMG_BOOL bCompatibleAll=IMG_TRUE, bCompatibleVersion=IMG_TRUE, bCompatibleLenMax=IMG_TRUE, bCompatibleBNC=IMG_TRUE, bCompatibleV=IMG_TRUE;
+	IMG_UINT32 ui32NumBIFTilingConfigs, *pui32BIFTilingXStrides, i, ui32B, ui32V, ui32N, ui32C;
+	RGXFWIF_BIFTILINGMODE eBIFTilingMode;
+	IMG_CHAR szV[8];
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	ui32B = psDevInfo->sDevFeatureCfg.ui32B;
+	ui32V = psDevInfo->sDevFeatureCfg.ui32V;
+	ui32N = psDevInfo->sDevFeatureCfg.ui32N;
+	ui32C = psDevInfo->sDevFeatureCfg.ui32C;
+
+	OSSNPrintf(szV, sizeof(szV),"%d",ui32V);
+
+	/* Check if BVNC numbers of client and driver are compatible */
+	rgx_bvnc_packed(&sBVNC.ui64BNC, sBVNC.aszV, sBVNC.ui32VLenMax,  ui32B, szV, ui32N, ui32C);
+
+	RGX_BVNC_EQUAL(sBVNC, *psClientBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
+
+	if (!bCompatibleAll)
+	{
+		if (!bCompatibleVersion)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and client (%d).",
+					__FUNCTION__, 
+					sBVNC.ui32LayoutVersion, 
+					psClientBVNC->ui32LayoutVersion));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+
+		if (!bCompatibleLenMax)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and client (%d).",
+					__FUNCTION__, 
+					sBVNC.ui32VLenMax, 
+					psClientBVNC->ui32VLenMax));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+
+		if (!bCompatibleBNC)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible driver BNC (%d._.%d.%d) / client BNC (%d._.%d.%d).",
+					__FUNCTION__, 
+					RGX_BVNC_PACKED_EXTR_B(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_N(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_C(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_B(*psClientBVNC), 
+					RGX_BVNC_PACKED_EXTR_N(*psClientBVNC), 
+					RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+		
+		if (!bCompatibleV)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible driver BVNC (%d.%s.%d.%d) / client BVNC (%d.%s.%d.%d).",
+					__FUNCTION__, 
+					RGX_BVNC_PACKED_EXTR_B(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_V(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_N(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_C(sBVNC), 
+					RGX_BVNC_PACKED_EXTR_B(*psClientBVNC), 
+					RGX_BVNC_PACKED_EXTR_V(*psClientBVNC),
+					RGX_BVNC_PACKED_EXTR_N(*psClientBVNC), 
+					RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver BVNC (%d.%s.%d.%d) and client BVNC (%d.%s.%d.%d) match. [ OK ]",
+				__FUNCTION__, 
+				RGX_BVNC_PACKED_EXTR_B(sBVNC), 
+				RGX_BVNC_PACKED_EXTR_V(sBVNC), 
+				RGX_BVNC_PACKED_EXTR_N(sBVNC), 
+				RGX_BVNC_PACKED_EXTR_C(sBVNC), 
+				RGX_BVNC_PACKED_EXTR_B(*psClientBVNC), 
+				RGX_BVNC_PACKED_EXTR_V(*psClientBVNC), 
+				RGX_BVNC_PACKED_EXTR_N(*psClientBVNC), 
+				RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
+	}
+
+	PVRSRVSystemBIFTilingGetConfig(psDeviceNode->psDevConfig,
+	                               &eBIFTilingMode,
+	                               &ui32NumBIFTilingConfigs);
+	pui32BIFTilingXStrides = OSAllocMem(sizeof(IMG_UINT32) * ui32NumBIFTilingConfigs);
+	if(pui32BIFTilingXStrides == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: OSAllocMem failed (%u)", eError));
+		goto failed_BIF_tiling_alloc;
+	}
+	for(i = 0; i < ui32NumBIFTilingConfigs; i++)
+	{
+		eError = PVRSRVSystemBIFTilingHeapGetXStride(psDeviceNode->psDevConfig,
+		                                             i+1,
+		                                             &pui32BIFTilingXStrides[i]);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+			         "%s: Failed to get BIF tiling X stride for heap %u (%u)",
+			          __func__, i + 1, eError));
+			goto failed_BIF_heap_init;
+		}
+	}
+
+	eError = RGXSetupFirmware(psDeviceNode,
+	                          bEnableSignatureChecks,
+	                          ui32SignatureChecksBufSize,
+	                          ui32HWPerfFWBufSizeKB,
+	                          ui64HWPerfFilter,
+	                          ui32RGXFWAlignChecksArrLength,
+	                          pui32RGXFWAlignChecks,
+	                          ui32ConfigFlags,
+	                          ui32LogType,
+	                          eBIFTilingMode,
+	                          ui32NumBIFTilingConfigs,
+	                          pui32BIFTilingXStrides,
+	                          ui32FilterFlags,
+	                          ui32JonesDisableMask,
+	                          ui32HWRDebugDumpLimit,
+	                          ui32HWPerfCountersDataSize,
+	                          ppsHWPerfPMR,
+	                          psRGXFwInit,
+	                          eRGXRDPowerIslandingConf,
+	                          eFirmwarePerf);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: RGXSetupFirmware failed (%u)", eError));
+		goto failed_init_firmware;
+	}
+
+	OSFreeMem(pui32BIFTilingXStrides);
+
+	PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableLogGroup,
+	                                    RGXFWTraceQueryFilter,
+	                                    RGXFWTraceSetFilter,
+	                                    psDeviceNode,
+	                                    NULL);
+	PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_FirmwareLogType,
+	                                    RGXFWTraceQueryLogType,
+	                                    RGXFWTraceSetLogType,
+	                                    psDeviceNode,
+	                                    NULL);
+
+	/* FW Poison values are not passed through from the init code
+	 * so grab them here */
+	OSCreateKMAppHintState(&pvAppHintState);
+
+	ui32AppHintDefault = PVRSRV_APPHINT_ENABLEFWPOISONONFREE;
+	OSGetKMAppHintBOOL(pvAppHintState,
+	                   EnableFWPoisonOnFree,
+	                   &ui32AppHintDefault,
+	                   &psDevInfo->bEnableFWPoisonOnFree);
+
+	ui32AppHintDefault = PVRSRV_APPHINT_FWPOISONONFREEVALUE;
+	OSGetKMAppHintUINT32(pvAppHintState,
+	                     FWPoisonOnFreeValue,
+	                     &ui32AppHintDefault,
+	                     (IMG_UINT32*)&psDevInfo->ubFWPoisonOnFreeValue);
+
+	OSFreeKMAppHintState(pvAppHintState);
+
+	PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_EnableFWPoisonOnFree,
+	                                  RGXQueryFWPoisonOnFree,
+	                                  RGXSetFWPoisonOnFree,
+	                                  psDeviceNode,
+	                                  NULL);
+
+	PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_FWPoisonOnFreeValue,
+	                                    RGXQueryFWPoisonOnFreeValue,
+	                                    RGXSetFWPoisonOnFreeValue,
+	                                    psDeviceNode,
+	                                    NULL);
+
+	return PVRSRV_OK;
+
+failed_init_firmware:
+failed_BIF_heap_init:
+	OSFreeMem(pui32BIFTilingXStrides);
+failed_BIF_tiling_alloc:
+failed_to_pass_compatibility_check:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+/*
+ * PVRSRVRGXInitFirmwareExtendedKM
+ */
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXInitFirmwareExtendedKM(CONNECTION_DATA        *psConnection,
+                                PVRSRV_DEVICE_NODE     *psDeviceNode,
+                                IMG_UINT32             ui32RGXFWAlignChecksArrLength,
+                                IMG_UINT32             *pui32RGXFWAlignChecks,
+                                RGXFWIF_DEV_VIRTADDR   *psRGXFwInit,
+                                PMR                    **ppsHWPerfPMR,
+                                RGX_FW_INIT_IN_PARAMS  *psInParams)
+{
+	PVRSRV_ERROR eError;
+	RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
+	IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
+	RGXFWIF_COMPCHECKS_BVNC *psFirmwareBVNC = &(psInParams->sFirmwareBVNC);
+
+	PVRSRV_RGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+	IMG_CHAR	szV[8];
+
+	OSSNPrintf(szV, sizeof(szV),"%d",psDevInfo->sDevFeatureCfg.ui32V);
+	rgx_bvnc_packed(&sBVNC.ui64BNC, sBVNC.aszV, sBVNC.ui32VLenMax, psDevInfo->sDevFeatureCfg.ui32B, szV, psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C);
+
+	/* Check if BVNC numbers of firmware and driver are compatible */
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	RGX_BVNC_EQUAL(sBVNC, *psFirmwareBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
+#else
+	bCompatibleAll = IMG_TRUE;
+#endif
+	if (!bCompatibleAll)
+	{
+		if (!bCompatibleVersion)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and firmware (%d).",
+			         __FUNCTION__,
+			         sBVNC.ui32LayoutVersion,
+			         psFirmwareBVNC->ui32LayoutVersion));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+
+		if (!bCompatibleLenMax)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and firmware (%d).",
+			         __FUNCTION__,
+			         sBVNC.ui32VLenMax,
+			         psFirmwareBVNC->ui32VLenMax));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+
+		if (!bCompatibleBNC)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible driver BNC (%d._.%d.%d) / firmware BNC (%d._.%d.%d).",
+			         __FUNCTION__,
+			         RGX_BVNC_PACKED_EXTR_B(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_N(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_C(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_B(*psFirmwareBVNC),
+			         RGX_BVNC_PACKED_EXTR_N(*psFirmwareBVNC),
+			         RGX_BVNC_PACKED_EXTR_C(*psFirmwareBVNC)));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+
+		if (!bCompatibleV)
+		{
+			PVR_LOG(("(FAIL) %s: Incompatible driver BVNC (%d.%s.%d.%d) / firmware BVNC (%d.%s.%d.%d).",
+			         __FUNCTION__,
+			         RGX_BVNC_PACKED_EXTR_B(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_V(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_N(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_C(sBVNC),
+			         RGX_BVNC_PACKED_EXTR_B(*psFirmwareBVNC),
+			         RGX_BVNC_PACKED_EXTR_V(*psFirmwareBVNC),
+			         RGX_BVNC_PACKED_EXTR_N(*psFirmwareBVNC),
+			         RGX_BVNC_PACKED_EXTR_C(*psFirmwareBVNC)));
+			eError = PVRSRV_ERROR_BVNC_MISMATCH;
+			PVR_DBG_BREAK;
+			goto failed_to_pass_compatibility_check;
+		}
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver BVNC (%d.%s.%d.%d) and firmware BVNC (%d.%s.%d.%d) match. [ OK ]",
+		         __FUNCTION__,
+		         RGX_BVNC_PACKED_EXTR_B(sBVNC),
+		         RGX_BVNC_PACKED_EXTR_V(sBVNC),
+		         RGX_BVNC_PACKED_EXTR_N(sBVNC),
+		         RGX_BVNC_PACKED_EXTR_C(sBVNC),
+		         RGX_BVNC_PACKED_EXTR_B(*psFirmwareBVNC),
+		         RGX_BVNC_PACKED_EXTR_V(*psFirmwareBVNC),
+		         RGX_BVNC_PACKED_EXTR_N(*psFirmwareBVNC),
+		         RGX_BVNC_PACKED_EXTR_C(*psFirmwareBVNC)));
+	}
+
+	eError = PVRSRVRGXInitFirmwareKM(psConnection,
+	                                 psDeviceNode,
+	                                 psRGXFwInit,
+	                                 psInParams->bEnableSignatureChecks,
+	                                 psInParams->ui32SignatureChecksBufSize,
+	                                 psInParams->ui32HWPerfFWBufSizeKB,
+	                                 psInParams->ui64HWPerfFilter,
+	                                 ui32RGXFWAlignChecksArrLength,
+	                                 pui32RGXFWAlignChecks,
+	                                 psInParams->ui32ConfigFlags,
+	                                 psInParams->ui32LogType,
+	                                 psInParams->ui32FilterFlags,
+	                                 psInParams->ui32JonesDisableMask,
+	                                 psInParams->ui32HWRDebugDumpLimit,
+	                                 &(psInParams->sClientBVNC),
+	                                 psInParams->ui32HWPerfCountersDataSize,
+	                                 ppsHWPerfPMR,
+	                                 psInParams->eRGXRDPowerIslandingConf,
+	                                 psInParams->eFirmwarePerf);
+	return eError;
+
+failed_to_pass_compatibility_check:
+	PVR_ASSERT(eError != PVRSRV_OK);
+
+	return eError;
+}
+
+/* See device.h for function declaration */
+static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
+									 DEVMEM_MEMDESC **psMemDesc,
+									 IMG_UINT32 *puiSyncPrimVAddr,
+									 IMG_UINT32 *puiSyncPrimBlockSize)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	PVRSRV_ERROR eError;
+	RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
+	IMG_DEVMEM_SIZE_T uiUFOBlockSize = sizeof(IMG_UINT32);
+	IMG_DEVMEM_ALIGN_T ui32UFOBlockAlign = sizeof(IMG_UINT32);
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	/* Size and align are 'expanded' because we request an Exportalign allocation */
+	DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
+										&uiUFOBlockSize,
+										&ui32UFOBlockAlign);
+
+	eError = DevmemFwAllocateExportable(psDeviceNode,
+										uiUFOBlockSize,
+										ui32UFOBlockAlign,
+										PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+										PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+										PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+										PVRSRV_MEMALLOCFLAG_CACHE_COHERENT | 
+										PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+										PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+										PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+										PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
+										"FwExUFOBlock",
+										psMemDesc);
+	if (eError != PVRSRV_OK)
+	{
+		goto e0;
+	}
+
+	RGXSetFirmwareAddress(&pFirmwareAddr, *psMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+	*puiSyncPrimVAddr = pFirmwareAddr.ui32Addr;
+	*puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
+
+	return PVRSRV_OK;
+
+e0:
+	return eError;
+}
+
+/* See device.h for function declaration */
+static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
+							DEVMEM_MEMDESC *psMemDesc)
+{
+	/*
+		If the system has snooping of the device cache then the UFO block
+		might be in the cache so we need to flush it out before freeing
+		the memory
+
+		When the device is being shutdown/destroyed we don't care anymore.
+		Several necessary data structures to issue a flush were destroyed
+		already.
+	*/
+	if (PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig) &&
+		psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_DEINIT)
+	{
+		RGXFWIF_KCCB_CMD sFlushInvalCmd;
+		PVRSRV_ERROR eError;
+
+		/* Schedule the SLC flush command ... */
+#if defined(PDUMP)
+		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+#endif
+		sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
+		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bDMContext = IMG_FALSE;
+		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = 0;
+		sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
+
+		eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
+											RGXFWIF_DM_GP,
+											&sFlushInvalCmd,
+											sizeof(sFlushInvalCmd),
+											PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: Failed to schedule SLC flush command with error (%u)", eError));
+		}
+		else
+		{
+			/* Wait for the SLC flush to complete */
+			eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: SLC flush and invalidate aborted with error (%u)", eError));
+			}
+		}
+	}
+
+	RGXUnsetFirmwareAddress(psMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, psMemDesc);
+}
+
+/*
+	DevDeInitRGX
+*/
+PVRSRV_ERROR DevDeInitRGX (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_RGXDEV_INFO			*psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
+	PVRSRV_ERROR				eError;
+	DEVICE_MEMORY_INFO		    *psDevMemoryInfo;
+	IMG_UINT32		ui32Temp=0;
+	if (!psDevInfo)
+	{
+		/* Can happen if DevInitRGX failed */
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Null DevInfo"));
+		return PVRSRV_OK;
+	}
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+	if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+	{
+		OSAtomicWrite(&psDeviceNode->sDummyPage.atRefCounter, 0);
+		PVR_UNREFERENCED_PARAMETER(ui32Temp);
+	}
+	else
+#else
+	{
+		/*Delete the Dummy page related info */
+		ui32Temp = (IMG_UINT32)OSAtomicRead(&psDeviceNode->sDummyPage.atRefCounter);
+		if(0 != ui32Temp)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"%s: Dummy page reference counter is non zero", __func__));
+			PVR_ASSERT(0);
+		}
+	}
+#endif
+#if defined(PDUMP)
+		if(NULL != psDeviceNode->sDummyPage.hPdumpDummyPg)
+		{
+			PDUMPCOMMENT("Error dummy page handle is still active");
+		}
+#endif
+
+#if defined(SUPPORT_PDVFS) && !defined(RGXFW_META_SUPPORT_2ND_THREAD)
+	OSDisableTimer(psDeviceNode->psDevConfig->sDVFS.sPDVFSData.hReactiveTimer);
+	OSRemoveTimer(psDeviceNode->psDevConfig->sDVFS.sPDVFSData.hReactiveTimer);
+#endif
+
+	/*The lock type need to be dispatch type here because it can be acquired from MISR (Z-buffer) path */
+	OSLockDestroy(psDeviceNode->sDummyPage.psDummyPgLock);
+
+	/* Unregister debug request notifiers first as they could depend on anything. */
+	if (psDevInfo->hDbgReqNotify)
+	{
+		PVRSRVUnregisterDbgRequestNotify(psDevInfo->hDbgReqNotify);
+	}
+
+	/* Cancel notifications to this device */
+	PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
+	psDeviceNode->hCmdCompNotify = NULL;
+
+	/*
+	 *  De-initialise in reverse order, so stage 2 init is undone first.
+	 */
+	if (psDevInfo->bDevInit2Done)
+	{
+		psDevInfo->bDevInit2Done = IMG_FALSE;
+
+#if !defined(NO_HARDWARE)
+		(void) SysUninstallDeviceLISR(psDevInfo->pvLISRData);
+		(void) OSUninstallMISR(psDevInfo->pvMISRData);
+		(void) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
+		if (psDevInfo->pvAPMISRData != NULL)
+		{
+			(void) OSUninstallMISR(psDevInfo->pvAPMISRData);
+		}
+#endif /* !NO_HARDWARE */
+
+		/* Remove the device from the power manager */
+		eError = PVRSRVRemovePowerDevice(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+		OSLockDestroy(psDevInfo->hGPUUtilLock);
+
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+		/* Free DVFS Table */
+		if (psDevInfo->psGpuDVFSTable != NULL)
+		{
+			OSFreeMem(psDevInfo->psGpuDVFSTable);
+			psDevInfo->psGpuDVFSTable = NULL;
+		}
+#endif
+
+		/* De-init Freelists/ZBuffers... */
+		OSLockDestroy(psDevInfo->hLockFreeList);
+		OSLockDestroy(psDevInfo->hLockZSBuffer);
+
+		/* Unregister MMU related stuff */
+		eError = RGXMMUInit_Unregister(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)", eError));
+			return eError;
+		}
+
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+		{
+			/* Unregister MMU related stuff */
+			eError = RGXMipsMMUInit_Unregister(psDeviceNode);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed RGXMipsMMUInit_Unregister (0x%x)", eError));
+				return eError;
+			}
+		}
+	}
+
+	/* UnMap Regs */
+	if (psDevInfo->pvRegsBaseKM != NULL)
+	{
+#if !defined(NO_HARDWARE)
+		OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+						 psDevInfo->ui32RegSize,
+						 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
+#endif /* !NO_HARDWARE */
+		psDevInfo->pvRegsBaseKM = NULL;
+	}
+
+#if 0 /* not required at this time */
+	if (psDevInfo->hTimer)
+	{
+		eError = OSRemoveTimer(psDevInfo->hTimer);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed to remove timer"));
+			return 	eError;
+		}
+		psDevInfo->hTimer = NULL;
+	}
+#endif
+
+    psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+	RGXDeInitHeaps(psDevMemoryInfo);
+
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	if (psDevInfo->psRGXFWCodeMemDesc)
+	{
+		/* Free fw code */
+		PDUMPCOMMENT("Freeing FW code memory");
+		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWCodeMemDesc);
+		psDevInfo->psRGXFWCodeMemDesc = NULL;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_WARNING,"No firmware code memory to free"));
+	}
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		if (psDevInfo->sTrampoline.sPages.u.pvHandle)
+		{
+			/* Free trampoline region */
+			PDUMPCOMMENT("Freeing trampoline memory");
+			RGXFreeTrampoline(psDeviceNode);
+		}
+	}
+
+	if (psDevInfo->psRGXFWDataMemDesc)
+	{
+		/* Free fw data */
+		PDUMPCOMMENT("Freeing FW data memory");
+		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWDataMemDesc);
+		psDevInfo->psRGXFWDataMemDesc = NULL;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_WARNING,"No firmware data memory to free"));
+	}
+
+	if (psDevInfo->psRGXFWCorememMemDesc)
+	{
+		/* Free fw data */
+		PDUMPCOMMENT("Freeing FW coremem memory");
+		DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc);
+		DevmemFwFree(psDevInfo, psDevInfo->psRGXFWCorememMemDesc);
+		psDevInfo->psRGXFWCorememMemDesc = NULL;
+	}
+#endif
+
+	/*
+	   Free the firmware allocations.
+	 */
+	RGXFreeFirmware(psDevInfo);
+	RGXDeInitDestroyFWKernelMemoryContext(psDeviceNode);
+
+	/* De-initialise non-device specific (TL) users of RGX device memory */
+	RGXHWPerfHostDeInit();
+	eError = HTBDeInit();
+	PVR_LOG_IF_ERROR(eError, "HTBDeInit");
+
+	/* destroy the context list locks */
+	OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
+	OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
+	OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
+	OSWRLockDestroy(psDevInfo->hTDMCtxListLock);
+	OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
+	OSWRLockDestroy(psDevInfo->hKickSyncCtxListLock);
+	OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
+
+
+	if ((psDevInfo->hNMILock != NULL) && (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		OSLockDestroy(psDevInfo->hNMILock);
+	}
+
+#if defined(SUPPORT_PAGE_FAULT_DEBUG)
+	if (psDevInfo->hDebugFaultInfoLock != NULL)
+	{
+		OSLockDestroy(psDevInfo->hDebugFaultInfoLock);
+	}
+	if (psDevInfo->hMMUCtxUnregLock != NULL)
+	{
+		OSLockDestroy(psDevInfo->hMMUCtxUnregLock);
+	}
+#endif
+
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/* Free the init scripts. */
+	OSFreeMem(psDevInfo->psScripts);
+#endif
+
+	/* Free device BVNC string */
+	if(NULL != psDevInfo->sDevFeatureCfg.pszBVNCString)
+	{
+		OSFreeMem(psDevInfo->sDevFeatureCfg.pszBVNCString);
+	}
+
+	/* DeAllocate devinfo */
+	OSFreeMem(psDevInfo);
+
+	psDeviceNode->pvDevice = NULL;
+
+	return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR RGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
+
+	psDevInfo->bDumpedKCCBCtlAlready = IMG_FALSE;
+
+	return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+static INLINE DEVMEM_HEAP_BLUEPRINT _blueprint_init(IMG_CHAR *name,
+	IMG_UINT64 heap_base,
+	IMG_DEVMEM_SIZE_T heap_length,
+	IMG_UINT32 log2_import_alignment,
+	IMG_UINT32 tiling_mode)
+{
+	DEVMEM_HEAP_BLUEPRINT b = {
+		.pszName = name,
+		.sHeapBaseAddr.uiAddr = heap_base,
+		.uiHeapLength = heap_length,
+		.uiLog2DataPageSize = RGXHeapDerivePageSize(OSGetPageShift()),
+		.uiLog2ImportAlignment = log2_import_alignment,
+		.uiLog2TilingStrideFactor = (RGX_BIF_TILING_HEAP_LOG2_ALIGN_TO_STRIDE_BASE - tiling_mode)
+	};
+	void *pvAppHintState = NULL;
+	IMG_UINT32 ui32AppHintDefault = PVRSRV_APPHINT_GENERAL_NON4K_HEAP_PAGE_SIZE;
+	IMG_UINT32 ui32GeneralNon4KHeapPageSize;
+
+	if (!OSStringCompare(name, RGX_GENERAL_NON4K_HEAP_IDENT))
+	{
+		OSCreateKMAppHintState(&pvAppHintState);
+		OSGetKMAppHintUINT32(pvAppHintState, GeneralNon4KHeapPageSize,
+				&ui32AppHintDefault, &ui32GeneralNon4KHeapPageSize);
+		switch (ui32GeneralNon4KHeapPageSize)
+		{
+			case (1<<RGX_HEAP_4KB_PAGE_SHIFT):
+				b.uiLog2DataPageSize = RGX_HEAP_4KB_PAGE_SHIFT;
+				break;
+			case (1<<RGX_HEAP_16KB_PAGE_SHIFT):
+				b.uiLog2DataPageSize = RGX_HEAP_16KB_PAGE_SHIFT;
+				break;
+			case (1<<RGX_HEAP_64KB_PAGE_SHIFT):
+				b.uiLog2DataPageSize = RGX_HEAP_64KB_PAGE_SHIFT;
+				break;
+			case (1<<RGX_HEAP_256KB_PAGE_SHIFT):
+				b.uiLog2DataPageSize = RGX_HEAP_256KB_PAGE_SHIFT;
+				break;
+			case (1<<RGX_HEAP_1MB_PAGE_SHIFT):
+				b.uiLog2DataPageSize = RGX_HEAP_1MB_PAGE_SHIFT;
+				break;
+			case (1<<RGX_HEAP_2MB_PAGE_SHIFT):
+				b.uiLog2DataPageSize = RGX_HEAP_2MB_PAGE_SHIFT;
+				break;
+			default:
+				PVR_DPF((PVR_DBG_ERROR,"Invalid AppHint GeneralAltHeapPageSize [%d] value, using 4KB",
+						ui32AppHintDefault));
+				break;
+		}
+		OSFreeKMAppHintState(pvAppHintState);
+	}
+
+	return b;
+}
+
+#define INIT_HEAP(NAME) \
+do { \
+	*psDeviceMemoryHeapCursor = _blueprint_init( \
+			RGX_ ## NAME ## _HEAP_IDENT, \
+			RGX_ ## NAME ## _HEAP_BASE, \
+			RGX_ ## NAME ## _HEAP_SIZE, \
+			0, 0); \
+	psDeviceMemoryHeapCursor++; \
+} while (0)
+
+#define INIT_HEAP_NAME(STR, NAME) \
+do { \
+	*psDeviceMemoryHeapCursor = _blueprint_init( \
+			STR, \
+			RGX_ ## NAME ## _HEAP_BASE, \
+			RGX_ ## NAME ## _HEAP_SIZE, \
+			0, 0); \
+	psDeviceMemoryHeapCursor++; \
+} while (0)
+
+#define INIT_TILING_HEAP(D, N, M)		\
+do { \
+	IMG_UINT32 xstride; \
+	PVRSRVSystemBIFTilingHeapGetXStride((D)->psDeviceNode->psDevConfig, N, &xstride); \
+	*psDeviceMemoryHeapCursor = _blueprint_init( \
+			RGX_BIF_TILING_HEAP_ ## N ## _IDENT, \
+			RGX_BIF_TILING_HEAP_ ## N ## _BASE, \
+			RGX_BIF_TILING_HEAP_SIZE, \
+			RGX_BIF_TILING_HEAP_ALIGN_LOG2_FROM_XSTRIDE(xstride), \
+			M); \
+	psDeviceMemoryHeapCursor++; \
+} while (0)
+
+static PVRSRV_ERROR RGXInitHeaps(PVRSRV_RGXDEV_INFO *psDevInfo,
+								 DEVICE_MEMORY_INFO *psNewMemoryInfo,
+								 IMG_UINT32 *pui32DummyPgSize)
+{
+	IMG_UINT64	ui64ErnsBrns;
+	DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor;
+	IMG_UINT32 uiTilingMode;
+	IMG_UINT32 uiNumHeaps;
+
+	ui64ErnsBrns = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
+
+	/* FIXME - consider whether this ought not to be on the device node itself */
+	psNewMemoryInfo->psDeviceMemoryHeap = OSAllocMem(sizeof(DEVMEM_HEAP_BLUEPRINT) * RGX_MAX_HEAP_ID);
+	if(psNewMemoryInfo->psDeviceMemoryHeap == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_BLUEPRINT"));
+		goto e0;
+	}
+
+	PVRSRVSystemBIFTilingGetConfig(psDevInfo->psDeviceNode->psDevConfig, &uiTilingMode, &uiNumHeaps);
+
+	/* Calculate the dummy page size which is the maximum page size supported
+	 * by heaps which can have sparse allocations
+	 *
+	 * The heaps that can have sparse allocations are general and Doppler for now.
+	 * As it was suggested the doppler allocations doesn't have to be backed by dummy
+	 * and taking into account its 2MB page size supported in future, we take
+	 * general heap page size as reference for now */
+	*pui32DummyPgSize = RGXHeapDerivePageSize(OSGetPageShift());
+
+	/* Initialise the heaps */
+	psDeviceMemoryHeapCursor = psNewMemoryInfo->psDeviceMemoryHeap;
+
+	INIT_HEAP(GENERAL_SVM);
+	INIT_HEAP(GENERAL);
+
+	if (ui64ErnsBrns & FIX_HW_BRN_63142_BIT_MASK)
+	{
+		/* BRN63142 heap must be at the top of an aligned 16GB range. */
+		INIT_HEAP(RGNHDR_BRN_63142);
+		PVR_ASSERT((RGX_RGNHDR_BRN_63142_HEAP_BASE & IMG_UINT64_C(0x3FFFFFFFF)) +
+		           RGX_RGNHDR_BRN_63142_HEAP_SIZE == IMG_UINT64_C(0x400000000));
+	}
+
+	INIT_HEAP(GENERAL_NON4K);
+	INIT_HEAP(VISTEST);
+
+	if (ui64ErnsBrns & FIX_HW_BRN_52402_BIT_MASK)
+	{
+		INIT_HEAP_NAME("PDS Code and Data", PDSCODEDATA_BRN_52402);
+		INIT_HEAP_NAME("USC Code", USCCODE_BRN_52402);
+	}
+	else
+	{
+		INIT_HEAP(PDSCODEDATA);
+		INIT_HEAP(USCCODE);
+	}
+
+	if (ui64ErnsBrns & (FIX_HW_BRN_52402_BIT_MASK | FIX_HW_BRN_55091_BIT_MASK))
+	{
+		INIT_HEAP_NAME("TQ3DParameters", TQ3DPARAMETERS_BRN_52402_55091);
+	}
+	else
+	{
+		INIT_HEAP(TQ3DPARAMETERS);
+	}
+
+	INIT_TILING_HEAP(psDevInfo, 1, uiTilingMode);
+	INIT_TILING_HEAP(psDevInfo, 2, uiTilingMode);
+	INIT_TILING_HEAP(psDevInfo, 3, uiTilingMode);
+	INIT_TILING_HEAP(psDevInfo, 4, uiTilingMode);
+	INIT_HEAP(DOPPLER);
+	INIT_HEAP(DOPPLER_OVERFLOW);
+	INIT_HEAP(TDM_TPU_YUV_COEFFS);
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK)
+	{
+		INIT_HEAP(SERVICES_SIGNALS);
+		INIT_HEAP(SIGNALS);
+	}
+	INIT_HEAP_NAME("HWBRN37200", HWBRN37200);
+	INIT_HEAP_NAME("Firmware", FIRMWARE);
+
+	/* set the heap count */
+	psNewMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeapCursor - psNewMemoryInfo->psDeviceMemoryHeap);
+
+	PVR_ASSERT(psNewMemoryInfo->ui32HeapCount <= RGX_MAX_HEAP_ID);
+
+    /* the new way: we'll set up 2 heap configs: one will be for Meta
+       only, and has only the firmware heap in it. 
+       The remaining one shall be for clients only, and shall have all
+       the other heaps in it */
+
+    psNewMemoryInfo->uiNumHeapConfigs = 2;
+	psNewMemoryInfo->psDeviceMemoryHeapConfigArray = OSAllocMem(sizeof(DEVMEM_HEAP_CONFIG) * psNewMemoryInfo->uiNumHeapConfigs);
+    if (psNewMemoryInfo->psDeviceMemoryHeapConfigArray == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_CONFIG"));
+		goto e1;
+	}
+    
+    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].pszName = "Default Heap Configuration";
+    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].uiNumHeaps = psNewMemoryInfo->ui32HeapCount-1;
+    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].psHeapBlueprintArray = psNewMemoryInfo->psDeviceMemoryHeap;
+
+    psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].pszName = "Firmware Heap Configuration";
+    if(ui64ErnsBrns & FIX_HW_BRN_37200_BIT_MASK)
+    {
+    	psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 2;
+    	psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-2;
+    }else
+    {
+    	psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 1;
+    	psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-1;
+    }
+
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	if (RGXVzInitHeaps(psNewMemoryInfo, psDeviceMemoryHeapCursor) != PVRSRV_OK)
+	{
+		goto e1;
+	}
+#endif
+
+	return PVRSRV_OK;
+e1:
+	OSFreeMem(psNewMemoryInfo->psDeviceMemoryHeap);
+e0:
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+#undef INIT_HEAP
+#undef INIT_HEAP_NAME
+#undef INIT_TILING_HEAP
+
+static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
+{
+#if defined(SUPPORT_PVRSRV_GPUVIRT)
+	RGXVzDeInitHeaps(psDevMemoryInfo);
+#endif
+	OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeapConfigArray);
+	OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeap);
+}
+
+/*This function searches the given array for a given search value */
+static void *RGXSearchTable( IMG_UINT64 *pui64Array,
+								IMG_UINT uiEnd,
+								IMG_UINT64 ui64SearchValue,
+								IMG_UINT uiRowCount)
+{
+	IMG_UINT uiStart = 0, index;
+	IMG_UINT64 value, *pui64Ptr = NULL;
+
+	while(uiStart < uiEnd)
+	{
+		index = (uiStart + uiEnd)/2;
+		pui64Ptr = pui64Array + (index * uiRowCount);
+		value = *(pui64Ptr);
+
+		if(value == ui64SearchValue)
+		{
+			return (void *)pui64Ptr;
+		}
+
+		if(value > ui64SearchValue)
+		{
+			uiEnd = index;
+		}else
+		{
+			uiStart = index + 1;
+		}
+	}
+	return NULL;
+}
+
+#if defined(DEBUG)
+static void RGXDumpParsedBVNCConfig(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+	IMG_UINT64 ui64Temp = 0, ui64Temp2 = 1;
+
+	PVR_LOG(( "NC: 		%d", psDevInfo->sDevFeatureCfg.ui32NumClusters));
+	PVR_LOG(( "CSF: 		%d", psDevInfo->sDevFeatureCfg.ui32CtrlStreamFormat));
+	PVR_LOG(( "FBCDCA:	%d", psDevInfo->sDevFeatureCfg.ui32FBCDCArch));
+	PVR_LOG(( "MCMB: 		%d", psDevInfo->sDevFeatureCfg.ui32MCMB));
+	PVR_LOG(( "MCMS: 		%d", psDevInfo->sDevFeatureCfg.ui32MCMS));
+	PVR_LOG(( "MDMACnt: 	%d", psDevInfo->sDevFeatureCfg.ui32MDMACount));
+	PVR_LOG(( "NIIP: 		%d", psDevInfo->sDevFeatureCfg.ui32NIIP));
+	PVR_LOG(( "PBW: 		%d", psDevInfo->sDevFeatureCfg.ui32PBW));
+	PVR_LOG(( "STEArch: 	%d", psDevInfo->sDevFeatureCfg.ui32STEArch));
+	PVR_LOG(( "SVCEA: 	%d", psDevInfo->sDevFeatureCfg.ui32SVCE));
+	PVR_LOG(( "SLCBanks: 	%d", psDevInfo->sDevFeatureCfg.ui32SLCBanks));
+	PVR_LOG(( "SLCCLS: 	%d", psDevInfo->sDevFeatureCfg.ui32CacheLineSize));
+	PVR_LOG(( "SLCSize: 	%d", psDevInfo->sDevFeatureCfg.ui32SLCSize));
+	PVR_LOG(( "VASB:	 	%d", psDevInfo->sDevFeatureCfg.ui32VASB));
+	PVR_LOG(( "META:	 	%d", psDevInfo->sDevFeatureCfg.ui32META));
+
+	/* Dump the features with no values */
+	ui64Temp = psDevInfo->sDevFeatureCfg.ui64Features;
+	while(ui64Temp)
+	{
+		if(ui64Temp & 0x01)
+		{
+			IMG_PCHAR psString = "Unknown feature, debug list should be updated....";
+			switch(ui64Temp2)
+			{
+			case RGX_FEATURE_AXI_ACELITE_BIT_MASK: psString = "RGX_FEATURE_AXI_ACELITE";break;
+			case RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK:
+				psString = "RGX_FEATURE_CLUSTER_GROUPING";break;
+			case RGX_FEATURE_COMPUTE_BIT_MASK:
+				psString = "RGX_FEATURE_COMPUTE";break;
+			case RGX_FEATURE_COMPUTE_MORTON_CAPABLE_BIT_MASK:
+				psString = "RGX_FEATURE_COMPUTE_MORTON_CAPABLE";break;
+			case RGX_FEATURE_COMPUTE_OVERLAP_BIT_MASK:
+				psString = "RGX_FEATURE_COMPUTE_OVERLAP";break;
+			case RGX_FEATURE_COMPUTE_OVERLAP_WITH_BARRIERS_BIT_MASK:
+				psString = "RGX_FEATURE_COMPUTE_OVERLAP_WITH_BARRIERS"; break;
+			case RGX_FEATURE_DYNAMIC_DUST_POWER_BIT_MASK:
+				psString = "RGX_FEATURE_DYNAMIC_DUST_POWER";break;
+			case RGX_FEATURE_FASTRENDER_DM_BIT_MASK:
+				psString = "RGX_FEATURE_FASTRENDER_DM";break;
+			case RGX_FEATURE_GPU_CPU_COHERENCY_BIT_MASK:
+				psString = "RGX_FEATURE_GPU_CPU_COHERENCY";break;
+			case RGX_FEATURE_GPU_VIRTUALISATION_BIT_MASK:
+				psString = "RGX_FEATURE_GPU_VIRTUALISATION";break;
+			case RGX_FEATURE_GS_RTA_SUPPORT_BIT_MASK:
+				psString = "RGX_FEATURE_GS_RTA_SUPPORT";break;
+			case RGX_FEATURE_META_DMA_BIT_MASK:
+				psString = "RGX_FEATURE_META_DMA";break;
+			case RGX_FEATURE_MIPS_BIT_MASK:
+				psString = "RGX_FEATURE_MIPS";break;
+			case RGX_FEATURE_PBE2_IN_XE_BIT_MASK:
+				psString = "RGX_FEATURE_PBE2_IN_XE";break;
+			case RGX_FEATURE_PBVNC_COREID_REG_BIT_MASK:
+				psString = "RGX_FEATURE_PBVNC_COREID_REG";break;
+			case RGX_FEATURE_PDS_PER_DUST_BIT_MASK:
+				psString = "RGX_FEATURE_PDS_PER_DUST";break;
+			case RGX_FEATURE_PDS_TEMPSIZE8_BIT_MASK:
+				psString = "RGX_FEATURE_PDS_TEMPSIZE8";break;
+			case RGX_FEATURE_PERFBUS_BIT_MASK:
+				psString = "RGX_FEATURE_PERFBUS";break;
+			case RGX_FEATURE_RAY_TRACING_BIT_MASK:
+				psString = "RGX_FEATURE_RAY_TRACING";break;
+			case RGX_FEATURE_ROGUEXE_BIT_MASK:
+				psString = "RGX_FEATURE_ROGUEXE";break;
+			case RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK:
+				psString = "RGX_FEATURE_S7_CACHE_HIERARCHY";break;
+			case RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK:
+				psString = "RGX_FEATURE_S7_TOP_INFRASTRUCTURE";break;
+			case RGX_FEATURE_SCALABLE_VDM_GPP_BIT_MASK:
+				psString = "RGX_FEATURE_SCALABLE_VDM_GPP";break;
+			case RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK:
+				psString = "RGX_FEATURE_SIGNAL_SNOOPING";break;
+			case RGX_FEATURE_SINGLE_BIF_BIT_MASK:
+				psString = "RGX_FEATURE_SINGLE_BIF";break;
+			case RGX_FEATURE_SLCSIZE8_BIT_MASK:
+				psString = "RGX_FEATURE_SLCSIZE8";break;
+			case RGX_FEATURE_SLC_HYBRID_CACHELINE_64_128_BIT_MASK:
+				psString = "RGX_FEATURE_SLC_HYBRID_CACHELINE_64_128"; break;
+			case RGX_FEATURE_SLC_VIVT_BIT_MASK:
+				psString = "RGX_FEATURE_SLC_VIVT";break;
+			case RGX_FEATURE_SYS_BUS_SECURE_RESET_BIT_MASK:
+				psString = "RGX_FEATURE_SYS_BUS_SECURE_RESET"; break;
+			case RGX_FEATURE_TESSELLATION_BIT_MASK:
+				psString = "RGX_FEATURE_TESSELLATION";break;
+			case RGX_FEATURE_TLA_BIT_MASK:
+				psString = "RGX_FEATURE_TLA";break;
+			case RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_BIT_MASK:
+				psString = "RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS";break;
+			case RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_BIT_MASK:
+				psString = "RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS";break;
+			case RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_BIT_MASK:
+				psString = "RGX_FEATURE_TPU_FILTERING_MODE_CONTROL";break;
+			case RGX_FEATURE_VDM_DRAWINDIRECT_BIT_MASK:
+				psString = "RGX_FEATURE_VDM_DRAWINDIRECT";break;
+			case RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_BIT_MASK:
+				psString = "RGX_FEATURE_VDM_OBJECT_LEVEL_LLS";break;
+			case RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK:
+				psString = "RGX_FEATURE_XT_TOP_INFRASTRUCTURE";break;
+
+
+			default:PVR_DPF((PVR_DBG_WARNING,"Feature with Mask doesn't not exist: 0x%016llx", ui64Temp));
+			break;
+			}
+			PVR_LOG(("%s", psString));
+		}
+		ui64Temp >>= 1;
+		ui64Temp2 <<= 1;
+	}
+
+	/*Dump the ERN and BRN flags for this core */
+	ui64Temp = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
+	ui64Temp2 = 1;
+
+	while(ui64Temp)
+	{
+		if(ui64Temp & 0x1)
+		{
+			IMG_UINT32	ui32ErnBrnId = 0;
+			switch(ui64Temp2)
+			{
+			case HW_ERN_36400_BIT_MASK: ui32ErnBrnId = 36400; break;
+			case FIX_HW_BRN_37200_BIT_MASK: ui32ErnBrnId = 37200; break;
+			case FIX_HW_BRN_37918_BIT_MASK: ui32ErnBrnId = 37918; break;
+			case FIX_HW_BRN_38344_BIT_MASK: ui32ErnBrnId = 38344; break;
+			case HW_ERN_41805_BIT_MASK: ui32ErnBrnId = 41805; break;
+			case HW_ERN_42290_BIT_MASK: ui32ErnBrnId = 42290; break;
+			case FIX_HW_BRN_42321_BIT_MASK: ui32ErnBrnId = 42321; break;
+			case FIX_HW_BRN_42480_BIT_MASK: ui32ErnBrnId = 42480; break;
+			case HW_ERN_42606_BIT_MASK: ui32ErnBrnId = 42606; break;
+			case FIX_HW_BRN_43276_BIT_MASK: ui32ErnBrnId = 43276; break;
+			case FIX_HW_BRN_44455_BIT_MASK: ui32ErnBrnId = 44455; break;
+			case FIX_HW_BRN_44871_BIT_MASK: ui32ErnBrnId = 44871; break;
+			case HW_ERN_44885_BIT_MASK: ui32ErnBrnId = 44885; break;
+			case HW_ERN_45914_BIT_MASK: ui32ErnBrnId = 45914; break;
+			case HW_ERN_46066_BIT_MASK: ui32ErnBrnId = 46066; break;
+			case HW_ERN_47025_BIT_MASK: ui32ErnBrnId = 47025; break;
+			case HW_ERN_49144_BIT_MASK: ui32ErnBrnId = 49144; break;
+			case HW_ERN_50539_BIT_MASK: ui32ErnBrnId = 50539; break;
+			case FIX_HW_BRN_50767_BIT_MASK: ui32ErnBrnId = 50767; break;
+			case FIX_HW_BRN_51281_BIT_MASK: ui32ErnBrnId = 51281; break;
+			case HW_ERN_51468_BIT_MASK: ui32ErnBrnId = 51468; break;
+			case FIX_HW_BRN_52402_BIT_MASK: ui32ErnBrnId = 52402; break;
+			case FIX_HW_BRN_52563_BIT_MASK: ui32ErnBrnId = 52563; break;
+			case FIX_HW_BRN_54141_BIT_MASK: ui32ErnBrnId = 54141; break;
+			case FIX_HW_BRN_54441_BIT_MASK: ui32ErnBrnId = 54441; break;
+			case FIX_HW_BRN_55091_BIT_MASK: ui32ErnBrnId = 55091; break;
+			case FIX_HW_BRN_57193_BIT_MASK: ui32ErnBrnId = 57193; break;
+			case HW_ERN_57596_BIT_MASK: ui32ErnBrnId = 57596; break;
+			case FIX_HW_BRN_60084_BIT_MASK: ui32ErnBrnId = 60084; break;
+			case HW_ERN_61389_BIT_MASK: ui32ErnBrnId = 61389; break;
+			case FIX_HW_BRN_61450_BIT_MASK: ui32ErnBrnId = 61450; break;
+			case FIX_HW_BRN_62204_BIT_MASK: ui32ErnBrnId = 62204; break;
+			default:
+				PVR_LOG(("Unknown ErnBrn bit: 0x%0llx", ui64Temp2));
+				break;
+			}
+			PVR_LOG(("ERN/BRN : %d",ui32ErnBrnId));
+		}
+		ui64Temp >>= 1;
+		ui64Temp2 <<= 1;
+	}
+
+}
+#endif
+
+static void RGXConfigFeaturesWithValues(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_RGXDEV_INFO	*psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	psDevInfo->sDevFeatureCfg.ui32MAXDMCount =	RGXFWIF_DM_MIN_CNT;
+	psDevInfo->sDevFeatureCfg.ui32MAXDMMTSCount =	RGXFWIF_DM_MIN_MTS_CNT;
+
+	/* ui64Features must be already initialized */
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+	{
+		psDevInfo->sDevFeatureCfg.ui32MAXDMCount += RGXFWIF_RAY_TRACING_DM_CNT;
+		psDevInfo->sDevFeatureCfg.ui32MAXDMMTSCount += RGXFWIF_RAY_TRACING_DM_MTS_CNT;
+	}
+
+	/* Get the max number of dusts in the core */
+	if(0 != psDevInfo->sDevFeatureCfg.ui32NumClusters)
+	{
+		psDevInfo->sDevFeatureCfg.ui32MAXDustCount = MAX(1, (psDevInfo->sDevFeatureCfg.ui32NumClusters / 2)) ;
+	}
+}
+
+static inline
+IMG_UINT32 GetFeatureValue(IMG_UINT64 ui64CfgInfo,
+							IMG_PCHAR pcFeature,
+							IMG_PUINT32 pui32FeatureValList,
+							IMG_UINT64 ui64FeatureMask,
+							IMG_UINT32 ui32FeaturePos,
+							IMG_UINT32 ui64FeatureMaxValue)
+{
+	IMG_UINT64	ui64Indx = 0;
+	IMG_UINT32	uiValue = 0;
+	ui64Indx = (ui64CfgInfo & ui64FeatureMask) >> ui32FeaturePos;
+	if(ui64Indx < ui64FeatureMaxValue)
+	{
+		uiValue = pui32FeatureValList[ui64Indx];
+	}else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Array out of bounds access attempted %s", pcFeature));
+	}
+	return uiValue;
+}
+
+#define	GET_FEAT_VALUE(CfgInfo, Feature, FeatureValList) 	\
+			GetFeatureValue(CfgInfo, #Feature, (IMG_PUINT32)FeatureValList, \
+							Feature##_BIT_MASK, Feature##_POS, FeatureValList##_MAX_VALUE)
+							
+static void RGXParseBVNCFeatures(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64CfgInfo)
+{
+	PVRSRV_RGXDEV_INFO	*psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	/*Get the SLC cacheline size info in kilo bytes */
+	psDevInfo->sDevFeatureCfg.ui32SLCSize = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_SLC_SIZE_IN_BYTES, SLCSKB) *1024 ;
+
+	/*Get the control stream format architecture info */
+	psDevInfo->sDevFeatureCfg.ui32CtrlStreamFormat = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT, CSF);
+
+	psDevInfo->sDevFeatureCfg.ui32FBCDCArch = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_FBCDC_ARCHITECTURE, FBCDCArch);
+
+	psDevInfo->sDevFeatureCfg.ui32MCMB = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_META_COREMEM_BANKS, MCRMB);
+
+	psDevInfo->sDevFeatureCfg.ui32MCMS = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_META_COREMEM_SIZE, MCRMS) *1024;
+
+	psDevInfo->sDevFeatureCfg.ui32MDMACount = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_META_DMA_CHANNEL_COUNT, MDCC);
+
+	if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		psDevInfo->sDevFeatureCfg.ui32META = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_META, META);
+	}else
+	{
+		psDevInfo->sDevFeatureCfg.ui32META = 0;
+	}
+
+	psDevInfo->sDevFeatureCfg.ui32NumClusters = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_NUM_CLUSTERS, NC);
+
+	psDevInfo->sDevFeatureCfg.ui32NIIP = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_NUM_ISP_IPP_PIPES, NIIP);
+
+	psDevInfo->sDevFeatureCfg.ui32PBW = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_PHYS_BUS_WIDTH, PBW);
+
+	psDevInfo->sDevFeatureCfg.ui32SLCBanks = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_SLC_BANKS, SLCB);
+
+	psDevInfo->sDevFeatureCfg.ui32CacheLineSize = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS, SLCCLSb);
+
+	psDevInfo->sDevFeatureCfg.ui32STEArch = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_SCALABLE_TE_ARCH, STEA);
+
+	psDevInfo->sDevFeatureCfg.ui32SVCE = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_SCALABLE_VCE, SVCEA);
+
+	psDevInfo->sDevFeatureCfg.ui32VASB = GET_FEAT_VALUE(ui64CfgInfo, RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS, VASB);
+
+	RGXConfigFeaturesWithValues(psDeviceNode);
+}
+#undef GET_FEAT_VALUE
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+static void RGXAcquireBVNCAppHint(IMG_CHAR *pszBVNCAppHint,
+								  IMG_CHAR **apszRGXBVNCList,
+								  IMG_UINT32 ui32BVNCListCount,
+								  IMG_UINT32 *pui32BVNCCount)
+{
+	IMG_CHAR *pszAppHintDefault = NULL;
+	void *pvAppHintState = NULL;
+	IMG_UINT32 ui32BVNCIndex = 0;
+
+	OSCreateKMAppHintState(&pvAppHintState);
+	pszAppHintDefault = PVRSRV_APPHINT_RGXBVNC;
+	if (!OSGetKMAppHintSTRING(pvAppHintState,
+						 RGXBVNC,
+						 &pszAppHintDefault,
+						 pszBVNCAppHint,
+						 RGXBVNC_BUFFER_SIZE))
+	{
+		*pui32BVNCCount = 0;
+		return;
+	}
+	OSFreeKMAppHintState(pvAppHintState);
+
+	while (*pszBVNCAppHint != '\0')
+	{
+		if (ui32BVNCIndex >= ui32BVNCListCount)
+		{
+			break;
+		}
+		apszRGXBVNCList[ui32BVNCIndex++] = pszBVNCAppHint;
+		while (1)
+		{
+			if (*pszBVNCAppHint == ',')
+			{
+				pszBVNCAppHint[0] = '\0';
+				pszBVNCAppHint++;
+				break;
+			} else if (*pszBVNCAppHint == '\0')
+			{
+				break;
+			}
+			pszBVNCAppHint++;
+		}
+	}
+	*pui32BVNCCount = ui32BVNCIndex;
+}
+#endif
+
+/*Function that parses the BVNC List passed as module parameter */
+static PVRSRV_ERROR RGXParseBVNCList(IMG_UINT64 *pB,
+									 IMG_UINT64 *pV,
+									 IMG_UINT64 *pN,
+									 IMG_UINT64 *pC,
+									 const IMG_UINT32 ui32RGXDevCount)
+{
+	unsigned int ui32ScanCount = 0;
+	IMG_CHAR *pszBVNCString = NULL;
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	if (ui32RGXDevCount == 0) {
+		IMG_CHAR pszBVNCAppHint[RGXBVNC_BUFFER_SIZE] = {};
+		RGXAcquireBVNCAppHint(pszBVNCAppHint, gazRGXBVNCList, PVRSRV_MAX_DEVICES, &gui32RGXLoadTimeDevCount);
+	}
+#endif
+
+	/*4 components of a BVNC string is B, V, N & C */
+#define RGX_BVNC_INFO_PARAMS (4)
+
+	/*If only one BVNC parameter is specified, the same is applied for all RGX
+	 * devices detected */
+	if(1 == gui32RGXLoadTimeDevCount)
+	{
+		pszBVNCString = gazRGXBVNCList[0];
+	}else
+	{
+
+#if defined(DEBUG)
+		int i =0;
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: No. of BVNC module params : %u", __func__, gui32RGXLoadTimeDevCount));
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: BVNC module param list ... ",__func__));
+		for(i=0; i < gui32RGXLoadTimeDevCount; i++)
+		{
+			PVR_DPF((PVR_DBG_MESSAGE, "%s, ", gazRGXBVNCList[i]));
+		}
+#endif
+
+		if (gui32RGXLoadTimeDevCount == 0)
+			return PVRSRV_ERROR_INVALID_BVNC_PARAMS;
+
+		/* total number of RGX devices detected should always be
+		 * less than the gazRGXBVNCList count */
+		if(ui32RGXDevCount < gui32RGXLoadTimeDevCount)
+		{
+			pszBVNCString = gazRGXBVNCList[ui32RGXDevCount];
+		}else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Given module parameters list is shorter than "
+					"number of actual devices", __func__));
+			return PVRSRV_ERROR_INVALID_BVNC_PARAMS;
+		}
+	}
+
+	if(NULL == pszBVNCString)
+	{
+		return PVRSRV_ERROR_INVALID_BVNC_PARAMS;
+	}
+
+	/* Parse the given RGX_BVNC string */
+	ui32ScanCount = OSVSScanf(pszBVNCString, "%llu.%llu.%llu.%llu", pB, pV, pN, pC);
+	if(RGX_BVNC_INFO_PARAMS != ui32ScanCount)
+	{
+		ui32ScanCount = OSVSScanf(pszBVNCString, "%llu.%llup.%llu.%llu", pB, pV, pN, pC);
+	}
+	if(RGX_BVNC_INFO_PARAMS == ui32ScanCount)
+	{
+		PVR_LOG(("BVNC module parameter honoured: %s", pszBVNCString));
+	}else
+	{
+		return PVRSRV_ERROR_INVALID_BVNC_PARAMS;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*This function detects the rogue variant and configures the
+ * essential config info associated with such a device
+ * The config info include features, errata etc etc */
+static PVRSRV_ERROR RGXGetBVNCConfig(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	static IMG_UINT32 ui32RGXDevCnt = 0;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bDetectBVNC = IMG_TRUE;
+
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	IMG_UINT64	ui64BVNC, *pui64Cfg, B=0, V=0, N=0, C=0;
+
+	/*Order of BVNC rules
+	1. RGX_BVNC Module parameter
+	2. Detected BVNC (Hardware) / Compiled BVNC (No Hardware)
+	3. If none of above report failure */
+
+	/* Check for load time RGX BVNC config */
+	eError = RGXParseBVNCList(&B,&V,&N,&C, ui32RGXDevCnt);
+	if(PVRSRV_OK == eError)
+	{
+		bDetectBVNC = IMG_FALSE;
+	}
+
+	/*if BVNC is not specified as module parameter or if specified BVNC list is insufficient
+	 * Try to detect the device */
+	if(IMG_TRUE == bDetectBVNC)
+	{
+#if !defined(NO_HARDWARE) && !defined(PVRSRV_GPUVIRT_GUESTDRV) && defined(SUPPORT_MULTIBVNC_RUNTIME_BVNC_ACQUISITION)
+		IMG_UINT64 ui32ID;
+		IMG_HANDLE hSysData;
+		PVRSRV_ERROR ePreErr = PVRSRV_OK, ePostErr = PVRSRV_OK;
+
+		hSysData = psDeviceNode->psDevConfig->hSysData;
+
+		/* Power-up the device as required to read the registers */
+		if(psDeviceNode->psDevConfig->pfnPrePowerState)
+		{
+			ePreErr = psDeviceNode->psDevConfig->pfnPrePowerState(hSysData, PVRSRV_DEV_POWER_STATE_ON,
+					PVRSRV_DEV_POWER_STATE_OFF, IMG_FALSE);
+			if (PVRSRV_OK != ePreErr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: System Pre-Power up failed", __func__));
+				return ePreErr;
+			}
+		}
+
+		if(psDeviceNode->psDevConfig->pfnPostPowerState)
+		{
+			ePostErr = psDeviceNode->psDevConfig->pfnPostPowerState(hSysData, PVRSRV_DEV_POWER_STATE_ON,
+					PVRSRV_DEV_POWER_STATE_OFF, IMG_FALSE);
+			if (PVRSRV_OK != ePostErr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: System Post Power up failed", __func__));
+				return ePostErr;
+			}
+		}
+
+		ui32ID = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_CORE_ID__PBVNC);
+
+		if(GET_B(ui32ID))
+		{
+			B = (ui32ID & ~RGX_CR_CORE_ID__PBVNC__BRANCH_ID_CLRMSK) >>
+													RGX_CR_CORE_ID__PBVNC__BRANCH_ID_SHIFT;
+			V = (ui32ID & ~RGX_CR_CORE_ID__PBVNC__VERSION_ID_CLRMSK) >>
+													RGX_CR_CORE_ID__PBVNC__VERSION_ID_SHIFT;
+			N = (ui32ID & ~RGX_CR_CORE_ID__PBVNC__NUMBER_OF_SCALABLE_UNITS_CLRMSK) >>
+													RGX_CR_CORE_ID__PBVNC__NUMBER_OF_SCALABLE_UNITS_SHIFT;
+			C = (ui32ID & ~RGX_CR_CORE_ID__PBVNC__CONFIG_ID_CLRMSK) >>
+													RGX_CR_CORE_ID__PBVNC__CONFIG_ID_SHIFT;
+
+		}
+		else
+		{
+			IMG_UINT64 ui32CoreID, ui32CoreRev;
+			ui32CoreRev = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_CORE_REVISION);
+			ui32CoreID = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_CORE_ID);
+			B = (ui32CoreRev & ~RGX_CR_CORE_REVISION_MAJOR_CLRMSK) >>
+													RGX_CR_CORE_REVISION_MAJOR_SHIFT;
+			V = (ui32CoreRev & ~RGX_CR_CORE_REVISION_MINOR_CLRMSK) >>
+													RGX_CR_CORE_REVISION_MINOR_SHIFT;
+			N = (ui32CoreID & ~RGX_CR_CORE_ID_CONFIG_N_CLRMSK) >>
+													RGX_CR_CORE_ID_CONFIG_N_SHIFT;
+			C = (ui32CoreID & ~RGX_CR_CORE_ID_CONFIG_C_CLRMSK) >>
+													RGX_CR_CORE_ID_CONFIG_C_SHIFT;
+		}
+		PVR_LOG(("%s: Read BVNC %llu.%llu.%llu.%llu from device registers", __func__, B, V, N, C));
+
+		/* Power-down the device */
+		if(psDeviceNode->psDevConfig->pfnPrePowerState)
+		{
+			ePreErr = psDeviceNode->psDevConfig->pfnPrePowerState(hSysData, PVRSRV_DEV_POWER_STATE_OFF,
+					PVRSRV_DEV_POWER_STATE_ON, IMG_FALSE);
+			if (PVRSRV_OK != ePreErr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: System Pre-Power down failed", __func__));
+				return ePreErr;
+			}
+		}
+
+		if(psDeviceNode->psDevConfig->pfnPostPowerState)
+		{
+			ePostErr = psDeviceNode->psDevConfig->pfnPostPowerState(hSysData, PVRSRV_DEV_POWER_STATE_OFF,
+					PVRSRV_DEV_POWER_STATE_ON, IMG_FALSE);
+			if (PVRSRV_OK != ePostErr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: System Post Power down failed", __func__));
+				return ePostErr;
+			}
+		}
+#else
+#if defined(RGX_BVNC_KM_B)	&& defined(RGX_BVNC_KM_V) && defined(RGX_BVNC_KM_N) && defined(RGX_BVNC_KM_C)
+		B = RGX_BVNC_KM_B;
+		N = RGX_BVNC_KM_N;
+		C = RGX_BVNC_KM_C;
+		{
+			IMG_UINT32	ui32ScanCount = 0;
+			ui32ScanCount = OSVSScanf(RGX_BVNC_KM_V_ST, "%llu", &V);
+			if(1 != ui32ScanCount)
+			{
+				ui32ScanCount = OSVSScanf(RGX_BVNC_KM_V_ST, "%llup", &V);
+				if(1 != ui32ScanCount)
+				{
+					V = 0;
+				}
+			}
+		}
+		PVR_LOG(("%s: Reverting to compile time BVNC %s", __func__, RGX_BVNC_KM));
+#else
+		PVR_LOG(("%s: Unable to determine the BVNC", __func__));
+#endif
+#endif
+	}
+	ui64BVNC = BVNC_PACK(B,0,N,C);
+
+	/* Get the BVNC configuration */
+	PVR_DPF((PVR_DBG_MESSAGE, "%s: Detected BVNC INFO: 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",__func__,
+							B,
+							V,
+							N,
+							C,
+							ui64BVNC));
+
+	/*Extract the information from the BVNC & ERN/BRN Table */
+	pui64Cfg = (IMG_UINT64 *)RGXSearchTable((IMG_UINT64 *)gaFeatures, sizeof(gaFeatures)/sizeof(gaFeatures[0]),
+														ui64BVNC,
+														sizeof(gaFeatures[0])/sizeof(IMG_UINT64));
+	if(pui64Cfg)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: BVNC Feature Cfg: 0x%016llx 0x%016llx 0x%016llx\n",__func__,
+												pui64Cfg[0], pui64Cfg[1], pui64Cfg[2]));
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: BVNC Feature Lookup failed. Unsupported BVNC: 0x%016llx",
+											__func__, ui64BVNC));
+		return PVRSRV_ERROR_BVNC_UNSUPPORTED;
+	}
+
+
+	psDevInfo->sDevFeatureCfg.ui64Features = pui64Cfg[1];
+	/*Parsing feature config depends on available features on the core
+	 * hence this parsing should always follow the above feature assignment */
+	RGXParseBVNCFeatures(psDeviceNode, pui64Cfg[2]);
+
+	/* Get the ERN and BRN configuration */
+	ui64BVNC = BVNC_PACK(B,V,N,C);
+
+	pui64Cfg = (IMG_UINT64 *)RGXSearchTable((IMG_UINT64 *)gaErnsBrns, sizeof(gaErnsBrns)/sizeof(gaErnsBrns[0]),
+				ui64BVNC,
+				sizeof(gaErnsBrns[0])/sizeof(IMG_UINT64));
+	if(pui64Cfg)
+	{
+		psDevInfo->sDevFeatureCfg.ui64ErnsBrns = pui64Cfg[1];
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: BVNC ERN/BRN Cfg: 0x%016llx 0x%016llx \n",
+				__func__, *pui64Cfg, psDevInfo->sDevFeatureCfg.ui64ErnsBrns));
+
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: BVNC ERN/BRN Lookup failed. Unsupported BVNC: 0x%016llx",
+				__func__, ui64BVNC));
+		psDevInfo->sDevFeatureCfg.ui64ErnsBrns = 0;
+		return PVRSRV_ERROR_BVNC_UNSUPPORTED;
+	}
+
+	psDevInfo->sDevFeatureCfg.ui32B = (IMG_UINT32)B;
+	psDevInfo->sDevFeatureCfg.ui32V = (IMG_UINT32)V;
+	psDevInfo->sDevFeatureCfg.ui32N = (IMG_UINT32)N;
+	psDevInfo->sDevFeatureCfg.ui32C = (IMG_UINT32)C;
+
+	ui32RGXDevCnt++;
+#if defined(DEBUG)
+	RGXDumpParsedBVNCConfig(psDeviceNode);
+#endif
+	return PVRSRV_OK;
+}
+
+/*
+ * This function checks if a particular feature is available on the given rgx device */
+static IMG_BOOL RGXCheckFeatureSupported(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT64 ui64FeatureMask)
+{
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDevNode->pvDevice;
+	/* FIXME: need to implement a bounds check for passed feature mask */
+	if(psDevInfo->sDevFeatureCfg.ui64Features & ui64FeatureMask)
+	{
+		return IMG_TRUE;
+	}
+	return IMG_FALSE;
+}
+
+/*
+ * * This function returns the value of a feature on the given rgx device */
+static IMG_INT32 RGXGetSupportedFeatureValue(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT64 ui64FeatureMask)
+{
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDevNode->pvDevice;
+	/*FIXME: need to implement a bounds check for passed feature mask */
+
+	switch(ui64FeatureMask)
+	{
+	case RGX_FEATURE_PHYS_BUS_WIDTH_BIT_MASK:
+		return psDevInfo->sDevFeatureCfg.ui32PBW;
+	case RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_BIT_MASK:
+		return psDevInfo->sDevFeatureCfg.ui32CacheLineSize;
+	default:
+		return -1;
+	}
+}
+
+/*
+	RGXRegisterDevice
+*/
+PVRSRV_ERROR RGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+    PVRSRV_ERROR eError;
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	PVRSRV_RGXDEV_INFO	*psDevInfo;
+
+	PDUMPCOMMENT("Device Name: %s", psDeviceNode->psDevConfig->pszName);
+
+	if (psDeviceNode->psDevConfig->pszVersion)
+	{
+		PDUMPCOMMENT("Device Version: %s", psDeviceNode->psDevConfig->pszVersion);
+	}
+
+	#if defined(RGX_FEATURE_SYSTEM_CACHE)
+	PDUMPCOMMENT("RGX System Level Cache is present");
+	#endif /* RGX_FEATURE_SYSTEM_CACHE */
+
+	PDUMPCOMMENT("RGX Initialisation (Part 1)");
+
+	/*********************
+	 * Device node setup *
+	 *********************/
+	/* Setup static data and callbacks on the device agnostic device node */
+#if defined(PDUMP)
+	psDeviceNode->sDevId.pszPDumpRegName	= RGX_PDUMPREG_NAME;
+	/*
+		FIXME: This should not be required as PMR's should give the memspace
+		name. However, due to limitations within PDump we need a memspace name
+		when pdumping with MMU context with virtual address in which case we
+		don't have a PMR to get the name from.
+
+		There is also the issue obtaining a namespace name for the catbase which
+		is required when we PDump the write of the physical catbase into the FW
+		structure
+	*/
+	psDeviceNode->sDevId.pszPDumpDevName	= PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+	psDeviceNode->pfnPDumpInitDevice = &RGXResetPDump;
+#endif /* PDUMP */
+
+	OSAtomicWrite(&psDeviceNode->eHealthStatus, PVRSRV_DEVICE_HEALTH_STATUS_OK);
+	OSAtomicWrite(&psDeviceNode->eHealthReason, PVRSRV_DEVICE_HEALTH_REASON_NONE);
+
+	/* Configure MMU specific stuff */
+	RGXMMUInit_Register(psDeviceNode);
+
+	psDeviceNode->pfnMMUCacheInvalidate = RGXMMUCacheInvalidate;
+
+	psDeviceNode->pfnMMUCacheInvalidateKick = RGXMMUCacheInvalidateKick;
+
+	/* Register RGX to receive notifies when other devices complete some work */
+	PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
+
+	psDeviceNode->pfnInitDeviceCompatCheck	= &RGXDevInitCompatCheck;
+
+	/* Register callbacks for creation of device memory contexts */
+	psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
+	psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
+
+	/* Register callbacks for Unified Fence Objects */
+	psDeviceNode->pfnAllocUFOBlock = RGXAllocUFOBlock;
+	psDeviceNode->pfnFreeUFOBlock = RGXFreeUFOBlock;
+
+	/* Register callback for checking the device's health */
+	psDeviceNode->pfnUpdateHealthStatus = RGXUpdateHealthStatus;
+
+	/* Register method to service the FW HWPerf buffer */
+	psDeviceNode->pfnServiceHWPerf = RGXHWPerfDataStoreCB;
+
+	/* Register callback for getting the device version information string */
+	psDeviceNode->pfnDeviceVersionString = RGXDevVersionString;
+
+	/* Register callback for getting the device clock speed */
+	psDeviceNode->pfnDeviceClockSpeed = RGXDevClockSpeed;
+
+	/* Register callback for soft resetting some device modules */
+	psDeviceNode->pfnSoftReset = RGXSoftReset;
+
+	/* Register callback for resetting the HWR logs */
+	psDeviceNode->pfnResetHWRLogs = RGXResetHWRLogs;
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(RGXFW_ALIGNCHECKS)
+	/* Register callback for checking alignment of UM structures */
+	psDeviceNode->pfnAlignmentCheck = RGXAlignmentCheck;
+#endif
+
+	/*Register callback for checking the supported features and getting the
+	 * corresponding values */
+	psDeviceNode->pfnCheckDeviceFeature = RGXCheckFeatureSupported;
+	psDeviceNode->pfnGetDeviceFeatureValue = RGXGetSupportedFeatureValue;
+	
+	/*Set up required support for dummy page */
+	OSAtomicWrite(&(psDeviceNode->sDummyPage.atRefCounter), 0);
+
+	/*Set the order to 0 */
+	psDeviceNode->sDummyPage.sDummyPageHandle.ui32Order = 0;
+
+	/*Set the size of the Dummy page to zero */
+	psDeviceNode->sDummyPage.ui32Log2DummyPgSize = 0;
+
+	/*Set the Dummy page phys addr */
+	psDeviceNode->sDummyPage.ui64DummyPgPhysAddr = MMU_BAD_PHYS_ADDR;
+
+	/*The lock type need to be dispatch type here because it can be acquired from MISR (Z-buffer) path */
+	eError = OSLockCreate(&psDeviceNode->sDummyPage.psDummyPgLock ,LOCK_TYPE_DISPATCH);
+	if(PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create dummy page lock", __func__));
+		return eError;
+	}
+#if defined(PDUMP)
+	psDeviceNode->sDummyPage.hPdumpDummyPg = NULL;
+#endif
+
+	/*********************
+	 * Device info setup *
+	 *********************/
+	/* Allocate device control block */
+	psDevInfo = OSAllocZMem(sizeof(*psDevInfo));
+	if (psDevInfo == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitRGXPart1 : Failed to alloc memory for DevInfo"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+
+	/* create locks for the context lists stored in the DevInfo structure.
+	 * these lists are modified on context create/destroy and read by the
+	 * watchdog thread
+	 */
+
+	eError = OSWRLockCreate(&(psDevInfo->hRenderCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create render context list lock", __func__));
+		goto e0;
+	}
+
+	eError = OSWRLockCreate(&(psDevInfo->hComputeCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create compute context list lock", __func__));
+		goto e1;
+	}
+
+	eError = OSWRLockCreate(&(psDevInfo->hTransferCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create transfer context list lock", __func__));
+		goto e2;
+	}
+
+	eError = OSWRLockCreate(&(psDevInfo->hTDMCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create TDM context list lock", __func__));
+		goto e3;
+	}
+
+	eError = OSWRLockCreate(&(psDevInfo->hRaytraceCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create raytrace context list lock", __func__));
+		goto e4;
+	}
+
+	eError = OSWRLockCreate(&(psDevInfo->hKickSyncCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create kick sync context list lock", __func__));
+		goto e5;
+	}
+
+	eError = OSWRLockCreate(&(psDevInfo->hMemoryCtxListLock));
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create memory context list lock", __func__));
+		goto e6;
+	}
+
+	dllist_init(&(psDevInfo->sKCCBDeferredCommandsListHead));
+
+	dllist_init(&(psDevInfo->sRenderCtxtListHead));
+	dllist_init(&(psDevInfo->sComputeCtxtListHead));
+	dllist_init(&(psDevInfo->sTransferCtxtListHead));
+	dllist_init(&(psDevInfo->sTDMCtxtListHead));
+	dllist_init(&(psDevInfo->sRaytraceCtxtListHead));
+	dllist_init(&(psDevInfo->sKickSyncCtxtListHead));
+
+	dllist_init(&(psDevInfo->sCommonCtxtListHead));
+	psDevInfo->ui32CommonCtxtCurrentID = 1;
+
+	dllist_init(&psDevInfo->sMemoryContextList);
+
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/* Allocate space for scripts. */
+	psDevInfo->psScripts = OSAllocMem(sizeof(*psDevInfo->psScripts));
+	if (!psDevInfo->psScripts)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate memory for scripts", __func__));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e7;
+	}
+#endif
+
+	/* Setup static data and callbacks on the device specific device info */
+	psDevInfo->psDeviceNode		= psDeviceNode;
+
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+	psDevInfo->pvDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+	/*
+	 * Map RGX Registers
+	 */
+#if !defined(NO_HARDWARE)
+	psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psDeviceNode->psDevConfig->sRegsCpuPBase,
+												psDeviceNode->psDevConfig->ui32RegsSize,
+										     PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
+
+	if (psDevInfo->pvRegsBaseKM == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to create RGX register mapping", __func__));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto e8;
+	}
+#endif
+
+	psDeviceNode->pvDevice = psDevInfo;
+
+	eError = RGXGetBVNCConfig(psDeviceNode);
+	if(PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Unsupported Device detected by driver", __func__));
+		goto e9;
+	}
+
+	/* pdump info about the core */
+	PDUMPCOMMENT("RGX Version Information (KM): %d.%d.%d.%d",
+	             psDevInfo->sDevFeatureCfg.ui32B,
+	             psDevInfo->sDevFeatureCfg.ui32V,
+	             psDevInfo->sDevFeatureCfg.ui32N,
+	             psDevInfo->sDevFeatureCfg.ui32C);
+
+	eError = RGXInitHeaps(psDevInfo, psDevMemoryInfo,
+						  &psDeviceNode->sDummyPage.ui32Log2DummyPgSize);
+	if (eError != PVRSRV_OK)
+	{
+		goto e9;
+	}
+
+	eError = RGXHWPerfInit(psDeviceNode);
+	PVR_LOGG_IF_ERROR(eError, "RGXHWPerfInit", e9);
+
+	/* Register callback for dumping debug info */
+	eError = PVRSRVRegisterDbgRequestNotify(&psDevInfo->hDbgReqNotify,
+											psDeviceNode,
+											RGXDebugRequestNotify,
+											DEBUG_REQUEST_SYS,
+											psDevInfo);
+	PVR_LOG_IF_ERROR(eError, "PVRSRVRegisterDbgRequestNotify");
+
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		RGXMipsMMUInit_Register(psDeviceNode);
+	}
+
+	/* The device shared-virtual-memory heap address-space size is stored here for faster
+	   look-up without having to walk the device heap configuration structures during
+	   client device connection  (i.e. this size is relative to a zero-based offset) */
+	if(psDevInfo->sDevFeatureCfg.ui64ErnsBrns & (FIX_HW_BRN_52402_BIT_MASK | FIX_HW_BRN_55091_BIT_MASK))
+	{
+		psDeviceNode->ui64GeneralSVMHeapTopVA = 0;
+	}else
+	{
+		psDeviceNode->ui64GeneralSVMHeapTopVA = RGX_GENERAL_SVM_HEAP_BASE + RGX_GENERAL_SVM_HEAP_SIZE;
+	}
+
+	if(NULL != psDeviceNode->psDevConfig->pfnSysDevFeatureDepInit)
+	{
+		psDeviceNode->psDevConfig->pfnSysDevFeatureDepInit(psDeviceNode->psDevConfig, \
+				psDevInfo->sDevFeatureCfg.ui64Features);
+	}
+
+	return PVRSRV_OK;
+
+e9:
+#if !defined(NO_HARDWARE)
+	OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+							 psDevInfo->ui32RegSize,
+							 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
+e8:
+#endif /* !NO_HARDWARE */
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	OSFreeMem(psDevInfo->psScripts);
+e7:
+#endif
+	OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
+e6:
+	OSWRLockDestroy(psDevInfo->hKickSyncCtxListLock);
+e5:
+	OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
+e4:
+	OSWRLockDestroy(psDevInfo->hTDMCtxListLock);
+e3:
+	OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
+e2:
+	OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
+e1:
+	OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
+e0:
+	OSFreeMem(psDevInfo);
+
+	/*Destroy the dummy page lock created above */
+	OSLockDestroy(psDeviceNode->sDummyPage.psDummyPgLock);
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitGuestKM(CONNECTION_DATA		*psConnection,
+								PVRSRV_DEVICE_NODE		*psDeviceNode,
+								IMG_BOOL				bEnableSignatureChecks,
+								IMG_UINT32				ui32SignatureChecksBufSize,
+								IMG_UINT32				ui32RGXFWAlignChecksArrLength,
+								IMG_UINT32				*pui32RGXFWAlignChecks,
+								IMG_UINT32				ui32DeviceFlags,
+								RGXFWIF_COMPCHECKS_BVNC	*psClientBVNC)
+{
+	PVRSRV_ERROR	eError;
+
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/*
+	 * Guest drivers do not support the following functionality:
+	 *  - Perform actual on-chip firmware loading, config & init
+	 *  - Perform actual on-chip firmware RDPowIsland(ing)
+	 *  - Perform actual on-chip firmware tracing, HWPerf
+	 *  - Configure firmware perf counters
+	 */
+	eError =  PVRSRVRGXInitAllocFWImgMemKM(psConnection,
+											psDeviceNode,
+											0,		/* uiFWCodeLen */
+											0,		/* uiFWDataLen */
+											0,		/* uiFWCorememLen */
+											NULL,	/* ppsFWCodePMR */
+											NULL,	/* psFWCodeDevVAddrBase */
+											NULL,	/* ppsFWDataPMR */
+											NULL,	/* psFWDataDevVAddrBase */
+											NULL,	/* ppsFWCorememPMR */
+											NULL,	/* psFWCorememDevVAddrBase */
+											NULL	/* psFWCorememMetaVAddrBase */);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitGuest: PVRSRVRGXInitAllocFWImgMemKM failed (%u)", eError));
+		goto e0;
+	}
+
+	eError =  PVRSRVRGXInitFirmwareKM(psConnection,
+									  psDeviceNode,
+									  NULL,	/* psRGXFwInit */
+									  bEnableSignatureChecks,
+									  ui32SignatureChecksBufSize,
+									  0,	/* ui32HWPerfFWBufSizeKB */
+									  0,	/* ui64HWPerfFilter */
+									  ui32RGXFWAlignChecksArrLength,
+									  pui32RGXFWAlignChecks,
+									  0,	/* ui32ConfigFlags */
+									  0,	/* ui32LogType */
+									  0,	/* ui32FilterFlags */
+									  0,	/* ui32JonesDisableMask */
+									  0,	/* ui32HWRDebugDumpLimit */
+									  psClientBVNC,
+									  0,	/* ui32HWPerfCountersDataSize */
+									  NULL,	/* ppsHWPerfPMR */
+									  0,	/* eRGXRDPowerIslandingConf */
+									  0		/* eFirmwarePerf */);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitGuest: PVRSRVRGXInitFirmwareKM failed (%u)", eError));
+		goto e0;
+	}
+
+	eError =   PVRSRVRGXInitDevPart2KM(psConnection,
+									   psDeviceNode,
+									   NULL,	/* psDbgScript */
+									   ui32DeviceFlags,
+									   0,		/* ui32HWPerfHostBufSizeKB */
+									   0,		/* ui32HWPerfHostFilter */
+									   0,		/* eActivePMConf */
+									   NULL,	/* psFWCodePMR */
+									   NULL,	/* psFWDataPMR */
+									   NULL,	/* psFWCorePMR */
+									   NULL		/* psHWPerfPMR */);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitGuest: PVRSRVRGXInitDevPart2KM failed (%u)", eError));
+		goto e0;
+	}
+e0:
+#else
+	eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+
+	return eError;
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXInitFinaliseFWImageKM(CONNECTION_DATA *psConnection,
+                               PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+	{
+		void *pvFWImage;
+		PVRSRV_ERROR eError;
+
+		eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc, &pvFWImage);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "PVRSRVRGXInitFinaliseFWImageKM: Acquire mapping for FW data failed (%u)",
+					 eError));
+			return eError;
+		}
+
+		eError = RGXBootldrDataInit(psDeviceNode, pvFWImage);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "PVRSRVRGXInitLoadFWImageKM: ELF parameters injection failed (%u)",
+					 eError));
+			return eError;
+		}
+
+		DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+
+	}
+	return PVRSRV_OK;
+}
 
 /*************************************************************************/ /*!
 @Function       RGXDevVersionString
@@ -3258,11 +4949,12 @@
 static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode, 
 					IMG_CHAR **ppszVersionString)
 {
-#if defined(COMPAT_BVNC_MASK_B) || defined(COMPAT_BVNC_MASK_V) || defined(COMPAT_BVNC_MASK_N) || defined(COMPAT_BVNC_MASK_C) || defined(NO_HARDWARE) || defined(EMULATOR)
-	IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (SW)";
+#if defined(NO_HARDWARE) || defined(EMULATOR)
+	IMG_PCHAR pszFormatString = "Rogue Version: %s (SW)";
 #else
-	IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (HW)";
+	IMG_PCHAR pszFormatString = "Rogue Version: %s (HW)";
 #endif
+	PVRSRV_RGXDEV_INFO *psDevInfo;
 	size_t uiStringLength;
 
 	if (psDeviceNode == NULL || ppszVersionString == NULL)
@@ -3270,20 +4962,42 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	uiStringLength = OSStringLength(pszFormatString);
-	uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_B));
-	uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_V));
-	uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_N));
-	uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_C));
+	psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
 
-	*ppszVersionString = OSAllocZMem(uiStringLength * sizeof(IMG_CHAR));
+	if(NULL == psDevInfo->sDevFeatureCfg.pszBVNCString)
+	{
+		IMG_CHAR pszBVNCInfo[MAX_BVNC_STRING_LEN];
+		size_t uiBVNCStringSize;
+
+		OSSNPrintf(pszBVNCInfo, MAX_BVNC_STRING_LEN, "%d.%d.%d.%d", \
+				psDevInfo->sDevFeatureCfg.ui32B, \
+				psDevInfo->sDevFeatureCfg.ui32V, \
+				psDevInfo->sDevFeatureCfg.ui32N, \
+				psDevInfo->sDevFeatureCfg.ui32C);
+
+		uiBVNCStringSize = (OSStringLength(pszBVNCInfo) + 1) * sizeof(IMG_CHAR);
+		psDevInfo->sDevFeatureCfg.pszBVNCString = OSAllocMem(uiBVNCStringSize);
+		if(NULL == psDevInfo->sDevFeatureCfg.pszBVNCString)
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,
+					 "%s: Allocating memory for BVNC Info string failed ",
+					 __func__));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+		OSCachedMemCopy(psDevInfo->sDevFeatureCfg.pszBVNCString,pszBVNCInfo,uiBVNCStringSize);
+	}
+
+	uiStringLength = OSStringLength(psDevInfo->sDevFeatureCfg.pszBVNCString) +
+	                 OSStringLength(pszFormatString);
+	*ppszVersionString = OSAllocZMem(uiStringLength);
 	if (*ppszVersionString == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
 	OSSNPrintf(*ppszVersionString, uiStringLength, pszFormatString, 
-		   RGX_BVNC_KM_B, TOSTRING(RGX_BVNC_KM_V), RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+			psDevInfo->sDevFeatureCfg.pszBVNCString);
 
 	return PVRSRV_OK;
 }
@@ -3307,71 +5021,6 @@
 	return PVRSRV_OK;
 }
 
-/**************************************************************************/ /*!
-@Function       RGXSoftReset
-@Description    Resets some modules of the RGX device
-@Input          psDeviceNode		Device node
-@Input          ui64ResetValue1 A mask for which each bit set corresponds
-                                to a module to reset (via the SOFT_RESET
-                                register).
-@Input          ui64ResetValue2 A mask for which each bit set corresponds
-                                to a module to reset (via the SOFT_RESET2
-                                register).
-@Return         PVRSRV_ERROR
-*/ /***************************************************************************/
-static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                 IMG_UINT64  ui64ResetValue1,
-                                 IMG_UINT64  ui64ResetValue2)
-{
-#if defined(PVRSRV_GPUVIRT_GUESTDRV)
-	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
-	PVR_UNREFERENCED_PARAMETER(ui64ResetValue1);
-	PVR_UNREFERENCED_PARAMETER(ui64ResetValue2);
-#else
-	PVRSRV_RGXDEV_INFO        *psDevInfo;
-
-	PVR_ASSERT(psDeviceNode != NULL);
-	PVR_ASSERT(psDeviceNode->pvDevice != NULL);
-
-	if ((ui64ResetValue1 & RGX_CR_SOFT_RESET_MASKFULL) != ui64ResetValue1
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-		|| (ui64ResetValue2 & RGX_CR_SOFT_RESET2_MASKFULL) != ui64ResetValue2
-#endif
-		)
-	{
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-	/* the device info */
-	psDevInfo = psDeviceNode->pvDevice;
-
-	/* Set in soft-reset */
-	OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue1);
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2, ui64ResetValue2);
-#endif
-
-	/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
-	(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2);
-#endif
-
-	/* Take the modules out of reset... */
-	OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, 0);
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2, 0);
-#endif
-
-	/* ...and fence again */
-	(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	(void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2);
-#endif
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
-	return PVRSRV_OK;
-}
-
 /******************************************************************************
  End of file (rgxinit.c)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxinit.h b/drivers/staging/imgtec/rogue/rgxinit.h
index bd3c911..428b597 100644
--- a/drivers/staging/imgtec/rogue/rgxinit.h
+++ b/drivers/staging/imgtec/rogue/rgxinit.h
@@ -50,6 +50,8 @@
 #include "rgxscript.h"
 #include "device.h"
 #include "rgxdevice.h"
+#include "rgx_bridge.h"
+
 
 /*!
 *******************************************************************************
@@ -69,9 +71,8 @@
 PVRSRV_ERROR PVRSRVRGXInitDevPart2KM (CONNECTION_DATA       *psConnection,
                                       PVRSRV_DEVICE_NODE	*psDeviceNode,
 									  RGX_INIT_COMMAND		*psDbgScript,
-									  RGX_INIT_COMMAND		*psDbgBusScript,
-									  RGX_INIT_COMMAND		*psDeinitScript,
 									  IMG_UINT32			ui32DeviceFlags,
+									  IMG_UINT32			ui32HWPerfHostBufSizeKB,
 									  IMG_UINT32			ui32HWPerfHostFilter,
 									  RGX_ACTIVEPM_CONF		eActivePMConf,
 									  PMR					*psFWCodePMR,
@@ -93,14 +94,22 @@
                                           IMG_DEV_VIRTADDR     *psFWCorememDevVAddrBase,
                                           RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase);
 
-#if defined(RGX_FEATURE_MIPS)
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXInitMipsWrapperRegistersKM(PVRSRV_DEVICE_NODE *psDeviceNode,
 												 IMG_UINT32 ui32Remap1Config1Offset,
 												 IMG_UINT32 ui32Remap1Config2Offset,
 												 IMG_UINT32 ui32WrapperConfigOffset,
 												 IMG_UINT32 ui32BootCodeOffset);
-#endif
+
+IMG_EXPORT 
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRGXInitGuestKM(CONNECTION_DATA			*psConnection,
+												PVRSRV_DEVICE_NODE		*psDeviceNode,
+												IMG_BOOL				bEnableSignatureChecks,
+												IMG_UINT32				ui32SignatureChecksBufSize,
+												IMG_UINT32				ui32RGXFWAlignChecksArrLength,
+												IMG_UINT32				*pui32RGXFWAlignChecks,
+												IMG_UINT32				ui32DeviceFlags,
+												RGXFWIF_COMPCHECKS_BVNC *psClientBVNC);
 
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXPdumpBootldrDataInitKM(PVRSRV_DEVICE_NODE *psDeviceNode,
@@ -130,7 +139,7 @@
                         IMG_UINT32               ui32SignatureChecksBufSize,
                         IMG_UINT32               ui32HWPerfFWBufSizeKB,
                         IMG_UINT64               ui64HWPerfFilter,
-                        IMG_UINT32               ui32RGXFWAlignChecksSize,
+                        IMG_UINT32               ui32RGXFWAlignChecksArrLength,
                         IMG_UINT32               *pui32RGXFWAlignChecks,
                         IMG_UINT32               ui32ConfigFlags,
                         IMG_UINT32               ui32LogType,
@@ -143,6 +152,28 @@
                         RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
                         FW_PERF_CONF             eFirmwarePerf);
 
+/*!
+*******************************************************************************
+
+ @Function	PVRSRVRGXInitFirmwareExtendedKM
+
+ @Description
+
+ Server-side RGX firmware initialisation, extends PVRSRVRGXInitFirmwareKM
+
+ @Input pvDeviceNode - device node
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVRGXInitFirmwareExtendedKM(CONNECTION_DATA        *psConnection,
+                                PVRSRV_DEVICE_NODE     *psDeviceNode,
+                                IMG_UINT32             ui32RGXFWAlignChecksArrLength,
+                                IMG_UINT32             *pui32RGXFWAlignChecks,
+                                RGXFWIF_DEV_VIRTADDR   *psRGXFwInit,
+                                PMR                    **ppsHWPerfPMR,
+                                RGX_FW_INIT_IN_PARAMS  *psInParams);
 
 /*!
 *******************************************************************************
@@ -155,19 +186,13 @@
 
  @Input psDeviceNode - Device node
 
- @Input hFWCodePMR   - PMR holding the Firmware code
-
- @input ui64FWImgLen - Size of Firmware code allocation
-
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
 
 IMG_EXPORT PVRSRV_ERROR
 PVRSRVRGXInitFinaliseFWImageKM(CONNECTION_DATA *psConnection,
-                               PVRSRV_DEVICE_NODE *psDeviceNode,
-                               PMR *psFWImagePMR,
-                               IMG_UINT64 ui64FWImgLen);
+                               PVRSRV_DEVICE_NODE *psDeviceNode);
 
 /*!
 *******************************************************************************
@@ -268,7 +293,7 @@
  @Function		PVRSRVGPUVIRTPopulateLMASubArenasKM
 
  @Description	Populates the LMA arenas based on the min max values passed by
-				the client during initialization. GPU Virtualization Validation
+				the client during initialization. GPU Virtualisation Validation
 				only.
 
  @Input			pvDeviceNode	: Pointer to a device info structure.
@@ -283,47 +308,7 @@
 PVRSRV_ERROR PVRSRVGPUVIRTPopulateLMASubArenasKM(CONNECTION_DATA    * psConnection,
                                                  PVRSRV_DEVICE_NODE	* psDeviceNode,
                                                  IMG_UINT32         ui32NumElements,
-                                                 IMG_UINT32         aui32Elements[]);
-
-#if defined(SUPPORT_PVRSRV_GPUVIRT)
-/*!
-*******************************************************************************
-
- @Function		PVRSRVGPUVIRTPopulateLMASubArenasKM
-
-@Description	Called to perform additional initialization during firmware
- 	 	 	 	kernel context creation.
-******************************************************************************/
-PVRSRV_ERROR RGXVirtInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE	*psDeviceNode);
-
-/*!
-*******************************************************************************
-
- @Function		PVRSRVGPUVIRTPopulateLMASubArenasKM
-
- @Description	Called to perform additional deinitialization during firmware
- 	 	 	 	kernel context destruction.
-******************************************************************************/
-void RGXVirtDeInitDestroyFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode);
-
-/*!
-*******************************************************************************
-
- @Function		PVRSRVGPUVIRTPopulateLMASubArenasKM
-
- @Description	Called to perform additional initialization
-******************************************************************************/
-PVRSRV_ERROR RGXVirtInitHeaps(DEVICE_MEMORY_INFO *psNewMemoryInfo, 
-							  DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor);
-
-/*!
-*******************************************************************************
-
- @Function		RGXVirtDeInitHeaps
-
- @Description	Called to perform additional deinitialization
-******************************************************************************/
-void RGXVirtDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
-#endif
+                                                 IMG_UINT32         aui32Elements[],
+                                                 IMG_BOOL bEnableTrustedDeviceAceConfig);
 
 #endif /* __RGXINIT_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxkicksync.c b/drivers/staging/imgtec/rogue/rgxkicksync.c
index f81cc97..caa91aa 100644
--- a/drivers/staging/imgtec/rogue/rgxkicksync.c
+++ b/drivers/staging/imgtec/rogue/rgxkicksync.c
@@ -47,6 +47,8 @@
 #include "rgxmem.h"
 #include "rgxfwutils.h"
 #include "allocmem.h"
+#include "sync.h"
+#include "rgxhwperf.h"
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 #include "pvr_sync.h"
@@ -78,14 +80,12 @@
 
 	/* Prepare cleanup struct */
 	* ppsKickSyncContext = NULL;
-	psKickSyncContext = OSAllocMem(sizeof(* psKickSyncContext));
+	psKickSyncContext = OSAllocZMem(sizeof(*psKickSyncContext));
 	if (psKickSyncContext == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	OSMemSet(psKickSyncContext, 0, sizeof(*psKickSyncContext));
-
 	psKickSyncContext->psDeviceNode = psDeviceNode;
 
 	/* Allocate cleanup sync */
@@ -147,7 +147,8 @@
 	eError = RGXFWRequestCommonContextCleanUp(psKickSyncContext->psDeviceNode,
 	                                          psKickSyncContext->psServerCommonContext,
 	                                          psKickSyncContext->psSync,
-	                                          RGXFWIF_DM_3D);
+	                                          RGXFWIF_DM_3D,
+	                                          PDUMP_FLAGS_NONE);
 
 	if (eError == PVRSRV_ERROR_RETRY)
 	{
@@ -181,17 +182,19 @@
 
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContext,
-                                 
+
+                                 IMG_UINT32                    ui32ClientCacheOpSeqNum,
+
                                  IMG_UINT32                    ui32ClientFenceCount,
                                  SYNC_PRIMITIVE_BLOCK           ** pauiClientFenceUFOSyncPrimBlock,
                                  IMG_UINT32                  * paui32ClientFenceOffset,
                                  IMG_UINT32                  * paui32ClientFenceValue,
-                                 
+
                                  IMG_UINT32                    ui32ClientUpdateCount,
                                  SYNC_PRIMITIVE_BLOCK           ** pauiClientUpdateUFOSyncPrimBlock,
                                  IMG_UINT32                  * paui32ClientUpdateOffset,
                                  IMG_UINT32                  * paui32ClientUpdateValue,
-                                 
+
                                  IMG_UINT32                    ui32ServerSyncPrims,
                                  IMG_UINT32                  * paui32ServerSyncFlags,
                                  SERVER_SYNC_PRIMITIVE      ** pasServerSyncs,
@@ -201,8 +204,7 @@
                                  IMG_INT32                   * pi32UpdateFenceFD,
                                  IMG_CHAR                      szFenceName[32],
 
-                                 IMG_UINT32                    ui32ExtJobRef,
-                                 IMG_UINT32                    ui32IntJobRef)
+                                 IMG_UINT32                    ui32ExtJobRef)
 {
 	RGXFWIF_KCCB_CMD         sKickSyncKCCBCmd;
 	RGX_CCB_CMD_HELPER_DATA  asCmdHelperData[1];
@@ -213,12 +215,12 @@
 	PRGXFWIF_UFO_ADDR        *pauiClientUpdateUFOAddress;
 	IMG_INT32                i32UpdateFenceFD = -1;
 	IMG_UINT32               ui32JobId;
+	IMG_UINT32               ui32FWCtx = FWCommonContextGetFWAddress(psKickSyncContext->psServerCommonContext).ui32Addr;
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 	/* Android fd sync update info */
 	struct pvr_sync_append_data *psFDFenceData = NULL;
 #endif
-	PVR_UNREFERENCED_PARAMETER(ui32IntJobRef);
 	
 	ui32JobId = OSAtomicIncrement(&psKickSyncContext->hJobId);
 
@@ -299,16 +301,18 @@
 	                                paui32ClientUpdateValue,
 	                                ui32ServerSyncPrims,
 	                                paui32ServerSyncFlags,
+	                                SYNC_FLAG_MASK_ALL,
 	                                pasServerSyncs,
 	                                0,
 	                                NULL,
 	                                NULL,
 	                                NULL,
 	                                NULL,
-	                                RGXFWIF_CCB_CMD_TYPE_3D,
+	                                RGXFWIF_CCB_CMD_TYPE_NULL,
 	                                ui32ExtJobRef,
 	                                ui32JobId,
-	                                IMG_FALSE,
+	                                PDUMP_FLAGS_NONE,
+	                                NULL,
 	                                "KickSync",
 	                                asCmdHelperData);
 	if (eError != PVRSRV_OK)
@@ -319,7 +323,6 @@
 	eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asCmdHelperData), asCmdHelperData);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXKickSync: Failed to acquire space for client CCB command"));
 		goto fail_cmdaquire;
 	}
 
@@ -351,24 +354,36 @@
 	sKickSyncKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psKickSyncContext->psServerCommonContext);
 	sKickSyncKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psKickSyncContext->psServerCommonContext));
 	sKickSyncKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
-
+	sKickSyncKCCBCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
+	sKickSyncKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+	
 	/*
-	 * Submit the compute command to the firmware.
+	 * Submit the kicksync command to the firmware.
 	 */
+	RGX_HWPERF_HOST_ENQ(psKickSyncContext, OSGetCurrentClientProcessIDKM(),
+	                    ui32FWCtx, ui32ExtJobRef, ui32JobId,
+	                    RGX_HWPERF_KICK_TYPE_SYNC);
+
 	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 	{
 		eError2 = RGXScheduleCommand(psKickSyncContext->psDeviceNode->pvDevice,
 		                             RGXFWIF_DM_3D,
 		                             & sKickSyncKCCBCmd,
 		                             sizeof(sKickSyncKCCBCmd),
-		                             IMG_FALSE);
+		                             ui32ClientCacheOpSeqNum,
+		                             PDUMP_FLAGS_NONE);
 		if (eError2 != PVRSRV_ERROR_RETRY)
 		{
 			break;
 		}
 		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
 	} END_LOOP_UNTIL_TIMEOUT();
-	
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+		RGXHWPerfFTraceGPUEnqueueEvent(psKickSyncContext->psDeviceNode->pvDevice,
+					ui32FWCtx, ui32JobId, RGX_HWPERF_KICK_TYPE_SYNC);
+#endif
+
 	if (eError2 != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,
diff --git a/drivers/staging/imgtec/rogue/rgxkicksync.h b/drivers/staging/imgtec/rogue/rgxkicksync.h
index cd84b8f..91422ee 100644
--- a/drivers/staging/imgtec/rogue/rgxkicksync.h
+++ b/drivers/staging/imgtec/rogue/rgxkicksync.h
@@ -80,28 +80,29 @@
  */ /**************************************************************************/
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKicksyncContext,
-                                 
+
+                                 IMG_UINT32                    ui32ClientCacheOpSeqNum,
+
                                  IMG_UINT32                    ui32ClientFenceCount,
                                  SYNC_PRIMITIVE_BLOCK           ** pauiClientFenceUFOSyncPrimBlock,
                                  IMG_UINT32                  * paui32ClientFenceSyncOffset,
                                  IMG_UINT32                  * paui32ClientFenceValue,
-                                 
+
                                  IMG_UINT32                    ui32ClientUpdateCount,
                                  SYNC_PRIMITIVE_BLOCK           ** pauiClientUpdateUFOSyncPrimBlock,
                                  IMG_UINT32                  * paui32ClientUpdateSyncOffset,
                                  IMG_UINT32                  * paui32ClientUpdateValue,
-                                 
+
                                  IMG_UINT32                    ui32ServerSyncPrims,
                                  IMG_UINT32                  * paui32ServerSyncFlags,
                                  SERVER_SYNC_PRIMITIVE      ** pasServerSyncs,
-                                 
+
                                  IMG_INT32                     i32CheckFenceFD,
                                  IMG_INT32                     i32UpdateTimelineFD,
                                  IMG_INT32                   * pi32UpdateFenceFD,
                                  IMG_CHAR                      szFenceName[32],
 
-                                 IMG_UINT32                    ui32ExtJobRef,
-                                 IMG_UINT32                    ui32IntJobRef);
+                                 IMG_UINT32                    ui32ExtJobRef);
 
 #endif /* __RGXKICKSYNC_H__ */
 
diff --git a/drivers/staging/imgtec/rogue/rgxlayer.h b/drivers/staging/imgtec/rogue/rgxlayer.h
index 8846438..c23a2cf 100644
--- a/drivers/staging/imgtec/rogue/rgxlayer.h
+++ b/drivers/staging/imgtec/rogue/rgxlayer.h
@@ -63,18 +63,21 @@
 #include "img_defs.h"
 #include "img_types.h"
 #include "pvrsrv_error.h" /* includes pvrsrv_errors.h */
+#if defined(SUPPORT_KERNEL_SRVINIT)
+#include "rgx_bvnc_defs_km.h"
+#endif
 
 #include "rgx_firmware_processor.h"
 /* includes:
- * rgx_meta.h or rgx_mips.h,
+ * rgx_meta.h and rgx_mips.h,
  * rgxdefs_km.h,
- * rgx_cr_defs_km.h,
+ * rgx_cr_defs_km.h (under SUPPORT_KERNEL_SRVINIT),
  * RGX_BVNC_CORE_KM_HEADER (rgxcore_km_B.V.N.C.h),
  * RGX_BNC_CONFIG_KM_HEADER (rgxconfig_km_B.V.N.C.h)
  */
 
 #include "rgx_fwif_shared.h"
-/* Required because of RGXFWIF_DEV_VIRTADDR but this header
+/* FIXME required because of RGXFWIF_DEV_VIRTADDR but this header
  * includes a lot of other headers..  RGXFWIF_DEV_VIRTADDR must be moved
  * somewhere else (either img_types.h or a new header) */
 
@@ -137,8 +140,8 @@
 ******************************************************************************/
 IMG_INTERNAL
 void RGXCommentLogInit(const void *hPrivate,
-                       IMG_CHAR *pszString,
-                       ...) IMG_FORMAT_PRINTF(2, 3);
+                       const IMG_CHAR *pszString,
+                       ...) __printf(2, 3);
 
 /*!
 *******************************************************************************
@@ -156,8 +159,56 @@
 ******************************************************************************/
 IMG_INTERNAL
 void RGXErrorLogInit(const void *hPrivate,
-                     IMG_CHAR *pszString,
-                     ...) IMG_FORMAT_PRINTF(2, 3);
+                     const IMG_CHAR *pszString,
+                     ...) __printf(2, 3);
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceHasFeatureInit
+
+ @Description    Checks if a device has a particular feature
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64Feature  : Feature to check
+
+ @Return         IMG_TRUE if the given feature is available, IMG_FALSE otherwise
+
+******************************************************************************/
+IMG_INTERNAL
+IMG_BOOL RGXDeviceHasFeatureInit(const void *hPrivate, IMG_UINT64 ui64Feature);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceHasErnBrnInit
+
+ @Description    Checks if a device has a particular errata
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64ErnsBrns : Flags to check
+
+ @Return         IMG_TRUE if the given errata is available, IMG_FALSE otherwise
+
+******************************************************************************/
+IMG_BOOL RGXDeviceHasErnBrnInit(const void *hPrivate, IMG_UINT64 ui64ErnsBrns);
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetFWCorememSize
+
+ @Description    Get the FW coremem size
+
+ @Input          hPrivate   : Implementation specific data
+
+ @Return         FW coremem size
+
+******************************************************************************/
+IMG_INTERNAL
+IMG_UINT32 RGXGetFWCorememSize(const void *hPrivate);
 
 
 #if defined (__cplusplus)
diff --git a/drivers/staging/imgtec/rogue/rgxlayer_impl.c b/drivers/staging/imgtec/rogue/rgxlayer_impl.c
index 49a4b26..e3e4081 100644
--- a/drivers/staging/imgtec/rogue/rgxlayer_impl.c
+++ b/drivers/staging/imgtec/rogue/rgxlayer_impl.c
@@ -54,6 +54,11 @@
 #include "srvinit_osfunc.h"
 #include "pvr_debug.h"
 
+#if defined(SUPPORT_KERNEL_SRVINIT)
+#include "device.h"
+#include "rgxdevice.h"
+#endif
+
 #if defined(PDUMP)
 #include "client_pdump_bridge.h"
 #endif
@@ -78,7 +83,7 @@
 }
 
 void RGXCommentLogInit(const void *hPrivate,
-                       IMG_CHAR *pszString,
+                       const IMG_CHAR *pszString,
                        ...)
 {
 #if defined(PDUMP)
@@ -103,7 +108,7 @@
 }
 
 void RGXErrorLogInit(const void *hPrivate,
-                     IMG_CHAR *pszString,
+                     const IMG_CHAR *pszString,
                      ...)
 {
 	IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
@@ -118,3 +123,54 @@
 	PVR_DPF((PVR_DBG_ERROR, "%s", szBuffer));
 }
 
+#if defined(SUPPORT_KERNEL_SRVINIT)
+IMG_BOOL RGXDeviceHasFeatureInit(const void *hPrivate, IMG_UINT64 ui64Feature)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)(((RGX_INIT_LAYER_PARAMS *)hPrivate)->hServices);
+	psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	return (psDevInfo->sDevFeatureCfg.ui64Features & ui64Feature) != 0;
+}
+
+IMG_BOOL RGXDeviceHasErnBrnInit(const void *hPrivate, IMG_UINT64 ui64ErnsBrns)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)(((RGX_INIT_LAYER_PARAMS *)hPrivate)->hServices);
+	psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	return (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & ui64ErnsBrns) != 0;
+}
+#endif
+
+IMG_UINT32 RGXGetFWCorememSize(const void *hPrivate)
+{
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)(((RGX_INIT_LAYER_PARAMS *)hPrivate)->hServices);
+	psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	return psDevInfo->sDevFeatureCfg.ui32MCMS;
+#elif defined(RGX_META_COREMEM_CODE) || defined(RGX_META_COREMEM_DATA)
+	PVR_UNREFERENCED_PARAMETER(hPrivate);
+
+	return RGX_META_COREMEM_SIZE;
+#else
+	PVR_UNREFERENCED_PARAMETER(hPrivate);
+
+	return 0;
+#endif
+}
+
diff --git a/drivers/staging/imgtec/rogue/rgxlayer_km.h b/drivers/staging/imgtec/rogue/rgxlayer_km.h
index 2e25088..924bf03 100644
--- a/drivers/staging/imgtec/rogue/rgxlayer_km.h
+++ b/drivers/staging/imgtec/rogue/rgxlayer_km.h
@@ -63,10 +63,11 @@
 #include "img_types.h"
 #include "img_defs.h"
 #include "pvrsrv_error.h" /* includes pvrsrv_errors.h */
+#include "rgx_bvnc_defs_km.h"
 
 #include "rgx_firmware_processor.h"
 /* includes:
- * rgx_meta.h or rgx_mips.h,
+ * rgx_meta.h and rgx_mips.h,
  * rgxdefs_km.h,
  * rgx_cr_defs_km.h,
  * RGX_BVNC_CORE_KM_HEADER (rgxcore_km_B.V.N.C.h),
@@ -179,8 +180,9 @@
 
 ******************************************************************************/
 void RGXCommentLogPower(const void *hPrivate,
-                        IMG_CHAR *pszString,
-                        ...) IMG_FORMAT_PRINTF(2, 3);
+                        const IMG_CHAR *pszString,
+                        ...) __printf(2, 3);
+
 
 /*!
 *******************************************************************************
@@ -218,31 +220,373 @@
 
 ******************************************************************************/
 #if defined(PDUMP)
-#if !defined(RGX_FEATURE_SLC_VIVT)
+
 void RGXWriteKernelMMUPC64(const void *hPrivate,
                            IMG_UINT32 ui32PCReg,
                            IMG_UINT32 ui32PCRegAlignShift,
                            IMG_UINT32 ui32PCRegShift,
                            IMG_UINT64 ui64PCVal);
-#else
+
 void RGXWriteKernelMMUPC32(const void *hPrivate,
                            IMG_UINT32 ui32PCReg,
                            IMG_UINT32 ui32PCRegAlignShift,
                            IMG_UINT32 ui32PCRegShift,
                            IMG_UINT32 ui32PCVal);
-#endif
+
 
 #else  /* defined(PDUMP) */
-#if !defined(RGX_FEATURE_SLC_VIVT)
+
 #define RGXWriteKernelMMUPC64(priv, pcreg, alignshift, shift, pcval) \
 	RGXWriteReg64(priv, pcreg, pcval)
-#else
+
 #define RGXWriteKernelMMUPC32(priv, pcreg, alignshift, shift, pcval) \
 	RGXWriteReg32(priv, pcreg, pcval)
-#endif
+
 #endif /* defined(PDUMP) */
 
 
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireGPURegsAddr
+
+ @Description     Acquire the GPU registers base device physical address
+
+ @Input           hPrivate       : Implementation specific data
+ @Input           psGPURegsAddr  : Returned GPU registers base address
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireGPURegsAddr(const void *hPrivate, IMG_DEV_PHYADDR *psGPURegsAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXMIPSWrapperConfig
+
+ @Description     Write GPU register bank transaction ID and MIPS boot mode
+                  to the MIPS wrapper config register (passed as argument).
+                  In a driver-live scenario without PDump this is the same as
+                  RGXWriteReg64 and it doesn't need to be reimplemented.
+
+ @Input           hPrivate          : Implementation specific data
+ @Input           ui32RegAddr       : Register offset inside the register bank
+ @Input           ui64GPURegsAddr   : GPU registers base address
+ @Input           ui32GPURegsAlign  : Register bank transactions alignment
+ @Input           ui32BootMode      : Mips BOOT ISA mode
+
+ @Return          void
+
+******************************************************************************/
+#if defined(PDUMP)
+void RGXMIPSWrapperConfig(const void *hPrivate,
+                          IMG_UINT32 ui32RegAddr,
+                          IMG_UINT64 ui64GPURegsAddr,
+                          IMG_UINT32 ui32GPURegsAlign,
+                          IMG_UINT32 ui32BootMode);
+#else
+#define RGXMIPSWrapperConfig(priv, regaddr, gpuregsaddr, gpuregsalign, bootmode) \
+	RGXWriteReg64(priv, regaddr, ((gpuregsaddr) >> (gpuregsalign)) | (bootmode))
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireBootRemapAddr
+
+ @Description     Acquire the device physical address of the MIPS bootloader
+                  accessed through remap region
+
+ @Input           hPrivate         : Implementation specific data
+ @Output          psBootRemapAddr  : Base address of the remapped bootloader
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireBootRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psBootRemapAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXBootRemapConfig
+
+ @Description     Configure the bootloader remap registers passed as arguments.
+                  In a driver-live scenario without PDump this is the same as
+                  two RGXWriteReg64 and it doesn't need to be reimplemented.
+
+ @Input           hPrivate             : Implementation specific data
+ @Input           ui32Config1RegAddr   : Remap config1 register offset
+ @Input           ui64Config1RegValue  : Remap config1 register value
+ @Input           ui32Config2RegAddr   : Remap config2 register offset
+ @Input           ui64Config2PhyAddr   : Output remapped aligned physical address
+ @Input           ui64Config2PhyMask   : Mask for the output physical address
+ @Input           ui64Config2Settings  : Extra settings for this remap region
+
+ @Return          void
+
+******************************************************************************/
+#if defined(PDUMP)
+void RGXBootRemapConfig(const void *hPrivate,
+                        IMG_UINT32 ui32Config1RegAddr,
+                        IMG_UINT64 ui64Config1RegValue,
+                        IMG_UINT32 ui32Config2RegAddr,
+                        IMG_UINT64 ui64Config2PhyAddr,
+                        IMG_UINT64 ui64Config2PhyMask,
+                        IMG_UINT64 ui64Config2Settings);
+#else
+#define RGXBootRemapConfig(priv, c1reg, c1val, c2reg, c2phyaddr, c2phymask, c2settings) do { \
+		RGXWriteReg64(priv, c1reg, (c1val)); \
+		RGXWriteReg64(priv, c2reg, ((c2phyaddr) & (c2phymask)) | (c2settings)); \
+	} while (0)
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireCodeRemapAddr
+
+ @Description     Acquire the device physical address of the MIPS code
+                  accessed through remap region
+
+ @Input           hPrivate         : Implementation specific data
+ @Output          psCodeRemapAddr  : Base address of the remapped code
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireCodeRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psCodeRemapAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXCodeRemapConfig
+
+ @Description     Configure the code remap registers passed as arguments.
+                  In a driver-live scenario without PDump this is the same as
+                  two RGXWriteReg64 and it doesn't need to be reimplemented.
+
+ @Input           hPrivate             : Implementation specific data
+ @Input           ui32Config1RegAddr   : Remap config1 register offset
+ @Input           ui64Config1RegValue  : Remap config1 register value
+ @Input           ui32Config2RegAddr   : Remap config2 register offset
+ @Input           ui64Config2PhyAddr   : Output remapped aligned physical address
+ @Input           ui64Config2PhyMask   : Mask for the output physical address
+ @Input           ui64Config2Settings  : Extra settings for this remap region
+
+ @Return          void
+
+******************************************************************************/
+#if defined(PDUMP)
+void RGXCodeRemapConfig(const void *hPrivate,
+                        IMG_UINT32 ui32Config1RegAddr,
+                        IMG_UINT64 ui64Config1RegValue,
+                        IMG_UINT32 ui32Config2RegAddr,
+                        IMG_UINT64 ui64Config2PhyAddr,
+                        IMG_UINT64 ui64Config2PhyMask,
+                        IMG_UINT64 ui64Config2Settings);
+#else
+#define RGXCodeRemapConfig(priv, c1reg, c1val, c2reg, c2phyaddr, c2phymask, c2settings) do { \
+		RGXWriteReg64(priv, c1reg, (c1val)); \
+		RGXWriteReg64(priv, c2reg, ((c2phyaddr) & (c2phymask)) | (c2settings)); \
+	} while (0)
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireDataRemapAddr
+
+ @Description     Acquire the device physical address of the MIPS data
+                  accessed through remap region
+
+ @Input           hPrivate         : Implementation specific data
+ @Output          psDataRemapAddr  : Base address of the remapped data
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireDataRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psDataRemapAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXDataRemapConfig
+
+ @Description     Configure the data remap registers passed as arguments.
+                  In a driver-live scenario without PDump this is the same as
+                  two RGXWriteReg64 and it doesn't need to be reimplemented.
+
+ @Input           hPrivate             : Implementation specific data
+ @Input           ui32Config1RegAddr   : Remap config1 register offset
+ @Input           ui64Config1RegValue  : Remap config1 register value
+ @Input           ui32Config2RegAddr   : Remap config2 register offset
+ @Input           ui64Config2PhyAddr   : Output remapped aligned physical address
+ @Input           ui64Config2PhyMask   : Mask for the output physical address
+ @Input           ui64Config2Settings  : Extra settings for this remap region
+
+ @Return          void
+
+******************************************************************************/
+#if defined(PDUMP)
+void RGXDataRemapConfig(const void *hPrivate,
+                        IMG_UINT32 ui32Config1RegAddr,
+                        IMG_UINT64 ui64Config1RegValue,
+                        IMG_UINT32 ui32Config2RegAddr,
+                        IMG_UINT64 ui64Config2PhyAddr,
+                        IMG_UINT64 ui64Config2PhyMask,
+                        IMG_UINT64 ui64Config2Settings);
+#else
+#define RGXDataRemapConfig(priv, c1reg, c1val, c2reg, c2phyaddr, c2phymask, c2settings) do { \
+		RGXWriteReg64(priv, c1reg, (c1val)); \
+		RGXWriteReg64(priv, c2reg, ((c2phyaddr) & (c2phymask)) | (c2settings)); \
+	} while (0)
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireTrampolineRemapAddr
+
+ @Description     Acquire the device physical address of the MIPS data
+                  accessed through remap region
+
+ @Input           hPrivate             : Implementation specific data
+ @Output          psTrampolineRemapAddr: Base address of the remapped data
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireTrampolineRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psTrampolineRemapAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXTrampolineRemapConfig
+
+ @Description     Configure the trampoline remap registers passed as arguments.
+                  In a driver-live scenario without PDump this is the same as
+                  two RGXWriteReg64 and it doesn't need to be reimplemented.
+
+ @Input           hPrivate             : Implementation specific data
+ @Input           ui32Config1RegAddr   : Remap config1 register offset
+ @Input           ui64Config1RegValue  : Remap config1 register value
+ @Input           ui32Config2RegAddr   : Remap config2 register offset
+ @Input           ui64Config2PhyAddr   : Output remapped aligned physical address
+ @Input           ui64Config2PhyMask   : Mask for the output physical address
+ @Input           ui64Config2Settings  : Extra settings for this remap region
+
+ @Return          void
+
+******************************************************************************/
+#define RGXTrampolineRemapConfig(priv, c1reg, c1val, c2reg, c2phyaddr, c2phymask, c2settings) do { \
+		RGXWriteReg64(priv, c1reg, (c1val)); \
+		RGXWriteReg64(priv, c2reg, ((c2phyaddr) & (c2phymask)) | (c2settings)); \
+	} while (0)
+
+/*!
+*******************************************************************************
+
+ @Function        RGXDoFWSlaveBoot
+
+ @Description     Returns whether or not a FW Slave Boot is required
+                  while powering on
+
+ @Input           hPrivate       : Implementation specific data
+
+ @Return          IMG_BOOL
+
+******************************************************************************/
+IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXIOCoherencyTest
+
+ @Description    Performs a coherency test
+
+ @Input          hPrivate         : Implementation specific data
+
+ @Return         PVRSRV_OK if the test succeeds,
+                 PVRSRV_ERROR_INIT_FAILURE if the test fails at some point
+
+******************************************************************************/
+PVRSRV_ERROR RGXIOCoherencyTest(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceHasFeaturePower
+
+ @Description    Checks if a device has a particular feature
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64Feature  : Feature to check
+
+ @Return         IMG_TRUE if the given feature is available, IMG_FALSE otherwise
+
+******************************************************************************/
+IMG_BOOL RGXDeviceHasFeaturePower(const void *hPrivate, IMG_UINT64 ui64Feature);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceHasErnBrnPower
+
+ @Description    Checks if a device has a particular errata
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64ErnsBrns : Flags to check
+
+ @Return         IMG_TRUE if the given errata is available, IMG_FALSE otherwise
+
+******************************************************************************/
+IMG_BOOL RGXDeviceHasErnBrnPower(const void *hPrivate, IMG_UINT64 ui64ErnsBrns);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetDeviceSLCBanks
+
+ @Description    Returns the number of SLC banks used by the device
+
+ @Input          hPrivate    : Implementation specific data
+
+ @Return         Number of SLC banks
+
+******************************************************************************/
+IMG_UINT32 RGXGetDeviceSLCBanks(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetDeviceSLCSize
+
+ @Description    Returns the device SLC size
+
+ @Input          hPrivate    : Implementation specific data
+
+ @Return         SLC size
+
+******************************************************************************/
+IMG_UINT32 RGXGetDeviceSLCSize(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetDeviceCacheLineSize
+
+ @Description    Returns the device cache line size
+
+ @Input          hPrivate    : Implementation specific data
+
+ @Return         Cache line size
+
+******************************************************************************/
+IMG_UINT32 RGXGetDeviceCacheLineSize(const void *hPrivate);
+
 #if defined (__cplusplus)
 }
 #endif
diff --git a/drivers/staging/imgtec/rogue/rgxlayer_km_impl.c b/drivers/staging/imgtec/rogue/rgxlayer_km_impl.c
index 3601c27..a412124 100644
--- a/drivers/staging/imgtec/rogue/rgxlayer_km_impl.c
+++ b/drivers/staging/imgtec/rogue/rgxlayer_km_impl.c
@@ -41,66 +41,110 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+#if defined (PDUMP)
+#include <stdarg.h>
+#endif
+
 #include "rgxlayer_km_impl.h"
 #include "pdump_km.h"
 #include "devicemem_utils.h"
 #include "pvrsrv.h"
 #include "rgxdevice.h"
-
+#include "rgxfwutils.h"
 
 void RGXWriteReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
 {
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 	void *pvRegsBase;
 
 	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
 	pvRegsBase = psDevInfo->pvRegsBaseKM;
 
-	OSWriteHWReg32(pvRegsBase, ui32RegAddr, ui32RegValue);
-	PDUMPREG32(RGX_PDUMPREG_NAME, ui32RegAddr, ui32RegValue, PDUMP_FLAGS_CONTINUOUS);
+#if defined(PDUMP)
+	if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+#endif
+	{
+		OSWriteHWReg32(pvRegsBase, ui32RegAddr, ui32RegValue);
+	}
+
+	PDUMPREG32(RGX_PDUMPREG_NAME, ui32RegAddr, ui32RegValue, psPowerParams->ui32PdumpFlags);
 }
 
 void RGXWriteReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT64 ui64RegValue)
 {
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 	void *pvRegsBase;
 
 	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
 	pvRegsBase = psDevInfo->pvRegsBaseKM;
 
-	OSWriteHWReg64(pvRegsBase, ui32RegAddr, ui64RegValue);
-	PDUMPREG64(RGX_PDUMPREG_NAME, ui32RegAddr, ui64RegValue, PDUMP_FLAGS_CONTINUOUS);
+#if defined(PDUMP)
+	if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+#endif
+	{
+		OSWriteHWReg64(pvRegsBase, ui32RegAddr, ui64RegValue);
+	}
+
+	PDUMPREG64(RGX_PDUMPREG_NAME, ui32RegAddr, ui64RegValue, psPowerParams->ui32PdumpFlags);
 }
 
 IMG_UINT32 RGXReadReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr)
 {
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 	void *pvRegsBase;
 	IMG_UINT32 ui32RegValue;
 
 	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
 	pvRegsBase = psDevInfo->pvRegsBaseKM;
 
-	ui32RegValue = OSReadHWReg32(pvRegsBase, ui32RegAddr);
-	PDUMPREGREAD32(RGX_PDUMPREG_NAME, ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
+#if defined(PDUMP)
+	if(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
+	{
+		ui32RegValue = IMG_UINT32_MAX;
+	}
+	else
+#endif
+	{
+		ui32RegValue = OSReadHWReg32(pvRegsBase, ui32RegAddr);
+	}
+
+	PDUMPREGREAD32(RGX_PDUMPREG_NAME, ui32RegAddr, psPowerParams->ui32PdumpFlags);
 
 	return ui32RegValue;
 }
 
 IMG_UINT64 RGXReadReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr)
 {
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 	void *pvRegsBase;
 	IMG_UINT64 ui64RegValue;
 
 	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
 	pvRegsBase = psDevInfo->pvRegsBaseKM;
 
-	ui64RegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
+#if defined(PDUMP)
+	if(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
+	{
+		ui64RegValue = IMG_UINT64_MAX;
+	}
+	else
+#endif
+	{
+		ui64RegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
+	}
+
 	PDUMPREGREAD64(RGX_PDUMPREG_NAME, ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
 
 	return ui64RegValue;
@@ -111,26 +155,33 @@
                           IMG_UINT32 ui32RegValue,
                           IMG_UINT32 ui32RegMask)
 {
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 	void *pvRegsBase;
 
 	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
 	pvRegsBase = psDevInfo->pvRegsBaseKM;
 
-	if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
-	                         ui32RegValue,
-	                         ui32RegMask) != PVRSRV_OK)
+#if defined(PDUMP)
+	if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+#endif
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXPollReg32: Poll for Reg (0x%x) failed", ui32RegAddr));
-		return PVRSRV_ERROR_TIMEOUT;
+		if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
+		                         ui32RegValue,
+		                         ui32RegMask) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXPollReg32: Poll for Reg (0x%x) failed", ui32RegAddr));
+			return PVRSRV_ERROR_TIMEOUT;
+		}
 	}
 
 	PDUMPREGPOL(RGX_PDUMPREG_NAME,
 	            ui32RegAddr,
 	            ui32RegValue,
 	            ui32RegMask,
-	            PDUMP_FLAGS_CONTINUOUS,
+	            psPowerParams->ui32PdumpFlags,
 	            PDUMP_POLL_OPERATOR_EQUAL);
 
 	return PVRSRV_OK;
@@ -141,6 +192,7 @@
                           IMG_UINT64 ui64RegValue,
                           IMG_UINT64 ui64RegMask)
 {
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 	void *pvRegsBase;
 
@@ -151,37 +203,44 @@
 	IMG_UINT32 ui32LowerMask = (IMG_UINT32) (ui64RegMask);
 
 	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
 	pvRegsBase = psDevInfo->pvRegsBaseKM;
 
-	if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr + 4),
-	                         ui32UpperValue,
-	                         ui32UpperMask) != PVRSRV_OK)
+#if defined(PDUMP)
+	if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+#endif
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
-		return PVRSRV_ERROR_TIMEOUT;
+		if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr + 4),
+		                         ui32UpperValue,
+		                         ui32UpperMask) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
+			return PVRSRV_ERROR_TIMEOUT;
+		}
+
+		if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
+		                         ui32LowerValue,
+		                         ui32LowerMask) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
+			return PVRSRV_ERROR_TIMEOUT;
+		}
 	}
 
 	PDUMPREGPOL(RGX_PDUMPREG_NAME,
 	            ui32RegAddr + 4,
 	            ui32UpperValue,
 	            ui32UpperMask,
-	            PDUMP_FLAGS_CONTINUOUS,
+	            psPowerParams->ui32PdumpFlags,
 	            PDUMP_POLL_OPERATOR_EQUAL);
 
-	if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
-	                         ui32LowerValue,
-	                         ui32LowerMask) != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
-		return PVRSRV_ERROR_TIMEOUT;
-	}
 
 	PDUMPREGPOL(RGX_PDUMPREG_NAME,
 	            ui32RegAddr,
 	            ui32LowerValue,
 	            ui32LowerMask,
-	            PDUMP_FLAGS_CONTINUOUS,
+	            psPowerParams->ui32PdumpFlags,
 	            PDUMP_POLL_OPERATOR_EQUAL);
 
 	return PVRSRV_OK;
@@ -194,24 +253,21 @@
 	PDUMPIDLWITHFLAGS(ui32Cycles, PDUMP_FLAGS_CONTINUOUS);
 }
 
-void RGXCommentLogPower(const void *hPrivate, IMG_CHAR *pszString, ...)
+void RGXCommentLogPower(const void *hPrivate, const IMG_CHAR *pszString, ...)
 {
 #if defined(PDUMP)
-	IMG_CHAR szBuffer[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
 	va_list argList;
-
 	va_start(argList, pszString);
-	vsnprintf(szBuffer, sizeof(szBuffer), pszString, argList);
+	PDumpCommentWithFlagsVA(PDUMP_FLAGS_CONTINUOUS, pszString, argList);
 	va_end(argList);
-
-	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, szBuffer);
 	PVR_UNREFERENCED_PARAMETER(hPrivate);
 #else
-	PVR_UNREFERENCED_PARAMETER(pszString);
 	PVR_UNREFERENCED_PARAMETER(hPrivate);
+	PVR_UNREFERENCED_PARAMETER(pszString);
 #endif
 }
 
+
 void RGXAcquireKernelMMUPC(const void *hPrivate, IMG_DEV_PHYADDR *psPCAddr)
 {
 	PVR_ASSERT(hPrivate != NULL);
@@ -219,7 +275,7 @@
 }
 
 #if defined(PDUMP)
-#if !defined(RGX_FEATURE_SLC_VIVT)
+
 void RGXWriteKernelMMUPC64(const void *hPrivate,
                            IMG_UINT32 ui32PCReg,
                            IMG_UINT32 ui32PCRegAlignShift,
@@ -243,7 +299,7 @@
 	                          ui32PCRegShift,
 	                          PDUMP_FLAGS_CONTINUOUS);
 }
-#else
+
 void RGXWriteKernelMMUPC32(const void *hPrivate,
                            IMG_UINT32 ui32PCReg,
                            IMG_UINT32 ui32PCRegAlignShift,
@@ -267,6 +323,448 @@
 	                          ui32PCRegShift,
 	                          PDUMP_FLAGS_CONTINUOUS);
 }
-#endif
+
 #endif /* defined(PDUMP) */
 
+
+void RGXAcquireGPURegsAddr(const void *hPrivate, IMG_DEV_PHYADDR *psGPURegsAddr)
+{
+	PVR_ASSERT(hPrivate != NULL);
+	*psGPURegsAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sGPURegAddr;
+}
+
+#if defined(PDUMP)
+void RGXMIPSWrapperConfig(const void *hPrivate,
+                          IMG_UINT32 ui32RegAddr,
+                          IMG_UINT64 ui64GPURegsAddr,
+                          IMG_UINT32 ui32GPURegsAlign,
+                          IMG_UINT32 ui32BootMode)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+	OSWriteHWReg64(psDevInfo->pvRegsBaseKM,
+	               ui32RegAddr,
+	               (ui64GPURegsAddr >> ui32GPURegsAlign) | ui32BootMode);
+
+	/* Store register offset to temp PDump variable */
+	PDumpRegLabelToInternalVar(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
+
+	/* Align register transactions identifier */
+	PDumpWriteVarSHRValueOp(":SYSMEM:$1", ui32GPURegsAlign, PDUMP_FLAGS_CONTINUOUS);
+
+	/* Enable micromips instruction encoding */
+	PDumpWriteVarORValueOp(":SYSMEM:$1", ui32BootMode, PDUMP_FLAGS_CONTINUOUS);
+
+	/* Do the actual register write */
+	PDumpInternalVarToReg64(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", 0);
+}
+#endif
+
+void RGXAcquireBootRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psBootRemapAddr)
+{
+	PVR_ASSERT(hPrivate != NULL);
+	*psBootRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sBootRemapAddr;
+}
+
+void RGXAcquireCodeRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psCodeRemapAddr)
+{
+	PVR_ASSERT(hPrivate != NULL);
+	*psCodeRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sCodeRemapAddr;
+}
+
+void RGXAcquireDataRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psDataRemapAddr)
+{
+	PVR_ASSERT(hPrivate != NULL);
+	*psDataRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sDataRemapAddr;
+}
+
+void RGXAcquireTrampolineRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psTrampolineRemapAddr)
+{
+	PVR_ASSERT(hPrivate != NULL);
+	*psTrampolineRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sTrampolineRemapAddr;
+}
+
+#if defined(PDUMP)
+static inline
+void RGXWriteRemapConfig2Reg(void *pvRegs,
+                             PMR *psPMR,
+                             IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+                             IMG_UINT32 ui32RegAddr,
+                             IMG_UINT64 ui64PhyAddr,
+                             IMG_UINT64 ui64PhyMask,
+                             IMG_UINT64 ui64Settings)
+{
+	OSWriteHWReg64(pvRegs, ui32RegAddr, (ui64PhyAddr & ui64PhyMask) | ui64Settings);
+
+	/* Store memory offset to temp PDump variable */
+	PDumpMemLabelToInternalVar(":SYSMEM:$1", psPMR, uiLogicalOffset, PDUMP_FLAGS_CONTINUOUS);
+
+	/* Keep only the relevant bits of the output physical address */
+	PDumpWriteVarANDValueOp(":SYSMEM:$1", ui64PhyMask, PDUMP_FLAGS_CONTINUOUS);
+
+	/* Extra settings for this remapped region */
+	PDumpWriteVarORValueOp(":SYSMEM:$1", ui64Settings, PDUMP_FLAGS_CONTINUOUS);
+
+	/* Do the actual register write */
+	PDumpInternalVarToReg32(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
+}
+
+void RGXBootRemapConfig(const void *hPrivate,
+                        IMG_UINT32 ui32Config1RegAddr,
+                        IMG_UINT64 ui64Config1RegValue,
+                        IMG_UINT32 ui32Config2RegAddr,
+                        IMG_UINT64 ui64Config2PhyAddr,
+                        IMG_UINT64 ui64Config2PhyMask,
+                        IMG_UINT64 ui64Config2Settings)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32BootRemapMemOffset = RGXMIPSFW_BOOT_NMI_CODE_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+	/* Write remap config1 register */
+	RGXWriteReg64(hPrivate,
+	              ui32Config1RegAddr,
+	              ui64Config1RegValue);
+
+	/* Write remap config2 register */
+	RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
+	                        psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
+	                        psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32BootRemapMemOffset,
+	                        ui32Config2RegAddr,
+	                        ui64Config2PhyAddr,
+	                        ui64Config2PhyMask,
+	                        ui64Config2Settings);
+}
+
+void RGXCodeRemapConfig(const void *hPrivate,
+                        IMG_UINT32 ui32Config1RegAddr,
+                        IMG_UINT64 ui64Config1RegValue,
+                        IMG_UINT32 ui32Config2RegAddr,
+                        IMG_UINT64 ui64Config2PhyAddr,
+                        IMG_UINT64 ui64Config2PhyMask,
+                        IMG_UINT64 ui64Config2Settings)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32CodeRemapMemOffset = RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+	/* Write remap config1 register */
+	RGXWriteReg64(hPrivate,
+	              ui32Config1RegAddr,
+	              ui64Config1RegValue);
+
+	/* Write remap config2 register */
+	RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
+	                        psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
+	                        psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32CodeRemapMemOffset,
+	                        ui32Config2RegAddr,
+	                        ui64Config2PhyAddr,
+	                        ui64Config2PhyMask,
+	                        ui64Config2Settings);
+}
+
+void RGXDataRemapConfig(const void *hPrivate,
+                        IMG_UINT32 ui32Config1RegAddr,
+                        IMG_UINT64 ui64Config1RegValue,
+                        IMG_UINT32 ui32Config2RegAddr,
+                        IMG_UINT64 ui64Config2PhyAddr,
+                        IMG_UINT64 ui64Config2PhyMask,
+                        IMG_UINT64 ui64Config2Settings)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32DataRemapMemOffset = RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+	/* Write remap config1 register */
+	RGXWriteReg64(hPrivate,
+	              ui32Config1RegAddr,
+	              ui64Config1RegValue);
+
+	/* Write remap config2 register */
+	RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
+	                        psDevInfo->psRGXFWDataMemDesc->psImport->hPMR,
+	                        psDevInfo->psRGXFWDataMemDesc->uiOffset + ui32DataRemapMemOffset,
+	                        ui32Config2RegAddr,
+	                        ui64Config2PhyAddr,
+	                        ui64Config2PhyMask,
+	                        ui64Config2Settings);
+}
+#endif
+
+
+
+#define MAX_NUM_COHERENCY_TESTS  (10)
+IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	PVRSRV_DEVICE_CONFIG *psDevConfig;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+	if (psDevInfo->ui32CoherencyTestsDone >= MAX_NUM_COHERENCY_TESTS)
+	{
+		return IMG_FALSE;
+	}
+
+	psDevConfig = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevConfig;
+
+	return PVRSRVSystemSnoopingOfCPUCache(psDevConfig);
+}
+
+static PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	/* Wait for Slave Port to be Ready */
+	eError = RGXPollReg32(hPrivate,
+	                      RGX_CR_META_SP_MSLVCTRL1,
+	                      RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+	                      RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
+	if (eError != PVRSRV_OK) return eError;
+
+	/* Issue a Write */
+	RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0, ui32RegAddr);
+	RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT, ui32RegValue);
+
+	return eError;
+}
+
+PVRSRV_ERROR RGXIOCoherencyTest(const void *hPrivate)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+	DEVMEM_MEMDESC *psIOCoherencyTestMemDesc;
+	IMG_UINT32 *pui32CpuVirtAddr;
+	RGXFWIF_DEV_VIRTADDR sCoherencyTestBuffer;
+	IMG_DEVMEM_SIZE_T uiCoherencyBlockSize = sizeof(IMG_UINT64);
+	IMG_DEVMEM_ALIGN_T uiCoherencyBlockAlign = sizeof(IMG_UINT64);
+	IMG_UINT64 ui64SegOutAddrTopCached = 0, ui64SegOutAddrTopUncached = 0;
+	IMG_UINT32 ui32SLCCTRL = 0;
+	IMG_UINT32 ui32TestNum;
+	IMG_BOOL   bFeatureS7;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+	/* Size and align are 'expanded' because we request an export align allocation */
+	DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
+	                                    &uiCoherencyBlockSize,
+	                                    &uiCoherencyBlockAlign);
+
+	/* Allocate, acquire cpu address and set firmware address */
+	eError = DevmemFwAllocateExportable(psDevInfo->psDeviceNode,
+	                                    uiCoherencyBlockSize,
+	                                    uiCoherencyBlockAlign,
+	                                    PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+	                                    PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+	                                    PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+	                                    PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT |
+	                                    PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT |
+	                                    PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+	                                    PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+	                                    PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+	                                    PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
+	                                    "FwExIoCoherencyTestBuffer",
+	                                    &psIOCoherencyTestMemDesc);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	eError = DevmemAcquireCpuVirtAddr(psIOCoherencyTestMemDesc,
+	                                  (void **) &pui32CpuVirtAddr);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* Create a FW address which is uncached in the Meta DCache and in the SLC
+	 * using the Meta bootloader segment.
+	 * This segment is the only one configured correctly out of reset
+	 * (when this test is meant to be executed).
+	 */
+	{
+		RGXSetFirmwareAddress(&sCoherencyTestBuffer,
+		                      psIOCoherencyTestMemDesc,
+		                      0,
+		                      RFW_FWADDR_FLAG_NONE);
+
+		/* Undo most of the FW mappings done by RGXSetFirmwareAddress */
+		sCoherencyTestBuffer.ui32Addr &= ~RGXFW_SEGMMU_DATA_META_CACHE_MASK;
+		sCoherencyTestBuffer.ui32Addr &= ~RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK;
+		sCoherencyTestBuffer.ui32Addr -= RGXFW_SEGMMU_DATA_BASE_ADDRESS;
+
+		/* Map the buffer in the bootloader segment as uncached */
+		sCoherencyTestBuffer.ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
+		sCoherencyTestBuffer.ui32Addr |= RGXFW_SEGMMU_DATA_META_UNCACHED;
+	}
+
+	bFeatureS7 = RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK);
+
+	if (bFeatureS7)
+	{
+		if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_49144_BIT_MASK))
+		{
+			ui64SegOutAddrTopCached   = RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED_ERN_49144(META_MMU_CONTEXT_MAPPING);
+			ui64SegOutAddrTopUncached = RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED_ERN_49144(META_MMU_CONTEXT_MAPPING);
+		}
+		else if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_45914_BIT_MASK))
+		{
+			ui64SegOutAddrTopCached   = RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED_ERN_45914(META_MMU_CONTEXT_MAPPING);
+			ui64SegOutAddrTopUncached = RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED_ERN_45914(META_MMU_CONTEXT_MAPPING);
+		}
+
+		/* Configure META to use SLC force-linefill for the bootloader segment */
+		RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
+		                         (ui64SegOutAddrTopUncached |  RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
+	}
+	else
+	{
+		/* Bypass the SLC when IO coherency is enabled */
+		ui32SLCCTRL = RGXReadReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS);
+		RGXWriteReg32(hPrivate,
+		              RGX_CR_SLC_CTRL_BYPASS,
+		              ui32SLCCTRL | RGX_CR_SLC_CTRL_BYPASS_BYP_CC_EN);
+	}
+
+	for (ui32TestNum = 1; ui32TestNum < 3; ui32TestNum++)
+	{
+		IMG_UINT32 i;
+		IMG_BOOL bPassed = IMG_TRUE;
+
+		PVR_LOG(("Startup I/O Coherency Test [pass #%u]", ui32TestNum));
+
+		for (i = 0; i < uiCoherencyBlockSize/sizeof(IMG_UINT32); i++)
+		{
+			IMG_UINT32 ui32FWAddr, ui32FWValue;
+			PVRSRV_ERROR eError2;
+
+			/* Ensures line is in dcache */
+			ui32FWValue = pui32CpuVirtAddr[i];
+
+			/* Dirty allocation in dcache */
+			pui32CpuVirtAddr[i] = i + ui32TestNum;
+
+			/* Flush possible cpu store-buffer(ing) */
+			OSWriteMemoryBarrier();
+
+			/* Read back value using RGX slave-port interface */
+			ui32FWAddr = sCoherencyTestBuffer.ui32Addr + (i * sizeof(IMG_UINT32));
+
+			eError2 = RGXReadMETAAddr(psDevInfo, ui32FWAddr, &ui32FWValue);
+
+			if (eError2 != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "RGXReadWithSP error: %s",
+				         PVRSRVGetErrorStringKM(eError2)));
+			}
+
+			/* Compare to see if I/O coherency worked */
+			if (pui32CpuVirtAddr[i] != ui32FWValue)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Expected: %x, Got: %x",
+				         pui32CpuVirtAddr[i], ui32FWValue));
+
+				bPassed = IMG_FALSE;
+				eError = PVRSRV_ERROR_INIT_FAILURE;
+			}
+		}
+
+		PVR_LOG(("I/O Coherency Test [pass #%u] completed, Passed? %d",
+		         ui32TestNum, bPassed));
+	}
+
+	if (bFeatureS7)
+	{
+		/* Restore bootloader segment settings */
+		RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
+		                         (ui64SegOutAddrTopCached |  RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
+	}
+	else
+	{
+		/* Restore SLC bypass settings */
+		RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS, ui32SLCCTRL);
+	}
+
+	RGXUnsetFirmwareAddress(psIOCoherencyTestMemDesc);
+	DevmemReleaseCpuVirtAddr(psIOCoherencyTestMemDesc);
+	DevmemFwFree(psDevInfo, psIOCoherencyTestMemDesc);
+
+	if (eError == PVRSRV_OK)
+	{
+		PVR_LOG(("I/O Coherency Test succeeded"));
+		psDevInfo->ui32CoherencyTestsDone = MAX_NUM_COHERENCY_TESTS + 1;
+	}
+	else
+	{
+		PVR_LOG(("I/O Coherency Test FAILED"));
+		psDevInfo->ui32CoherencyTestsDone++;
+	}
+
+	return eError;
+}
+
+IMG_BOOL RGXDeviceHasFeaturePower(const void *hPrivate, IMG_UINT64 ui64Feature)
+{
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
+
+	return (psDevInfo->sDevFeatureCfg.ui64Features & ui64Feature) != 0;
+}
+
+IMG_BOOL RGXDeviceHasErnBrnPower(const void *hPrivate, IMG_UINT64 ui64ErnsBrns)
+{
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
+
+	return (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & ui64ErnsBrns) != 0;
+}
+
+IMG_UINT32 RGXGetDeviceSLCBanks(const void *hPrivate)
+{
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
+
+	return psDevInfo->sDevFeatureCfg.ui32SLCBanks;
+}
+
+IMG_UINT32 RGXGetDeviceSLCSize(const void *hPrivate)
+{
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
+
+	return psDevInfo->sDevFeatureCfg.ui32SLCSize;
+}
+
+IMG_UINT32 RGXGetDeviceCacheLineSize(const void *hPrivate)
+{
+	RGX_POWER_LAYER_PARAMS *psPowerParams;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_ASSERT(hPrivate != NULL);
+	psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
+	psDevInfo = psPowerParams->psDevInfo;
+
+	return psDevInfo->sDevFeatureCfg.ui32CacheLineSize;
+}
+
diff --git a/drivers/staging/imgtec/rogue/rgxlayer_km_impl.h b/drivers/staging/imgtec/rogue/rgxlayer_km_impl.h
index 2da616c..20812cf 100644
--- a/drivers/staging/imgtec/rogue/rgxlayer_km_impl.h
+++ b/drivers/staging/imgtec/rogue/rgxlayer_km_impl.h
@@ -50,7 +50,16 @@
 {
 	void *psDevInfo;
 	void *psDevConfig;
+#if defined(PDUMP)
+	IMG_UINT32 ui32PdumpFlags;
+#endif
+
 	IMG_DEV_PHYADDR sPCAddr;
+	IMG_DEV_PHYADDR sGPURegAddr;
+	IMG_DEV_PHYADDR sBootRemapAddr;
+	IMG_DEV_PHYADDR sCodeRemapAddr;
+	IMG_DEV_PHYADDR sDataRemapAddr;
+	IMG_DEV_PHYADDR sTrampolineRemapAddr;
 } RGX_POWER_LAYER_PARAMS;
 
 #endif /* !defined (__RGXLAYER_KM_IMPL_H__) */
diff --git a/drivers/staging/imgtec/rogue/rgxmem.c b/drivers/staging/imgtec/rogue/rgxmem.c
index e0b4d68..d8e0b94 100644
--- a/drivers/staging/imgtec/rogue/rgxmem.c
+++ b/drivers/staging/imgtec/rogue/rgxmem.c
@@ -51,11 +51,19 @@
 #include "rgx_fwif_km.h"
 #include "rgxfwutils.h"
 #include "pdump_km.h"
+#include "pdump_physmem.h"
+#include "pvr_notifier.h"
 #include "pvrsrv.h"
 #include "sync_internal.h"
 #include "rgx_memallocflags.h"
-
+#include "rgx_bvnc_defs_km.h"
+/*
+	FIXME:
+	For now just get global state, but what we really want is to do
+	this per memory context
+*/
 static IMG_UINT32 gui32CacheOpps = 0;
+/* FIXME: End */
 
 typedef struct _SERVER_MMU_CONTEXT_ {
 	DEVMEM_MEMDESC *psFWMemContextMemDesc;
@@ -66,11 +74,14 @@
 	PVRSRV_RGXDEV_INFO *psDevInfo;
 } SERVER_MMU_CONTEXT;
 
+
+
 void RGXMMUCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode,
 						   IMG_HANDLE hDeviceData,
 						   MMU_LEVEL eMMULevel,
 						   IMG_BOOL bUnmap)
 {
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
 	PVR_UNREFERENCED_PARAMETER(bUnmap);
 
 	switch (eMMULevel)
@@ -80,7 +91,10 @@
 		case MMU_LEVEL_2:	gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_PD;
 							break;
 		case MMU_LEVEL_1:	gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_PT;
-							gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_TLB;
+							if(!(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SLC_VIVT_BIT_MASK))
+							{
+								gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_TLB;
+							}
 							break;
 		default:
 							PVR_ASSERT(0);
@@ -88,69 +102,24 @@
 	}
 }
 
-PVRSRV_ERROR RGXSLCCacheInvalidateRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
-									PMR *psPmr)
+PVRSRV_ERROR RGXMMUCacheInvalidateKick(PVRSRV_DEVICE_NODE *psDevInfo,
+                                       IMG_UINT32 *pui32MMUInvalidateUpdate,
+                                       IMG_BOOL bInterrupt)
 {
-	RGXFWIF_KCCB_CMD sFlushInvalCmd;
-	IMG_UINT32 ulPMRFlags;
-	IMG_UINT32 ui32DeviceCacheFlags;
-	PVRSRV_ERROR eError = PVRSRV_OK;
+	PVRSRV_ERROR eError;
 
-	PVR_ASSERT(psDeviceNode);
-
-	/* In DEINIT state, we stop scheduling SLC flush commands, because we don't know in what state the firmware is.
-	 * Anyway, if we are in DEINIT state, we don't care anymore about FW memory consistency
-	 */
-	if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_DEINIT)
-	{
-
-		/* get the PMR's caching flags */
-		ulPMRFlags = PMR_Flags(psPmr);
-
-		ui32DeviceCacheFlags = DevmemDeviceCacheMode(ulPMRFlags);
-
-		/* Schedule a SLC flush and invalidate if
-		 * - the memory is cached.
-		 * - we can't get the caching attributes (by precaution).
-		 */
-		if ((ui32DeviceCacheFlags == PVRSRV_MEMALLOCFLAG_GPU_CACHED) || (eError != PVRSRV_OK))
-		{
-			/* Schedule the SLC flush command ... */
-#if defined(PDUMP)
-			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
-#endif
-			sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
-			sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
-			sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bDMContext = IMG_FALSE;
-			sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = 0;
-			sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
-
-			eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
-												RGXFWIF_DM_GP,
-												&sFlushInvalCmd,
-												sizeof(sFlushInvalCmd),
-												IMG_TRUE);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,"RGXSLCCacheInvalidateRequest: Failed to schedule SLC flush command with error (%u)", eError));
-			}
-			else
-			{
-				/* Wait for the SLC flush to complete */
-				eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
-				if (eError != PVRSRV_OK)
-				{
-					PVR_DPF((PVR_DBG_ERROR,"RGXSLCCacheInvalidateRequest: SLC flush and invalidate aborted with error (%u)", eError));
-				}
-			}
-		}
-	}
+	eError = RGXPreKickCacheCommand(psDevInfo->pvDevice,
+	                                RGXFWIF_DM_GP,
+	                                pui32MMUInvalidateUpdate,
+	                                bInterrupt);
 
 	return eError;
 }
 
-
-PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo, RGXFWIF_DM eDM)
+PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                    RGXFWIF_DM eDM,
+                                    IMG_UINT32 *pui32MMUInvalidateUpdate,
+                                    IMG_BOOL bInterrupt)
 {
 	PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
 	RGXFWIF_KCCB_CMD sFlushCmd;
@@ -161,16 +130,9 @@
 		goto _PVRSRVPowerLock_Exit;
 	}
 
-	sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_MMUCACHE;
-	/* Set which memory context this command is for (all ctxs for now) */
-	gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL;
-#if 0
-	sFlushCmd.uCmdData.sMMUCacheData.psMemoryContext = ???
-#endif
-
 	/* PVRSRVPowerLock guarantees atomicity between commands and global variables consistency.
 	 * This is helpful in a scenario with several applications allocating resources. */
-	eError = PVRSRVPowerLock();
+	eError = PVRSRVPowerLock(psDeviceNode);
 
 	if (eError != PVRSRV_OK)
 	{
@@ -179,8 +141,33 @@
 		goto _PVRSRVPowerLock_Exit;
 	}
 
+	*pui32MMUInvalidateUpdate = psDeviceNode->ui32NextMMUInvalidateUpdate;
+
+	/* Setup cmd and add the device nodes sync object */
+	sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_MMUCACHE;
+	sFlushCmd.uCmdData.sMMUCacheData.ui32MMUCacheSyncUpdateValue = psDeviceNode->ui32NextMMUInvalidateUpdate;
+	SyncPrimGetFirmwareAddr(psDeviceNode->psMMUCacheSyncPrim,
+	                        &sFlushCmd.uCmdData.sMMUCacheData.sMMUCacheSync.ui32Addr);
+
+	/* Set the update value for the next kick */
+	psDeviceNode->ui32NextMMUInvalidateUpdate++;
+
+	/* Set which memory context this command is for (all ctxs for now) */
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SLC_VIVT_BIT_MASK)
+	{
+		gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL;
+	}
+	/* Indicate the firmware should signal command completion to the host */
+	if(bInterrupt)
+	{
+		gui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_INTERRUPT;
+	}
+#if 0
+	sFlushCmd.uCmdData.sMMUCacheData.psMemoryContext = ???
+#endif
+
 	PDUMPPOWCMDSTART();
-	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
 										 PVRSRV_DEV_POWER_STATE_ON,
 										 IMG_FALSE);
 	PDUMPPOWCMDEND();
@@ -217,7 +204,7 @@
 	}
 
 _PVRSRVSetDevicePowerStateKM_Exit:
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 _PVRSRVPowerLock_Exit:
 	return eError;
@@ -285,12 +272,12 @@
 	/*
 	 * Release the page catalogue address acquired in RGXRegisterMemoryContext().
 	 */
-	MMU_ReleaseBaseAddr(NULL);
+	MMU_ReleaseBaseAddr(NULL /* FIXME */);
 	
 	/*
 	 * Free the firmware memory context.
 	 */
-	DevmemFwFree(psServerMMUContext->psFWMemContextMemDesc);
+	DevmemFwFree(psDevInfo, psServerMMUContext->psFWMemContextMemDesc);
 
 	OSFreeMem(psServerMMUContext);
 }
@@ -350,6 +337,7 @@
 			application.
 		*/
 		PDUMPCOMMENT("Allocate RGX firmware memory context");
+		/* FIXME: why cache-consistent? */
 		eError = DevmemFwAllocate(psDevInfo,
 								sizeof(*psFWMemContext),
 								uiFWMemContextMemAllocFlags,
@@ -399,16 +387,18 @@
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 {
 		IMG_UINT32 ui32OSid = 0, ui32OSidReg = 0;
+        IMG_BOOL   bOSidAxiProt;
 
-		MMU_GetOSids(psMMUContext, &ui32OSid, &ui32OSidReg);
+        MMU_GetOSids(psMMUContext, &ui32OSid, &ui32OSidReg, &bOSidAxiProt);
 
-		psFWMemContext->ui32OSid = ui32OSidReg;
+        psFWMemContext->ui32OSid     = ui32OSidReg;
+        psFWMemContext->bOSidAxiProt = bOSidAxiProt;
 }
 #endif
 
 #if defined(PDUMP)
 		{
-			IMG_CHAR			aszName[PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT];
+			IMG_CHAR			aszName[PHYSMEM_PDUMP_MEMSPNAME_SYMB_ADDR_MAX_LENGTH];
 			IMG_DEVMEM_OFFSET_T uiOffset = 0;
 
 			/*
@@ -423,7 +413,7 @@
 			eError = DevmemPDumpPageCatBaseToSAddr(psFWMemContextMemDesc, 
 												   &uiOffset, 
 												   aszName, 
-												   PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT);
+												   PHYSMEM_PDUMP_MEMSPNAME_SYMB_ADDR_MAX_LENGTH);
 
 			if (eError != PVRSRV_OK)
 			{
@@ -496,7 +486,7 @@
 fail_acquire_base_addr:
 	/* Done before jumping to the fail point as the release is done before exit */
 fail_acquire_cpu_addr:
-	DevmemFwFree(psServerMMUContext->psFWMemContextMemDesc);
+	DevmemFwFree(psDevInfo, psServerMMUContext->psFWMemContextMemDesc);
 fail_alloc_fw_ctx:
 	OSFreeMem(psServerMMUContext);
 fail_alloc_server_ctx:
diff --git a/drivers/staging/imgtec/rogue/rgxmem.h b/drivers/staging/imgtec/rogue/rgxmem.h
index 2669a8c..0575616 100644
--- a/drivers/staging/imgtec/rogue/rgxmem.h
+++ b/drivers/staging/imgtec/rogue/rgxmem.h
@@ -61,6 +61,9 @@
 	IMG_BOOL bUnregistered;
 } RGXMEM_PROCESS_INFO;
 
+IMG_DEV_PHYADDR GetPC(MMU_CONTEXT * psContext);
+	
+/* FIXME: SyncPrim should be stored on the memory context */
 void RGXMMUSyncPrimAlloc(PVRSRV_DEVICE_NODE *psDeviceNode);
 void RGXMMUSyncPrimFree(void);
 
@@ -69,10 +72,14 @@
 						   MMU_LEVEL eMMULevel,
 						   IMG_BOOL bUnmap);
 
-PVRSRV_ERROR RGXSLCCacheInvalidateRequest(PVRSRV_DEVICE_NODE	*psDeviceNode,
-									PMR *psPmr);
+PVRSRV_ERROR RGXMMUCacheInvalidateKick(PVRSRV_DEVICE_NODE *psDevInfo,
+                                       IMG_UINT32 *pui32NextMMUInvalidateUpdate,
+                                       IMG_BOOL bInterrupt);
 
-PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo, RGXFWIF_DM eDM);
+PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                    RGXFWIF_DM eDM,
+                                    IMG_UINT32 *pui32MMUInvalidateUpdate,
+                                    IMG_BOOL bInterrupt);
 
 void RGXUnregisterMemoryContext(IMG_HANDLE hPrivData);
 PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE	*psDeviceNode,
diff --git a/drivers/staging/imgtec/rogue/rgxmipsmmuinit.c b/drivers/staging/imgtec/rogue/rgxmipsmmuinit.c
new file mode 100644
index 0000000..bd9fd1c
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxmipsmmuinit.c
@@ -0,0 +1,920 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific MMU initialisation
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include "rgxmipsmmuinit.h"
+
+#include "device.h"
+#include "img_types.h"
+#include "mmu_common.h"
+#include "pdump_mmu.h"
+#include "rgxheapconfig.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "rgx_memallocflags.h"
+#include "pdump_km.h"
+#include "rgx_mips.h"
+
+/*
+ * Bits of PT, PD and PC not involving addresses
+ */
+
+/* Position of the MIPS PT entry indicating entry validity */
+#define RGX_MIPS_MMUCTRL_PTE_PROTMASK	   (RGX_MIPS_MMUCTRL_PT_DATA_VALID_EN | \
+                                            RGX_MIPS_MMUCTRL_PT_DATA_GLOBAL_EN | \
+                                            RGX_MIPS_MMUCTRL_PT_DATA_WRITABLE_EN | \
+                                            ~RGX_MIPS_MMUCTRL_PT_CACHE_POLICY_CLRMSK);
+/* Currently there is no page directory for MIPS MMU */
+#define RGX_MIPS_MMUCTRL_PDE_PROTMASK        0
+/* Currently there is no page catalog for MIPS MMU */
+#define RGX_MIPS_MMUCTRL_PCE_PROTMASK	     0
+
+
+static MMU_PxE_CONFIG sRGXMMUPCEConfig;
+static MMU_DEVVADDR_CONFIG sRGXMMUTopLevelDevVAddrConfig;
+
+
+/*
+ *
+ *  Configuration for heaps with 4kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_4KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_4KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_4KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig4KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 16kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_16KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_16KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_16KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig16KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 64kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_64KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_64KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_64KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig64KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 256kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_256KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_256KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_256KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig256KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 1MB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_1MBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_1MBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_1MBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig1MB;
+
+
+/*
+ *
+ *  Configuration for heaps with 2MB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_2MBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_2MBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_2MBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig2MB;
+
+
+/* Forward declaration of protection bits derivation functions, for
+   the following structure */
+static IMG_UINT64 RGXDerivePCEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static IMG_UINT32 RGXDerivePCEProt4(IMG_UINT32 uiProtFlags);
+static IMG_UINT64 RGXDerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static IMG_UINT32 RGXDerivePDEProt4(IMG_UINT32 uiProtFlags);
+static IMG_UINT64 RGXDerivePTEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static IMG_UINT32 RGXDerivePTEProt4(IMG_UINT32 uiProtFlags);
+
+static PVRSRV_ERROR RGXGetPageSizeConfigCB(IMG_UINT32 uiLog2DataPageSize,
+										   const MMU_PxE_CONFIG **ppsMMUPDEConfig,
+										   const MMU_PxE_CONFIG **ppsMMUPTEConfig,
+										   const MMU_DEVVADDR_CONFIG **ppsMMUDevVAddrConfig,
+										   IMG_HANDLE *phPriv);
+
+static PVRSRV_ERROR RGXPutPageSizeConfigCB(IMG_HANDLE hPriv);
+
+static PVRSRV_ERROR RGXGetPageSizeFromPDE4(IMG_UINT32 ui32PDE, IMG_UINT32 *pui32Log2PageSize);
+static PVRSRV_ERROR RGXGetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32Log2PageSize);
+
+static MMU_DEVICEATTRIBS sRGXMMUDeviceAttributes;
+
+PVRSRV_ERROR RGXMipsMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	sRGXMMUDeviceAttributes.pszMMUPxPDumpMemSpaceName =
+		PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL]);
+
+	/*
+	 * Setup sRGXMMUPCEConfig, no PC in MIPS MMU currently
+	 */
+	sRGXMMUPCEConfig.uiBytesPerEntry = 0; /* 32 bit entries */
+	sRGXMMUPCEConfig.uiAddrMask = 0; /* Mask to get significant address bits of PC entry */
+
+	sRGXMMUPCEConfig.uiAddrShift = 0; /* Shift this many bits to get PD address in PC entry */
+	sRGXMMUPCEConfig.uiAddrLog2Align = (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE; /* Alignment of PD AND PC */
+
+	sRGXMMUPCEConfig.uiProtMask = RGX_MIPS_MMUCTRL_PCE_PROTMASK; //Mask to get the status bits of the PC */
+	sRGXMMUPCEConfig.uiProtShift = 0; /* Shift this many bits to have status bits starting with bit 0 */
+
+	sRGXMMUPCEConfig.uiValidEnMask = RGX_MIPS_MMUCTRL_PC_DATA_VALID_EN; /* Mask to get entry valid bit of the PC */
+	sRGXMMUPCEConfig.uiValidEnShift = RGX_MIPS_MMUCTRL_PC_DATA_VALID_SHIFT; /* Shift this many bits to have entry valid bit starting with bit 0 */
+
+	/*
+	 *  Setup sRGXMMUTopLevelDevVAddrConfig
+	 */
+	sRGXMMUTopLevelDevVAddrConfig.uiPCIndexMask = 0; /* Get the PC address bits from a 40 bit virt. address (in a 64bit UINT) */
+	sRGXMMUTopLevelDevVAddrConfig.uiPCIndexShift = 0;
+	sRGXMMUTopLevelDevVAddrConfig.uiNumEntriesPC = 0;
+
+	sRGXMMUTopLevelDevVAddrConfig.uiPDIndexMask = 0; /* Get the PD address bits from a 40 bit virt. address (in a 64bit UINT) */
+	sRGXMMUTopLevelDevVAddrConfig.uiPDIndexShift = 0;
+	sRGXMMUTopLevelDevVAddrConfig.uiNumEntriesPD = 0;
+
+	sRGXMMUTopLevelDevVAddrConfig.uiPTIndexMask = IMG_UINT64_C(0xfffffff000); /* Get the PT address bits from a 40 bit virt. address (in a 64bit UINT) */
+	sRGXMMUTopLevelDevVAddrConfig.uiPTIndexShift = (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE;
+	sRGXMMUTopLevelDevVAddrConfig.uiNumEntriesPT = RGX_FIRMWARE_HEAP_SIZE >> sRGXMMUTopLevelDevVAddrConfig.uiPTIndexShift;
+
+/*
+ *
+ *  Configuration for heaps with 4kB Data-Page size
+ *
+ */
+
+	/*
+	 * Setup sRGXMMUPDEConfig_4KBDP. No PD in MIPS MMU currently
+	 */
+	sRGXMMUPDEConfig_4KBDP.uiBytesPerEntry = 0;
+
+	/* No PD used for MIPS */
+	sRGXMMUPDEConfig_4KBDP.uiAddrMask = 0;
+	sRGXMMUPDEConfig_4KBDP.uiAddrShift = 0;
+	sRGXMMUPDEConfig_4KBDP.uiAddrLog2Align = (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE;
+
+	sRGXMMUPDEConfig_4KBDP.uiVarCtrlMask = IMG_UINT64_C(0x0);
+	sRGXMMUPDEConfig_4KBDP.uiVarCtrlShift = 0;
+
+	sRGXMMUPDEConfig_4KBDP.uiProtMask = RGX_MIPS_MMUCTRL_PDE_PROTMASK;
+	sRGXMMUPDEConfig_4KBDP.uiProtShift = 0;
+
+	sRGXMMUPDEConfig_4KBDP.uiValidEnMask = RGX_MIPS_MMUCTRL_PD_DATA_VALID_EN;
+	sRGXMMUPDEConfig_4KBDP.uiValidEnShift = RGX_MIPS_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+	/*
+	 * Setup sRGXMMUPTEConfig_4KBDP.
+	 */
+	sRGXMMUPTEConfig_4KBDP.uiBytesPerEntry = 1 << RGXMIPSFW_LOG2_PTE_ENTRY_SIZE;
+
+	sRGXMMUPTEConfig_4KBDP.uiAddrMask = IMG_UINT64_C(0xffffffffc0);
+	sRGXMMUPTEConfig_4KBDP.uiAddrShift = RGX_MIPS_MMUCTRL_PT_PFN_SHIFT;
+	sRGXMMUPTEConfig_4KBDP.uiAddrLog2Align = (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE;
+
+	sRGXMMUPTEConfig_4KBDP.uiProtMask = RGX_MIPS_MMUCTRL_PTE_PROTMASK;
+	sRGXMMUPTEConfig_4KBDP.uiProtShift = 0;
+
+	sRGXMMUPTEConfig_4KBDP.uiValidEnMask = RGX_MIPS_MMUCTRL_PT_DATA_VALID_EN;
+	sRGXMMUPTEConfig_4KBDP.uiValidEnShift = RGX_MIPS_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+	/*
+	 * Setup sRGXMMUDevVAddrConfig_4KBDP
+	 */
+	sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexMask = 0;
+	sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexShift = 0;
+	sRGXMMUDevVAddrConfig_4KBDP.uiNumEntriesPC = 0;
+
+
+	sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexMask = 0;
+	sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexShift = 0;
+	sRGXMMUDevVAddrConfig_4KBDP.uiNumEntriesPD = 0;
+
+	sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexMask = ~RGX_MIPS_MMUCTRL_VADDR_PT_INDEX_CLRMSK;
+	sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexShift = RGX_MIPS_MMUCTRL_VADDR_PT_INDEX_SHIFT;
+	sRGXMMUDevVAddrConfig_4KBDP.uiNumEntriesPT = RGX_FIRMWARE_HEAP_SIZE >> sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexShift;
+
+
+	sRGXMMUDevVAddrConfig_4KBDP.uiPageOffsetMask = IMG_UINT64_C(0x0000000fff);
+	sRGXMMUDevVAddrConfig_4KBDP.uiPageOffsetShift = 0;
+	sRGXMMUDevVAddrConfig_4KBDP.uiOffsetInBytes = RGX_FIRMWARE_HEAP_BASE & IMG_UINT64_C(0x00ffffffff);
+
+	/*
+	 * Setup gsPageSizeConfig4KB
+	 */
+	gsPageSizeConfig4KB.psPDEConfig = &sRGXMMUPDEConfig_4KBDP;
+	gsPageSizeConfig4KB.psPTEConfig = &sRGXMMUPTEConfig_4KBDP;
+	gsPageSizeConfig4KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_4KBDP;
+	gsPageSizeConfig4KB.uiRefCount = 0;
+	gsPageSizeConfig4KB.uiMaxRefCount = 0;
+
+
+/*
+ *
+ *  Configuration for heaps with 16kB Data-Page size
+ *
+ */
+
+	/*
+	 * Setup sRGXMMUPDEConfig_16KBDP
+	 */
+	sRGXMMUPDEConfig_16KBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPDEConfig_16KBDP.uiAddrMask = 0;
+	sRGXMMUPDEConfig_16KBDP.uiAddrShift = 0; /* These are for a page directory ENTRY, meaning the address of a PT cropped to suit the PD */
+	sRGXMMUPDEConfig_16KBDP.uiAddrLog2Align = 0; /* Alignment of the page tables NOT directories */
+
+	sRGXMMUPDEConfig_16KBDP.uiVarCtrlMask = 0;
+	sRGXMMUPDEConfig_16KBDP.uiVarCtrlShift = 0;
+
+	sRGXMMUPDEConfig_16KBDP.uiProtMask = 0;
+	sRGXMMUPDEConfig_16KBDP.uiProtShift = 0;
+
+	sRGXMMUPDEConfig_16KBDP.uiValidEnMask = 0;
+	sRGXMMUPDEConfig_16KBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUPTEConfig_16KBDP. Not supported yet
+	 */
+	sRGXMMUPTEConfig_16KBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPTEConfig_16KBDP.uiAddrMask = 0;
+	sRGXMMUPTEConfig_16KBDP.uiAddrShift = 0; /* These are for a page table ENTRY, meaning the address of a PAGE cropped to suit the PD */
+	sRGXMMUPTEConfig_16KBDP.uiAddrLog2Align = 0; /* Alignment of the pages NOT tables */
+
+	sRGXMMUPTEConfig_16KBDP.uiProtMask = 0;
+	sRGXMMUPTEConfig_16KBDP.uiProtShift = 0;
+
+	sRGXMMUPTEConfig_16KBDP.uiValidEnMask = 0;
+	sRGXMMUPTEConfig_16KBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUDevVAddrConfig_16KBDP
+	 */
+	sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexMask = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexShift = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiNumEntriesPC = 0;
+
+	sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexMask = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexShift = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiNumEntriesPD= 0;
+
+	sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexMask = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexShift = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiNumEntriesPT = 0;
+
+	sRGXMMUDevVAddrConfig_16KBDP.uiPageOffsetMask = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiPageOffsetShift = 0;
+	sRGXMMUDevVAddrConfig_16KBDP.uiOffsetInBytes = 0;
+
+	/*
+	 * Setup gsPageSizeConfig16KB
+	 */
+	gsPageSizeConfig16KB.psPDEConfig = &sRGXMMUPDEConfig_16KBDP;
+	gsPageSizeConfig16KB.psPTEConfig = &sRGXMMUPTEConfig_16KBDP;
+	gsPageSizeConfig16KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_16KBDP;
+	gsPageSizeConfig16KB.uiRefCount = 0;
+	gsPageSizeConfig16KB.uiMaxRefCount = 0;
+
+
+/*
+ *
+ *  Configuration for heaps with 64kB Data-Page size. Not supported yet
+ *
+ */
+
+	/*
+	 * Setup sRGXMMUPDEConfig_64KBDP
+	 */
+	sRGXMMUPDEConfig_64KBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPDEConfig_64KBDP.uiAddrMask = 0;
+	sRGXMMUPDEConfig_64KBDP.uiAddrShift = 0;
+	sRGXMMUPDEConfig_64KBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPDEConfig_64KBDP.uiVarCtrlMask = 0;
+	sRGXMMUPDEConfig_64KBDP.uiVarCtrlShift = 0;
+
+	sRGXMMUPDEConfig_64KBDP.uiProtMask = 0;
+	sRGXMMUPDEConfig_64KBDP.uiProtShift = 0;
+
+	sRGXMMUPDEConfig_64KBDP.uiValidEnMask = 0;
+	sRGXMMUPDEConfig_64KBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUPTEConfig_64KBDP.
+	 *
+	 */
+	sRGXMMUPTEConfig_64KBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPTEConfig_64KBDP.uiAddrMask = 0;
+	sRGXMMUPTEConfig_64KBDP.uiAddrShift = 0;
+	sRGXMMUPTEConfig_64KBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPTEConfig_64KBDP.uiProtMask = 0;
+	sRGXMMUPTEConfig_64KBDP.uiProtShift = 0;
+
+	sRGXMMUPTEConfig_64KBDP.uiValidEnMask = 0;
+	sRGXMMUPTEConfig_64KBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUDevVAddrConfig_64KBDP.
+	 */
+	sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexMask = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexShift = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiNumEntriesPC = 0;
+
+	sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexMask = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexShift = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiNumEntriesPD = 0;
+
+	sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexMask = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexShift = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiNumEntriesPT = 0;
+
+	sRGXMMUDevVAddrConfig_64KBDP.uiPageOffsetMask = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiPageOffsetShift = 0;
+	sRGXMMUDevVAddrConfig_64KBDP.uiOffsetInBytes = 0;
+
+	/*
+	 * Setup gsPageSizeConfig64KB.
+	 */
+	gsPageSizeConfig64KB.psPDEConfig = &sRGXMMUPDEConfig_64KBDP;
+	gsPageSizeConfig64KB.psPTEConfig = &sRGXMMUPTEConfig_64KBDP;
+	gsPageSizeConfig64KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_64KBDP;
+	gsPageSizeConfig64KB.uiRefCount = 0;
+	gsPageSizeConfig64KB.uiMaxRefCount = 0;
+
+
+/*
+ *
+ *  Configuration for heaps with 256kB Data-Page size. Not supported yet
+ *
+ */
+
+	/*
+	 * Setup sRGXMMUPDEConfig_256KBDP
+	 */
+	sRGXMMUPDEConfig_256KBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPDEConfig_256KBDP.uiAddrMask = 0;
+	sRGXMMUPDEConfig_256KBDP.uiAddrShift = 0;
+	sRGXMMUPDEConfig_256KBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPDEConfig_256KBDP.uiVarCtrlMask = 0;
+	sRGXMMUPDEConfig_256KBDP.uiVarCtrlShift = 0;
+
+	sRGXMMUPDEConfig_256KBDP.uiProtMask = 0;
+	sRGXMMUPDEConfig_256KBDP.uiProtShift = 0;
+
+	sRGXMMUPDEConfig_256KBDP.uiValidEnMask = 0;
+	sRGXMMUPDEConfig_256KBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup MMU_PxE_CONFIG sRGXMMUPTEConfig_256KBDP
+	 */
+	sRGXMMUPTEConfig_256KBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPTEConfig_256KBDP.uiAddrMask = 0;
+	sRGXMMUPTEConfig_256KBDP.uiAddrShift = 0;
+	sRGXMMUPTEConfig_256KBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPTEConfig_256KBDP.uiProtMask = 0;
+	sRGXMMUPTEConfig_256KBDP.uiProtShift = 0;
+
+	sRGXMMUPTEConfig_256KBDP.uiValidEnMask = 0;
+	sRGXMMUPTEConfig_256KBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUDevVAddrConfig_256KBDP
+	 */
+	sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexMask = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexShift = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiNumEntriesPC = 0;
+
+	sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexMask = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexShift = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiNumEntriesPD = 0;
+
+	sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexMask = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexShift = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiNumEntriesPT = 0;
+
+	sRGXMMUDevVAddrConfig_256KBDP.uiPageOffsetMask = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiPageOffsetShift = 0;
+	sRGXMMUDevVAddrConfig_256KBDP.uiOffsetInBytes = 0;
+
+	/*
+	 * Setup gsPageSizeConfig256KB
+	 */
+	gsPageSizeConfig256KB.psPDEConfig = &sRGXMMUPDEConfig_256KBDP;
+	gsPageSizeConfig256KB.psPTEConfig = &sRGXMMUPTEConfig_256KBDP;
+	gsPageSizeConfig256KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_256KBDP;
+	gsPageSizeConfig256KB.uiRefCount = 0;
+	gsPageSizeConfig256KB.uiMaxRefCount = 0;
+
+	/*
+	 * Setup sRGXMMUPDEConfig_1MBDP.  Not supported yet
+	 */
+	sRGXMMUPDEConfig_1MBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPDEConfig_1MBDP.uiAddrMask = 0;
+	sRGXMMUPDEConfig_1MBDP.uiAddrShift = 0;
+	sRGXMMUPDEConfig_1MBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPDEConfig_1MBDP.uiVarCtrlMask = 0;
+	sRGXMMUPDEConfig_1MBDP.uiVarCtrlShift = 0;
+
+	sRGXMMUPDEConfig_1MBDP.uiProtMask = 0;
+	sRGXMMUPDEConfig_1MBDP.uiProtShift = 0;
+
+	sRGXMMUPDEConfig_1MBDP.uiValidEnMask = 0;
+	sRGXMMUPDEConfig_1MBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUPTEConfig_1MBDP
+	 */
+	sRGXMMUPTEConfig_1MBDP.uiBytesPerEntry = 8;
+
+	sRGXMMUPTEConfig_1MBDP.uiAddrMask = 0;
+	sRGXMMUPTEConfig_1MBDP.uiAddrShift = 0;
+	sRGXMMUPTEConfig_1MBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPTEConfig_1MBDP.uiProtMask = 0;
+	sRGXMMUPTEConfig_1MBDP.uiProtShift = 0;
+
+	sRGXMMUPTEConfig_1MBDP.uiValidEnMask = 0;
+	sRGXMMUPTEConfig_1MBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUDevVAddrConfig_1MBDP
+	 */
+	sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexMask = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexShift = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiNumEntriesPC = 0;
+
+	sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexMask = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexShift = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiNumEntriesPD = 0;
+
+	sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexMask = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexShift = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiNumEntriesPT = 0;
+
+	sRGXMMUDevVAddrConfig_1MBDP.uiPageOffsetMask = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiPageOffsetShift = 0;
+	sRGXMMUDevVAddrConfig_1MBDP.uiOffsetInBytes = 0;
+
+	/*
+	 * Setup gsPageSizeConfig1MB
+	 */
+	gsPageSizeConfig1MB.psPDEConfig = &sRGXMMUPDEConfig_1MBDP;
+	gsPageSizeConfig1MB.psPTEConfig = &sRGXMMUPTEConfig_1MBDP;
+	gsPageSizeConfig1MB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_1MBDP;
+	gsPageSizeConfig1MB.uiRefCount = 0;
+	gsPageSizeConfig1MB.uiMaxRefCount = 0;
+
+	/*
+	 * Setup sRGXMMUPDEConfig_2MBDP. Not supported yet
+	 */
+	sRGXMMUPDEConfig_2MBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPDEConfig_2MBDP.uiAddrMask = 0;
+	sRGXMMUPDEConfig_2MBDP.uiAddrShift = 0;
+	sRGXMMUPDEConfig_2MBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPDEConfig_2MBDP.uiVarCtrlMask = 0;
+	sRGXMMUPDEConfig_2MBDP.uiVarCtrlShift = 0;
+
+	sRGXMMUPDEConfig_2MBDP.uiProtMask = 0;
+	sRGXMMUPDEConfig_2MBDP.uiProtShift = 0;
+
+	sRGXMMUPDEConfig_2MBDP.uiValidEnMask = 0;
+	sRGXMMUPDEConfig_2MBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUPTEConfig_2MBDP
+	 */
+	sRGXMMUPTEConfig_2MBDP.uiBytesPerEntry = 0;
+
+	sRGXMMUPTEConfig_2MBDP.uiAddrMask = 0;
+	sRGXMMUPTEConfig_2MBDP.uiAddrShift = 0;
+	sRGXMMUPTEConfig_2MBDP.uiAddrLog2Align = 0;
+
+	sRGXMMUPTEConfig_2MBDP.uiProtMask = 0;
+	sRGXMMUPTEConfig_2MBDP.uiProtShift = 0;
+
+	sRGXMMUPTEConfig_2MBDP.uiValidEnMask = 0;
+	sRGXMMUPTEConfig_2MBDP.uiValidEnShift = 0;
+
+	/*
+	 * Setup sRGXMMUDevVAddrConfig_2MBDP
+	 */
+	sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexMask = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexShift = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiNumEntriesPC = 0;
+
+	sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexMask = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexShift = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiNumEntriesPD = 0;
+
+	sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexMask = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexShift = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiNumEntriesPT = 0;
+
+	sRGXMMUDevVAddrConfig_2MBDP.uiPageOffsetMask = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiPageOffsetShift = 0;
+	sRGXMMUDevVAddrConfig_2MBDP.uiOffsetInBytes = 0;
+
+	/*
+	 * Setup gsPageSizeConfig2MB
+	 */
+	gsPageSizeConfig2MB.psPDEConfig = &sRGXMMUPDEConfig_2MBDP;
+	gsPageSizeConfig2MB.psPTEConfig = &sRGXMMUPTEConfig_2MBDP;
+	gsPageSizeConfig2MB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_2MBDP;
+	gsPageSizeConfig2MB.uiRefCount = 0;
+	gsPageSizeConfig2MB.uiMaxRefCount = 0;
+
+	/*
+	 * Setup sRGXMMUDeviceAttributes
+	 */
+	sRGXMMUDeviceAttributes.eMMUType = PDUMP_MMU_TYPE_MIPS_MICROAPTIV;
+	sRGXMMUDeviceAttributes.eTopLevel = MMU_LEVEL_1;
+	/* The page table fits in one big physical page as big as the page table itself */
+	sRGXMMUDeviceAttributes.ui32BaseAlign = RGXMIPSFW_LOG2_PAGETABLE_PAGE_SIZE;
+	/* The base configuration is set to 4kB pages*/
+	sRGXMMUDeviceAttributes.psBaseConfig = &sRGXMMUPTEConfig_4KBDP;
+	sRGXMMUDeviceAttributes.psTopLevelDevVAddrConfig = &sRGXMMUTopLevelDevVAddrConfig;
+
+	/* Functions for deriving page table/dir/cat protection bits */
+	sRGXMMUDeviceAttributes.pfnDerivePCEProt8 = RGXDerivePCEProt8;
+	sRGXMMUDeviceAttributes.pfnDerivePCEProt4 = RGXDerivePCEProt4;
+	sRGXMMUDeviceAttributes.pfnDerivePDEProt8 = RGXDerivePDEProt8;
+	sRGXMMUDeviceAttributes.pfnDerivePDEProt4 = RGXDerivePDEProt4;
+	sRGXMMUDeviceAttributes.pfnDerivePTEProt8 = RGXDerivePTEProt8;
+	sRGXMMUDeviceAttributes.pfnDerivePTEProt4 = RGXDerivePTEProt4;
+
+	/* Functions for establishing configurations for PDE/PTE/DEVVADDR
+	   on per-heap basis */
+	sRGXMMUDeviceAttributes.pfnGetPageSizeConfiguration = RGXGetPageSizeConfigCB;
+	sRGXMMUDeviceAttributes.pfnPutPageSizeConfiguration = RGXPutPageSizeConfigCB;
+
+	sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE4 = RGXGetPageSizeFromPDE4;
+	sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE8 = RGXGetPageSizeFromPDE8;
+
+	psDeviceNode->psFirmwareMMUDevAttrs = &sRGXMMUDeviceAttributes;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXMipsMMUInit_Unregister(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+
+	eError = PVRSRV_OK;
+
+#if defined(PDUMP)
+	psDeviceNode->pfnMMUGetContextID = NULL;
+#endif
+
+	psDeviceNode->psFirmwareMMUDevAttrs = NULL;
+
+#if defined(DEBUG)
+	PVR_DPF((PVR_DBG_MESSAGE, "Variable Page Size Heap Stats:"));
+	PVR_DPF((PVR_DBG_MESSAGE, "Max 4K page heaps: %d",
+			 gsPageSizeConfig4KB.uiMaxRefCount));
+	PVR_DPF((PVR_DBG_VERBOSE, "Current 4K page heaps (should be 0): %d",
+			 gsPageSizeConfig4KB.uiRefCount));
+	PVR_DPF((PVR_DBG_MESSAGE, "Max 16K page heaps: %d",
+			 gsPageSizeConfig16KB.uiMaxRefCount));
+	PVR_DPF((PVR_DBG_VERBOSE, "Current 16K page heaps (should be 0): %d",
+			 gsPageSizeConfig16KB.uiRefCount));
+	PVR_DPF((PVR_DBG_MESSAGE, "Max 64K page heaps: %d",
+			 gsPageSizeConfig64KB.uiMaxRefCount));
+	PVR_DPF((PVR_DBG_VERBOSE, "Current 64K page heaps (should be 0): %d",
+			 gsPageSizeConfig64KB.uiRefCount));
+	PVR_DPF((PVR_DBG_MESSAGE, "Max 256K page heaps: %d",
+			 gsPageSizeConfig256KB.uiMaxRefCount));
+	PVR_DPF((PVR_DBG_VERBOSE, "Current 256K page heaps (should be 0): %d",
+			 gsPageSizeConfig256KB.uiRefCount));
+	PVR_DPF((PVR_DBG_MESSAGE, "Max 1M page heaps: %d",
+			 gsPageSizeConfig1MB.uiMaxRefCount));
+	PVR_DPF((PVR_DBG_VERBOSE, "Current 1M page heaps (should be 0): %d",
+			 gsPageSizeConfig1MB.uiRefCount));
+	PVR_DPF((PVR_DBG_MESSAGE, "Max 2M page heaps: %d",
+			 gsPageSizeConfig2MB.uiMaxRefCount));
+	PVR_DPF((PVR_DBG_VERBOSE, "Current 2M page heaps (should be 0): %d",
+			 gsPageSizeConfig2MB.uiRefCount));
+#endif
+	if (gsPageSizeConfig4KB.uiRefCount > 0 ||
+		gsPageSizeConfig16KB.uiRefCount > 0 ||
+		gsPageSizeConfig64KB.uiRefCount > 0 ||
+		gsPageSizeConfig256KB.uiRefCount > 0 ||
+		gsPageSizeConfig1MB.uiRefCount > 0 ||
+		gsPageSizeConfig2MB.uiRefCount > 0
+		)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXMMUInit_Unregister: Unbalanced MMU API Usage (Internal error)"));
+	}
+
+	return eError;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePCEProt4
+@Description    calculate the PCE protection flags based on a 4 byte entry
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT32 RGXDerivePCEProt4(IMG_UINT32 uiProtFlags)
+{
+	PVR_DPF((PVR_DBG_ERROR, "Page Catalog not supported on MIPS MMU"));
+	return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePCEProt8
+@Description    calculate the PCE protection flags based on an 8 byte entry
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT64 RGXDerivePCEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+	PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+	PVR_UNREFERENCED_PARAMETER(uiLog2DataPageSize);
+
+	PVR_DPF((PVR_DBG_ERROR, "Page Catalog not supported on MIPS MMU"));
+	return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePDEProt4
+@Description    derive the PDE protection flags based on a 4 byte entry
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT32 RGXDerivePDEProt4(IMG_UINT32 uiProtFlags)
+{
+	PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+	PVR_DPF((PVR_DBG_ERROR, "Page Directory not supported on MIPS MMU"));
+	return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePDEProt8
+@Description    derive the PDE protection flags based on an 8 byte entry
+
+@Input          uiLog2DataPageSize The log2 of the required page size.
+				E.g, for 4KiB pages, this parameter must be 12.
+				For 2MiB pages, it must be set to 21.
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT64 RGXDerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+	PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+	PVR_DPF((PVR_DBG_ERROR, "Page Directory not supported on MIPS MMU"));
+	return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePTEProt4
+@Description    calculate the PTE protection flags based on a 4 byte entry
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT32 RGXDerivePTEProt4(IMG_UINT32 uiProtFlags)
+{
+	IMG_UINT32 ui32MMUFlags = 0;
+
+	if(((MMU_PROTFLAGS_READABLE|MMU_PROTFLAGS_WRITEABLE) & uiProtFlags) == (MMU_PROTFLAGS_READABLE|MMU_PROTFLAGS_WRITEABLE))
+	{
+		/* read/write */
+		ui32MMUFlags |= RGX_MIPS_MMUCTRL_PT_DATA_WRITABLE_EN;
+	}
+	else if(MMU_PROTFLAGS_READABLE & uiProtFlags)
+	{
+		/* read only */
+	}
+	else if(MMU_PROTFLAGS_WRITEABLE & uiProtFlags)
+	{
+		/* write only */
+		ui32MMUFlags |= RGX_MIPS_MMUCTRL_PT_DATA_READ_INHIBIT_EN;
+	}
+	else if ((MMU_PROTFLAGS_INVALID & uiProtFlags) == 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXDerivePTEProt4: neither read nor write specified..."));
+	}
+
+	/* cache coherency */
+	if(MMU_PROTFLAGS_CACHE_COHERENT & uiProtFlags)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXDerivePTEProt4: cache coherency not supported for MIPS caches"));
+	}
+
+	/* cache setup */
+	if ((MMU_PROTFLAGS_CACHED & uiProtFlags) == 0)
+	{
+		ui32MMUFlags |= (RGX_MIPS_MMUCTRL_PT_UNCACHED_POLICY <<
+						 RGX_MIPS_MMUCTRL_PT_CACHE_POLICY_SHIFT);
+	}
+	else
+	{
+		ui32MMUFlags |= (RGX_MIPS_MMUCTRL_PT_CACHED_POLICY <<
+						 RGX_MIPS_MMUCTRL_PT_CACHE_POLICY_SHIFT);
+	}
+
+	if ((uiProtFlags & MMU_PROTFLAGS_INVALID) == 0)
+	{
+		ui32MMUFlags |= RGX_MIPS_MMUCTRL_PT_DATA_VALID_EN;
+		ui32MMUFlags |= RGX_MIPS_MMUCTRL_PT_DATA_GLOBAL_EN;
+	}
+
+	if (MMU_PROTFLAGS_DEVICE(PMMETA_PROTECT) & uiProtFlags)
+	{
+		/* PVR_DPF((PVR_DBG_WARNING, "RGXDerivePTEProt4: PMMETA Protect not existent for MIPS, option discarded")); */
+	}
+
+	return ui32MMUFlags;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePTEProt8
+@Description    calculate the PTE protection flags based on an 8 byte entry
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT64 RGXDerivePTEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+	PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+	PVR_UNREFERENCED_PARAMETER(uiLog2DataPageSize);
+
+	PVR_DPF((PVR_DBG_ERROR, "8-byte PTE not supported on this device"));
+
+	return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXGetPageSizeConfig
+@Description    Set up configuration for variable sized data pages.
+				RGXPutPageSizeConfigCB has to be called to ensure correct
+				refcounting.
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXGetPageSizeConfigCB(IMG_UINT32 uiLog2DataPageSize,
+										   const MMU_PxE_CONFIG **ppsMMUPDEConfig,
+										   const MMU_PxE_CONFIG **ppsMMUPTEConfig,
+										   const MMU_DEVVADDR_CONFIG **ppsMMUDevVAddrConfig,
+										   IMG_HANDLE *phPriv)
+{
+	MMU_PAGESIZECONFIG *psPageSizeConfig;
+
+	switch (uiLog2DataPageSize)
+	{
+	case RGXMIPSFW_LOG2_PAGE_SIZE:
+		psPageSizeConfig = &gsPageSizeConfig4KB;
+		break;
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+				 "RGXGetPageSizeConfigCB: Invalid Data Page Size 1<<0x%x",
+				 uiLog2DataPageSize));
+		return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+	}
+
+	/* Refer caller's pointers to the data */
+	*ppsMMUPDEConfig = psPageSizeConfig->psPDEConfig;
+	*ppsMMUPTEConfig = psPageSizeConfig->psPTEConfig;
+	*ppsMMUDevVAddrConfig = psPageSizeConfig->psDevVAddrConfig;
+
+#if defined(SUPPORT_MMU_PAGESIZECONFIG_REFCOUNT)
+	/* Increment ref-count - not that we're allocating anything here
+	   (I'm using static structs), but one day we might, so we want
+	   the Get/Put code to be balanced properly */
+	psPageSizeConfig->uiRefCount ++;
+
+	/* This is purely for debug statistics */
+	psPageSizeConfig->uiMaxRefCount = MAX(psPageSizeConfig->uiMaxRefCount,
+										  psPageSizeConfig->uiRefCount);
+#endif
+
+	*phPriv = (IMG_HANDLE)(uintptr_t)uiLog2DataPageSize;
+	PVR_ASSERT (uiLog2DataPageSize == (IMG_UINT32)(uintptr_t)*phPriv);
+
+	return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXPutPageSizeConfig
+@Description    Tells this code that the mmu module is done with the
+				configurations set in RGXGetPageSizeConfig.  This can
+				be a no-op.
+				Called after RGXGetPageSizeConfigCB.
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXPutPageSizeConfigCB(IMG_HANDLE hPriv)
+{
+#if defined(SUPPORT_MMU_PAGESIZECONFIG_REFCOUNT)
+	MMU_PAGESIZECONFIG *psPageSizeConfig;
+	IMG_UINT32 uiLog2DataPageSize;
+
+	uiLog2DataPageSize = (IMG_UINT32)(uintptr_t) hPriv;
+
+	switch (uiLog2DataPageSize)
+	{
+	case RGXMIPSFW_LOG2_PAGE_SIZE:
+		psPageSizeConfig = &gsPageSizeConfig4KB;
+		break;
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+				 "RGXPutPageSizeConfigCB: Invalid Data Page Size 1<<0x%x",
+				 uiLog2DataPageSize));
+		return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+	}
+
+	/* Ref-count here is not especially useful, but it's an extra
+	   check that the API is being used correctly */
+	psPageSizeConfig->uiRefCount --;
+#else
+	PVR_UNREFERENCED_PARAMETER(hPriv);
+#endif
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR RGXGetPageSizeFromPDE4(IMG_UINT32 ui32PDE, IMG_UINT32 *pui32Log2PageSize)
+{
+	PVR_UNREFERENCED_PARAMETER(ui32PDE);
+	PVR_UNREFERENCED_PARAMETER(pui32Log2PageSize);
+	PVR_DPF((PVR_DBG_ERROR, "PDE not supported on MIPS"));
+	return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+}
+
+static PVRSRV_ERROR RGXGetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32Log2PageSize)
+{
+	PVR_UNREFERENCED_PARAMETER(ui64PDE);
+	PVR_UNREFERENCED_PARAMETER(pui32Log2PageSize);
+	PVR_DPF((PVR_DBG_ERROR, "PDE not supported on MIPS"));
+	return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+}
diff --git a/drivers/staging/imgtec/rogue/rgxmipsmmuinit.h b/drivers/staging/imgtec/rogue/rgxmipsmmuinit.h
new file mode 100644
index 0000000..67fe492
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxmipsmmuinit.h
@@ -0,0 +1,127 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific MMU initialisation for the MIPS firmware
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* NB: this file is not to be included arbitrarily.  It exists solely
+   for the linkage between rgxinit.c and rgxmmuinit.c, the former
+   being otherwise cluttered by the contents of the latter */
+
+#ifndef _SRVKM_RGXMIPSMMUINIT_H_
+#define _SRVKM_RGXMIPSMMUINIT_H_
+
+#include "device.h"
+#include "img_types.h"
+#include "mmu_common.h"
+#include "img_defs.h"
+
+/*
+
+		Labelling of fields within virtual address. No PD and PC are used currently for
+		the MIPS MMU
+*/
+/*
+Page Table entry #
+*/
+#define RGX_MIPS_MMUCTRL_VADDR_PT_INDEX_SHIFT        (12U)
+#define RGX_MIPS_MMUCTRL_VADDR_PT_INDEX_CLRMSK       (IMG_UINT64_C(0XFFFFFFFF00000FFF))
+
+
+/* PC entries related definitions */
+/* No PC is currently used for MIPS MMU */
+#define RGX_MIPS_MMUCTRL_PC_DATA_VALID_EN            (0U)
+#define RGX_MIPS_MMUCTRL_PC_DATA_VALID_SHIFT         (0U)
+#define RGX_MIPS_MMUCTRL_PC_DATA_VALID_CLRMSK        (0U)
+
+#define RGX_MIPS_MMUCTRL_PC_DATA_READ_ONLY_SHIFT     (0U)
+#define RGX_MIPS_MMUCTRL_PC_DATA_READ_ONLY_CLRMSK    (0U)
+#define RGX_MIPS_MMUCTRL_PC_DATA_READ_ONLY_EN        (0U)
+
+/* PD entries related definitions */
+/* No PD is currently used for MIPS MMU */
+#define RGX_MIPS_MMUCTRL_PD_DATA_VALID_EN            (0U)
+#define RGX_MIPS_MMUCTRL_PD_DATA_VALID_SHIFT         (0U)
+#define RGX_MIPS_MMUCTRL_PD_DATA_VALID_CLRMSK        (0U)
+
+#define RGX_MIPS_MMUCTRL_PD_DATA_READ_ONLY_SHIFT     (0U)
+#define RGX_MIPS_MMUCTRL_PD_DATA_READ_ONLY_CLRMSK    (0U)
+#define RGX_MIPS_MMUCTRL_PD_DATA_READ_ONLY_EN        (0U)
+
+
+/* PT entries related definitions */
+#define RGX_MIPS_MMUCTRL_PT_DATA_READ_INHIBIT_SHIFT  (31U)
+#define RGX_MIPS_MMUCTRL_PT_DATA_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
+#define RGX_MIPS_MMUCTRL_PT_DATA_READ_INHIBIT_EN     (0X80000000)
+
+#define RGX_MIPS_MMUCTRL_PT_DATA_WRITABLE_SHIFT      (2U)
+#define RGX_MIPS_MMUCTRL_PT_DATA_WRITABLE_CLRMSK     (0XFFFFFFFB)
+#define RGX_MIPS_MMUCTRL_PT_DATA_WRITABLE_EN         (0X00000004)
+
+#define RGX_MIPS_MMUCTRL_PT_DATA_VALID_SHIFT         (1U)
+#define RGX_MIPS_MMUCTRL_PT_DATA_VALID_CLRMSK        (0XFFFFFFFD)
+#define RGX_MIPS_MMUCTRL_PT_DATA_VALID_EN            (0X00000002)
+
+#define RGX_MIPS_MMUCTRL_PT_DATA_GLOBAL_SHIFT        (0U)
+#define RGX_MIPS_MMUCTRL_PT_DATA_GLOBAL_CLRMSK       (0XFFFFFFFE)
+#define RGX_MIPS_MMUCTRL_PT_DATA_GLOBAL_EN           (0X00000001)
+
+#define RGX_MIPS_MMUCTRL_PT_CACHE_POLICY_SHIFT       (3U)
+#define RGX_MIPS_MMUCTRL_PT_CACHE_POLICY_CLRMSK      (0XFFFFFFC7)
+
+/* "Uncached" caching policy*/
+#define RGX_MIPS_MMUCTRL_PT_UNCACHED_POLICY          (0X00000007)
+/* "Write-back write-allocate" caching policy*/
+#define RGX_MIPS_MMUCTRL_PT_CACHED_POLICY            (0X00000003)
+
+/* Physical page number inside MIPS MMU entries */
+#define RGX_MIPS_MMUCTRL_PT_PFN_SHIFT                (6U)
+#define RGX_MIPS_MMUCTRL_PT_PFN_CLRMSK               (0XFC00003F)
+
+/* Flags MIPS MMU entries */
+#define RGX_MIPS_MMUCTRL_PT_FLAGS_SHIFT              (0U)
+#define RGX_MIPS_MMUCTRL_PT_FLAGS_CLRMSK             (0XFFFFFFC0)
+
+
+IMG_EXPORT PVRSRV_ERROR RGXMipsMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_EXPORT PVRSRV_ERROR RGXMipsMMUInit_Unregister(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+
+#endif /* #ifndef _SRVKM_RGXMIPSMMUINIT_H_ */
diff --git a/drivers/staging/imgtec/rogue/rgxmmuinit.c b/drivers/staging/imgtec/rogue/rgxmmuinit.c
index b78e634..ad9c006 100644
--- a/drivers/staging/imgtec/rogue/rgxmmuinit.c
+++ b/drivers/staging/imgtec/rogue/rgxmmuinit.c
@@ -51,6 +51,7 @@
 #include "pvr_debug.h"
 #include "pvrsrv_error.h"
 #include "rgx_memallocflags.h"
+#include "rgx_heaps.h"
 #include "pdump_km.h"
 
 
@@ -180,34 +181,6 @@
 
 PVRSRV_ERROR RGXMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-	/*
-	 * Setup sRGXMMUDeviceAttributes
-	 */
-	sRGXMMUDeviceAttributes.eMMUType = PDUMP_MMU_TYPE_VARPAGE_40BIT;
-	sRGXMMUDeviceAttributes.eTopLevel = MMU_LEVEL_3;
-	sRGXMMUDeviceAttributes.ui32BaseAlign = RGX_MMUCTRL_PC_DATA_PD_BASE_ALIGNSHIFT;
-	sRGXMMUDeviceAttributes.psBaseConfig = &sRGXMMUPCEConfig;
-	sRGXMMUDeviceAttributes.psTopLevelDevVAddrConfig = &sRGXMMUTopLevelDevVAddrConfig;
-
-	/* Functions for deriving page table/dir/cat protection bits */
-	sRGXMMUDeviceAttributes.pfnDerivePCEProt8 = RGXDerivePCEProt8;
-	sRGXMMUDeviceAttributes.pfnDerivePCEProt4 = RGXDerivePCEProt4;
-	sRGXMMUDeviceAttributes.pfnDerivePDEProt8 = RGXDerivePDEProt8;
-	sRGXMMUDeviceAttributes.pfnDerivePDEProt4 = RGXDerivePDEProt4;
-	sRGXMMUDeviceAttributes.pfnDerivePTEProt8 = RGXDerivePTEProt8;
-	sRGXMMUDeviceAttributes.pfnDerivePTEProt4 = RGXDerivePTEProt4;
-
-	/* Functions for establishing configurations for PDE/PTE/DEVVADDR
-	   on per-heap basis */
-	sRGXMMUDeviceAttributes.pfnGetPageSizeConfiguration = RGXGetPageSizeConfigCB;
-	sRGXMMUDeviceAttributes.pfnPutPageSizeConfiguration = RGXPutPageSizeConfigCB;
-
-	sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE4 = RGXGetPageSizeFromPDE4;
-	sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE8 = RGXGetPageSizeFromPDE8;
-
-	
-	
-	
 	/* Setup of Px Entries:
 	 * 
 	 * 
@@ -249,6 +222,9 @@
      */
     
 	
+	sRGXMMUDeviceAttributes.pszMMUPxPDumpMemSpaceName =
+		PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+
 	/*
 	 * Setup sRGXMMUPCEConfig
 	 */
@@ -705,6 +681,7 @@
 	/*
 	 * Setup sRGXMMUDeviceAttributes
 	 */
+	sRGXMMUDeviceAttributes.eMMUType = PDUMP_MMU_TYPE_VARPAGE_40BIT;
 	sRGXMMUDeviceAttributes.eTopLevel = MMU_LEVEL_3;
 	sRGXMMUDeviceAttributes.ui32BaseAlign = RGX_MMUCTRL_PC_DATA_PD_BASE_ALIGNSHIFT;
 	sRGXMMUDeviceAttributes.psBaseConfig = &sRGXMMUPCEConfig;
@@ -723,6 +700,9 @@
 	sRGXMMUDeviceAttributes.pfnGetPageSizeConfiguration = RGXGetPageSizeConfigCB;
 	sRGXMMUDeviceAttributes.pfnPutPageSizeConfiguration = RGXPutPageSizeConfigCB;
 
+	sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE4 = RGXGetPageSizeFromPDE4;
+	sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE8 = RGXGetPageSizeFromPDE8;
+
 	psDeviceNode->psMMUDevAttrs = &sRGXMMUDeviceAttributes;
 
 	return PVRSRV_OK;
@@ -838,22 +818,22 @@
 	{
 		switch (uiLog2DataPageSize)
 		{
-			case 12:
+			case RGX_HEAP_4KB_PAGE_SHIFT:
 				ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB;
 				break;
-			case 14:
+			case RGX_HEAP_16KB_PAGE_SHIFT:
 				ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB;
 				break;
-			case 16:
+			case RGX_HEAP_64KB_PAGE_SHIFT:
 				ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB;
 				break;
-			case 18:
+			case RGX_HEAP_256KB_PAGE_SHIFT:
 				ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB;
 				break;
-			case 20:
+			case RGX_HEAP_1MB_PAGE_SHIFT:
 				ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB;
 				break;
-			case 21:
+			case RGX_HEAP_2MB_PAGE_SHIFT:
 				ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_2MB;
 				break;
 			default:
@@ -952,22 +932,22 @@
 
     switch (uiLog2DataPageSize)
     {
-    case 12:
+    case RGX_HEAP_4KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig4KB;
         break;
-    case 14:
+    case RGX_HEAP_16KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig16KB;
         break;
-    case 16:
+    case RGX_HEAP_64KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig64KB;
         break;
-    case 18:
+    case RGX_HEAP_256KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig256KB;
         break;
-    case 20:
+    case RGX_HEAP_1MB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig1MB;
         break;
-    case 21:
+    case RGX_HEAP_2MB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig2MB;
         break;
     default:
@@ -1017,22 +997,22 @@
 
     switch (uiLog2DataPageSize)
     {
-    case 12:
+    case RGX_HEAP_4KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig4KB;
         break;
-    case 14:
+    case RGX_HEAP_16KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig16KB;
         break;
-    case 16:
+    case RGX_HEAP_64KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig64KB;
         break;
-    case 18:
+    case RGX_HEAP_256KB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig256KB;
         break;
-    case 20:
+    case RGX_HEAP_1MB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig1MB;
         break;
-    case 21:
+    case RGX_HEAP_2MB_PAGE_SHIFT:
         psPageSizeConfig = &gsPageSizeConfig2MB;
         break;
     default:
@@ -1064,26 +1044,25 @@
 	switch (ui64PDE & (~RGX_MMUCTRL_PD_DATA_PAGE_SIZE_CLRMSK))
 	{
 		case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB:
-			*pui32Log2PageSize = 12;
+			*pui32Log2PageSize = RGX_HEAP_4KB_PAGE_SHIFT;
 			break;
 		case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB:
-			*pui32Log2PageSize = 14;
+			*pui32Log2PageSize = RGX_HEAP_16KB_PAGE_SHIFT;
 			break;
 		case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB:
-			*pui32Log2PageSize = 16;
+			*pui32Log2PageSize = RGX_HEAP_64KB_PAGE_SHIFT;
 			break;
 		case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB:
-			*pui32Log2PageSize = 18;
+			*pui32Log2PageSize = RGX_HEAP_256KB_PAGE_SHIFT;
 			break;
 		case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB:
-			*pui32Log2PageSize = 20;
+			*pui32Log2PageSize = RGX_HEAP_1MB_PAGE_SHIFT;
 			break;
 		case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_2MB:
-			*pui32Log2PageSize = 21;
+			*pui32Log2PageSize = RGX_HEAP_2MB_PAGE_SHIFT;
 			break;
 		default:
 			return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
-			break;
 	}
 	return PVRSRV_OK;
 }
diff --git a/drivers/staging/imgtec/rogue/rgxpdump.c b/drivers/staging/imgtec/rogue/rgxpdump.c
index 5ba27bd..067c928 100644
--- a/drivers/staging/imgtec/rogue/rgxpdump.c
+++ b/drivers/staging/imgtec/rogue/rgxpdump.c
@@ -45,6 +45,7 @@
 
 #include "devicemem_pdump.h"
 #include "rgxpdump.h"
+#include "rgx_bvnc_defs_km.h"
 
 /*
  * There are two different set of functions one for META and one for MIPS
@@ -52,7 +53,6 @@
  * the MIPS MMU yet. So for MIPS builds we cannot use DevmemPDumpSaveToFileVirtual,
  * we have to use DevmemPDumpSaveToFile instead.
  */
-#if defined(RGX_FEATURE_META)
 static PVRSRV_ERROR _MetaDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                PVRSRV_DEVICE_NODE *psDeviceNode,
                                                IMG_UINT32 ui32PDumpFlags)
@@ -78,24 +78,25 @@
 								 0,
 								 ui32PDumpFlags);
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	/* RT signatures */
-	PDumpCommentWithFlags(ui32PDumpFlags, "** Dump RTU signatures and checksums Buffer");
-	DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigRTChecksMemDesc,
-								 0,
-								 psDevInfo->ui32SigRTChecksSize,
-								 "out.rtsig",
-								 0,
-								 ui32PDumpFlags);
-	/* SH signatures */
-	PDumpCommentWithFlags(ui32PDumpFlags, "** Dump SHG signatures and checksums Buffer");
-	DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigSHChecksMemDesc,
-								 0,
-								 psDevInfo->ui32SigSHChecksSize,
-								 "out.shsig",
-								 0,
-								 ui32PDumpFlags);
-#endif
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+	{
+		/* RT signatures */
+		PDumpCommentWithFlags(ui32PDumpFlags, "** Dump RTU signatures and checksums Buffer");
+		DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigRTChecksMemDesc,
+									 0,
+									 psDevInfo->ui32SigRTChecksSize,
+									 "out.rtsig",
+									 0,
+									 ui32PDumpFlags);
+		/* SH signatures */
+		PDumpCommentWithFlags(ui32PDumpFlags, "** Dump SHG signatures and checksums Buffer");
+		DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigSHChecksMemDesc,
+									 0,
+									 psDevInfo->ui32SigSHChecksSize,
+									 "out.shsig",
+									 0,
+									 ui32PDumpFlags);
+	}
 
 	return PVRSRV_OK;
 }
@@ -107,14 +108,29 @@
 	IMG_UINT32 		ui32ThreadNum, ui32Size, ui32OutFileOffset;
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(ui32ThreadNum);
+	PVR_UNREFERENCED_PARAMETER(ui32OutFileOffset);
+#else
 	/* Dump trace buffers */
 	PDumpCommentWithFlags(ui32PDumpFlags, "** Dump trace buffers");
 	for(ui32ThreadNum = 0, ui32OutFileOffset = 0; ui32ThreadNum < RGXFW_THREAD_NUM; ui32ThreadNum++)
 	{
+		/*
+		 * Some compilers cannot cope with the use of offsetof() below - the specific problem being the use of
+		 * a non-const variable in the expression, which it needs to be const. Typical compiler error produced is
+		 * "expression must have a constant value".
+		 */
+		const IMG_DEVMEM_OFFSET_T uiTraceBufThreadNumOff
+		= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_TRACEBUF *)0)->sTraceBuf[ui32ThreadNum]);
+
 		/* ui32TracePointer tracepointer */
 		ui32Size = sizeof(IMG_UINT32);
 		DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
-								offsetof(RGXFWIF_TRACEBUF, sTraceBuf[ui32ThreadNum]),
+								uiTraceBufThreadNumOff,
 								ui32Size,
 								"out.trace",
 								ui32OutFileOffset,
@@ -137,7 +153,9 @@
 				+ RGXFW_TRACE_BUFFER_ASSERT_SIZE * sizeof(IMG_CHAR)
 				+ sizeof(IMG_UINT32);
 		DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
-								offsetof(RGXFWIF_TRACEBUF, sTraceBuf[ui32ThreadNum]) + offsetof(RGXFWIF_TRACEBUF_SPACE, sAssertBuf),
+								offsetof(RGXFWIF_TRACEBUF, sTraceBuf) /* move to first element of sTraceBuf */
+									+ ui32ThreadNum * sizeof(RGXFWIF_TRACEBUF_SPACE) /* skip required number of sTraceBuf elements */
+									+ offsetof(RGXFWIF_TRACEBUF_SPACE, sAssertBuf), /* offset into its sAssertBuf, to be pdumped */
 								ui32Size,
 								"out.trace",
 								ui32OutFileOffset,
@@ -156,11 +174,13 @@
 								 "out.hwperf",
 								 0,
 								 ui32PDumpFlags);
+#endif
+
 	return PVRSRV_OK;
 
 }
 
-#else /* RGX_FEATURE_META */
+
 static PVRSRV_ERROR _MipsDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                PVRSRV_DEVICE_NODE *psDeviceNode,
                                                IMG_UINT32 ui32PDumpFlags)
@@ -186,23 +206,24 @@
 								 "out.3dsig",
 								 0);
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-	/* RT signatures */
-	PDumpCommentWithFlags(ui32PDumpFlags, "** Dump RTU signatures and checksums Buffer");
-	DevmemPDumpSaveToFile(psDevInfo->psRGXFWSigRTChecksMemDesc,
-								 0,
-								 psDevInfo->ui32SigRTChecksSize,
-								 "out.rtsig",
-								 0);
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+	{
+		/* RT signatures */
+		PDumpCommentWithFlags(ui32PDumpFlags, "** Dump RTU signatures and checksums Buffer");
+		DevmemPDumpSaveToFile(psDevInfo->psRGXFWSigRTChecksMemDesc,
+									 0,
+									 psDevInfo->ui32SigRTChecksSize,
+									 "out.rtsig",
+									 0);
 
-	/* SH signatures */
-	PDumpCommentWithFlags(ui32PDumpFlags, "** Dump SHG signatures and checksums Buffer");
-	DevmemPDumpSaveToFile(psDevInfo->psRGXFWSigSHChecksMemDesc,
-								 0,
-								 psDevInfo->ui32SigSHChecksSize,
-								 "out.shsig",
-								 0);
-#endif
+		/* SH signatures */
+		PDumpCommentWithFlags(ui32PDumpFlags, "** Dump SHG signatures and checksums Buffer");
+		DevmemPDumpSaveToFile(psDevInfo->psRGXFWSigSHChecksMemDesc,
+									 0,
+									 psDevInfo->ui32SigSHChecksSize,
+									 "out.shsig",
+									 0);
+	}
 
 	return PVRSRV_OK;
 
@@ -212,19 +233,35 @@
                                            PVRSRV_DEVICE_NODE *psDeviceNode,
                                            IMG_UINT32 ui32PDumpFlags)
 {
-	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
-	IMG_UINT32 		ui32ThreadNum, ui32Size, ui32OutFileOffset;
-
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
 	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#else
 
+	IMG_UINT32 		ui32ThreadNum, ui32Size, ui32OutFileOffset;
+	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	PVR_UNREFERENCED_PARAMETER(psConnection);
 	/* Dump trace buffers */
 	PDumpCommentWithFlags(ui32PDumpFlags, "** Dump trace buffers");
 	for(ui32ThreadNum = 0, ui32OutFileOffset = 0; ui32ThreadNum < RGXFW_THREAD_NUM; ui32ThreadNum++)
 	{
+		/*
+		 * Some compilers cannot cope with the use of offsetof() below - the specific problem being the use of
+		 * a non-const variable in the expression, which it needs to be const. Typical compiler error produced is
+		 * "expression must have a constant value".
+		 */
+		const IMG_DEVMEM_OFFSET_T uiTraceBufOff
+		= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_TRACEBUF *)0)->sTraceBuf[ui32ThreadNum]);
+
+		/* Same again... */
+		const IMG_DEVMEM_OFFSET_T uiTraceBufSpaceAssertBufOff
+		= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_TRACEBUF_SPACE *)0)->sAssertBuf);
+
 		/* ui32TracePointer tracepointer */
 		ui32Size = sizeof(IMG_UINT32);
 		DevmemPDumpSaveToFile(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
-								offsetof(RGXFWIF_TRACEBUF, sTraceBuf[ui32ThreadNum]),
+								uiTraceBufOff,
 								ui32Size,
 								"out.trace",
 								ui32OutFileOffset);
@@ -245,7 +282,7 @@
 				+ RGXFW_TRACE_BUFFER_ASSERT_SIZE * sizeof(IMG_CHAR)
 				+ sizeof(IMG_UINT32);
 		DevmemPDumpSaveToFile(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
-								offsetof(RGXFWIF_TRACEBUF, sTraceBuf[ui32ThreadNum]) + offsetof(RGXFWIF_TRACEBUF_SPACE, sAssertBuf),
+								uiTraceBufOff + uiTraceBufSpaceAssertBufOff,
 								ui32Size,
 								"out.trace",
 								ui32OutFileOffset);
@@ -259,10 +296,11 @@
 								 psDevInfo->ui32RGXFWIfHWPerfBufSize,
 								 "out.hwperf",
 								 0);
+#endif
+
 	return PVRSRV_OK;
 
 }
-#endif /* RGX_FEATURE_META */
 
 
 /*
@@ -272,19 +310,19 @@
                                           PVRSRV_DEVICE_NODE	*psDeviceNode,
                                           IMG_UINT32			ui32PDumpFlags)
 {	
-	if (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
+	if( (psDeviceNode->pfnCheckDeviceFeature) && \
+			psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_MIPS_BIT_MASK))
 	{
-#if defined(RGX_FEATURE_META)
-		return _MetaDumpSignatureBufferKM(psConnection,
-        	                                  psDeviceNode,
-                	                          ui32PDumpFlags);
-#else
 		return _MipsDumpSignatureBufferKM(psConnection,
-                        	                  psDeviceNode,
-                                	          ui32PDumpFlags);
-#endif
+										  psDeviceNode,
+										  ui32PDumpFlags);
 	}
-	return PVRSRV_OK;
+	else
+	{
+		return _MetaDumpSignatureBufferKM(psConnection,
+											  psDeviceNode,
+											  ui32PDumpFlags);
+	}
 }
 
 
@@ -293,15 +331,14 @@
                                       PVRSRV_DEVICE_NODE *psDeviceNode,
                                       IMG_UINT32 ui32PDumpFlags)
 {	
-	if (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
-	{	
-#if defined(RGX_FEATURE_META)
-		return _MetaDumpTraceBufferKM(psConnection, psDeviceNode, ui32PDumpFlags);
-#else
+	if( (psDeviceNode->pfnCheckDeviceFeature) && \
+			psDeviceNode->pfnCheckDeviceFeature(psDeviceNode, RGX_FEATURE_MIPS_BIT_MASK))
+	{
 		return _MipsDumpTraceBufferKM(psConnection, psDeviceNode, ui32PDumpFlags);
-#endif
+	}else
+	{
+		return _MetaDumpTraceBufferKM(psConnection, psDeviceNode, ui32PDumpFlags);
 	}
-	return PVRSRV_OK;
 }
 
 #endif /* PDUMP */
diff --git a/drivers/staging/imgtec/rogue/rgxpdvfs.c b/drivers/staging/imgtec/rogue/rgxpdvfs.c
new file mode 100644
index 0000000..fd75830
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxpdvfs.c
@@ -0,0 +1,233 @@
+/*************************************************************************/ /*!
+@File           rgxpdvfs.c
+@Title          RGX Proactive DVFS Functionality
+@Codingstyle    IMG
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Kernel mode Proactive DVFS Functionality.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "rgxpdvfs.h"
+#include "rgxfwutils.h"
+
+#define USEC_TO_MSEC 1000
+
+PVRSRV_ERROR PDVFSLimitMaxFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32MaxOPPPoint)
+{
+	RGXFWIF_KCCB_CMD		sGPCCBCmd;
+	PVRSRV_ERROR			eError;
+
+	if(psDevInfo->bPDVFSEnabled != IMG_TRUE)
+	{
+		/* No error message to avoid excessive messages */
+		return PVRSRV_OK;
+	}
+
+	/* send feedback */
+	sGPCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_PDVFS_LIMIT_MAX_FREQ;
+	sGPCCBCmd.uCmdData.sPDVFSMaxFreqData.ui32MaxOPPPoint = ui32MaxOPPPoint;
+
+
+	/* Submit command to the firmware.  */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+									RGXFWIF_DM_GP,
+									&sGPCCBCmd,
+									sizeof(sGPCCBCmd),
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+	
+	return PVRSRV_OK;
+}
+
+
+void PDVFSRequestReactiveUpdate(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	RGXFWIF_KCCB_CMD sGPCCBCmd;
+	PVRSRV_ERROR eError;
+
+	if(psDevInfo->bPDVFSEnabled != IMG_TRUE)
+	{
+		/* No error message to avoid excessive messages */
+		return;
+	}
+
+	if(psDevInfo->psDeviceNode->psDevConfig->sDVFS.sPDVFSData.bWorkInFrame == IMG_FALSE)
+	{
+		return;
+	}
+
+	sGPCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_PDVFS_REQUEST_REACTIVE_UPDATE;
+
+	/* Submit command to the firmware.  */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psDevInfo,
+		                            RGXFWIF_DM_GP,
+		                            &sGPCCBCmd,
+		                            sizeof(sGPCCBCmd),
+		                            0,
+		                            PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	psDevInfo->psDeviceNode->psDevConfig->sDVFS.sPDVFSData.bWorkInFrame = IMG_FALSE;
+}
+
+/*************************************************************************/ /*!
+@Function       PDVFSProcessCoreClkRateChange
+@Description    Processes the core clock rate change request or notification.
+                Processes as notification, if SUPPORT_PDVFS_GPIO feature is enabled
+                i.e. firmware (PDVFS) can use GPIO to change core clock rate
+                else processes as request (uses system layer API to change core
+                clock rate)
+@Input          psDevInfo            A pointer to PVRSRV_RGXDEV_INFO.
+@Input          ui32CoreClockRate    New core clock rate.
+@Return         PVRSRV_ERROR.
+*/ /**************************************************************************/
+PVRSRV_ERROR PDVFSProcessCoreClkRateChange(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32CoreClockRate)
+{
+	PVRSRV_DEVICE_CONFIG *psDevConfig = psDevInfo->psDeviceNode->psDevConfig;
+	IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = &psDevConfig->sDVFS.sDVFSDeviceCfg;
+	RGX_TIMING_INFORMATION *psRGXTimingInfo = ((RGX_DATA*)(psDevConfig->hDevData))->psRGXTimingInfo;
+	PVRSRV_ERROR eError;
+
+#if !defined (SUPPORT_PDVFS_GPIO)
+	IMG_UINT32 ui32CoreClockRateCurrent = psRGXTimingInfo->ui32CoreClockSpeed;
+#endif
+	IMG_UINT32 ui32Index;
+	const IMG_OPP *psOpp = NULL;
+
+
+	if(psDevInfo->bPDVFSEnabled != IMG_TRUE)
+	{
+		/* No error message to avoid excessive messages */
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,"Core clock rate = %u\n", ui32CoreClockRate));
+
+	/**
+	 * Find the matching OPP (Exact).
+	 */
+	for (ui32Index = 0; ui32Index < psDVFSDeviceCfg->ui32OPPTableSize; ui32Index++)
+	{
+		if (ui32CoreClockRate == psDVFSDeviceCfg->pasOPPTable[ui32Index].ui32Freq)
+		{
+			psOpp = &psDVFSDeviceCfg->pasOPPTable[ui32Index];
+			break;
+		}
+	}
+
+	if (!psOpp)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Frequency not present in OPP table - %u", ui32CoreClockRate));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = PVRSRVDevicePreClockSpeedChange(psDevInfo->psDeviceNode, psDVFSDeviceCfg->bIdleReq, NULL);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange failed"));
+		return eError;
+	}
+
+#if !defined (SUPPORT_PDVFS_GPIO)
+	/**
+	 * Increasing frequency, change voltage first
+	 */
+	if(ui32CoreClockRate > ui32CoreClockRateCurrent)
+	{
+		psDVFSDeviceCfg->pfnSetVoltage(psOpp->ui32Volt);
+	}
+
+	psDVFSDeviceCfg->pfnSetFrequency(ui32CoreClockRate);
+
+	/**
+	 * Decreasing frequency, change frequency first
+	 */
+	if (ui32CoreClockRate < ui32CoreClockRateCurrent)
+	{
+		psDVFSDeviceCfg->pfnSetVoltage(psOpp->ui32Volt);
+	}
+#endif
+
+	psRGXTimingInfo->ui32CoreClockSpeed = ui32CoreClockRate;
+
+	PVRSRVDevicePostClockSpeedChange(psDevInfo->psDeviceNode, psDVFSDeviceCfg->bIdleReq, NULL);
+
+	return PVRSRV_OK;
+}
+
+#if defined (RGXFW_META_SUPPORT_2ND_THREAD)
+/*************************************************************************/ /*!
+@Function       RGXPDVFSCheckCoreClkRateChange 
+@Description    Checks if core clock rate has changed since the last snap-shot.
+@Input          psDevInfo    A pointer to PVRSRV_RGXDEV_INFO.
+@Return         None.
+*/ /**************************************************************************/
+void RGXPDVFSCheckCoreClkRateChange(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	IMG_UINT32 ui32CoreClkRate = *(psDevInfo->pui32RGXFWIFCoreClkRate);
+
+	if(psDevInfo->bPDVFSEnabled != IMG_TRUE)
+	{
+		/* No error message to avoid excessive messages */
+		return;
+	}
+
+	if ((ui32CoreClkRate != 0) &&
+		(psDevInfo->ui32CoreClkRateSnapshot != ui32CoreClkRate))
+	{
+		psDevInfo->ui32CoreClkRateSnapshot = ui32CoreClkRate;
+		PDVFSProcessCoreClkRateChange(psDevInfo, ui32CoreClkRate);
+	}
+}
+#endif
diff --git a/drivers/staging/imgtec/rogue/cache_internal.h b/drivers/staging/imgtec/rogue/rgxpdvfs.h
similarity index 76%
rename from drivers/staging/imgtec/rogue/cache_internal.h
rename to drivers/staging/imgtec/rogue/rgxpdvfs.h
index 8326724..dade22a 100644
--- a/drivers/staging/imgtec/rogue/cache_internal.h
+++ b/drivers/staging/imgtec/rogue/rgxpdvfs.h
@@ -1,8 +1,9 @@
 /*************************************************************************/ /*!
-@File
-@Title          Services cache management header
+@File           rgxpdvfs.h
+@Title          RGX Proactive DVFS Functionality
+@Codingstyle    IMG
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Defines for cache management which are visible internally only.
+@Description    Header for the kernel mode Proactive DVFS Functionality.
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,18 +42,23 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _CACHE_INTERNAL_H_
-#define _CACHE_INTERNAL_H_
+#ifndef RGXPDVFS_H
+#define RGXPDVFS_H
 #include "img_types.h"
-#include "pvrsrv_devmem.h"
-#include "cache_external.h"
+#include "rgxdevice.h"
+#define PDVFS_REACTIVE_INTERVAL_MS 16
 
-typedef struct _CACHE_BATCH_OP_ENTRY_
-{
-	IMG_UINT32			ui32PMREntryIndex;
-	PVRSRV_CACHE_OP  	eCacheOp;
-	IMG_DEVMEM_SIZE_T	uiSize;
-    IMG_DEVMEM_OFFSET_T uiOffset;
-} CACHE_BATCH_OP_ENTRY;
 
-#endif	/* _CACHE_INTERNAL_H_ */
+IMG_INTERNAL
+PVRSRV_ERROR PDVFSLimitMaxFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32MaxOPPPoint);
+
+void PDVFSRequestReactiveUpdate(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR PDVFSProcessCoreClkRateChange(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32CoreClockRate);
+
+#if defined (RGXFW_META_SUPPORT_2ND_THREAD)
+IMG_INTERNAL
+void RGXPDVFSCheckCoreClkRateChange(PVRSRV_RGXDEV_INFO *psDevInfo);
+#endif
+
+#endif /* RGXPDVFS_H */
diff --git a/drivers/staging/imgtec/rogue/rgxpower.c b/drivers/staging/imgtec/rogue/rgxpower.c
index 97cb287..327afc7 100644
--- a/drivers/staging/imgtec/rogue/rgxpower.c
+++ b/drivers/staging/imgtec/rogue/rgxpower.c
@@ -50,11 +50,14 @@
 #include "pvr_debug.h"
 #include "osfunc.h"
 #include "rgxdebug.h"
+#include "devicemem.h"
 #include "devicemem_pdump.h"
 #include "rgxtimecorr.h"
 #include "devicemem_utils.h"
 #include "htbserver.h"
 #include "rgxstartstop.h"
+#include "sync.h"
+#include "lists.h"
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #include "process_stats.h"
@@ -63,8 +66,31 @@
 #include "pvr_dvfs_device.h"
 #endif
 
-extern IMG_UINT32 g_ui32HostSampleIRQCount;
+static PVRSRV_ERROR RGXFWNotifyHostTimeout(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	PVRSRV_ERROR     eError;
+	RGXFWIF_KCCB_CMD sCmd;
+	RGXFWIF_RUNTIME_CFG	*psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
 
+	/* Send the Timeout notification to the FW */
+	/* Extending the APM Latency Change command structure with the notification boolean for 
+	   backwards compatibility reasons */
+	sCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
+	sCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_APM_LATENCY_CHANGE;
+	sCmd.uCmdData.sPowData.uPoweReqData.ui32ActivePMLatencyms = psRuntimeCfg->ui32ActivePMLatencyms;
+	sCmd.uCmdData.sPowData.bNotifyTimeout = IMG_TRUE;
+
+	/* Ensure the new APM latency is written to memory before requesting the FW to read it */
+	OSMemoryBarrier();
+
+	eError = RGXSendCommand(psDevInfo,
+	                        RGXFWIF_DM_GP,
+	                        &sCmd,
+	                        sizeof(sCmd),
+	                        PDUMP_FLAGS_NONE);
+
+	return eError;
+}
 
 static void _RGXUpdateGPUUtilStats(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
@@ -95,11 +121,11 @@
 }
 
 
-static PVRSRV_ERROR RGXDoStop(PVRSRV_DEVICE_NODE *psDeviceNode)
+static INLINE PVRSRV_ERROR RGXDoStop(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 	PVRSRV_ERROR eError;
 
-#if defined(SUPPORT_TRUSTED_DEVICE)
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
 	PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
 
 	if (psDevConfig->pfnTDRGXStop == NULL)
@@ -108,7 +134,7 @@
 		return PVRSRV_ERROR_NOT_IMPLEMENTED;
 	}
 
-	eError = psDevConfig->pfnTDRGXStop();
+	eError = psDevConfig->pfnTDRGXStop(psDevConfig->hSysData);
 #else
 	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
@@ -135,28 +161,29 @@
 		PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
 		RGXFWIF_KCCB_CMD	sPowCmd;
 		RGXFWIF_TRACEBUF	*psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
-		IMG_UINT32			ui32DM;
 
 		/* Send the Power off request to the FW */
 		sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
 		sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_OFF_REQ;
 		sPowCmd.uCmdData.sPowData.uPoweReqData.bForced = bForced;
 
-		SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
-
-		/* Send one pow command to each DM to make sure we flush all the DMs pipelines */
-		for (ui32DM = 0; ui32DM < RGXFWIF_DM_MAX; ui32DM++)
+		eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+		if (eError != PVRSRV_OK)
 		{
-			eError = RGXSendCommand(psDevInfo,
-					ui32DM,
-					&sPowCmd,
-					sizeof(sPowCmd),
-					0);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Failed to send Power off request for DM%d", ui32DM));
-				return eError;
-			}
+			PVR_DPF((PVR_DBG_ERROR,"%s: Failed to set Power sync prim",
+				__FUNCTION__));
+			return eError;
+		}
+
+		eError = RGXSendCommand(psDevInfo,
+		                        RGXFWIF_DM_GP,
+		                        &sPowCmd,
+		                        sizeof(sPowCmd),
+		                        PDUMP_FLAGS_NONE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Failed to send Power off request"));
+			return eError;
 		}
 
 		/* Wait for the firmware to complete processing. It cannot use PVRSRVWaitForValueKM as it relies 
@@ -170,23 +197,30 @@
 			if (psFWTraceBuf->ePowState == RGXFWIF_POW_OFF)
 			{
 #if !defined(NO_HARDWARE)
-				/* Wait for the pending META/MIPS to host interrupts to come back. */
-				eError = PVRSRVPollForValueKM(&g_ui32HostSampleIRQCount,
-									          psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount,
-									          0xffffffff);
-
-				if (eError != PVRSRV_OK)
+				IMG_UINT32 ui32TID;
+				for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
 				{
-					PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Wait for pending interrupts failed. Host:%d, FW: %d",
-					g_ui32HostSampleIRQCount,
-					psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount));
+					/* Wait for the pending META/MIPS to host interrupts to come back. */
+					eError = PVRSRVPollForValueKM(&psDevInfo->aui32SampleIRQCount[ui32TID],
+										          psFWTraceBuf->aui32InterruptCount[ui32TID],
+										          0xffffffff);
 
-					RGX_WaitForInterruptsTimeout(psDevInfo);
+					if (eError != PVRSRV_OK)
+					{
+						PVR_DPF((PVR_DBG_ERROR, \
+								"RGXPrePowerState: Wait for pending interrupts failed. Thread %u: Host:%u, FW: %u", \
+								ui32TID, \
+								psDevInfo->aui32SampleIRQCount[ui32TID], \
+								psFWTraceBuf->aui32InterruptCount[ui32TID]));
+
+						RGX_WaitForInterruptsTimeout(psDevInfo);
+						break;
+					}
 				}
 #endif /* NO_HARDWARE */
 
 				/* Update GPU frequency and timer correlation related data */
-				RGXGPUFreqCalibratePrePowerState(psDeviceNode);
+				RGXGPUFreqCalibratePrePowerOff(psDeviceNode);
 
 				/* Update GPU state counters */
 				_RGXUpdateGPUUtilStats(psDevInfo);
@@ -195,7 +229,7 @@
 				eError = SuspendDVFS();
 				if (eError != PVRSRV_OK)
 				{
-					PVR_DPF((PVR_DBG_ERROR,"RGXPostPowerState: Failed to suspend DVFS"));
+					PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Failed to suspend DVFS"));
 					return eError;
 				}
 #endif
@@ -242,7 +276,7 @@
 {
 	PVRSRV_ERROR eError;
 
-#if defined(SUPPORT_TRUSTED_DEVICE)
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
 	PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
 
 	if (psDevConfig->pfnTDRGXStart == NULL)
@@ -251,7 +285,7 @@
 		return PVRSRV_ERROR_NOT_IMPLEMENTED;
 	}
 
-	eError = psDevConfig->pfnTDRGXStart();
+	eError = psDevConfig->pfnTDRGXStart(psDevConfig->hSysData);
 #else
 	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
@@ -280,14 +314,11 @@
 		if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
 		{
 			/* Update GPU frequency and timer correlation related data */
-			RGXGPUFreqCalibratePostPowerState(psDeviceNode);
+			RGXGPUFreqCalibratePostPowerOn(psDeviceNode);
 
 			/* Update GPU state counters */
 			_RGXUpdateGPUUtilStats(psDevInfo);
 
-			/*
-			 * Perform GPU reset and initialisation
-			 */
 			eError = RGXDoStart(psDeviceNode);
 			if (eError != PVRSRV_OK)
 			{
@@ -321,6 +352,28 @@
 			{
 				PVR_DPF((PVR_DBG_ERROR, "RGXPostPowerState: Polling for 'FW started' flag failed."));
 				eError = PVRSRV_ERROR_TIMEOUT;
+
+				/*
+				 * When bFirmwareStarted fails some info maybe gained by doing the following
+				 * debug dump but unfortunately it could lockup some cores or cause other power
+				 * lock issues. The code is placed here to provide a possible example approach
+				 * when all other ideas have been tried.
+				 */
+				/*{
+					PVRSRV_POWER_DEV *psPowerDev = psDeviceNode->psPowerDev;
+				
+					if (psPowerDev)
+					{
+						PVRSRV_DEV_POWER_STATE  eOldPowerState = psPowerDev->eCurrentPowerState;
+
+						PVRSRVPowerUnlock(psDeviceNode);
+						psPowerDev->eCurrentPowerState = PVRSRV_DEV_POWER_STATE_ON;
+						RGXDumpDebugInfo(NULL, psDeviceNode->pvDevice);
+						psPowerDev->eCurrentPowerState = eOldPowerState;
+						PVRSRVPowerLock(psDeviceNode);
+					}
+				}*/
+				
 				DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
 				return eError;
 			}
@@ -435,7 +488,7 @@
 		                           RGXFWIF_DM_GP,
 		                           &sCOREClkSpeedChangeCmd,
 		                           sizeof(sCOREClkSpeedChangeCmd),
-		                           0);
+		                           PDUMP_FLAGS_NONE);
 		PDUMPPOWCMDEND();
 
 		if (eError != PVRSRV_OK)
@@ -476,7 +529,7 @@
 	PVRSRV_RGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
 	PVRSRV_ERROR		eError;
 	RGXFWIF_KCCB_CMD 	sDustCountChange;
-	IMG_UINT32			ui32MaxAvailableDusts = MAX(1, RGX_FEATURE_NUM_CLUSTERS/2);
+	IMG_UINT32			ui32MaxAvailableDusts = MAX(1, (psDevInfo->sDevFeatureCfg.ui32NumClusters/2));
 	RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
 
 	if (ui32NumberOfDusts > ui32MaxAvailableDusts)
@@ -490,6 +543,25 @@
 		return eError;
 	}
 
+	#if defined(FIX_HW_BRN_59042)
+	if (ui32NumberOfDusts < ui32MaxAvailableDusts && (ui32NumberOfDusts & 0x1))
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"RGXDustCountChange: Invalid number of DUSTs (%u) due to HW restriction. Allowed values are :-",
+				ui32NumberOfDusts));
+		switch (ui32MaxAvailableDusts)
+		{
+			case 2:	PVR_DPF((PVR_DBG_ERROR, "0, 2")); break;
+			case 3:	PVR_DPF((PVR_DBG_ERROR, "0, 2, 3")); break;
+			case 4:	PVR_DPF((PVR_DBG_ERROR, "0, 2, 4")); break;
+			case 5:	PVR_DPF((PVR_DBG_ERROR, "0, 2, 4, 5")); break;
+			case 6:	PVR_DPF((PVR_DBG_ERROR, "0, 2, 4, 6")); break;
+			default: break;
+		}
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	#endif
+
 	psRuntimeCfg->ui32DefaultDustsNumInit = ui32NumberOfDusts;
 
 	#if !defined(NO_HARDWARE)
@@ -510,7 +582,13 @@
 	}
 	#endif
 
-	SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+	eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to set Power sync prim",
+			__FUNCTION__));
+		return eError;
+	}
 
 	sDustCountChange.eCmdType = RGXFWIF_KCCB_CMD_POW;
 	sDustCountChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_NUMDUST_CHANGE;
@@ -521,7 +599,7 @@
 				RGXFWIF_DM_GP,
 				&sDustCountChange,
 				sizeof(sDustCountChange),
-				0);
+				PDUMP_FLAGS_NONE);
 
 	if (eError != PVRSRV_OK)
 	{
@@ -565,7 +643,7 @@
 	RGXFWIF_RUNTIME_CFG	*psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
 	PVRSRV_DEV_POWER_STATE	ePowerState;
 
-	eError = PVRSRVPowerLock();
+	eError = PVRSRVPowerLock(psDeviceNode);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXAPMLatencyChange: Failed to acquire power lock"));
@@ -576,12 +654,13 @@
 	psRuntimeCfg->ui32ActivePMLatencyms = ui32ActivePMLatencyms;
 	psRuntimeCfg->bActivePMLatencyPersistant = bActivePMLatencyPersistant;
 
-	eError = PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
+	eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 
 	if ((eError == PVRSRV_OK) && (ePowerState != PVRSRV_DEV_POWER_STATE_OFF))
 	{
 		RGXFWIF_KCCB_CMD	sActivePMLatencyChange;
 		sActivePMLatencyChange.eCmdType = RGXFWIF_KCCB_CMD_POW;
+		sActivePMLatencyChange.uCmdData.sPowData.bNotifyTimeout = IMG_FALSE;
 		sActivePMLatencyChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_APM_LATENCY_CHANGE;
 		sActivePMLatencyChange.uCmdData.sPowData.uPoweReqData.ui32ActivePMLatencyms = ui32ActivePMLatencyms;
 
@@ -593,7 +672,7 @@
 					RGXFWIF_DM_GP,
 					&sActivePMLatencyChange,
 					sizeof(sActivePMLatencyChange),
-					0);
+					PDUMP_FLAGS_NONE);
 
 		if (eError != PVRSRV_OK)
 		{
@@ -603,7 +682,7 @@
 		}
 	}
 
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 	return PVRSRV_OK;
 }
@@ -626,12 +705,12 @@
 
 	/* Powerlock to avoid further requests from racing with the FW hand-shake from now on
 	   (previous kicks to this point are detected by the FW) */
-	eError = PVRSRVPowerLock();
+	eError = PVRSRVPowerLock(psDeviceNode);
 	if(eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXActivePowerRequest: Failed to acquire PowerLock (device index: %d, error: %s)", 
-					psDeviceNode->sDevId.ui32DeviceIndex,
-					PVRSRVGetErrorStringKM(eError)));
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Failed to acquire PowerLock (device: %p, error: %s)",
+				 __func__, psDeviceNode, PVRSRVGetErrorStringKM(eError)));
 		goto _RGXActivePowerRequest_PowerLock_failed;
 	}
 
@@ -646,10 +725,9 @@
 #endif
 
 		PDUMPPOWCMDSTART();
-		eError = 
-			PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
-					PVRSRV_DEV_POWER_STATE_OFF,
-					IMG_FALSE); /* forced */
+		eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+											 PVRSRV_DEV_POWER_STATE_OFF,
+											 IMG_FALSE); /* forced */
 		PDUMPPOWCMDEND();
 
 		if (eError == PVRSRV_OK)
@@ -663,7 +741,7 @@
 
 	}
 
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
 
 _RGXActivePowerRequest_PowerLock_failed:
 	OSReleaseBridgeLock();
@@ -701,7 +779,13 @@
 	}
 #endif
 
-	SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+	eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to set Power sync prim",
+			__FUNCTION__));
+		return eError;
+	}
 	sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
 	sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_FORCED_IDLE_REQ;
 	sPowCmd.uCmdData.sPowData.uPoweReqData.bCancelForcedIdle = IMG_FALSE;
@@ -713,7 +797,7 @@
 			RGXFWIF_DM_GP,
 			&sPowCmd,
 			sizeof(sPowCmd),
-			0);
+			PDUMP_FLAGS_NONE);
 
 	if (eError != PVRSRV_OK)
 	{
@@ -734,6 +818,7 @@
 
 	if (eError != PVRSRV_OK)
 	{
+		RGXFWNotifyHostTimeout(psDevInfo);
 		PVR_DPF((PVR_DBG_ERROR,"RGXForcedIdleRequest: Idle request failed. Firmware potentially left in forced idle state"));
 		return eError;
 	}
@@ -771,7 +856,13 @@
 	RGXFWIF_KCCB_CMD	sPowCmd;
 	PVRSRV_ERROR		eError = PVRSRV_OK;
 
-	SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+	eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to set Power sync prim",
+			__FUNCTION__));
+		goto ErrorExit;
+	}
 
 	/* Send the IDLE request to the FW */
 	sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
@@ -785,7 +876,7 @@
 			RGXFWIF_DM_GP,
 			&sPowCmd,
 			sizeof(sPowCmd),
-			0);
+			PDUMP_FLAGS_NONE);
 
 	if (eError != PVRSRV_OK)
 	{
diff --git a/drivers/staging/imgtec/rogue/rgxray.c b/drivers/staging/imgtec/rogue/rgxray.c
new file mode 100644
index 0000000..1980cc0
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxray.c
@@ -0,0 +1,2957 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX ray tracing routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX ray tracing routines
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+/* for the offsetof macro */
+#include <stddef.h>
+#if defined(INTEGRITY_OS)
+#include <string.h>
+#endif
+
+#include "pdump_km.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxray.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "devicemem_server.h"
+#include "osfunc.h"
+#include "pvrsrv.h"
+#include "rgxccb.h"
+#include "rgxhwperf.h"
+#include "rgxtimerquery.h"
+#include "htbuffer.h"
+
+#include "rgxdefs_km.h"
+#include "rgx_fwif_km.h"
+#include "physmem.h"
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "sync.h"
+#include "process_stats.h"
+
+
+/*
+ * FIXME: Defs copied from "rgxrpmdefs.h"
+ */
+
+typedef struct _RGX_RPM_DATA_RTU_FREE_PAGE_LIST {
+     IMG_UINT32 u32_0; 
+} RGX_RPM_DATA_RTU_FREE_PAGE_LIST;
+
+/*
+Page table index.
+                                                        The field is a pointer to a free page 
+*/
+#define RGX_RPM_DATA_RTU_FREE_PAGE_LIST_PTI_WOFF          (0U)
+#define RGX_RPM_DATA_RTU_FREE_PAGE_LIST_PTI_SHIFT         (0U)
+#define RGX_RPM_DATA_RTU_FREE_PAGE_LIST_PTI_CLRMSK        (0XFFC00000U)
+#define RGX_RPM_DATA_RTU_FREE_PAGE_LIST_SET_PTI(_ft_,_x_) ((_ft_).u32_0 = (((_ft_).u32_0 & RGX_RPM_DATA_RTU_FREE_PAGE_LIST_PTI_CLRMSK ) | (((_x_) & (0x003fffff))  <<  0)))
+#define RGX_RPM_DATA_RTU_FREE_PAGE_LIST_GET_PTI(_ft_)     (((_ft_).u32_0  >>  (0)) & 0x003fffff)
+
+typedef struct _RGX_RPM_DATA_RTU_PAGE_TABLE {
+     IMG_UINT32 u32_0; 
+} RGX_RPM_DATA_RTU_PAGE_TABLE;
+
+/*
+ Page Table State
+                                                        <br> 00: Empty Block
+                                                        <br> 01: Full Block
+                                                        <br> 10: Fragmented Block: Partially full page 
+*/
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_PTS_WOFF              (0U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_PTS_SHIFT             (30U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_PTS_CLRMSK            (0X3FFFFFFFU)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_SET_PTS(_ft_,_x_)     ((_ft_).u32_0 = (((_ft_).u32_0 & RGX_RPM_DATA_RTU_PAGE_TABLE_PTS_CLRMSK ) | (((_x_) & (0x00000003))  <<  30)))
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_GET_PTS(_ft_)         (((_ft_).u32_0  >>  (30)) & 0x00000003)
+/*
+ Primitives in Page.
+                                                        Number of unique primitives stored in this page.
+                                                        The memory manager will re-use this page when the RCNT drops to zero.  
+*/
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_RCNT_WOFF             (0U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_RCNT_SHIFT            (22U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_RCNT_CLRMSK           (0XC03FFFFFU)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_SET_RCNT(_ft_,_x_)    ((_ft_).u32_0 = (((_ft_).u32_0 & RGX_RPM_DATA_RTU_PAGE_TABLE_RCNT_CLRMSK ) | (((_x_) & (0x000000ff))  <<  22)))
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_GET_RCNT(_ft_)        (((_ft_).u32_0  >>  (22)) & 0x000000ff)
+/*
+Next page table index.
+                                                        The field is a pointer to the next page for this primitive.  
+*/
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_NPTI_WOFF             (0U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_NPTI_SHIFT            (0U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_NPTI_CLRMSK           (0XFFC00000U)
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_SET_NPTI(_ft_,_x_)    ((_ft_).u32_0 = (((_ft_).u32_0 & RGX_RPM_DATA_RTU_PAGE_TABLE_NPTI_CLRMSK ) | (((_x_) & (0x003fffff))  <<  0)))
+#define RGX_RPM_DATA_RTU_PAGE_TABLE_GET_NPTI(_ft_)        (((_ft_).u32_0  >>  (0)) & 0x003fffff)
+
+
+#define RGX_CR_RPM_PAGE_TABLE_BASE_VALUE_ALIGNSHIFT		(2U)
+#define RGX_CR_RPM_SHF_FPL_BASE_ALIGNSHIFT				(2U)
+
+
+typedef struct {
+	DEVMEM_MEMDESC				*psContextStateMemDesc;
+	RGX_SERVER_COMMON_CONTEXT	*psServerCommonContext;
+	IMG_UINT32					ui32Priority;
+#if 0	
+	/* FIXME - multiple frame contexts? */
+	RGX_RPM_FREELIST				*psSHFFreeList;
+	RGX_RPM_FREELIST				*psSHGFreeList;
+#endif
+} RGX_SERVER_RAY_SH_DATA;
+
+
+typedef enum {
+	NODE_EMPTY = 0,
+	NODE_SCENE_HIERARCHY,
+	NODE_RPM_PAGE_TABLE,
+	NODE_RPM_FREE_PAGE_LIST
+} RGX_DEVMEM_NODE_TYPE;
+
+typedef struct _RGX_DEVMEM_NODE_ {
+	RGX_DEVMEM_NODE_TYPE	eNodeType;			/*!< Alloc type */
+	PMR						*psPMR; 			/*!< Scene hierarchy/page table/free page list phys pages */
+	DEVMEMINT_HEAP			*psDevMemHeap;		/*!< Heap where the virtual mapping is made */
+	IMG_DEV_VIRTADDR		sAddr;				/*!< GPU virtual address where the phys pages are mapped into */
+	IMG_UINT32				ui32NumPhysPages;	/*!< Number of physical pages mapped in for this node */
+	IMG_UINT32				ui32StartOfMappingIndex;	/*!< Start of mapping index (i.e. OS page offset from virtual base) */
+	IMG_BOOL				bInternal;
+} RGX_DEVMEM_NODE;
+
+typedef struct _RGX_RPM_DEVMEM_DESC_ {
+	DLLIST_NODE			sMemoryDescBlock;		/*!< the hierarchy scene memory block  */
+	RGX_RPM_FREELIST	*psFreeList;			/*!< Free list this allocation is associated with */
+	IMG_UINT32			ui32NumPages;			/*!< Number of RPM pages added */
+	RGX_DEVMEM_NODE		sSceneHierarchyNode;	/*!< scene hierarchy block descriptor */
+	RGX_DEVMEM_NODE		sRPMPageListNode;		/*!< RPM page list block descriptor */
+	RGX_DEVMEM_NODE		sRPMFreeListNode;		/*!< RPM free list block descriptor */
+} RGX_RPM_DEVMEM_DESC;
+
+typedef struct _DEVMEM_RPM_FREELIST_LOOKUP_
+{
+	IMG_UINT32 ui32FreeListID;
+	RGX_RPM_FREELIST *psFreeList;
+} DEVMEM_RPM_FREELIST_LOOKUP;
+
+typedef struct {
+	RGX_SERVER_COMMON_CONTEXT	*psServerCommonContext;
+	IMG_UINT32					ui32Priority;
+	RGX_CLIENT_CCB *psFCClientCCB[DPX_MAX_RAY_CONTEXTS];
+	DEVMEM_MEMDESC *psFCClientCCBMemDesc[DPX_MAX_RAY_CONTEXTS];
+	DEVMEM_MEMDESC *psFCClientCCBCtrlMemDesc[DPX_MAX_RAY_CONTEXTS];
+} RGX_SERVER_RAY_RS_DATA;
+
+
+struct _RGX_SERVER_RAY_CONTEXT_ {
+	PVRSRV_DEVICE_NODE			*psDeviceNode;
+	DEVMEM_MEMDESC				*psFWRayContextMemDesc;
+	DEVMEM_MEMDESC				*psFWFrameworkMemDesc;
+	RGX_SERVER_RAY_SH_DATA		sSHData;
+	RGX_SERVER_RAY_RS_DATA		sRSData;
+	IMG_UINT32					ui32CleanupStatus;
+#define RAY_CLEANUP_SH_COMPLETE		(1 << 0)
+#define RAY_CLEANUP_RS_COMPLETE		(1 << 1)
+	PVRSRV_CLIENT_SYNC_PRIM		*psCleanupSync;
+	DLLIST_NODE					sListNode;
+	SYNC_ADDR_LIST				sSyncAddrListFence;
+	SYNC_ADDR_LIST				sSyncAddrListUpdate;
+	ATOMIC_T					hJobId;
+};
+
+
+#if 0
+static
+#ifdef __GNUC__
+	__attribute__((noreturn))
+#endif
+void sleep_for_ever(void)
+{
+#if defined(__KLOCWORK__) // klocworks would report an infinite loop because of while(1).
+	PVR_ASSERT(0); 
+#else
+	while(1)
+	{
+		OSSleepms(~0); // sleep the maximum amount of time possible
+	}
+#endif
+}
+#endif
+
+static
+PVRSRV_ERROR _RGXCreateRPMSparsePMR(CONNECTION_DATA *psConnection,
+									PVRSRV_DEVICE_NODE	 *psDeviceNode,
+									RGX_DEVMEM_NODE_TYPE eBlockType,
+									IMG_UINT32		ui32NumPages,
+									IMG_UINT32		uiLog2DopplerPageSize,
+									PMR				**ppsPMR);
+
+static PVRSRV_ERROR _RGXMapRPMPBBlock(RGX_DEVMEM_NODE	*psDevMemNode,
+					RGX_RPM_FREELIST *psFreeList,
+					RGX_DEVMEM_NODE_TYPE eBlockType,
+					DEVMEMINT_HEAP *psDevmemHeap,
+					IMG_UINT32 ui32NumPages,
+					IMG_DEV_VIRTADDR sDevVAddrBase);
+
+static
+PVRSRV_ERROR _RGXUnmapRPMPBBlock(RGX_DEVMEM_NODE	*psDevMemNode,
+					RGX_RPM_FREELIST *psFreeList,
+					IMG_DEV_VIRTADDR sDevVAddrBase);
+
+static
+PVRSRV_ERROR _CreateSHContext(CONNECTION_DATA *psConnection,
+							  PVRSRV_DEVICE_NODE *psDeviceNode,
+							  DEVMEM_MEMDESC *psAllocatedMemDesc,
+							  IMG_UINT32 ui32AllocatedOffset,
+							  DEVMEM_MEMDESC *psFWMemContextMemDesc,
+							  IMG_DEV_VIRTADDR sVRMCallStackAddr,
+							  IMG_UINT32 ui32Priority,
+							  RGX_COMMON_CONTEXT_INFO *psInfo,
+							  RGX_SERVER_RAY_SH_DATA *psSHData)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	RGXFWIF_VRDMCTX_STATE *psContextState;
+	PVRSRV_ERROR eError;
+	/*
+		Allocate device memory for the firmware GPU context suspend state.
+		Note: the FW reads/writes the state to memory by accessing the GPU register interface.
+	*/
+	PDUMPCOMMENT("Allocate RGX firmware SHG context suspend state");
+
+	eError = DevmemFwAllocate(psDevInfo,
+							  sizeof(RGXFWIF_VRDMCTX_STATE),
+							  RGX_FWCOMCTX_ALLOCFLAGS,
+							  "FwRaySHGContextSuspendState",
+							  &psSHData->psContextStateMemDesc);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to allocate firmware GPU context suspend state (%u)",
+				eError));
+		goto fail_shcontextsuspendalloc;
+	}
+
+	eError = DevmemAcquireCpuVirtAddr(psSHData->psContextStateMemDesc,
+                                      (void **)&psContextState);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to map firmware render context state (%u)",
+				eError));
+		goto fail_suspendcpuvirtacquire;
+	}
+	psContextState->uVRDMReg_VRM_CALL_STACK_POINTER = sVRMCallStackAddr.uiAddr;
+	DevmemReleaseCpuVirtAddr(psSHData->psContextStateMemDesc);
+
+	eError = FWCommonContextAllocate(psConnection,
+									 psDeviceNode,
+									 REQ_TYPE_SH,
+									 RGXFWIF_DM_SHG,
+									 psAllocatedMemDesc,
+									 ui32AllocatedOffset,
+									 psFWMemContextMemDesc,
+									 psSHData->psContextStateMemDesc,
+									 RGX_RTU_CCB_SIZE_LOG2,
+									 ui32Priority,
+									 psInfo,
+									 &psSHData->psServerCommonContext);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to init TA fw common context (%u)",
+				eError));
+		goto fail_shcommoncontext;
+	}
+	
+	/*
+	 * Dump the FW SH context suspend state buffer
+	 */
+	PDUMPCOMMENT("Dump the SH context suspend state buffer");
+	DevmemPDumpLoadMem(psSHData->psContextStateMemDesc,
+					   0,
+					   sizeof(RGXFWIF_VRDMCTX_STATE),
+					   PDUMP_FLAGS_CONTINUOUS);
+
+	psSHData->ui32Priority = ui32Priority;
+	return PVRSRV_OK;
+
+fail_shcommoncontext:
+fail_suspendcpuvirtacquire:
+	DevmemFwFree(psDevInfo, psSHData->psContextStateMemDesc);
+fail_shcontextsuspendalloc:
+	PVR_ASSERT(eError != PVRSRV_OK);
+
+	return eError;
+}
+
+static
+PVRSRV_ERROR _CreateRSContext(CONNECTION_DATA *psConnection,
+							  PVRSRV_DEVICE_NODE *psDeviceNode,
+							  DEVMEM_MEMDESC *psAllocatedMemDesc,
+							  IMG_UINT32 ui32AllocatedOffset,
+							  DEVMEM_MEMDESC *psFWMemContextMemDesc,
+							  IMG_UINT32 ui32Priority,
+							  RGX_COMMON_CONTEXT_INFO *psInfo,
+							  RGX_SERVER_RAY_RS_DATA *psRSData)
+{
+	PVRSRV_ERROR eError;
+
+	eError = FWCommonContextAllocate(psConnection,
+									 psDeviceNode,
+									 REQ_TYPE_RS,
+									 RGXFWIF_DM_RTU,
+									 psAllocatedMemDesc,
+									 ui32AllocatedOffset,
+									 psFWMemContextMemDesc,
+                                     NULL,
+									 RGX_RTU_CCB_SIZE_LOG2,
+									 ui32Priority,
+									 psInfo,
+									 &psRSData->psServerCommonContext);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to init 3D fw common context (%u)",
+				eError));
+		goto fail_rscommoncontext;
+	}
+
+	psRSData->ui32Priority = ui32Priority;
+	return PVRSRV_OK;
+
+fail_rscommoncontext:
+	PVR_ASSERT(eError != PVRSRV_OK);
+
+	return eError;
+}
+
+
+/*
+	Static functions used by ray context code
+*/
+
+static
+PVRSRV_ERROR _DestroySHContext(RGX_SERVER_RAY_SH_DATA *psSHData,
+							   PVRSRV_DEVICE_NODE *psDeviceNode,
+							   PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+{
+	PVRSRV_ERROR eError;
+
+	/* Check if the FW has finished with this resource ... */
+	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+											  psSHData->psServerCommonContext,
+											  psCleanupSync,
+											  RGXFWIF_DM_SHG,
+											  PDUMP_FLAGS_NONE);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		return eError;
+	}
+	else if (eError != PVRSRV_OK)
+	{
+		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+				__FUNCTION__,
+				PVRSRVGetErrorStringKM(eError)));
+		return eError;
+	}
+
+	/* ... it has so we can free its resources */
+	FWCommonContextFree(psSHData->psServerCommonContext);
+	DevmemFwFree(psDeviceNode->pvDevice, psSHData->psContextStateMemDesc);
+	psSHData->psContextStateMemDesc = NULL;
+	psSHData->psServerCommonContext = NULL;
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR _DestroyRSContext(RGX_SERVER_RAY_RS_DATA *psRSData,
+							   PVRSRV_DEVICE_NODE *psDeviceNode,
+							   PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+{
+	PVRSRV_ERROR eError;
+
+	/* Check if the FW has finished with this resource ... */
+	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+											  psRSData->psServerCommonContext,
+											  psCleanupSync,
+											  RGXFWIF_DM_RTU,
+											  PDUMP_FLAGS_NONE);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		return eError;
+	}
+	else if (eError != PVRSRV_OK)
+	{
+		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+				 __FUNCTION__,
+				 PVRSRVGetErrorStringKM(eError)));
+		return eError;
+	}
+
+	/* ... it has so we can free its resources */
+
+
+	FWCommonContextFree(psRSData->psServerCommonContext);
+	psRSData->psServerCommonContext = NULL;
+	return PVRSRV_OK;
+}
+
+
+/*
+ * RPM driver management rev 2
+ * 
+ * The RPM freelists are opaque to the client driver. Scene Hierarchy pages
+ * are managed in Blocks (analogous to PB blocks) which are alloc'd in KM
+ * and mapped into the client MMU context.
+ * 
+ * Page tables are set up for each existing Scene Memory Block.
+ * 
+ * Freelist entries are also updated according to the list of Scene Memory Blocks.
+ * 
+ * NOTES:
+ * 
+ * (1) Scene Hierarchy shrink is not expected to be used.
+ * (2) The RPM FreeLists are Circular buffers and must be contiguous in virtual space
+ * (3) Each PMR is created with no phys backing pages. Pages are mapped in on-demand
+ * via RGXGrowRPMFreeList.
+ * 
+ */
+#if defined(DEBUG)
+static PVRSRV_ERROR _ReadRPMFreePageList(PMR		 *psPMR,
+										 IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+										 IMG_UINT32  ui32PageCount)
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		uiIdx, j;
+	size_t			uNumBytesCopied;
+	RGX_RPM_DATA_RTU_FREE_PAGE_LIST		*psFreeListBuffer;
+	IMG_UINT32		ui32PTI[4];
+
+	/* Allocate scratch area for setting up Page table indices */
+	psFreeListBuffer = OSAllocMem(ui32PageCount * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST));
+    if (psFreeListBuffer == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_WriteRPMPageList: failed to allocate scratch page table"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	
+	/* Read scratch buffer from PMR (FPL entries must be contiguous) */
+	eError = PMR_ReadBytes(psPMR,
+				 uiLogicalOffset,
+				 (IMG_UINT8 *) psFreeListBuffer,
+				 ui32PageCount * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST),
+				 &uNumBytesCopied);
+
+	if (eError == PVRSRV_OK)
+	{
+		for (uiIdx = 0; uiIdx < ui32PageCount; uiIdx +=4)
+		{
+			for (j=0; j<4; j++)
+			{
+				ui32PTI[j] = RGX_RPM_DATA_RTU_FREE_PAGE_LIST_GET_PTI(psFreeListBuffer[uiIdx + j]);
+			}
+			PVR_DPF((PVR_DBG_MESSAGE, "%4d:  %7d %7d %7d %7d", uiIdx,
+					ui32PTI[0], ui32PTI[1], ui32PTI[2], ui32PTI[3]));
+		}
+	}
+
+	/* Free scratch buffer */
+	OSFreeMem(psFreeListBuffer);
+
+	return eError;
+}
+
+static IMG_BOOL RGXDumpRPMFreeListPageList(RGX_RPM_FREELIST *psFreeList)
+{
+	PVR_LOG(("RPM Freelist FWAddr 0x%08x, ID = %d, CheckSum 0x%016llx",
+				psFreeList->sFreeListFWDevVAddr.ui32Addr,
+				psFreeList->ui32FreelistID,
+				psFreeList->ui64FreelistChecksum));
+
+	/* Dump FreeList page list */
+	_ReadRPMFreePageList(psFreeList->psFreeListPMR, 0, psFreeList->ui32CurrentFLPages);
+
+	return IMG_TRUE;
+}
+#endif
+
+static PVRSRV_ERROR _UpdateFwRPMFreelistSize(RGX_RPM_FREELIST *psFreeList,
+											 IMG_BOOL bGrow,
+											 IMG_BOOL bRestartRPM,
+											 IMG_UINT32 ui32DeltaSize)
+{
+	PVRSRV_ERROR			eError;
+	RGXFWIF_KCCB_CMD		sGPCCBCmd;
+
+	if(!bGrow)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_UpdateFwRPMFreelistSize: RPM freelist shrink not supported."));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* send feedback */
+	sGPCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_DOPPLER_MEMORY_GROW;
+	sGPCCBCmd.uCmdData.sFreeListGSData.sFreeListFWDevVAddr.ui32Addr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
+	sGPCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32DeltaSize;
+	sGPCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = 
+		((bRestartRPM) ? RGX_FREELIST_GSDATA_RPM_RESTART_EN : 0) |
+		psFreeList->ui32CurrentFLPages;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "Send FW update: RPM freelist [FWAddr=0x%08x] has 0x%08x pages",
+								psFreeList->sFreeListFWDevVAddr.ui32Addr,
+								psFreeList->ui32CurrentFLPages));
+
+	/* Submit command to the firmware.  */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psFreeList->psDevInfo,
+									RGXFWIF_DM_GP,
+									&sGPCCBCmd,
+									sizeof(sGPCCBCmd),
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_UpdateFwRPMFreelistSize: failed to update FW freelist size. (error = %u)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+#if 0
+static void _CheckRPMFreelist(RGX_RPM_FREELIST *psFreeList,
+                   	   	   	   IMG_UINT32 ui32NumOfPagesToCheck,
+                   	   	   	   IMG_UINT64 ui64ExpectedCheckSum,
+                   	   	   	   IMG_UINT64 *pui64CalculatedCheckSum)
+{
+#if defined(NO_HARDWARE)
+	/* No checksum needed as we have all information in the pdumps */
+	PVR_UNREFERENCED_PARAMETER(psFreeList);
+	PVR_UNREFERENCED_PARAMETER(ui32NumOfPagesToCheck);
+	PVR_UNREFERENCED_PARAMETER(ui64ExpectedCheckSum);
+	*pui64CalculatedCheckSum = 0;
+#else
+	PVRSRV_ERROR eError;
+	size_t uiNumBytes;
+    IMG_UINT8* pui8Buffer;
+    IMG_UINT32* pui32Buffer;
+    IMG_UINT32 ui32CheckSumAdd = 0;
+    IMG_UINT32 ui32CheckSumXor = 0;
+    IMG_UINT32 ui32Entry;
+    IMG_UINT32 ui32Entry2;
+    IMG_BOOL  bFreelistBad = IMG_FALSE;
+
+	*pui64CalculatedCheckSum = 0;
+
+	/* Allocate Buffer of the size of the freelist */
+	pui8Buffer = OSAllocMem(psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
+    if (pui8Buffer == NULL)
+    {
+		PVR_LOG(("_CheckRPMFreelist: Failed to allocate buffer to check freelist %p!", psFreeList));
+		sleep_for_ever();
+		//PVR_ASSERT(0);
+        return;
+    }
+
+    /* Copy freelist content into Buffer */
+    eError = PMR_ReadBytes(psFreeList->psFreeListPMR,
+    				psFreeList->uiFreeListPMROffset + (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) * sizeof(IMG_UINT32),
+    				pui8Buffer,
+    				psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32),
+            		&uiNumBytes);
+    if (eError != PVRSRV_OK)
+    {
+		OSFreeMem(pui8Buffer);
+		PVR_LOG(("_CheckRPMFreelist: Failed to get freelist data for RPM freelist %p!", psFreeList));
+		sleep_for_ever();
+		//PVR_ASSERT(0);
+        return;
+    }
+
+    PVR_ASSERT(uiNumBytes == psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
+    PVR_ASSERT(ui32NumOfPagesToCheck <= psFreeList->ui32CurrentFLPages);
+
+    /* Generate checksum */
+    pui32Buffer = (IMG_UINT32 *)pui8Buffer;
+    for(ui32Entry = 0; ui32Entry < ui32NumOfPagesToCheck; ui32Entry++)
+    {
+    	ui32CheckSumAdd += pui32Buffer[ui32Entry];
+    	ui32CheckSumXor ^= pui32Buffer[ui32Entry];
+
+    	/* Check for double entries */
+    	for (ui32Entry2 = 0; ui32Entry2 < ui32NumOfPagesToCheck; ui32Entry2++)
+    	{
+			if ((ui32Entry != ui32Entry2) &&
+				(pui32Buffer[ui32Entry] == pui32Buffer[ui32Entry2]))
+			{
+				PVR_LOG(("_CheckRPMFreelist: RPM Freelist consistency failure: FW addr: 0x%08X, Double entry found 0x%08x on idx: %d and %d of %d",
+											psFreeList->sFreeListFWDevVAddr.ui32Addr,
+											pui32Buffer[ui32Entry2],
+											ui32Entry,
+											ui32Entry2,
+											psFreeList->ui32CurrentFLPages));
+				bFreelistBad = IMG_TRUE;
+			}
+    	}
+    }
+
+    OSFreeMem(pui8Buffer);
+
+	/* Check the calculated checksum against the expected checksum... */
+	*pui64CalculatedCheckSum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
+
+	if (ui64ExpectedCheckSum != 0  &&  ui64ExpectedCheckSum != *pui64CalculatedCheckSum)
+	{
+		PVR_LOG(("_CheckRPMFreelist: Checksum mismatch for RPM freelist %p!  Expected 0x%016llx calculated 0x%016llx",
+		        psFreeList, ui64ExpectedCheckSum, *pui64CalculatedCheckSum));
+		bFreelistBad = IMG_TRUE;
+	}
+    
+    if (bFreelistBad)
+    {
+		PVR_LOG(("_CheckRPMFreelist: Sleeping for ever!"));
+		sleep_for_ever();
+//		PVR_ASSERT(!bFreelistBad);
+	}
+#endif
+}
+#endif
+
+static PVRSRV_ERROR _WriteRPMFreePageList(PMR		 *psPMR,
+										  IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+										  IMG_UINT32  ui32NextPageIndex,
+										  IMG_UINT32  ui32PageCount)
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		uiIdx;
+	size_t		uNumBytesCopied;
+	RGX_RPM_DATA_RTU_FREE_PAGE_LIST		*psFreeListBuffer;
+
+	/* Allocate scratch area for setting up Page table indices */
+	psFreeListBuffer = OSAllocMem(ui32PageCount * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST));
+    if (psFreeListBuffer == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_WriteRPMPageList: failed to allocate scratch page table"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	
+	for (uiIdx = 0; uiIdx < ui32PageCount; uiIdx ++, ui32NextPageIndex ++)
+	{
+		psFreeListBuffer[uiIdx].u32_0 = 0;
+		RGX_RPM_DATA_RTU_FREE_PAGE_LIST_SET_PTI(psFreeListBuffer[uiIdx], ui32NextPageIndex);
+	}
+	
+	/* Copy scratch buffer to PMR */
+	eError = PMR_WriteBytes(psPMR,
+				 uiLogicalOffset,
+				 (IMG_UINT8 *) psFreeListBuffer,
+				 ui32PageCount * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST),
+				 &uNumBytesCopied);
+	
+	/* Free scratch buffer */
+	OSFreeMem(psFreeListBuffer);
+
+#if defined(PDUMP)
+	/* Pdump the Page tables */
+	PDUMPCOMMENT("Dump %u RPM free page list entries.", ui32PageCount);
+	PMRPDumpLoadMem(psPMR,
+					uiLogicalOffset,
+					ui32PageCount * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST),
+					PDUMP_FLAGS_CONTINUOUS,
+					IMG_FALSE);
+#endif
+	return eError;
+}
+
+
+static RGX_RPM_FREELIST* FindRPMFreeList(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FreelistID)
+{
+	DLLIST_NODE *psNode, *psNext;
+	RGX_RPM_FREELIST *psFreeList = NULL;
+
+	OSLockAcquire(psDevInfo->hLockRPMFreeList);
+	dllist_foreach_node(&psDevInfo->sRPMFreeListHead, psNode, psNext)
+	{
+		RGX_RPM_FREELIST *psThisFreeList = IMG_CONTAINER_OF(psNode, RGX_RPM_FREELIST, sNode);
+
+		if (psThisFreeList->ui32FreelistID == ui32FreelistID)
+		{
+			psFreeList = psThisFreeList;
+			break;
+		}
+	}
+	OSLockRelease(psDevInfo->hLockRPMFreeList);
+	
+	return psFreeList;
+}
+
+void RGXProcessRequestRPMGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
+							  IMG_UINT32 ui32FreelistID)
+{
+	RGX_RPM_FREELIST *psFreeList = NULL;
+	RGXFWIF_KCCB_CMD sVRDMCCBCmd;
+	IMG_UINT32 ui32GrowValue;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bRestartRPM = IMG_TRUE; /* FIXME */
+
+	PVR_ASSERT(psDevInfo);
+
+	/* find the freelist with the corresponding ID */
+	psFreeList = FindRPMFreeList(psDevInfo, ui32FreelistID);
+
+	if (psFreeList)
+	{
+		/* Try to grow the freelist */
+		eError = RGXGrowRPMFreeList(psFreeList,
+									psFreeList->ui32GrowFLPages,
+									&psFreeList->sMemoryBlockHead);
+		if (eError == PVRSRV_OK)
+		{
+			/* Grow successful, return size of grow size */
+			ui32GrowValue = psFreeList->ui32GrowFLPages;
+
+			psFreeList->ui32NumGrowReqByFW++;
+
+ #if defined(PVRSRV_ENABLE_PROCESS_STATS)
+			/* Update Stats */
+			PVRSRVStatsUpdateFreelistStats(0,
+	                               1, /* Add 1 to the appropriate counter (Requests by FW) */
+	                               psFreeList->ui32InitFLPages,
+	                               psFreeList->ui32NumHighPages,
+	                               psFreeList->ownerPid);
+
+ #endif
+
+		}
+		else
+		{
+			/* Grow failed */
+			ui32GrowValue = 0;
+			PVR_DPF((PVR_DBG_ERROR,"Grow for FreeList %p [ID %d] failed (error %u)",
+									psFreeList,
+									psFreeList->ui32FreelistID,
+									eError));
+		}
+
+		/* send feedback */
+		sVRDMCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_DOPPLER_MEMORY_GROW;
+		sVRDMCCBCmd.uCmdData.sFreeListGSData.sFreeListFWDevVAddr.ui32Addr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
+		sVRDMCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32GrowValue;
+		sVRDMCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = 
+			((bRestartRPM) ? RGX_FREELIST_GSDATA_RPM_RESTART_EN : 0) |
+			(psFreeList->ui32CurrentFLPages);
+
+		PVR_DPF((PVR_DBG_ERROR,"Send feedback to RPM after grow on freelist [ID %d]", ui32FreelistID));
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			eError = RGXScheduleCommand(psDevInfo,
+										RGXFWIF_DM_SHG,
+										&sVRDMCCBCmd,
+										sizeof(sVRDMCCBCmd),
+										0,
+										PDUMP_FLAGS_NONE);
+			if (eError != PVRSRV_ERROR_RETRY)
+			{
+				break;
+			}
+			OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+		} END_LOOP_UNTIL_TIMEOUT();
+		/* Kernel CCB should never fill up, as the FW is processing them right away  */
+
+		PVR_ASSERT(eError == PVRSRV_OK);
+	}
+	else
+	{
+		/* Should never happen */
+		PVR_DPF((PVR_DBG_ERROR,"FreeList Lookup for FreeList ID 0x%08x failed (Populate)", ui32FreelistID));
+		PVR_ASSERT(IMG_FALSE);
+	}
+}
+
+
+/*!
+ * RGXGrowRPMFreeList
+ *
+ * Allocate and map physical backing pages for RPM buffers
+ * 
+ * @param	ppsRPMDevMemDesc - RPM buffer descriptor representing new Scene memory block
+ * 								and its associated RPM page table and free page list entries
+ * @param	psRPMContext - RPM context
+ * @param	psFreeList - RPM freelist descriptor
+ * @param	ui32RequestNumPages - number of RPM pages to add to Doppler scene hierarchy
+ * @param	pListHeader - linked list of RGX_RPM_DEVMEM_DESC blocks
+ * 
+ */
+PVRSRV_ERROR RGXGrowRPMFreeList(RGX_RPM_FREELIST *psFreeList,
+								IMG_UINT32 ui32RequestNumPages,
+								PDLLIST_NODE pListHeader)
+{
+	PVRSRV_ERROR			eError;
+	RGX_SERVER_RPM_CONTEXT	*psRPMContext = psFreeList->psParentCtx;
+	RGX_RPM_DEVMEM_DESC		*psRPMDevMemDesc;
+	IMG_DEVMEM_OFFSET_T		uiPMROffset;
+	IMG_UINT32				ui32NextPageIndex;
+
+	/* Are we allowed to grow ? */
+	if (ui32RequestNumPages > psFreeList->psParentCtx->ui32UnallocatedPages)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXGrowRPMFreeList: Scene Hierarchy buffer exceeded (0x%x pages required, 0x%x pages available).",
+				ui32RequestNumPages, psFreeList->psParentCtx->ui32UnallocatedPages));
+		return PVRSRV_ERROR_RPM_PBSIZE_ALREADY_MAX;
+	}
+
+	/* Allocate descriptor */
+	psRPMDevMemDesc = OSAllocZMem(sizeof(*psRPMDevMemDesc));
+    if (psRPMDevMemDesc == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXGrowRPMFreeList: failed to allocate host data structure"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/*
+	 * Lock protects simultaneous manipulation of:
+	 * - the memory block list
+	 * - the freelist's ui32CurrentFLPages
+	 * - the context's ui32UnallocatedPages
+	 */
+	OSLockAcquire(psFreeList->psDevInfo->hLockRPMFreeList);
+	OSLockAcquire(psFreeList->psDevInfo->hLockRPMContext);
+
+	/* Update the sparse PMRs */
+	psRPMDevMemDesc->psFreeList = psFreeList;
+	psRPMDevMemDesc->ui32NumPages = ui32RequestNumPages;
+	psRPMDevMemDesc->sSceneHierarchyNode.psPMR = psRPMContext->psSceneHierarchyPMR;
+	psRPMDevMemDesc->sRPMPageListNode.psPMR = psRPMContext->psRPMPageTablePMR;
+	psRPMDevMemDesc->sRPMFreeListNode.psPMR = psFreeList->psFreeListPMR;
+
+
+	PVR_DPF((PVR_DBG_MESSAGE, "RGXGrowRPMFreeList: mapping %d pages for Doppler scene memory to VA 0x%llx with heap ID %p",
+			ui32RequestNumPages, psRPMContext->sSceneMemoryBaseAddr.uiAddr, psRPMContext->psSceneHeap));
+
+	/* 
+	 * 1. Doppler scene hierarchy
+	 */
+	PDUMPCOMMENT("Allocate %d pages with mapping index %d for Doppler scene memory.",
+				 ui32RequestNumPages,
+				 psRPMContext->ui32SceneMemorySparseMappingIndex);
+	eError = _RGXMapRPMPBBlock(&psRPMDevMemDesc->sSceneHierarchyNode,
+					psFreeList,
+					NODE_SCENE_HIERARCHY,
+					psRPMContext->psSceneHeap,
+					ui32RequestNumPages,
+					psRPMContext->sSceneMemoryBaseAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXGrowRPMFreeList: Unable to map RPM scene hierarchy block (status %d)", eError));
+		goto ErrorSceneBlock;
+	}
+
+	/* 
+	 * 2. RPM page list
+	 */
+	if (ui32RequestNumPages > psRPMContext->ui32RPMEntriesInPage)
+	{
+		/* we need to map in phys pages for RPM page table */
+		PDUMPCOMMENT("Allocate %d (%d requested) page table entries with mapping index %d for RPM page table.",
+					 ui32RequestNumPages - psRPMContext->ui32RPMEntriesInPage,
+					 ui32RequestNumPages,
+					 psRPMContext->ui32RPMPageTableSparseMappingIndex);
+		eError = _RGXMapRPMPBBlock(&psRPMDevMemDesc->sRPMPageListNode,
+						psFreeList,
+						NODE_RPM_PAGE_TABLE,
+						psRPMContext->psRPMPageTableHeap,
+						ui32RequestNumPages - psRPMContext->ui32RPMEntriesInPage,
+						psRPMContext->sRPMPageTableBaseAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXGrowRPMFreeList: Unable to map RPM page table block (status %d)", eError));
+			goto ErrorPageTableBlock;
+		}
+	}
+
+	/*
+	 * 3. Free page list (FPL)
+	 */
+	if (ui32RequestNumPages > psFreeList->ui32EntriesInPage)
+	{
+		/* we need to map in phys pages for RPM free page list */
+		PDUMPCOMMENT("Allocate %d (%d requested) FPL entries with mapping index %d for RPM free page list.",
+					 ui32RequestNumPages - psFreeList->ui32EntriesInPage,
+					 ui32RequestNumPages,
+					 psFreeList->ui32RPMFreeListSparseMappingIndex);
+		eError = _RGXMapRPMPBBlock(&psRPMDevMemDesc->sRPMFreeListNode,
+						psFreeList,
+						NODE_RPM_FREE_PAGE_LIST,
+						psRPMContext->psRPMPageTableHeap,
+						ui32RequestNumPages - psFreeList->ui32EntriesInPage,
+						psFreeList->sBaseDevVAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXGrowRPMFreeList: Unable to map RPM free page list (status %d)", eError));
+			goto ErrorFreeListBlock;
+		}
+	}
+
+	/*
+	 * Update FPL entries
+	 */
+
+	/* Calculate doppler page index from base of Doppler heap */
+	ui32NextPageIndex = (psRPMDevMemDesc->sSceneHierarchyNode.sAddr.uiAddr -
+		psRPMContext->sDopplerHeapBaseAddr.uiAddr) >> psFreeList->uiLog2DopplerPageSize;
+
+	/* Calculate write offset into FPL PMR assuming pages are mapped in order with no gaps */
+	uiPMROffset = (size_t)psFreeList->ui32CurrentFLPages * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST);
+
+	eError = _WriteRPMFreePageList(psFreeList->psFreeListPMR, uiPMROffset, ui32NextPageIndex, ui32RequestNumPages);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXGrowRPMFreeList: error writing RPM free list entries (%d)", eError));
+		goto ErrorFreeListWriteEntries;
+	}
+
+	{
+		/* 
+		 * Update the entries remaining in the last mapped RPM and FPL pages.
+		 * 
+		 * psRPMDevMemDesc->sRPMPageListNode.ui32NumPhysPages * 1024 entries are added (can be zero)
+		 * ui32RequestNumPages entries are committed
+		 * 
+		 * The number of entries remaining should always be less than a full page.
+		 */
+		IMG_UINT32	ui32PTEntriesPerChunk = OSGetPageSize() / sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST);
+		IMG_UINT32	ui32PTEntriesPerChunkClearMask = ~(ui32PTEntriesPerChunk - 1);
+
+		psRPMContext->ui32RPMEntriesInPage = psRPMContext->ui32RPMEntriesInPage +
+			(psRPMDevMemDesc->sRPMPageListNode.ui32NumPhysPages * ui32PTEntriesPerChunk) - ui32RequestNumPages;
+		PVR_ASSERT((psRPMContext->ui32RPMEntriesInPage & ui32PTEntriesPerChunkClearMask) == 0);
+
+		psFreeList->ui32EntriesInPage = psFreeList->ui32EntriesInPage +
+			(psRPMDevMemDesc->sRPMFreeListNode.ui32NumPhysPages * ui32PTEntriesPerChunk) - ui32RequestNumPages;
+		PVR_ASSERT((psFreeList->ui32EntriesInPage & ui32PTEntriesPerChunkClearMask) == 0);
+	}
+
+	/* Add node to link list */
+	dllist_add_to_head(pListHeader, &psRPMDevMemDesc->sMemoryDescBlock);
+
+	/* Update number of available pages */
+	psFreeList->ui32CurrentFLPages += ui32RequestNumPages;
+	psRPMContext->ui32UnallocatedPages -= ui32RequestNumPages;
+
+#if defined(DEBUG)
+	RGXDumpRPMFreeListPageList(psFreeList);
+#endif
+
+	OSLockRelease(psFreeList->psDevInfo->hLockRPMContext);
+	OSLockRelease(psFreeList->psDevInfo->hLockRPMFreeList);
+
+	PVR_DPF((PVR_DBG_MESSAGE,"RPM Freelist [%p, ID %d]: grow by %u pages (current pages %u/%u, unallocated pages %u)",
+			psFreeList,
+			psFreeList->ui32FreelistID,
+			ui32RequestNumPages,
+			psFreeList->ui32CurrentFLPages,
+			psRPMContext->ui32TotalRPMPages,
+			psRPMContext->ui32UnallocatedPages));
+
+	return PVRSRV_OK;
+
+	/* Error handling */
+ErrorFreeListWriteEntries:
+	/* TODO: unmap sparse block for RPM FPL */
+ErrorFreeListBlock:
+	/* TODO: unmap sparse block for RPM page table */
+ErrorPageTableBlock:
+	/* TODO: unmap sparse block for scene hierarchy */
+
+ErrorSceneBlock:	
+	OSLockRelease(psFreeList->psDevInfo->hLockRPMContext);
+	OSLockRelease(psFreeList->psDevInfo->hLockRPMFreeList);
+	OSFreeMem(psRPMDevMemDesc);
+
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+static PVRSRV_ERROR RGXShrinkRPMFreeList(PDLLIST_NODE pListHeader,
+										 RGX_RPM_FREELIST *psFreeList)
+{
+	DLLIST_NODE *psNode;
+	RGX_RPM_DEVMEM_DESC	*psRPMDevMemNode;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_UINT32 ui32OldValue;
+
+	/*
+	 * Lock protects simultaneous manipulation of:
+	 * - the memory block list
+	 * - the freelist's ui32CurrentFLPages value
+	 */
+	PVR_ASSERT(pListHeader);
+	PVR_ASSERT(psFreeList);
+	PVR_ASSERT(psFreeList->psDevInfo);
+	PVR_ASSERT(psFreeList->psDevInfo->hLockRPMFreeList);
+
+	OSLockAcquire(psFreeList->psDevInfo->hLockRPMFreeList);
+
+	/********************************************************************
+	 * All scene memory blocks must be freed together as non-contiguous
+	 * virtual mappings are not yet supported.
+	 ********************************************************************/
+
+	/* Get node from head of list and remove it */
+	psNode = dllist_get_next_node(pListHeader);
+	PVR_DPF((PVR_DBG_MESSAGE, "Found node %p", psNode));
+	if (psNode)
+	{
+		dllist_remove_node(psNode);
+
+		psRPMDevMemNode = IMG_CONTAINER_OF(psNode, RGX_RPM_DEVMEM_DESC, sMemoryDescBlock);
+		PVR_ASSERT(psRPMDevMemNode);
+		PVR_ASSERT(psRPMDevMemNode->psFreeList);
+		PVR_ASSERT(psRPMDevMemNode->sSceneHierarchyNode.psPMR);
+
+		/* remove scene hierarchy block */
+		PVR_DPF((PVR_DBG_MESSAGE, "Removing scene hierarchy node"));
+		eError = _RGXUnmapRPMPBBlock(&psRPMDevMemNode->sSceneHierarchyNode,
+									 psRPMDevMemNode->psFreeList,
+									 psFreeList->psParentCtx->sSceneMemoryBaseAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "RGXShrinkRPMFreeList: Failed to unmap %d pages with mapping index %d (status %d)",
+					psRPMDevMemNode->sSceneHierarchyNode.ui32NumPhysPages,
+					psRPMDevMemNode->sSceneHierarchyNode.ui32StartOfMappingIndex,
+					eError));
+			goto UnMapError;
+		}
+
+		/* 
+		 * If the grow size is sub OS page size then the page lists may not need updating 
+		 */
+		if (psRPMDevMemNode->sRPMPageListNode.eNodeType != NODE_EMPTY)
+		{
+			/* unmap the RPM page table backing pages */
+			PVR_DPF((PVR_DBG_MESSAGE, "Removing RPM page list node"));
+			PVR_ASSERT(psRPMDevMemNode->sRPMPageListNode.psPMR);
+			eError = _RGXUnmapRPMPBBlock(&psRPMDevMemNode->sRPMPageListNode,
+										 psRPMDevMemNode->psFreeList,
+										 psFreeList->psParentCtx->sRPMPageTableBaseAddr);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "RGXShrinkRPMFreeList: Failed to unmap %d pages with mapping index %d (status %d)",
+						psRPMDevMemNode->sRPMPageListNode.ui32NumPhysPages,
+						psRPMDevMemNode->sRPMPageListNode.ui32StartOfMappingIndex,
+						eError));
+				goto UnMapError;
+			}
+		}
+
+		if (psRPMDevMemNode->sRPMFreeListNode.eNodeType != NODE_EMPTY)
+		{
+			/* unmap the RPM free page list backing pages */
+			PVR_DPF((PVR_DBG_MESSAGE, "Removing RPM free list node"));
+			PVR_ASSERT(psRPMDevMemNode->sRPMFreeListNode.psPMR);
+			eError = _RGXUnmapRPMPBBlock(&psRPMDevMemNode->sRPMFreeListNode,
+										 psRPMDevMemNode->psFreeList,
+										 psFreeList->sBaseDevVAddr);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "RGXShrinkRPMFreeList: Failed to unmap %d pages with mapping index %d (status %d)",
+						psRPMDevMemNode->sRPMFreeListNode.ui32NumPhysPages,
+						psRPMDevMemNode->sRPMFreeListNode.ui32StartOfMappingIndex,
+						eError));
+				goto UnMapError;
+			}
+		}
+
+		/* update available RPM pages in freelist (NOTE: may be different from phys page count) */
+		ui32OldValue = psFreeList->ui32CurrentFLPages;
+		psFreeList->ui32CurrentFLPages -= psRPMDevMemNode->ui32NumPages;
+
+		/* check underflow */
+		PVR_ASSERT(ui32OldValue > psFreeList->ui32CurrentFLPages);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "Freelist [%p, ID %d]: shrink by %u pages (current pages %u/%u)",
+								psFreeList,
+								psFreeList->ui32FreelistID,
+								psRPMDevMemNode->ui32NumPages,
+								psFreeList->ui32CurrentFLPages,
+								psFreeList->psParentCtx->ui32UnallocatedPages));
+
+		OSFreeMem(psRPMDevMemNode);
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_WARNING,"Freelist [0x%p]: shrink denied. PB already at zero PB size (%u pages)",
+								psFreeList,
+								psFreeList->ui32CurrentFLPages));
+		eError = PVRSRV_ERROR_PBSIZE_ALREADY_MIN;
+	}
+
+	OSLockRelease(psFreeList->psDevInfo->hLockRPMFreeList);
+	return PVRSRV_OK;
+
+UnMapError:
+	OSFreeMem(psRPMDevMemNode);
+	OSLockRelease(psFreeList->psDevInfo->hLockRPMFreeList);
+
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+
+/*!
+ *	_RGXCreateRPMSparsePMR
+ * 
+ * Creates a PMR container with no phys pages initially. Phys pages will be allocated
+ * and mapped later when requested by client or by HW RPM Out of Memory event.
+ * The PMR is created with zero phys backing pages.
+ * The sparse PMR is associated to either the RPM context or to the RPM freelist(s):
+ * 
+ * RGX_SERVER_RPM_CONTEXT - Scene hierarchy, page table
+ * RGX_RPM_FREELIST - free page list PMR
+ * 
+ * @param	eBlockType - whether block is for scene hierarchy pages or page
+ * 				tables. This parameter is used to calculate size.
+ * @param	ui32NumPages - total number of pages
+ * @param	uiLog2DopplerPageSize - log2 Doppler/RPM page size
+ * @param	ppsPMR - (Output) new PMR container.
+ * 
+ * See the documentation for more details.
+ */
+static
+PVRSRV_ERROR _RGXCreateRPMSparsePMR(CONNECTION_DATA *psConnection,
+									PVRSRV_DEVICE_NODE	 *psDeviceNode,
+									RGX_DEVMEM_NODE_TYPE eBlockType,
+									IMG_UINT32		ui32NumPages,
+									IMG_UINT32		uiLog2DopplerPageSize,
+									PMR				**ppsPMR)
+{
+	PVRSRV_ERROR		eError;
+	IMG_DEVMEM_SIZE_T	uiMaxSize = 0;
+	IMG_UINT32			ui32NumVirtPages = 0; /*!< number of virtual pages to cover virtual range */
+	IMG_UINT32			ui32Log2OSPageSize = OSGetPageShift();
+	IMG_UINT32			ui32ChunkSize = OSGetPageSize();
+	PVRSRV_MEMALLOCFLAGS_T uiCustomFlags = 0;
+
+	/* Work out the allocation logical size = virtual size */
+	switch(eBlockType)
+	{
+		case NODE_EMPTY:
+			PVR_ASSERT(IMG_FALSE);
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		case NODE_SCENE_HIERARCHY:
+			PDUMPCOMMENT("Allocate Scene Hierarchy PMR (Pages %08X)", ui32NumPages);
+			uiMaxSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * (1 << uiLog2DopplerPageSize);
+			break;
+		case NODE_RPM_PAGE_TABLE:
+			PDUMPCOMMENT("Allocate RPM Page Table PMR (Page entries %08X)", ui32NumPages);
+			uiMaxSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * sizeof(RGX_RPM_DATA_RTU_PAGE_TABLE);
+			break;
+		case NODE_RPM_FREE_PAGE_LIST:
+			/* 
+			 * Each RPM free page list (FPL) supports the maximum range.
+			 * In practise the maximum range is divided between allocations in each FPL
+			 */
+			PDUMPCOMMENT("Allocate RPM Free Page List PMR (Page entries %08X)", ui32NumPages);
+			uiMaxSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST);
+			uiCustomFlags |= PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; /*(PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_UNCACHED); */
+			break;
+		/* no default case because the build should error out if a case is unhandled */
+	}
+
+	uiMaxSize = (uiMaxSize + ui32ChunkSize - 1) & ~(ui32ChunkSize - 1);
+	ui32NumVirtPages = uiMaxSize >> ui32Log2OSPageSize;
+
+	eError = PhysmemNewRamBackedPMR(psConnection,
+									psDeviceNode,
+									uiMaxSize, /* the maximum size which should match num virtual pages * page size */
+									ui32ChunkSize,
+									0,
+									ui32NumVirtPages,
+									NULL,
+									ui32Log2OSPageSize,
+									(PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING | uiCustomFlags),
+									strlen("RPM Buffer") + 1,
+									"RPM Buffer",
+									ppsPMR);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "_RGXCreateRPMSparsePMR: Failed to allocate sparse PMR of size: 0x%016llX",
+				 (IMG_UINT64)uiMaxSize));
+	}
+	
+	return eError;
+}
+
+/*!
+ *	_RGXMapRPMPBBlock
+ * 
+ * Maps in a block of phys pages for one of the following:
+ * 
+ * NODE_SCENE_HIERARCHY - scene hierarchy
+ * NODE_RPM_PAGE_TABLE - RPM page table entries
+ * NODE_RPM_FREE_PAGE_LIST - RPM free page list entries
+ * 
+ * @param	psDevMemNode - device mem block descriptor (allocated by caller)
+ * @param	psFreeList - free list descriptor
+ * @param	eBlockType - block type: scene memory, RPM page table or RPM page free list
+ * @param	psDevmemHeap - heap for GPU virtual mapping
+ * @param	ui32NumPages - number of pages for scene memory, OR
+ * 							number of PT entries for RPM page table or page free list
+ * @param	sDevVAddrBase - GPU virtual base address i.e. base address at start of sparse allocation
+ * 
+ * @return	PVRSRV_OK if no error occurred
+ */
+static
+PVRSRV_ERROR _RGXMapRPMPBBlock(RGX_DEVMEM_NODE	*psDevMemNode,
+					RGX_RPM_FREELIST *psFreeList,
+					RGX_DEVMEM_NODE_TYPE eBlockType,
+					DEVMEMINT_HEAP *psDevmemHeap,
+					IMG_UINT32 ui32NumPages,
+					IMG_DEV_VIRTADDR sDevVAddrBase)
+{
+	PVRSRV_ERROR	eError;
+    IMG_UINT64 		sCpuVAddrNULL = 0; 			/* no CPU mapping needed */
+	IMG_UINT32		*paui32AllocPageIndices;	/* table of virtual indices for sparse mapping */
+	IMG_PUINT32 	pui32MappingIndex = NULL;	/* virtual index where next physical chunk is mapped */
+	IMG_UINT32		i;
+	size_t			uiSize = 0;
+	IMG_UINT32		ui32Log2OSPageSize = OSGetPageShift();
+	IMG_UINT32		ui32ChunkSize = OSGetPageSize();
+	IMG_UINT32		ui32NumPhysPages = 0; /*!< number of physical pages for data pages or RPM PTs */
+	PVRSRV_MEMALLOCFLAGS_T uiCustomFlags = 0;
+
+
+	/* Allocate Memory Block for scene hierarchy */
+	switch(eBlockType)
+	{
+		case NODE_EMPTY:
+			PVR_ASSERT(IMG_FALSE);
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		case NODE_SCENE_HIERARCHY:
+			PDUMPCOMMENT("Allocate Scene Hierarchy Block (Pages %08X)", ui32NumPages);
+			uiSize = (size_t)ui32NumPages * (1 << psFreeList->psParentCtx->uiLog2DopplerPageSize);
+			pui32MappingIndex = &psFreeList->psParentCtx->ui32SceneMemorySparseMappingIndex;
+			break;
+		case NODE_RPM_PAGE_TABLE:
+			PDUMPCOMMENT("Allocate RPM Page Table Block (Page entries %08X)", ui32NumPages);
+			uiSize = (size_t)ui32NumPages * sizeof(RGX_RPM_DATA_RTU_PAGE_TABLE);
+			pui32MappingIndex = &psFreeList->psParentCtx->ui32RPMPageTableSparseMappingIndex;
+			break;
+		case NODE_RPM_FREE_PAGE_LIST:
+			PDUMPCOMMENT("Allocate RPM Free Page List Block (Page entries %08X)", ui32NumPages);
+			uiSize = (size_t)ui32NumPages * sizeof(RGX_RPM_DATA_RTU_FREE_PAGE_LIST);
+			pui32MappingIndex = &psFreeList->ui32RPMFreeListSparseMappingIndex;
+			uiCustomFlags |= PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; /*(PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE);*/
+			break;
+		/* no default case because the build should error out if a case is unhandled */
+	}
+
+	/* 
+	 * Round size up to multiple of the sparse chunk size = OS page size.
+	 */
+	uiSize = (uiSize + ui32ChunkSize - 1) & ~(ui32ChunkSize - 1);
+	ui32NumPhysPages = uiSize >> ui32Log2OSPageSize;
+
+	paui32AllocPageIndices = OSAllocMem(ui32NumPhysPages * sizeof(IMG_UINT32));
+    if (paui32AllocPageIndices == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_RGXCreateRPMPBBlockSparse: failed to allocate sparse mapping index list"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorAllocHost;
+	}
+	for(i=0; i<ui32NumPhysPages; i++)
+	{
+		paui32AllocPageIndices[i] = *pui32MappingIndex + i;
+	}
+
+	/* Set up some state */
+	psDevMemNode->eNodeType = eBlockType;
+	psDevMemNode->psDevMemHeap = psDevmemHeap;
+	if (eBlockType == NODE_SCENE_HIERARCHY)
+	{
+		/* the mapped-in scene hierarchy device address will be used to set up the FPL entries */
+		psDevMemNode->sAddr.uiAddr = sDevVAddrBase.uiAddr + (*pui32MappingIndex * ui32ChunkSize);
+	}
+	psDevMemNode->ui32NumPhysPages = ui32NumPhysPages;
+	psDevMemNode->ui32StartOfMappingIndex = *pui32MappingIndex;
+
+	{
+		if ((eBlockType == NODE_SCENE_HIERARCHY) &&
+			(ui32NumPhysPages > psFreeList->psParentCtx->ui32UnallocatedPages))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_RGXCreateRPMPBBlockSparse: virtual address space exceeded (0x%x pages required, 0x%x pages available).",
+					ui32NumPhysPages, psFreeList->psParentCtx->ui32UnallocatedPages));
+			OSFreeMem(paui32AllocPageIndices);
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		eError = PMRLockSysPhysAddresses(psDevMemNode->psPMR);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_RGXCreateRPMPBBlockSparse: unable to lock PMR physical pages (status %d)", eError));
+			goto ErrorLockPhys;
+		}
+
+		eError = DevmemIntChangeSparse(psDevmemHeap,
+						psDevMemNode->psPMR,
+						ui32NumPhysPages,
+						paui32AllocPageIndices,
+						0,
+						NULL,
+						SPARSE_RESIZE_ALLOC,
+						(PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | uiCustomFlags),
+						sDevVAddrBase,
+						sCpuVAddrNULL);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_RGXCreateRPMPBBlockSparse: change sparse mapping failed with %d pages starting at %d (status %d)",
+					ui32NumPhysPages, *pui32MappingIndex, eError));
+			goto ErrorSparseMapping;
+		}
+
+		/* FIXME: leave locked until destroy */
+		PMRUnlockSysPhysAddresses(psDevMemNode->psPMR);
+	}
+
+	/* 
+	 * Update the mapping index for the next allocation.
+	 * The virtual pages should be contiguous.
+	 */
+	*pui32MappingIndex += ui32NumPhysPages;
+
+	OSFreeMem(paui32AllocPageIndices);
+
+	return PVRSRV_OK;
+
+ErrorSparseMapping:
+	PMRUnlockSysPhysAddresses(psDevMemNode->psPMR);
+
+ErrorLockPhys:
+	OSFreeMem(paui32AllocPageIndices);
+
+ErrorAllocHost:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+/*!
+ * _RGXUnmapRPMPBBlock
+ * 
+ * NOTE: because the SHF and SHG requests for memory are interleaved, the
+ * page mapping offset cannot be updated (non-contiguous virtual mapping
+ * is not supported).
+ * 
+ * So either
+ *  (i) the allocated virtual address range is unusable after unmap
+ * (ii) all of the scene memory must be freed
+ * 
+ * @param	psDevMemNode - block to free
+ * @param	psFreeList - RPM free list
+ * @param	sDevVAddrBase - the virtual base address (i.e. where page 1 of the PMR is mapped)
+ */
+static
+PVRSRV_ERROR _RGXUnmapRPMPBBlock(RGX_DEVMEM_NODE	*psDevMemNode,
+					RGX_RPM_FREELIST *psFreeList,
+					IMG_DEV_VIRTADDR sDevVAddrBase)
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT64 		sCpuVAddrNULL = 0; 			/* no CPU mapping needed */
+	IMG_UINT32		*paui32FreePageIndices;		/* table of virtual indices for sparse unmapping */
+	IMG_UINT32		i;
+	IMG_UINT32		ui32NumPhysPages = psDevMemNode->ui32NumPhysPages; /*!< number of physical pages for data pages or RPM PTs */
+
+#if defined(PDUMP)
+	/* Free Memory Block for scene hierarchy */
+	switch(psDevMemNode->eNodeType)
+	{
+		case NODE_EMPTY:
+			PVR_ASSERT(IMG_FALSE);
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		case NODE_SCENE_HIERARCHY:
+			PDUMPCOMMENT("Free Scene Hierarchy Block (Pages %08X)", ui32NumPhysPages);
+			break;
+		case NODE_RPM_PAGE_TABLE:
+			PDUMPCOMMENT("Free RPM Page Table Block (Page entries %08X)", ui32NumPhysPages);
+			break;
+		case NODE_RPM_FREE_PAGE_LIST:
+			PDUMPCOMMENT("Free RPM Free Page List Block (Page entries %08X)", ui32NumPhysPages);
+			break;
+		/* no default case because the build should error out if a case is unhandled */
+	}
+#endif
+
+	paui32FreePageIndices = OSAllocMem(ui32NumPhysPages * sizeof(IMG_UINT32));
+    if (paui32FreePageIndices == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_RGXUnmapRPMPBBlock: failed to allocate sparse mapping index list"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorAllocHost;
+	}
+	for(i=0; i<ui32NumPhysPages; i++)
+	{
+		paui32FreePageIndices[i] = psDevMemNode->ui32StartOfMappingIndex + i;
+	}
+
+	{
+		eError = PMRLockSysPhysAddresses(psDevMemNode->psPMR);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_RGXUnmapRPMPBBlock: unable to lock PMR physical pages (status %d)", eError));
+			goto ErrorLockPhys;
+		}
+
+		eError = DevmemIntChangeSparse(psDevMemNode->psDevMemHeap,
+						psDevMemNode->psPMR,
+						0, /* no pages are mapped here */
+						NULL,
+						ui32NumPhysPages,
+						paui32FreePageIndices,
+						SPARSE_RESIZE_FREE,
+						(PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE),
+						sDevVAddrBase,
+						sCpuVAddrNULL);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_RGXUnmapRPMPBBlock: free sparse mapping failed with %d pages starting at %d (status %d)",
+					ui32NumPhysPages, psDevMemNode->ui32StartOfMappingIndex, eError));
+			goto ErrorSparseMapping;
+		}
+
+		PMRUnlockSysPhysAddresses(psDevMemNode->psPMR);
+	}
+
+	OSFreeMem(paui32FreePageIndices);
+
+	return PVRSRV_OK;
+
+ErrorSparseMapping:
+	PMRUnlockSysPhysAddresses(psDevMemNode->psPMR);
+
+ErrorLockPhys:
+	OSFreeMem(paui32FreePageIndices);
+
+ErrorAllocHost:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+
+/*!
+ *	RGXCreateRPMFreeList
+ * 
+ * @param	ui32InitFLPages - initial allocation of mapped-in physical pages
+ * @param	ui32GrowFLPages - physical pages to add to scene hierarchy if RPM OOM occurs
+ * @param	sFreeListDevVAddr - virtual base address of free list
+ * @param	sRPMPageListDevVAddr (DEPRECATED -- cached in RPM Context)
+ * @param	ui32FLSyncAddr (DEPRECATED)
+ * @param	ppsFreeList - returns a RPM freelist handle to client
+ * @param	puiHWFreeList - 'handle' to FW freelist, passed in VRDM kick (FIXME)
+ * @param	bIsExternal - flag which marks if the freelist is an external one
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateRPMFreeList(CONNECTION_DATA *psConnection,
+							   PVRSRV_DEVICE_NODE	 *psDeviceNode, 
+							   RGX_SERVER_RPM_CONTEXT	*psRPMContext,
+							   IMG_UINT32			ui32InitFLPages,
+							   IMG_UINT32			ui32GrowFLPages,
+							   IMG_DEV_VIRTADDR		sFreeListDevVAddr,
+							   RGX_RPM_FREELIST	  **ppsFreeList,
+							   IMG_UINT32		   *puiHWFreeList,
+							   IMG_BOOL				bIsExternal)
+{
+	PVRSRV_ERROR				eError;
+	RGXFWIF_RPM_FREELIST		*psFWRPMFreeList;
+	DEVMEM_MEMDESC				*psFWRPMFreelistMemDesc;
+	RGX_RPM_FREELIST			*psFreeList;
+	PVRSRV_RGXDEV_INFO			*psDevInfo = psDeviceNode->pvDevice;
+
+	/* Allocate kernel freelist struct */
+	psFreeList = OSAllocZMem(sizeof(*psFreeList));
+    if (psFreeList == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMFreeList: failed to allocate host data structure"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorAllocHost;
+	}
+
+	/* Allocate cleanup sync */
+	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+						   &psFreeList->psCleanupSync,
+						   "RPM free list cleanup");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXCreateRPMFreeList: Failed to allocate cleanup sync (0x%x)",
+				eError));
+		goto ErrorSyncAlloc;
+	}
+
+	/*
+	 * This FW FreeList context is only mapped into kernel for initialisation.
+	 * Otherwise this allocation is only used by the FW.
+	 * Therefore the GPU cache doesn't need coherency,
+	 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
+	 * 
+	 * TODO - RPM freelist will be modified after creation, but only from host-side.
+	 */
+	eError = DevmemFwAllocate(psDevInfo,
+							sizeof(*psFWRPMFreeList),
+							PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+							PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+							PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+							PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+							PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+							PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+							PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+							PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+							PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
+							"FwRPMFreeList",
+							&psFWRPMFreelistMemDesc);
+	if (eError != PVRSRV_OK) 
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMFreeList: DevmemAllocate for RGXFWIF_FREELIST failed"));
+		goto ErrorFWFreeListAlloc;
+	}
+
+	/* Initialise host data structures */
+	psFreeList->psConnection = psConnection;
+	psFreeList->psDevInfo = psDevInfo;
+	psFreeList->psParentCtx = psRPMContext;
+	psFreeList->psFWFreelistMemDesc = psFWRPMFreelistMemDesc;
+	psFreeList->sBaseDevVAddr = sFreeListDevVAddr;
+	RGXSetFirmwareAddress(&psFreeList->sFreeListFWDevVAddr, psFWRPMFreelistMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+	psFreeList->ui32FreelistID = psDevInfo->ui32RPMFreelistCurrID++;
+	//psFreeList->ui32MaxFLPages = ui32MaxFLPages;
+	/* TODO: is it really needed? */
+	if(bIsExternal == IMG_FALSE)
+	{
+		psFreeList->ui32InitFLPages = ui32InitFLPages;
+		psFreeList->ui32GrowFLPages = ui32GrowFLPages;
+	}
+	//psFreeList->ui32CurrentFLPages = ui32InitFLPages;
+	psFreeList->ui32RefCount = 0;
+	dllist_init(&psFreeList->sMemoryBlockHead);
+
+	/* Wizard2 -- support per-freelist Doppler virtual page size */
+	psFreeList->uiLog2DopplerPageSize = psRPMContext->uiLog2DopplerPageSize;
+
+	/* Initialise FW data structure */
+	eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWRPMFreeList);
+	PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", ErrorFWFreeListCpuMap);
+
+	/*
+	 * FIXME - the max pages are shared with the other freelists so this
+	 * over-estimates the number of free pages. The full check is
+	 * implemented in RGXGrowRPMFreeList.
+	 */
+	if(bIsExternal == IMG_TRUE)
+	{
+		/* An external RPM FreeList will never grow */
+		psFWRPMFreeList->ui32MaxPages = ui32InitFLPages;
+	}
+	else
+	{
+		psFWRPMFreeList->ui32MaxPages = psFreeList->psParentCtx->ui32TotalRPMPages;
+	}
+	psFWRPMFreeList->ui32CurrentPages = ui32InitFLPages;
+	psFWRPMFreeList->ui32GrowPages = ui32GrowFLPages;
+	psFWRPMFreeList->ui32ReadOffset = 0;
+	psFWRPMFreeList->ui32WriteOffset = RGX_CR_RPM_SHG_FPL_WRITE_TOGGLE_EN; /* FL is full */
+	psFWRPMFreeList->bReadToggle = IMG_FALSE;
+	psFWRPMFreeList->bWriteToggle = IMG_TRUE;
+	psFWRPMFreeList->sFreeListDevVAddr.uiAddr = sFreeListDevVAddr.uiAddr;
+	psFWRPMFreeList->ui32FreeListID = psFreeList->ui32FreelistID;
+	psFWRPMFreeList->bGrowPending = IMG_FALSE;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "RPM Freelist %p created: FW freelist: %p, Init pages 0x%08x, Max FL base address " IMG_DEVMEM_SIZE_FMTSPEC ", Init FL base address " IMG_DEVMEM_SIZE_FMTSPEC,
+			psFreeList,
+			psFWRPMFreeList,
+			ui32InitFLPages,
+			sFreeListDevVAddr.uiAddr,
+			psFWRPMFreeList->sFreeListDevVAddr.uiAddr));
+
+	PVR_DPF((PVR_DBG_MESSAGE,"RPM FW Freelist %p created: sync FW addr 0x%08x", psFWRPMFreeList, psFWRPMFreeList->sSyncAddr));
+
+	PDUMPCOMMENT("Dump FW RPM FreeList");
+	DevmemPDumpLoadMem(psFreeList->psFWFreelistMemDesc, 0, sizeof(*psFWRPMFreeList), PDUMP_FLAGS_CONTINUOUS);
+
+	/*
+	 * Separate dump of the Freelist's number of Pages and stack pointer.
+	 * This allows to easily modify the PB size in the out2.txt files.
+	 */
+	PDUMPCOMMENT("RPM FreeList TotalPages");
+	DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
+							offsetof(RGXFWIF_RPM_FREELIST, ui32CurrentPages),
+							psFWRPMFreeList->ui32CurrentPages,
+							PDUMP_FLAGS_CONTINUOUS);
+
+	PDUMPCOMMENT("RPM FreeList device virtual base address");
+	DevmemPDumpLoadMemValue64(psFreeList->psFWFreelistMemDesc,
+							offsetof(RGXFWIF_RPM_FREELIST, sFreeListDevVAddr),
+							psFWRPMFreeList->sFreeListDevVAddr.uiAddr,
+							PDUMP_FLAGS_CONTINUOUS);
+
+	DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+
+	if (bIsExternal == IMG_TRUE)
+	{
+		/* Mark the freelist as an external */
+		psFreeList->bIsExternal = IMG_TRUE;
+
+		/* In case of an external RPM FreeList it is not needed to:
+		 * 		- create sparse PMR
+		 * 		- allocate physical memory for the freelist
+		 * 		- add it to the list of freelist
+		 */
+
+		/* return values */
+		*puiHWFreeList = psFreeList->sFreeListFWDevVAddr.ui32Addr;
+		*ppsFreeList = psFreeList;
+
+		return PVRSRV_OK;
+	}
+
+	psFreeList->bIsExternal = IMG_FALSE;
+
+	/*
+	 * Create the sparse PMR for the RPM free page list
+	 */
+	eError = _RGXCreateRPMSparsePMR(psConnection, psDeviceNode,
+									NODE_RPM_FREE_PAGE_LIST,
+									psRPMContext->ui32TotalRPMPages,
+									psRPMContext->uiLog2DopplerPageSize,
+									&psFreeList->psFreeListPMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMContext: failed to allocate PMR for RPM Free page list (%d)", eError));
+		goto ErrorSparsePMR;
+	}
+
+	/*
+	 * Lock protects simultaneous manipulation of:
+	 * - the memory block list
+	 * - the freelist's ui32CurrentFLPages
+	 */
+	/* Add to list of freelists */
+	OSLockAcquire(psDevInfo->hLockRPMFreeList);
+	psFreeList->psParentCtx->uiFLRefCount++;
+	dllist_add_to_tail(&psDevInfo->sRPMFreeListHead, &psFreeList->sNode);
+	OSLockRelease(psDevInfo->hLockRPMFreeList);
+
+	/*
+	 * Add initial scene hierarchy block
+	 * Allocate phys memory for scene hierarchy, free page list and RPM page-in-use list
+	 */
+	eError = RGXGrowRPMFreeList(psFreeList, ui32InitFLPages, &psFreeList->sMemoryBlockHead);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMFreeList: error during phys memory allocation and mapping (%d)", eError));
+		goto ErrorGrowFreeList;
+	}
+
+	/* return values */
+	*puiHWFreeList = psFreeList->sFreeListFWDevVAddr.ui32Addr;
+	*ppsFreeList = psFreeList;
+
+	return PVRSRV_OK;
+
+	/* Error handling */
+ErrorGrowFreeList:
+	/* Remove freelists from list  */
+	OSLockAcquire(psDevInfo->hLockRPMFreeList);
+	dllist_remove_node(&psFreeList->sNode);
+	psFreeList->psParentCtx->uiFLRefCount--;
+	OSLockRelease(psDevInfo->hLockRPMFreeList);
+
+ErrorSparsePMR:
+	SyncPrimFree(psFreeList->psCleanupSync);
+
+ErrorFWFreeListCpuMap:
+	RGXUnsetFirmwareAddress(psFWRPMFreelistMemDesc);
+	DevmemFwFree(psDevInfo, psFWRPMFreelistMemDesc);
+
+ErrorFWFreeListAlloc:
+	PMRUnrefPMR(psFreeList->psFreeListPMR);
+
+ErrorSyncAlloc:
+	OSFreeMem(psFreeList);
+
+ErrorAllocHost:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+/*
+ *	RGXDestroyRPMFreeList
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyRPMFreeList(RGX_RPM_FREELIST *psFreeList)
+{
+	PVRSRV_ERROR eError;
+	//IMG_UINT64 ui64CheckSum;
+
+	PVR_ASSERT(psFreeList);
+
+	if(psFreeList->ui32RefCount != 0 && psFreeList->bIsExternal == IMG_FALSE)
+	{
+		/* Freelist still busy */
+		PVR_DPF((PVR_DBG_WARNING, "Freelist %p is busy", psFreeList));
+		return PVRSRV_ERROR_RETRY;
+	}
+
+	/* Freelist is not in use => start firmware cleanup */
+	eError = RGXFWRequestRPMFreeListCleanUp(psFreeList->psDevInfo,
+											psFreeList->sFreeListFWDevVAddr,
+											psFreeList->psCleanupSync);
+	if(eError != PVRSRV_OK)
+	{
+		/* Can happen if the firmware took too long to handle the cleanup request,
+		 * or if SLC-flushes didn't went through (due to some GPU lockup) */
+		return eError;
+	}
+
+	/* update the statistics */
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+	PVRSRVStatsUpdateFreelistStats(psFreeList->ui32NumGrowReqByApp,
+	                               psFreeList->ui32NumGrowReqByFW,
+	                               psFreeList->ui32InitFLPages,
+	                               psFreeList->ui32NumHighPages,
+	                               0); /* FIXME - owner PID */
+#endif
+
+	/* Destroy FW structures */
+	RGXUnsetFirmwareAddress(psFreeList->psFWFreelistMemDesc);
+	DevmemFwFree(psFreeList->psDevInfo, psFreeList->psFWFreelistMemDesc);
+
+	if(psFreeList->bIsExternal == IMG_FALSE)
+	{
+		/* Free the phys mem block descriptors. */
+		PVR_DPF((PVR_DBG_WARNING, "Cleaning RPM freelist index %d", psFreeList->ui32FreelistID));
+		while (!dllist_is_empty(&psFreeList->sMemoryBlockHead))
+		{
+			eError = RGXShrinkRPMFreeList(&psFreeList->sMemoryBlockHead, psFreeList);
+			PVR_ASSERT(eError == PVRSRV_OK);
+		}
+		psFreeList->psParentCtx->uiFLRefCount--;
+
+		/* consistency checks */
+		PVR_ASSERT(dllist_is_empty(&psFreeList->sMemoryBlockHead));
+		PVR_ASSERT(psFreeList->ui32CurrentFLPages == 0);
+
+		/* Free RPM Free page list PMR */
+		eError = PMRUnrefPMR(psFreeList->psFreeListPMR);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "RGXDestroyRPMFreeList: Failed to free RPM free page list PMR %p (error %u)",
+					 psFreeList->psFreeListPMR,
+					 eError));
+			PVR_ASSERT(IMG_FALSE);
+		}
+
+		/* Remove RPM FreeList from list */
+		OSLockAcquire(psFreeList->psDevInfo->hLockRPMFreeList);
+		dllist_remove_node(&psFreeList->sNode);
+		OSLockRelease(psFreeList->psDevInfo->hLockRPMFreeList);
+	}
+
+	SyncPrimFree(psFreeList->psCleanupSync);
+
+	/* free Freelist */
+	OSFreeMem(psFreeList);
+
+	return eError;
+}
+
+
+/*!
+ *	RGXAddBlockToRPMFreeListKM
+ * 
+ * NOTE: This API isn't used but it's provided for symmetry with the parameter
+ * management API.
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXAddBlockToRPMFreeListKM(RGX_RPM_FREELIST *psFreeList,
+										IMG_UINT32 ui32NumPages)
+{
+	PVRSRV_ERROR eError;
+
+	/* Check if we have reference to freelist's PMR */
+	if (psFreeList->psFreeListPMR == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,	"RPM Freelist is not configured for grow"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* grow freelist */
+	eError = RGXGrowRPMFreeList(psFreeList,
+								ui32NumPages,
+								&psFreeList->sMemoryBlockHead);
+	if(eError == PVRSRV_OK)
+	{
+		/* update freelist data in firmware */
+		_UpdateFwRPMFreelistSize(psFreeList, IMG_TRUE, IMG_TRUE, ui32NumPages);
+
+		psFreeList->ui32NumGrowReqByApp++;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+			/* Update Stats */
+			PVRSRVStatsUpdateFreelistStats(1, /* Add 1 to the appropriate counter (Requests by App)*/
+	                               0,
+	                               psFreeList->ui32InitFLPages,
+	                               psFreeList->ui32NumHighPages,
+	                               psFreeList->ownerPid);
+
+#endif
+	}
+
+	return eError;
+}
+
+
+/*
+ * RGXCreateRPMContext
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateRPMContext(CONNECTION_DATA * psConnection,
+								 PVRSRV_DEVICE_NODE	 *psDeviceNode, 
+								 RGX_SERVER_RPM_CONTEXT	**ppsRPMContext,
+								 IMG_UINT32			ui32TotalRPMPages,
+								 IMG_UINT32			uiLog2DopplerPageSize,
+								 IMG_DEV_VIRTADDR	sSceneMemoryBaseAddr,
+								 IMG_DEV_VIRTADDR	sDopplerHeapBaseAddr,
+								 DEVMEMINT_HEAP		*psSceneHeap,
+								 IMG_DEV_VIRTADDR	sRPMPageTableBaseAddr,
+								 DEVMEMINT_HEAP		*psRPMPageTableHeap,
+								 DEVMEM_MEMDESC		**ppsMemDesc,
+							     IMG_UINT32		     *puiHWFrameData)
+{
+	PVRSRV_ERROR					eError;
+	PVRSRV_RGXDEV_INFO 				*psDevInfo = psDeviceNode->pvDevice;
+	//DEVMEM_MEMDESC				*psFWRPMContextMemDesc;
+	RGX_SERVER_RPM_CONTEXT			*psRPMContext;
+	RGXFWIF_RAY_FRAME_DATA			*psFrameData;
+	RGXFWIF_DEV_VIRTADDR 			 sFirmwareAddr;
+
+	/* Allocate kernel RPM context */
+	psRPMContext = OSAllocZMem(sizeof(*psRPMContext));
+    if (psRPMContext == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMContext: failed to allocate host data structure"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorAllocHost;
+	}
+
+	*ppsRPMContext = psRPMContext;
+
+	/* Allocate cleanup sync */
+	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+						   &psRPMContext->psCleanupSync,
+						   "RPM context cleanup");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RGXCreateRPMContext: Failed to allocate cleanup sync (0x%x)",
+				eError));
+		goto ErrorSyncAlloc;
+	}
+
+	/*
+	 * 1. Create the sparse PMR for scene hierarchy
+	 */
+	eError = _RGXCreateRPMSparsePMR(psConnection, psDeviceNode,
+									NODE_SCENE_HIERARCHY,
+									ui32TotalRPMPages,
+									uiLog2DopplerPageSize,
+									&psRPMContext->psSceneHierarchyPMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMContext: failed to allocate PMR for Scene hierarchy (%d)", eError));
+		goto ErrorSparsePMR1;
+	}
+
+	/*
+	 * 2. Create the sparse PMR for the RPM page list
+	 */
+	eError = _RGXCreateRPMSparsePMR(psConnection, psDeviceNode,
+									NODE_RPM_PAGE_TABLE,
+									ui32TotalRPMPages,
+									uiLog2DopplerPageSize,
+									&psRPMContext->psRPMPageTablePMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMContext: failed to allocate PMR for RPM Page list (%d)", eError));
+		goto ErrorSparsePMR2;
+	}
+
+	/* Allocate FW structure and return FW address to client */
+	eError = DevmemFwAllocate(psDevInfo,
+							sizeof(*psFrameData),
+							PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+							PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+							PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+							PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+							PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+							PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+							PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+							PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+							PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
+							"FwRPMContext",
+							ppsMemDesc);
+	if (eError != PVRSRV_OK) 
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXCreateRPMContext: DevmemAllocate for RGXFWIF_FREELIST failed"));
+		goto ErrorFWRPMContextAlloc;
+	}
+
+	/* Update the unallocated pages, which are shared between the RPM freelists */
+	psRPMContext->ui32UnallocatedPages = psRPMContext->ui32TotalRPMPages = ui32TotalRPMPages;
+	psRPMContext->psDeviceNode = psDeviceNode;
+	psRPMContext->psFWRPMContextMemDesc = *ppsMemDesc;
+	psRPMContext->uiLog2DopplerPageSize = uiLog2DopplerPageSize;
+
+	/* Cache the virtual alloc state for future phys page mapping */
+	psRPMContext->sDopplerHeapBaseAddr = sDopplerHeapBaseAddr;
+	psRPMContext->sSceneMemoryBaseAddr = sSceneMemoryBaseAddr;
+	psRPMContext->psSceneHeap = psSceneHeap;
+	psRPMContext->sRPMPageTableBaseAddr = sRPMPageTableBaseAddr;
+	psRPMContext->psRPMPageTableHeap = psRPMPageTableHeap;
+
+	/*
+	 * TODO - implement RPM abort control using HW frame data to track
+	 * abort status in RTU.
+	 */
+	RGXSetFirmwareAddress(&sFirmwareAddr, *ppsMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+	*puiHWFrameData = sFirmwareAddr.ui32Addr;
+
+	//eError = DevmemAcquireCpuVirtAddr(*ppsMemDesc, (void **)&psFrameData);
+	//PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", ErrorFrameDataCpuMap);
+
+	/*
+	 * TODO: pdumping
+	 */
+
+
+	return PVRSRV_OK;
+
+	/* Error handling */
+
+	DevmemReleaseCpuVirtAddr(*ppsMemDesc);
+
+ErrorFWRPMContextAlloc:
+	PMRUnrefPMR(psRPMContext->psRPMPageTablePMR);
+
+ErrorSparsePMR2:
+	PMRUnrefPMR(psRPMContext->psSceneHierarchyPMR);
+
+ErrorSparsePMR1:
+	SyncPrimFree(psRPMContext->psCleanupSync);
+
+ErrorSyncAlloc:
+	OSFreeMem(psRPMContext);
+
+ErrorAllocHost:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}	
+
+
+/*
+ * RGXDestroyRPMContext
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyRPMContext(RGX_SERVER_RPM_CONTEXT *psCleanupData)
+{
+	PVRSRV_ERROR				 eError;
+	PVRSRV_RGXDEV_INFO 			*psDevInfo;
+	PRGXFWIF_RAY_FRAME_DATA		 psFrameData;
+
+	/* Wait for FW to process all commands */
+
+	PVR_ASSERT(psCleanupData);
+
+	RGXSetFirmwareAddress(&psFrameData, psCleanupData->psFWRPMContextMemDesc, 0, RFW_FWADDR_NOREF_FLAG);
+
+	/* Cleanup frame data in SHG */
+	eError = RGXFWRequestRayFrameDataCleanUp(psCleanupData->psDeviceNode,
+										  psFrameData,
+										  psCleanupData->psCleanupSync,
+										  RGXFWIF_DM_SHG);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "FrameData busy in SHG"));
+		return eError;
+	}
+
+	psDevInfo = psCleanupData->psDeviceNode->pvDevice;
+
+	/* Cleanup frame data in RTU */
+	eError = RGXFWRequestRayFrameDataCleanUp(psCleanupData->psDeviceNode,
+										  psFrameData,
+										  psCleanupData->psCleanupSync,
+										  RGXFWIF_DM_RTU);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "FrameData busy in RTU"));
+		return eError;
+	}
+
+	/* Free Scene hierarchy PMR (We should be the only one that holds a ref on the PMR) */
+	eError = PMRUnrefPMR(psCleanupData->psSceneHierarchyPMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "RGXDestroyRPMContext: Failed to free scene hierarchy PMR %p (error %u)",
+				 psCleanupData->psSceneHierarchyPMR,
+				 eError));
+		PVR_ASSERT(IMG_FALSE);
+	}
+
+	/* Free RPM Page list PMR */
+	eError = PMRUnrefPMR(psCleanupData->psRPMPageTablePMR);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				 "RGXDestroyRPMContext: Failed to free RPM page list PMR %p (error %u)",
+				 psCleanupData->psRPMPageTablePMR,
+				 eError));
+		PVR_ASSERT(IMG_FALSE);
+	}
+
+	if (psCleanupData->uiFLRefCount > 0)
+	{
+		/* Kernel RPM freelists hold reference to RPM context */
+		PVR_DPF((PVR_DBG_WARNING, "RGXDestroyRPMContext: Free list ref count non-zero."));
+		return PVRSRV_ERROR_NONZERO_REFCOUNT;
+	}
+
+	/* If we got here then SHG and RTU operations on this FrameData have finished */
+	SyncPrimFree(psCleanupData->psCleanupSync);
+
+	/* Free the FW RPM descriptor */
+	RGXUnsetFirmwareAddress(psCleanupData->psFWRPMContextMemDesc);
+	DevmemFwFree(psDevInfo, psCleanupData->psFWRPMContextMemDesc);
+
+	OSFreeMem(psCleanupData);
+
+	return PVRSRV_OK;
+}
+
+
+/*
+ * PVRSRVRGXCreateRayContextKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateRayContextKM(CONNECTION_DATA				*psConnection,
+											PVRSRV_DEVICE_NODE			*psDeviceNode,
+											IMG_UINT32					ui32Priority,
+											IMG_DEV_VIRTADDR			sMCUFenceAddr,
+											IMG_DEV_VIRTADDR			sVRMCallStackAddr,
+											IMG_UINT32					ui32FrameworkRegisterSize,
+											IMG_PBYTE					pabyFrameworkRegisters,
+											IMG_HANDLE					hMemCtxPrivData,
+											RGX_SERVER_RAY_CONTEXT	**ppsRayContext)
+{
+	PVRSRV_ERROR				eError;
+	PVRSRV_RGXDEV_INFO 			*psDevInfo = psDeviceNode->pvDevice;
+	RGX_SERVER_RAY_CONTEXT		*psRayContext;
+	DEVMEM_MEMDESC				*psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+	RGX_COMMON_CONTEXT_INFO		sInfo;
+	RGXFWIF_FWRAYCONTEXT		*pFWRayContext;
+	IMG_UINT32 i;
+
+	/* Prepare cleanup structure */
+    *ppsRayContext= NULL;
+	psRayContext = OSAllocZMem(sizeof(*psRayContext));
+    if (psRayContext == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psRayContext->psDeviceNode = psDeviceNode;
+
+	/*
+		Allocate device memory for the firmware ray context.
+	*/
+	PDUMPCOMMENT("Allocate RGX firmware ray context");
+
+	eError = DevmemFwAllocate(psDevInfo,
+							sizeof(RGXFWIF_FWRAYCONTEXT),
+							RGX_FWCOMCTX_ALLOCFLAGS,
+							"FwRayContext",
+							&psRayContext->psFWRayContextMemDesc);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to allocate firmware ray context (%u)",
+				eError));
+		goto fail_fwraycontext;
+	}
+					   
+	/* Allocate cleanup sync */
+	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+						   &psRayContext->psCleanupSync,
+						   "Ray context cleanup");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to allocate cleanup sync (0x%x)",
+				eError));
+		goto fail_syncalloc;
+	}
+	
+	/* 
+	 * Create the FW framework buffer
+	 */
+	eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, &psRayContext->psFWFrameworkMemDesc, ui32FrameworkRegisterSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to allocate firmware GPU framework state (%u)",
+				eError));
+		goto fail_frameworkcreate;
+	}
+	
+	/* Copy the Framework client data into the framework buffer */
+	eError = PVRSRVRGXFrameworkCopyCommand(psRayContext->psFWFrameworkMemDesc, pabyFrameworkRegisters, ui32FrameworkRegisterSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRayContextKM: Failed to populate the framework buffer (%u)",
+				eError));
+		goto fail_frameworkcopy;
+	}
+
+	sInfo.psFWFrameworkMemDesc = psRayContext->psFWFrameworkMemDesc;
+	sInfo.psMCUFenceAddr = &sMCUFenceAddr;
+	
+	eError = _CreateSHContext(psConnection,
+							  psDeviceNode,
+							  psRayContext->psFWRayContextMemDesc,
+							  offsetof(RGXFWIF_FWRAYCONTEXT, sSHGContext),
+							  psFWMemContextMemDesc,
+							  sVRMCallStackAddr,
+							  ui32Priority,
+							  &sInfo,
+							  &psRayContext->sSHData);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_shcontext;
+	}
+
+	eError = _CreateRSContext(psConnection,
+							  psDeviceNode,
+							  psRayContext->psFWRayContextMemDesc,
+							  offsetof(RGXFWIF_FWRAYCONTEXT, sRTUContext),
+							  psFWMemContextMemDesc,
+							  ui32Priority,
+							  &sInfo,
+							  &psRayContext->sRSData);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_rscontext;
+	}
+		
+	/*
+		Temporarily map the firmware context to the kernel and init it
+	*/
+	eError = DevmemAcquireCpuVirtAddr(psRayContext->psFWRayContextMemDesc,
+									  (void **)&pFWRayContext);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware %s ray context to CPU",
+								__FUNCTION__,
+								PVRSRVGetErrorStringKM(eError)));
+		goto fail_rscontext;
+	}
+
+	
+	for (i = 0; i < DPX_MAX_RAY_CONTEXTS; i++)
+	{
+		/* Allocate the frame context client CCB */
+		eError = RGXCreateCCB(psDevInfo,
+							  RGX_RTU_CCB_SIZE_LOG2,
+							  psConnection,
+							  REQ_TYPE_FC0 + i,
+							  psRayContext->sRSData.psServerCommonContext,
+							  &psRayContext->sRSData.psFCClientCCB[i],
+							  &psRayContext->sRSData.psFCClientCCBMemDesc[i],
+							  &psRayContext->sRSData.psFCClientCCBCtrlMemDesc[i]);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: failed to create CCB for frame context %u (%s)",
+									__FUNCTION__,
+									i,
+									PVRSRVGetErrorStringKM(eError)));
+			goto fail_rscontext;
+		}
+
+		/* Set the firmware CCB device addresses in the firmware common context */
+		RGXSetFirmwareAddress(&pFWRayContext->psCCB[i],
+							  psRayContext->sRSData.psFCClientCCBMemDesc[i],
+							  0, RFW_FWADDR_FLAG_NONE);
+		RGXSetFirmwareAddress(&pFWRayContext->psCCBCtl[i],
+							  psRayContext->sRSData.psFCClientCCBCtrlMemDesc[i],
+							  0, RFW_FWADDR_FLAG_NONE);
+	}
+	
+	pFWRayContext->ui32ActiveFCMask = 0;
+	pFWRayContext->ui32NextFC = RGXFWIF_INVALID_FRAME_CONTEXT;
+
+	/* We've finished the setup so release the CPU mapping */
+	DevmemReleaseCpuVirtAddr(psRayContext->psFWRayContextMemDesc);	
+		
+	/*
+		As the common context alloc will dump the SH and RS common contexts
+		after the've been setup we skip of the 2 common contexts and dump the
+		rest of the structure
+	*/
+	PDUMPCOMMENT("Dump shared part of ray context context");
+	DevmemPDumpLoadMem(psRayContext->psFWRayContextMemDesc,
+					   (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
+					   sizeof(RGXFWIF_FWRAYCONTEXT) - (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
+					   PDUMP_FLAGS_CONTINUOUS);
+
+	{
+		PVRSRV_RGXDEV_INFO			*psDevInfo = psDeviceNode->pvDevice;
+
+		OSWRLockAcquireWrite(psDevInfo->hRaytraceCtxListLock);
+		dllist_add_to_tail(&(psDevInfo->sRaytraceCtxtListHead), &(psRayContext->sListNode));
+		OSWRLockReleaseWrite(psDevInfo->hRaytraceCtxListLock);
+	}
+
+	*ppsRayContext= psRayContext;
+	return PVRSRV_OK;
+
+fail_rscontext:
+	_DestroySHContext(&psRayContext->sSHData,
+					  psDeviceNode,
+					  psRayContext->psCleanupSync);
+fail_shcontext:
+fail_frameworkcopy:
+	DevmemFwFree(psDevInfo, psRayContext->psFWFrameworkMemDesc);
+fail_frameworkcreate:
+	SyncPrimFree(psRayContext->psCleanupSync);
+fail_syncalloc:
+	DevmemFwFree(psDevInfo, psRayContext->psFWRayContextMemDesc);
+fail_fwraycontext:
+	OSFreeMem(psRayContext);
+	PVR_ASSERT(eError != PVRSRV_OK);
+
+	return eError;
+}
+
+
+/*
+ * PVRSRVRGXDestroyRayContextKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyRayContextKM(RGX_SERVER_RAY_CONTEXT *psRayContext)
+{
+	PVRSRV_ERROR				eError;
+	IMG_UINT32 i;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psRayContext->psDeviceNode->pvDevice;
+
+	/* remove node from list before calling destroy - as destroy, if successful
+	 * will invalidate the node
+	 * must be re-added if destroy fails
+	 */
+	OSWRLockAcquireWrite(psDevInfo->hRaytraceCtxListLock);
+	dllist_remove_node(&(psRayContext->sListNode));
+	OSWRLockReleaseWrite(psDevInfo->hRaytraceCtxListLock);
+
+	/* Cleanup the TA if we haven't already */
+	if ((psRayContext->ui32CleanupStatus & RAY_CLEANUP_SH_COMPLETE) == 0)
+	{
+		eError = _DestroySHContext(&psRayContext->sSHData,
+								   psRayContext->psDeviceNode,
+								   psRayContext->psCleanupSync);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			psRayContext->ui32CleanupStatus |= RAY_CLEANUP_SH_COMPLETE;
+		}
+		else
+		{
+			goto e0;
+		}
+	}
+
+	/* Cleanup the RS if we haven't already */
+	if ((psRayContext->ui32CleanupStatus & RAY_CLEANUP_RS_COMPLETE) == 0)
+	{
+		eError = _DestroyRSContext(&psRayContext->sRSData,
+								   psRayContext->psDeviceNode,
+								   psRayContext->psCleanupSync);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			psRayContext->ui32CleanupStatus |= RAY_CLEANUP_RS_COMPLETE;
+		}
+		else
+		{
+			goto e0;
+		}
+	}
+
+#if 0
+	/*
+	 * 	FIXME - De-allocate RPM freelists (should be called from UM)
+	 */
+	RGXDestroyRPMFreeList(psRayContext->sSHData.psSHFFreeList);
+	RGXDestroyRPMFreeList(psRayContext->sSHData.psSHGFreeList);
+#endif
+	
+	for (i = 0; i < DPX_MAX_RAY_CONTEXTS; i++)
+	{
+		RGXUnsetFirmwareAddress(psRayContext->sRSData.psFCClientCCBMemDesc[i]);
+		RGXUnsetFirmwareAddress(psRayContext->sRSData.psFCClientCCBCtrlMemDesc[i]);
+		RGXDestroyCCB(psDevInfo, psRayContext->sRSData.psFCClientCCB[i]);
+	}
+
+	/*
+		Only if both TA and 3D contexts have been cleaned up can we
+		free the shared resources
+	*/
+	if (psRayContext->ui32CleanupStatus == (RAY_CLEANUP_RS_COMPLETE | RAY_CLEANUP_SH_COMPLETE))
+	{
+		/* Free the framework buffer */
+		DevmemFwFree(psDevInfo, psRayContext->psFWFrameworkMemDesc);
+	
+		/* Free the firmware ray context */
+		DevmemFwFree(psDevInfo, psRayContext->psFWRayContextMemDesc);
+
+		/* Free the cleanup sync */
+		SyncPrimFree(psRayContext->psCleanupSync);
+
+		OSFreeMem(psRayContext);
+	}
+
+	return PVRSRV_OK;
+
+e0:
+	OSWRLockAcquireWrite(psDevInfo->hRaytraceCtxListLock);
+	dllist_add_to_tail(&(psDevInfo->sRaytraceCtxtListHead), &(psRayContext->sListNode));
+	OSWRLockReleaseWrite(psDevInfo->hRaytraceCtxListLock);
+	return eError;
+}
+
+/*
+ * PVRSRVRGXKickRSKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickRSKM(RGX_SERVER_RAY_CONTEXT		*psRayContext,
+								IMG_UINT32					ui32ClientCacheOpSeqNum,
+								IMG_UINT32					ui32ClientFenceCount,
+								SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
+								IMG_UINT32					*paui32ClientFenceSyncOffset,
+								IMG_UINT32					*paui32ClientFenceValue,
+								IMG_UINT32					ui32ClientUpdateCount,
+								SYNC_PRIMITIVE_BLOCK			**pauiClientUpdateUFOSyncPrimBlock,
+								IMG_UINT32					*paui32ClientUpdateSyncOffset,
+								IMG_UINT32					*paui32ClientUpdateValue,
+								IMG_UINT32					ui32ServerSyncPrims,
+								IMG_UINT32					*paui32ServerSyncFlags,
+								SERVER_SYNC_PRIMITIVE 		**pasServerSyncs,
+								IMG_UINT32					ui32CmdSize,
+								IMG_PBYTE					pui8DMCmd,
+								IMG_UINT32					ui32FCCmdSize,
+								IMG_PBYTE					pui8FCDMCmd,
+								IMG_UINT32					ui32FrameContextID,
+								IMG_UINT32					ui32PDumpFlags,
+								IMG_UINT32					ui32ExtJobRef)
+{
+	RGXFWIF_KCCB_CMD		sRSKCCBCmd;
+	RGX_CCB_CMD_HELPER_DATA	asRSCmdHelperData[1] = {{0}};
+	RGX_CCB_CMD_HELPER_DATA asFCCmdHelperData[1] = {{0}};
+	PVRSRV_ERROR			eError;
+	PVRSRV_ERROR			eError1;
+	PVRSRV_ERROR			eError2;
+	RGX_SERVER_RAY_RS_DATA *psRSData = &psRayContext->sRSData;
+	IMG_UINT32				i;
+	IMG_UINT32				ui32FCWoff;
+	IMG_UINT32				ui32RTUCmdOffset = 0;
+	IMG_UINT32				ui32JobId;
+	IMG_UINT32				ui32FWCtx;
+
+	PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+	PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+	PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+	
+	ui32JobId = OSAtomicIncrement(&psRayContext->hJobId);
+
+	eError = SyncAddrListPopulate(&psRayContext->sSyncAddrListFence,
+							ui32ClientFenceCount,
+							pauiClientFenceUFOSyncPrimBlock,
+							paui32ClientFenceSyncOffset);
+	if(eError != PVRSRV_OK)
+	{
+		goto err_populate_sync_addr_list;
+	}
+
+	eError = SyncAddrListPopulate(&psRayContext->sSyncAddrListUpdate,
+							ui32ClientUpdateCount,
+							pauiClientUpdateUFOSyncPrimBlock,
+							paui32ClientUpdateSyncOffset);
+	if(eError != PVRSRV_OK)
+	{
+		goto err_populate_sync_addr_list;
+	}
+
+	/* Sanity check the server fences */
+	for (i=0;i<ui32ServerSyncPrims;i++)
+	{
+		if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on RS) must fence", __FUNCTION__));
+			return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+		}
+	}
+
+	RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRayContext->psDeviceNode->pvDevice,
+	                          & pPreAddr,
+	                          & pPostAddr,
+	                          & pRMWUFOAddr);
+
+
+    if(pui8DMCmd != NULL)
+	{
+		eError = RGXCmdHelperInitCmdCCB(psRSData->psFCClientCCB[ui32FrameContextID],
+	                                0,
+                                    NULL,
+                                    NULL,
+	                                ui32ClientUpdateCount,
+	                                psRayContext->sSyncAddrListUpdate.pasFWAddrs,
+	                                paui32ClientUpdateValue,
+	                                ui32ServerSyncPrims,
+	                                paui32ServerSyncFlags,
+	                                SYNC_FLAG_MASK_ALL,
+	                                pasServerSyncs,
+	                                ui32CmdSize,
+	                                pui8DMCmd,
+	                                & pPreAddr,
+	                                & pPostAddr,
+	                                & pRMWUFOAddr,
+	                                RGXFWIF_CCB_CMD_TYPE_RTU,
+	                                ui32ExtJobRef,
+	                                ui32JobId,
+	                                ui32PDumpFlags,
+	                                NULL,
+	                                "FC",
+	                                asFCCmdHelperData);
+	}
+	else
+	{
+		eError = RGXCmdHelperInitCmdCCB(psRSData->psFCClientCCB[ui32FrameContextID],
+	                                0,
+                                    NULL,
+                                    NULL,
+	                                ui32ClientUpdateCount,
+	                                psRayContext->sSyncAddrListUpdate.pasFWAddrs,
+	                                paui32ClientUpdateValue,
+	                                ui32ServerSyncPrims,
+	                                paui32ServerSyncFlags,
+	                                SYNC_FLAG_MASK_ALL,
+	                                pasServerSyncs,
+	                                ui32CmdSize,
+	                                pui8DMCmd,
+	                                & pPreAddr,
+	                                & pPostAddr,
+	                                & pRMWUFOAddr,
+	                                RGXFWIF_CCB_CMD_TYPE_NULL,
+	                                ui32ExtJobRef,
+	                                ui32JobId,
+	                                ui32PDumpFlags,
+	                                NULL,
+	                                "FC",
+	                                asFCCmdHelperData);
+
+	}
+
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRVRGXKickRSKM_Exit;
+	}
+
+	eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asFCCmdHelperData),
+	                                   asFCCmdHelperData);
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRVRGXKickRSKM_Exit;
+	}
+	
+	ui32FCWoff = RGXCmdHelperGetCommandSize(IMG_ARR_NUM_ELEMS(asFCCmdHelperData),
+	                                        asFCCmdHelperData);
+	
+	*(IMG_UINT32*)pui8FCDMCmd = RGXGetHostWriteOffsetCCB(psRSData->psFCClientCCB[ui32FrameContextID]) + ui32FCWoff;
+
+	/*
+		We should reserved space in the kernel CCB here and fill in the command
+		directly.
+		This is so if there isn't space in the kernel CCB we can return with
+		retry back to services client before we take any operations
+	*/
+
+	/*
+		We might only be kicking for flush out a padding packet so only submit
+		the command if the create was successful
+	*/
+	eError1 = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psRSData->psServerCommonContext),
+	                                 ui32ClientFenceCount,
+	                                 psRayContext->sSyncAddrListFence.pasFWAddrs,
+	                                 paui32ClientFenceValue,
+	                                 0,
+                                     NULL,
+                                     NULL,
+	                                 ui32ServerSyncPrims,
+	                                 paui32ServerSyncFlags,
+	                                 SYNC_FLAG_MASK_ALL,
+	                                 pasServerSyncs,
+	                                 ui32FCCmdSize,
+	                                 pui8FCDMCmd,
+                                     NULL,
+	                                 & pPostAddr,
+	                                 & pRMWUFOAddr,
+	                                 RGXFWIF_CCB_CMD_TYPE_RTU_FC,
+	                                 ui32ExtJobRef,
+	                                 ui32JobId,
+	                                 ui32PDumpFlags,
+	                                 NULL,
+	                                 "RS",
+	                                 asRSCmdHelperData);
+	if (eError1 != PVRSRV_OK)
+	{
+		goto PVRSRVRGXKickRSKM_Exit;
+	}
+
+	eError1 = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asRSCmdHelperData),
+	                                    asRSCmdHelperData);
+	if (eError1 != PVRSRV_OK)
+	{
+		goto PVRSRVRGXKickRSKM_Exit;
+	}
+	
+	
+	/*
+		We should reserved space in the kernel CCB here and fill in the command
+		directly.
+		This is so if there isn't space in the kernel CCB we can return with
+		retry back to services client before we take any operations
+	*/
+
+	/*
+		We might only be kicking for flush out a padding packet so only submit
+		the command if the create was successful
+	*/
+	if (eError == PVRSRV_OK)
+	{
+		/*
+			All the required resources are ready at this point, we can't fail so
+			take the required server sync operations and commit all the resources
+		*/
+		RGXCmdHelperReleaseCmdCCB(IMG_ARR_NUM_ELEMS(asFCCmdHelperData),
+		                          asFCCmdHelperData, "FC", 0);
+	}
+		
+	if (eError1 == PVRSRV_OK)
+	{
+		/*
+			All the required resources are ready at this point, we can't fail so
+			take the required server sync operations and commit all the resources
+		*/
+		ui32RTUCmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRSData->psServerCommonContext));
+		RGXCmdHelperReleaseCmdCCB(IMG_ARR_NUM_ELEMS(asRSCmdHelperData),
+		                          asRSCmdHelperData, "RS",
+		                          FWCommonContextGetFWAddress(psRSData->psServerCommonContext).ui32Addr);
+	}
+	
+	/*
+	 * Construct the kernel RTU CCB command.
+	 * (Safe to release reference to ray context virtual address because
+	 * ray context destruction must flush the firmware).
+	 */
+	sRSKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+	sRSKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRSData->psServerCommonContext);
+	sRSKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRSData->psServerCommonContext));
+	sRSKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+	ui32FWCtx = FWCommonContextGetFWAddress(psRSData->psServerCommonContext).ui32Addr;
+
+	HTBLOGK(HTB_SF_MAIN_KICK_RTU,
+			sRSKCCBCmd.uCmdData.sCmdKickData.psContext,
+			ui32RTUCmdOffset
+			);
+	RGX_HWPERF_HOST_ENQ(psRayContext, OSGetCurrentClientProcessIDKM(),
+	                    ui32FWCtx, ui32ExtJobRef, ui32JobId,
+	                    RGX_HWPERF_KICK_TYPE_RS);
+
+	/*
+	 * Submit the RTU command to the firmware.
+	 */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError2 = RGXScheduleCommand(psRayContext->psDeviceNode->pvDevice,
+									RGXFWIF_DM_RTU,
+									&sRSKCCBCmd,
+									sizeof(sRSKCCBCmd),
+									ui32ClientCacheOpSeqNum,
+									ui32PDumpFlags);
+		if (eError2 != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (eError2 != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKickRSKM failed to schedule kernel RTU command. Error:%u", eError));
+		if (eError == PVRSRV_OK)
+		{
+			eError = eError2;
+		}
+		goto PVRSRVRGXKickRSKM_Exit;
+	}
+	else
+	{
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+		RGXHWPerfFTraceGPUEnqueueEvent(psRayContext->psDeviceNode->pvDevice,
+				ui32FWCtx, ui32JobId, RGX_HWPERF_KICK_TYPE_RS);
+#endif
+	}
+
+
+PVRSRVRGXKickRSKM_Exit:
+err_populate_sync_addr_list:
+	return eError;
+}
+
+/*
+ * PVRSRVRGXKickVRDMKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickVRDMKM(RGX_SERVER_RAY_CONTEXT		*psRayContext,
+								 IMG_UINT32					ui32ClientCacheOpSeqNum,
+								 IMG_UINT32					ui32ClientFenceCount,
+								 SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
+								 IMG_UINT32					*paui32ClientFenceSyncOffset,
+								 IMG_UINT32					*paui32ClientFenceValue,
+								 IMG_UINT32					ui32ClientUpdateCount,
+								 SYNC_PRIMITIVE_BLOCK			**pauiClientUpdateUFOSyncPrimBlock,
+								 IMG_UINT32					*paui32ClientUpdateSyncOffset,
+								 IMG_UINT32					*paui32ClientUpdateValue,
+								 IMG_UINT32					ui32ServerSyncPrims,
+								 IMG_UINT32					*paui32ServerSyncFlags,
+								 SERVER_SYNC_PRIMITIVE 		**pasServerSyncs,
+								 IMG_UINT32					ui32CmdSize,
+								 IMG_PBYTE					pui8DMCmd,
+								 IMG_UINT32					ui32PDumpFlags,
+								 IMG_UINT32					ui32ExtJobRef)
+{
+	RGXFWIF_KCCB_CMD		sSHKCCBCmd;
+	RGX_CCB_CMD_HELPER_DATA	sCmdHelperData;
+	PVRSRV_ERROR			eError;
+	PVRSRV_ERROR			eError2;
+	RGX_SERVER_RAY_SH_DATA *psSHData = &psRayContext->sSHData;
+	IMG_UINT32				i;
+	IMG_UINT32				ui32SHGCmdOffset = 0;
+	IMG_UINT32				ui32JobId;
+	IMG_UINT32				ui32FWCtx;
+
+	PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+	PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+	PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+
+	ui32JobId = OSAtomicIncrement(&psRayContext->hJobId);
+
+	eError = SyncAddrListPopulate(&psRayContext->sSyncAddrListFence,
+							ui32ClientFenceCount,
+							pauiClientFenceUFOSyncPrimBlock,
+							paui32ClientFenceSyncOffset);
+	if(eError != PVRSRV_OK)
+	{
+		goto err_populate_sync_addr_list;
+	}
+
+	eError = SyncAddrListPopulate(&psRayContext->sSyncAddrListUpdate,
+							ui32ClientUpdateCount,
+							pauiClientUpdateUFOSyncPrimBlock,
+							paui32ClientUpdateSyncOffset);
+	if(eError != PVRSRV_OK)
+	{
+		goto err_populate_sync_addr_list;
+	}
+
+	/* Sanity check the server fences */
+	for (i=0;i<ui32ServerSyncPrims;i++)
+	{
+		if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on SH) must fence", __FUNCTION__));
+			return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+		}
+	}
+
+	RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRayContext->psDeviceNode->pvDevice,
+	                          & pPreAddr,
+	                          & pPostAddr,
+	                          & pRMWUFOAddr);
+
+	eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psSHData->psServerCommonContext),
+	                                ui32ClientFenceCount,
+	                                psRayContext->sSyncAddrListFence.pasFWAddrs,
+	                                paui32ClientFenceValue,
+	                                ui32ClientUpdateCount,
+	                                psRayContext->sSyncAddrListUpdate.pasFWAddrs,
+	                                paui32ClientUpdateValue,
+	                                ui32ServerSyncPrims,
+	                                paui32ServerSyncFlags,
+	                                SYNC_FLAG_MASK_ALL,
+	                                pasServerSyncs,
+	                                ui32CmdSize,
+	                                pui8DMCmd,
+	                                & pPreAddr,
+	                                & pPostAddr,
+	                                & pRMWUFOAddr,
+	                                RGXFWIF_CCB_CMD_TYPE_SHG,
+	                                ui32ExtJobRef,
+	                                ui32JobId,
+	                                ui32PDumpFlags,
+	                                NULL,
+	                                "SH",
+	                                &sCmdHelperData);
+
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRVRGXKickSHKM_Exit;
+	}
+
+	eError = RGXCmdHelperAcquireCmdCCB(1, &sCmdHelperData);
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRVRGXKickSHKM_Exit;
+	}
+	
+	
+	/*
+		We should reserve space in the kernel CCB here and fill in the command
+		directly.
+		This is so if there isn't space in the kernel CCB we can return with
+		retry back to services client before we take any operations
+	*/
+
+	/*
+		We might only be kicking for flush out a padding packet so only submit
+		the command if the create was successful
+	*/
+	if (eError == PVRSRV_OK)
+	{
+		/*
+			All the required resources are ready at this point, we can't fail so
+			take the required server sync operations and commit all the resources
+		*/
+		ui32SHGCmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psSHData->psServerCommonContext));
+		RGXCmdHelperReleaseCmdCCB(1, &sCmdHelperData, "SH", FWCommonContextGetFWAddress(psSHData->psServerCommonContext).ui32Addr);
+	}
+	
+	/*
+	 * Construct the kernel SHG CCB command.
+	 * (Safe to release reference to ray context virtual address because
+	 * ray context destruction must flush the firmware).
+	 */
+	sSHKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+	sSHKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psSHData->psServerCommonContext);
+	sSHKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psSHData->psServerCommonContext));
+	sSHKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+	ui32FWCtx = FWCommonContextGetFWAddress(psSHData->psServerCommonContext).ui32Addr;
+
+	HTBLOGK(HTB_SF_MAIN_KICK_SHG,
+			sSHKCCBCmd.uCmdData.sCmdKickData.psContext,
+			ui32SHGCmdOffset
+			);
+	RGX_HWPERF_HOST_ENQ(psRayContext, OSGetCurrentClientProcessIDKM(),
+	                    ui32FWCtx, ui32ExtJobRef, ui32JobId,
+	                    RGX_HWPERF_KICK_TYPE_VRDM);
+
+	/*
+	 * Submit the RTU command to the firmware.
+	 */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError2 = RGXScheduleCommand(psRayContext->psDeviceNode->pvDevice,
+									RGXFWIF_DM_SHG,
+									&sSHKCCBCmd,
+									sizeof(sSHKCCBCmd),
+									ui32ClientCacheOpSeqNum,
+									ui32PDumpFlags);
+		if (eError2 != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (eError2 != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKickSHKM failed to schedule kernel RTU command. Error:%u", eError));
+		if (eError == PVRSRV_OK)
+		{
+			eError = eError2;
+		}
+		goto PVRSRVRGXKickSHKM_Exit;
+	}
+	else
+	{
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+		RGXHWPerfFTraceGPUEnqueueEvent(psRayContext->psDeviceNode->pvDevice,
+				ui32FWCtx, ui32JobId, RGX_HWPERF_KICK_TYPE_VRDM);
+#endif
+	}
+
+
+PVRSRVRGXKickSHKM_Exit:
+err_populate_sync_addr_list:
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXSetRayContextPriorityKM(CONNECTION_DATA *psConnection,
+                                              PVRSRV_DEVICE_NODE * psDeviceNode,
+												 RGX_SERVER_RAY_CONTEXT *psRayContext,
+												 IMG_UINT32 ui32Priority)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+	if (psRayContext->sSHData.ui32Priority != ui32Priority)
+	{
+		eError = ContextSetPriority(psRayContext->sSHData.psServerCommonContext,
+									psConnection,
+									psRayContext->psDeviceNode->pvDevice,
+									ui32Priority,
+									RGXFWIF_DM_SHG);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the SH part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			goto fail_shcontext;
+		}
+
+		psRayContext->sSHData.ui32Priority = ui32Priority;
+	}
+
+	if (psRayContext->sRSData.ui32Priority != ui32Priority)
+	{
+		eError = ContextSetPriority(psRayContext->sRSData.psServerCommonContext,
+									psConnection,
+									psRayContext->psDeviceNode->pvDevice,
+									ui32Priority,
+									RGXFWIF_DM_RTU);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the RS part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			goto fail_rscontext;
+		}
+
+		psRayContext->sRSData.ui32Priority = ui32Priority;
+	}
+	return PVRSRV_OK;
+
+fail_rscontext:
+fail_shcontext:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+void CheckForStalledRayCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+				DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				void *pvDumpDebugFile)
+{
+	DLLIST_NODE *psNode, *psNext;
+	OSWRLockAcquireRead(psDevInfo->hRaytraceCtxListLock);
+	dllist_foreach_node(&psDevInfo->sRaytraceCtxtListHead, psNode, psNext)
+	{
+		RGX_SERVER_RAY_CONTEXT *psCurrentServerRayCtx =
+			IMG_CONTAINER_OF(psNode, RGX_SERVER_RAY_CONTEXT, sListNode);
+
+		DumpStalledFWCommonContext(psCurrentServerRayCtx->sSHData.psServerCommonContext,
+								   pfnDumpDebugPrintf, pvDumpDebugFile);
+		DumpStalledFWCommonContext(psCurrentServerRayCtx->sRSData.psServerCommonContext,
+								   pfnDumpDebugPrintf, pvDumpDebugFile);
+	}
+	OSWRLockReleaseRead(psDevInfo->hRaytraceCtxListLock);
+}
+
+IMG_UINT32 CheckForStalledClientRayCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	DLLIST_NODE *psNode, *psNext;
+	IMG_UINT32 ui32ContextBitMask = 0;
+
+	OSWRLockAcquireRead(psDevInfo->hRaytraceCtxListLock);
+
+	dllist_foreach_node(&psDevInfo->sRaytraceCtxtListHead, psNode, psNext)
+	{
+		RGX_SERVER_RAY_CONTEXT *psCurrentServerRayCtx =
+			IMG_CONTAINER_OF(psNode, RGX_SERVER_RAY_CONTEXT, sListNode);
+		if(NULL != psCurrentServerRayCtx->sSHData.psServerCommonContext)
+		{
+			if (CheckStalledClientCommonContext(psCurrentServerRayCtx->sSHData.psServerCommonContext, RGX_KICK_TYPE_DM_RTU) == PVRSRV_ERROR_CCCB_STALLED)
+			{
+				ui32ContextBitMask |= RGX_KICK_TYPE_DM_RTU;
+			}
+		}
+
+		if(NULL != psCurrentServerRayCtx->sRSData.psServerCommonContext)
+		{
+			if (CheckStalledClientCommonContext(psCurrentServerRayCtx->sRSData.psServerCommonContext, RGX_KICK_TYPE_DM_SHG) == PVRSRV_ERROR_CCCB_STALLED)
+			{
+				ui32ContextBitMask |= RGX_KICK_TYPE_DM_SHG;
+			}
+		}
+	}
+
+	OSWRLockReleaseRead(psDevInfo->hRaytraceCtxListLock);
+	return ui32ContextBitMask;
+}
+
+/******************************************************************************
+ End of file (rgxSHGRTU.c)
+******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxray.h b/drivers/staging/imgtec/rogue/rgxray.h
new file mode 100644
index 0000000..e335089
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxray.h
@@ -0,0 +1,367 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX ray tracing functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX ray tracing functionality
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__RGXRAY_H__)
+#define __RGXRAY_H__
+
+#include "devicemem.h"
+#include "devicemem_server.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgx_fwif_shared.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgxfwutils.h"
+#include "pvr_notifier.h"
+
+typedef struct _RGX_SERVER_RAY_CONTEXT_ RGX_SERVER_RAY_CONTEXT;
+typedef struct _RGX_SERVER_RPM_CONTEXT_ RGX_SERVER_RPM_CONTEXT;
+typedef struct _RGX_RPM_FREELIST_ RGX_RPM_FREELIST;
+
+
+struct _RGX_SERVER_RPM_CONTEXT_
+{
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	DEVMEM_MEMDESC			*psFWRPMContextMemDesc;
+	//DEVMEM_MEMDESC		*psRTACtlMemDesc;
+	//DEVMEM_MEMDESC		*psRTArrayMemDesc;
+	PVRSRV_CLIENT_SYNC_PRIM	*psCleanupSync;
+	IMG_UINT32				uiFLRefCount;		/*!< increments each time a free list references this parent context */
+
+	DEVMEMINT_HEAP	*psSceneHeap;
+	DEVMEMINT_HEAP	*psRPMPageTableHeap;
+	DEVMEMINT_HEAP	*psRPMFreeListHeap;
+
+	IMG_DEV_VIRTADDR	sSceneMemoryBaseAddr;
+	IMG_DEV_VIRTADDR	sDopplerHeapBaseAddr;	/*!< Base address of the virtual heap where Doppler scene is mapped */
+	IMG_DEV_VIRTADDR	sRPMPageTableBaseAddr;
+
+	IMG_UINT32		ui32TotalRPMPages;			/*!< Total virtual pages available */
+	IMG_UINT32		uiLog2DopplerPageSize;		/*!< Doppler virtual page size, may be sub-4KB */
+	IMG_UINT32		ui32UnallocatedPages;		/*!< Unmapped pages which may be mapped and added to a RPM free list */
+	IMG_UINT32		ui32RPMEntriesInPage;		/*!< Number of remaining RPM page entries (dwords) in current mapped pages */
+
+	/* Sparse mappings */
+	PMR 		*psSceneHierarchyPMR;	/*!< Scene hierarchy phys page resource */
+	PMR 		*psRPMPageTablePMR;		/*!< RPM pages in use by scene hierarchy phys page resource */
+
+	/* Current page offset at the end of the physical allocation (PMR)
+	 * for the scene memory and RPM page tables. This is where new phys pages
+	 * will be mapped when the grow occurs (using sparse dev mem API). */
+	IMG_UINT32				ui32SceneMemorySparseMappingIndex;
+	IMG_UINT32				ui32RPMPageTableSparseMappingIndex;
+};
+
+/*
+ * RPM host freelist (analogous to PM host freelist)
+ */
+struct _RGX_RPM_FREELIST_ {
+    PVRSRV_RGXDEV_INFO 		*psDevInfo;
+    CONNECTION_DATA   		*psConnection;
+    RGX_SERVER_RPM_CONTEXT	*psParentCtx;
+
+	/* Free list PMR. Used for grow */
+	PMR						*psFreeListPMR;
+	IMG_DEVMEM_OFFSET_T		uiFreeListPMROffset;
+
+	IMG_DEV_VIRTADDR		sBaseDevVAddr;
+
+	/* Current page offset at the end of the physical allocation (PMR)
+	 * for the scene memory and RPM page tables. This is where new phys pages
+	 * will be mapped when the grow occurs (using sparse dev mem API). */
+	IMG_UINT32				ui32RPMFreeListSparseMappingIndex;
+
+	IMG_UINT32				ui32ReadOffset;			/*!< FPL circular buffer read offset */
+	IMG_UINT32				ui32WriteOffset;		/*!< FPL circular buffer write offset */
+
+	/* Freelist config */
+	IMG_UINT32				ui32MaxFLPages;
+	IMG_UINT32				ui32InitFLPages;
+	IMG_UINT32				ui32CurrentFLPages;
+	IMG_UINT32				ui32GrowFLPages;
+	IMG_UINT32				ui32FreelistID;
+	IMG_UINT64				ui64FreelistChecksum;	/* checksum over freelist content */
+	IMG_BOOL				bCheckFreelist;			/* freelist check enabled */
+	IMG_UINT32				ui32RefCount;			/* freelist reference counting */
+	IMG_UINT32				uiLog2DopplerPageSize;	/*!< Doppler virtual page size, may be sub-4KB */
+	IMG_UINT32				ui32EntriesInPage;		/*!< Number of remaining FPL page entries (dwords) in current mapped pages */
+
+	IMG_UINT32				ui32NumGrowReqByApp;	/* Total number of grow requests by Application*/
+	IMG_UINT32				ui32NumGrowReqByFW;		/* Total Number of grow requests by Firmware */
+	IMG_UINT32				ui32NumHighPages;		/* High Mark of pages in the freelist */
+
+	IMG_PID					ownerPid;			/* Pid of the owner of the list */
+
+	/* 
+	 * External freelists don't use common RPM memory and are not added to global list of freelists.
+	 * They're created and destroyed on demand, e.g. when loading offline hierarchies.
+	 */
+	IMG_BOOL				bIsExternal;		/* Mark if the freelist is external */
+
+	/* Memory Blocks */
+	DLLIST_NODE				sMemoryBlockHead;		/* head of list of RGX_RPM_DEVMEM_DESC block descriptors */
+	DLLIST_NODE				sNode;					/* node used to reference list of freelists on device */
+
+	/* FW data structures */
+	DEVMEM_MEMDESC			*psFWFreelistMemDesc;
+	RGXFWIF_DEV_VIRTADDR	sFreeListFWDevVAddr;
+
+	PVRSRV_CLIENT_SYNC_PRIM	*psCleanupSync;
+} ;
+
+
+/*!
+ *	RGXCreateRPMFreeList
+ * 
+ * @param	ui32MaxFLPages
+ * @param	ui32InitFLPages
+ * @param	ui32GrowFLPages
+ * @param	bCheckFreelist
+ * @param	sFreeListDevVAddr
+ * @param	sRPMPageListDevVAddr
+ * @param	psFreeListPMR
+ * @param	uiFreeListPMROffset
+ * @param	ppsFreeList
+ * @param	bIsExternal
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateRPMFreeList(CONNECTION_DATA *psConnection,
+							   PVRSRV_DEVICE_NODE	 *psDeviceNode, 
+							   RGX_SERVER_RPM_CONTEXT	*psRPMContext,
+							   IMG_UINT32			ui32InitFLPages,
+							   IMG_UINT32			ui32GrowFLPages,
+							   IMG_DEV_VIRTADDR		sFreeListDevVAddr,
+							   RGX_RPM_FREELIST	  **ppsFreeList,
+							   IMG_UINT32		   *puiHWFreeList,
+							   IMG_BOOL				bIsExternal);
+
+/*!
+ *	RGXGrowRPMFreeList
+ */
+PVRSRV_ERROR RGXGrowRPMFreeList(RGX_RPM_FREELIST *psFreeList,
+								IMG_UINT32 ui32RequestNumPages,
+								PDLLIST_NODE pListHeader);
+
+/*!
+ *	RGXDestroyRPMFreeList
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyRPMFreeList(RGX_RPM_FREELIST *psFreeList);
+
+/*!
+ * RGXCreateRPMContext
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateRPMContext(CONNECTION_DATA *psConnection,
+								 PVRSRV_DEVICE_NODE	 *psDeviceNode, 
+								 RGX_SERVER_RPM_CONTEXT	**ppsRPMContext,
+								 IMG_UINT32			ui32TotalRPMPages,
+								 IMG_UINT32			uiLog2DopplerPageSize,
+								 IMG_DEV_VIRTADDR	sSceneMemoryBaseAddr,
+								 IMG_DEV_VIRTADDR	sDopplerHeapBaseAddr,
+								 DEVMEMINT_HEAP		*psSceneHeap,
+								 IMG_DEV_VIRTADDR	sRPMPageTableBaseAddr,
+								 DEVMEMINT_HEAP		*psRPMPageTableHeap,
+								 DEVMEM_MEMDESC		**ppsMemDesc,
+							     IMG_UINT32		     *puiHWFrameData);
+
+/*!
+ * RGXDestroyRPMContext
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyRPMContext(RGX_SERVER_RPM_CONTEXT *psCleanupData);
+
+/*!
+	RGXProcessRequestRPMGrow
+*/
+IMG_EXPORT
+void RGXProcessRequestRPMGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
+							  IMG_UINT32 ui32FreelistID);
+
+
+/*! 
+	RGXAddBlockToRPMFreeListKM
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXAddBlockToRPMFreeListKM(RGX_RPM_FREELIST *psFreeList,
+										IMG_UINT32 ui32NumPages);
+
+
+/*!
+*******************************************************************************
+
+ @Function	PVRSRVRGXCreateRenderContextKM
+
+ @Description
+	Server-side implementation of RGXCreateRenderContext
+
+ @Input pvDeviceNode - device node
+ @Input psSHGCCBMemDesc - SHG CCB Memory descriptor
+ @Input psSHGCCBCtlMemDesc - SHG CCB Ctrl Memory descriptor
+ @Input psRTUCCBMemDesc - RTU CCB Memory descriptor
+ @Input psRTUCCBCtlMemDesc - RTU CCB Ctrl Memory descriptor
+ @Input ui32Priority - context priority
+ @Input sMCUFenceAddr - MCU Fence device virtual address
+ @Input sVRMCallStackAddr - VRM call stack device virtual address
+ @Input ui32FrameworkRegisterSize - framework register size
+ @Input pbyFrameworkRegisters - ptr to framework register
+ @Input hMemCtxPrivData - memory context private data
+ @Output ppsCleanupData - clean up data
+ @Output ppsFWRayContextMemDesc - firmware ray context memory descriptor
+ @Output ppsFWRayContextStateMemDesc - firmware ray context state memory descriptor
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateRayContextKM(CONNECTION_DATA				*psConnection,
+											PVRSRV_DEVICE_NODE			*psDeviceNode,
+											IMG_UINT32					ui32Priority,
+											IMG_DEV_VIRTADDR			sMCUFenceAddr,
+											IMG_DEV_VIRTADDR			sVRMCallStackAddr,
+											IMG_UINT32					ui32FrameworkCommandSize,
+											IMG_PBYTE					pabyFrameworkCommand,
+											IMG_HANDLE					hMemCtxPrivData,
+											RGX_SERVER_RAY_CONTEXT	**ppsRayContext);
+
+
+/*!
+*******************************************************************************
+
+ @Function	PVRSRVRGXDestroyRayContextKM
+
+ @Description
+	Server-side implementation of RGXDestroyRayContext
+
+ @Input psRayContext - Ray context
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyRayContextKM(RGX_SERVER_RAY_CONTEXT *psRayContext);
+
+
+/*!
+*******************************************************************************
+
+ @Function	PVRSRVRGXKickRSKM
+
+ @Description
+	Server-side implementation of RGXKickRS
+
+ @Input pvDeviceNode - device node
+ @Input psFWRayContextMemDesc - memdesc for the firmware render context
+ @Input ui32RTUcCCBWoffUpdate - New fw Woff for the client RTU CCB
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickRSKM(RGX_SERVER_RAY_CONTEXT		*psRayContext,
+								IMG_UINT32					ui32ClientCacheOpSeqNum,
+								IMG_UINT32					ui32ClientFenceCount,
+								SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
+								IMG_UINT32					*paui32ClientFenceOffset,
+								IMG_UINT32					*paui32ClientFenceValue,
+								IMG_UINT32					ui32ClientUpdateCount,
+								SYNC_PRIMITIVE_BLOCK			**pauiClientUpdateUFOSyncPrimBlock,
+								IMG_UINT32					*paui32ClientUpdateOffset,
+								IMG_UINT32					*paui32ClientUpdateValue,
+								IMG_UINT32					ui32ServerSyncPrims,
+								IMG_UINT32					*paui32ServerSyncFlags,
+								SERVER_SYNC_PRIMITIVE 		**pasServerSyncs,
+								IMG_UINT32					ui32CmdSize,
+								IMG_PBYTE					pui8DMCmd,
+								IMG_UINT32					ui32FCCmdSize,
+								IMG_PBYTE					pui8FCDMCmd,
+								IMG_UINT32					ui32FrameContextID,
+								IMG_UINT32					ui32PDumpFlags,
+								IMG_UINT32					ui32ExtJobRef);
+/*!
+*******************************************************************************
+
+ @Function	PVRSRVRGXKickVRDMKM
+
+ @Description
+	Server-side implementation of PVRSRVRGXKickVRDMKM
+
+ @Input pvDeviceNode - device node
+ @Input psFWRayContextMemDesc - memdesc for the firmware render context
+ @Input ui32SHGcCCBWoffUpdate - New fw Woff for the client SHG CCB
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickVRDMKM(RGX_SERVER_RAY_CONTEXT		*psRayContext,
+								 IMG_UINT32					ui32ClientCacheOpSeqNum,
+								 IMG_UINT32					ui32ClientFenceCount,
+								 SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
+								 IMG_UINT32					*paui32ClientFenceOffset,
+								 IMG_UINT32					*paui32ClientFenceValue,
+								 IMG_UINT32					ui32ClientUpdateCount,
+								 SYNC_PRIMITIVE_BLOCK			**pauiClientUpdateUFOSyncPrimBlock,
+								 IMG_UINT32					*paui32ClientUpdateOffset,
+								 IMG_UINT32					*paui32ClientUpdateValue,
+								 IMG_UINT32					ui32ServerSyncPrims,
+								 IMG_UINT32					*paui32ServerSyncFlags,
+								 SERVER_SYNC_PRIMITIVE 		**pasServerSyncs,
+								 IMG_UINT32					ui32CmdSize,
+								 IMG_PBYTE					pui8DMCmd,
+								 IMG_UINT32					ui32PDumpFlags,
+								 IMG_UINT32					ui32ExtJobRef);
+
+PVRSRV_ERROR PVRSRVRGXSetRayContextPriorityKM(CONNECTION_DATA *psConnection,
+                                              PVRSRV_DEVICE_NODE *psDevNode,
+												 RGX_SERVER_RAY_CONTEXT *psRayContext,
+												 IMG_UINT32 ui32Priority);
+
+/* Debug - check if ray context is waiting on a fence */
+void CheckForStalledRayCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+				DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				void *pvDumpDebugFile);
+
+/* Debug/Watchdog - check if client ray contexts are stalled */
+IMG_UINT32 CheckForStalledClientRayCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+#endif /* __RGXRAY_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxregconfig.c b/drivers/staging/imgtec/rogue/rgxregconfig.c
index 4529512..04c3923 100644
--- a/drivers/staging/imgtec/rogue/rgxregconfig.c
+++ b/drivers/staging/imgtec/rogue/rgxregconfig.c
@@ -118,7 +118,8 @@
 				RGXFWIF_DM_GP,
 				&sRegCfgCmd,
 				sizeof(sRegCfgCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXAddRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -160,7 +161,8 @@
 				RGXFWIF_DM_GP,
 				&sRegCfgCmd,
 				sizeof(sRegCfgCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXClearRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -198,7 +200,8 @@
 				RGXFWIF_DM_GP,
 				&sRegCfgCmd,
 				sizeof(sRegCfgCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXEnableRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
@@ -234,7 +237,8 @@
 				RGXFWIF_DM_GP,
 				&sRegCfgCmd,
 				sizeof(sRegCfgCmd),
-				IMG_TRUE);
+				0,
+				PDUMP_FLAGS_CONTINUOUS);
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDisableRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
diff --git a/drivers/staging/imgtec/rogue/rgxscript.h b/drivers/staging/imgtec/rogue/rgxscript.h
index 0a481fe..293e86c5 100644
--- a/drivers/staging/imgtec/rogue/rgxscript.h
+++ b/drivers/staging/imgtec/rogue/rgxscript.h
@@ -49,8 +49,6 @@
 #endif
 
 #define	RGX_MAX_DEBUG_COMMANDS	(320)
-#define	RGX_MAX_DBGBUS_COMMANDS	(4096)
-#define	RGX_MAX_DEINIT_COMMANDS	(32)
 #define RGX_DBG_CMD_NAME_SIZE	(40)
 
 typedef	enum _RGX_INIT_OPERATION
@@ -161,8 +159,6 @@
 typedef struct _RGX_INIT_SCRIPTS_
 {
 	RGX_INIT_COMMAND asDbgCommands[RGX_MAX_DEBUG_COMMANDS];
-	RGX_INIT_COMMAND asDbgBusCommands[RGX_MAX_DBGBUS_COMMANDS];
-	RGX_INIT_COMMAND asDeinitCommands[RGX_MAX_DEINIT_COMMANDS];
 } RGX_SCRIPTS;
 
 #if defined(__cplusplus)
diff --git a/drivers/staging/imgtec/rogue/rgxsignals.c b/drivers/staging/imgtec/rogue/rgxsignals.c
new file mode 100644
index 0000000..ca3d1eb
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxsignals.c
@@ -0,0 +1,96 @@
+/*************************************************************************/ /*!
+@File           rgxsignals.c
+@Title          RGX Signals routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX Signals routines
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "rgxsignals.h"
+
+#include "rgxmem.h"
+#include "rgx_fwif_km.h"
+#include "mmu_common.h"
+#include "devicemem.h"
+#include "rgxfwutils.h"
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXNotifySignalUpdateKM(CONNECTION_DATA *psConnection,
+	                                   PVRSRV_DEVICE_NODE	*psDeviceNode,
+	                                   IMG_HANDLE hMemCtxPrivData,
+	                                   IMG_DEV_VIRTADDR sDevSignalAddress)
+{
+	DEVMEM_MEMDESC *psFWMemContextMemDesc;
+	RGXFWIF_KCCB_CMD sKCCBCmd;
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+
+	/* Schedule the firmware command */
+	sKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE;
+	sKCCBCmd.uCmdData.sSignalUpdateData.sDevSignalAddress = sDevSignalAddress;
+	RGXSetFirmwareAddress(&sKCCBCmd.uCmdData.sSignalUpdateData.psFWMemContext,
+	                      psFWMemContextMemDesc,
+	                      0, RFW_FWADDR_NOREF_FLAG);
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand((PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice,
+		                            RGXFWIF_DM_GP,
+		                            &sKCCBCmd,
+		                            sizeof(sKCCBCmd),
+		                            0,
+		                            PDUMP_FLAGS_NONE);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXNotifySignalUpdateKM: Failed to schedule the FW command %d (%s)",
+				eError, PVRSRVGETERRORSTRING(eError)));
+	}
+
+	return eError;
+}
diff --git a/drivers/staging/imgtec/rogue/rgx_fwif_sig_km.h b/drivers/staging/imgtec/rogue/rgxsignals.h
similarity index 73%
rename from drivers/staging/imgtec/rogue/rgx_fwif_sig_km.h
rename to drivers/staging/imgtec/rogue/rgxsignals.h
index 3905dd2..e9c68ae 100644
--- a/drivers/staging/imgtec/rogue/rgx_fwif_sig_km.h
+++ b/drivers/staging/imgtec/rogue/rgxsignals.h
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
-@File
-@Title          RGX firmware signature checks
+@File           rgxsignals.h
+@Title          RGX Signals routines
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX firmware interface structures used by srvinit and server
+@Description    RGX Signals routines
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,23 +41,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#if !defined (__RGX_FWIF_SIG_KM_H__)
-#define __RGX_FWIF_SIG_KM_H__
+#if !defined(_RGX_SIGNALS_H)
+#define _RGX_SIGNALS_H
 
-/************************************************************************
-* RGX FW signature checks
-************************************************************************/
-#define RGXFW_SIG_BUFFER_SIZE_DEFAULT		(1024)
-#if defined(DEBUG) || defined(PDUMP)
-#define RGXFW_SIG_CHECKS_ENABLED_DEFAULT	(IMG_TRUE)
-#else
-#define RGXFW_SIG_CHECKS_ENABLED_DEFAULT	(IMG_FALSE)
-#endif /* DEBUG */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "connection_server.h"
+#include "device.h"
 
-#endif /*  __RGX_FWIF_SIG_KM_H__ */
+/*!
+*******************************************************************************
 
-/******************************************************************************
- End of file (rgx_fwif_sig_km.h)
+ @Function	PVRSRVRGXNotifySignalUpdateKM
+
+ @Description   Server-side implementation of RGXNotifySignalUpdate
+
+ @Input hMemCtxPrivData - memory context private data
+ @Input sDevSignalAddress - device virtual address of the updated signal
+
+ @Return   PVRSRV_ERROR
+
 ******************************************************************************/
 
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXNotifySignalUpdateKM(CONNECTION_DATA *psConnection,
+                                           PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           IMG_HANDLE hMemCtxPrivData,
+                                           IMG_DEV_VIRTADDR sDevSignalAddress);
 
+#endif
diff --git a/drivers/staging/imgtec/rogue/rgxsrvinit.c b/drivers/staging/imgtec/rogue/rgxsrvinit.c
index cd3a5ea..139050c 100644
--- a/drivers/staging/imgtec/rogue/rgxsrvinit.c
+++ b/drivers/staging/imgtec/rogue/rgxsrvinit.c
@@ -45,27 +45,31 @@
 #include "srvinit.h"
 #include "pvr_debug.h"
 #include "osfunc.h"
+#include "km_apphint_defs.h"
+#include "htbuffer_types.h"
+#include "htbuffer_init.h"
 
 #include "devicemem.h"
 #include "devicemem_pdump.h"
 
 #include "client_rgxinit_bridge.h"
-#include "rgx_fwif_km.h"
-#include "rgx_fwif_client.h"
-#include "rgx_fwif_alignchecks.h"
-#include "rgx_fwif_sig_km.h"
-#if !defined(SUPPORT_KERNEL_SRVINIT) && defined(PDUMP)
+
 #include "rgx_fwif_sig.h"
-#endif
 
 #include "rgx_compat_bvnc.h"
 
 #include "srvinit_osfunc.h"
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+#include "rgxdefs.h"
+#else
+#include "rgxdefs_km.h"
+#endif
+
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 #include "virt_validation_defs.h"
 #endif
 
-#include "srvinit_param.h"
 #include "srvinit_pdump.h"
 
 #include "rgx_fwif_hwperf.h"
@@ -78,13 +82,17 @@
 #include "rgxfwimageutils.h"
 
 #include "rgx_hwperf_km.h"
+#include "rgx_bvnc_defs_km.h"
+
 #if !defined(SUPPORT_KERNEL_SRVINIT)
 #include "rgx_hwperf.h"
-/* Check server assumptions of certain HWPerf types which can not be used 
- * directly in the KM server. */
-static_assert(RGXFW_HWPERF_L1_PADDING_DEFAULT>=RGX_HWPERF_V2_MAX_PACKET_SIZE,
-			  "RGXFW_HWPERF_L1_PADDING_DEFAULT overflows max HWPerf packet size");
+#include "rgx_fwif_km.h"
+#include "rgx_fwif_client.h"
+#include "rgx_fwif_alignchecks.h"
+#else
+#include "rgxdevice.h"
 #endif
+static RGX_INIT_COMMAND asDbgCommands[RGX_MAX_DEBUG_COMMANDS];
 
 #if defined(SUPPORT_TRUSTED_DEVICE)
 #if !defined(SUPPORT_KERNEL_SRVINIT)
@@ -94,85 +102,561 @@
 #include "pvrsrv_device.h"
 #endif
 
-static RGX_INIT_COMMAND asDbgCommands[RGX_MAX_DEBUG_COMMANDS];
-static RGX_INIT_COMMAND asDbgBusCommands[RGX_MAX_DBGBUS_COMMANDS];
-static RGX_INIT_COMMAND asDeinitCommands[RGX_MAX_DEINIT_COMMANDS];
-
 
 #define	HW_PERF_FILTER_DEFAULT         0x00000000 /* Default to no HWPerf */
 #define HW_PERF_FILTER_DEFAULT_ALL_ON  0xFFFFFFFF /* All events */
 
-/* Services initialisation parameters */
-SrvInitParamInitBOOL(EnableSignatureChecks, RGXFW_SIG_CHECKS_ENABLED_DEFAULT);
-SrvInitParamInitUINT32(SignatureChecksBufSize, RGXFW_SIG_BUFFER_SIZE_DEFAULT);
-SrvInitParamInitBOOL(Enable2ndThread, IMG_FALSE);
-SrvInitParamInitUINT32(EnableFWContextSwitch, RGXFWIF_INICFG_CTXSWITCH_DM_ALL);
-SrvInitParamInitUINT32(FWContextSwitchProfile, 2); /* Default to maximum coverage */
-SrvInitParamInitUINT32(FirmwarePerf, FW_PERF_CONF_NONE);
-SrvInitParamInitBOOL(EnableHWPerf, IMG_FALSE);
-SrvInitParamInitUINT32(HWPerfFWBufSizeInKB, 0);	/* Default to server default */
-SrvInitParamInitUINT32(HWPerfFilter0, HW_PERF_FILTER_DEFAULT);
-SrvInitParamInitUINT32(HWPerfFilter1, HW_PERF_FILTER_DEFAULT);
-SrvInitParamInitBOOL(EnableHWPerfHost, IMG_FALSE);
-SrvInitParamInitUINT32(HWPerfHostFilter, HW_PERF_FILTER_DEFAULT);
-SrvInitParamInitBOOL(HWPerfDisableCustomCounterFilter, IMG_FALSE);
-SrvInitParamInitUINT32(EnableAPM, RGX_ACTIVEPM_DEFAULT);
-SrvInitParamInitUINT32(EnableRDPowerIsland, RGX_RD_POWER_ISLAND_DEFAULT);
-SrvInitParamInitUINT32(UseMETAT1, RGX_META_T1_OFF); /* Default to not using thread 1 */
-SrvInitParamInitBOOL(DustRequestInject, IMG_FALSE);
 
-#if defined(HWR_DEFAULT_ENABLED)
-SrvInitParamInitBOOL(EnableHWR, IMG_TRUE);
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(SUPPORT_VALIDATION)
+#include "pvrsrv_apphint.h"
+#endif
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(LINUX)
+#include "km_apphint.h"
+#include "os_srvinit_param.h"
 #else
-SrvInitParamInitBOOL(EnableHWR, IMG_FALSE);
-#endif
+#include "srvinit_param.h"
+/*!
+*******************************************************************************
+ * AppHint mnemonic data type helper tables
+******************************************************************************/
+/* apphint map of name vs. enable flag */
+static SRV_INIT_PARAM_UINT32_LOOKUP htb_loggroup_tbl[] = {
+#define X(a, b) { #b, HTB_LOG_GROUP_FLAG(a) },
+	HTB_LOG_SFGROUPLIST
+#undef X
+};
+/* apphint map of arg vs. OpMode */
+static SRV_INIT_PARAM_UINT32_LOOKUP htb_opmode_tbl[] = {
+	{ "droplatest", HTB_OPMODE_DROPLATEST},
+	{ "dropoldest", HTB_OPMODE_DROPOLDEST},
+	/* HTB should never be started in HTB_OPMODE_BLOCK
+	 * as this can lead to deadlocks
+	 */
+};
 
-#if defined(DEBUG)
-SrvInitParamInitUINT32(HWRDebugDumpLimit, RGXFWIF_HWR_DEBUG_DUMP_ALL);
-SrvInitParamInitBOOL(CheckMList, IMG_TRUE);
-#else
-SrvInitParamInitUINT32(HWRDebugDumpLimit, 1); /* dump only first HWR */
-SrvInitParamInitBOOL(CheckMList, IMG_FALSE);
-#endif
-SrvInitParamInitBOOL(ZeroFreelist, IMG_FALSE);
-SrvInitParamInitBOOL(DisableClockGating, IMG_FALSE);
-SrvInitParamInitBOOL(DisablePDP, IMG_FALSE);
-#if defined(SUPPORT_GPUTRACE_EVENTS)
-SrvInitParamInitBOOL(EnableFTraceGPU, IMG_FALSE);
-#endif
-#if defined(HW_ERN_41805) || defined(HW_ERN_42606)
-SrvInitParamInitUINT32(TruncateMode, 0);
-#endif
-#if defined(HW_ERN_42290) && defined(RGX_FEATURE_TPU_FILTERING_MODE_CONTROL)
-SrvInitParamInitBOOL(NewFilteringMode, IMG_TRUE);
-#endif
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-SrvInitParamInitUINT32(JonesDisableMask, 0);
-#endif
-SrvInitParamInitBOOL(DisableFEDLogging, IMG_FALSE);
-SrvInitParamInitBOOL(EnableRTUBypass, IMG_FALSE);
-#if defined(DEBUG)
-SrvInitParamInitBOOL(AssertOutOfMemory, IMG_FALSE);
-#endif
-SrvInitParamInitBOOL(EnableCDMKillingRandMode, IMG_FALSE);
-SrvInitParamInitBOOL(DisableDMOverlap, IMG_FALSE);
-
-static SRV_INIT_PARAM_UINT32_LOOKUP asLogTypeTable[] = {
+static SRV_INIT_PARAM_UINT32_LOOKUP fwt_logtype_tbl[] = {
 	{ "trace", 2},
 	{ "tbi", 1},
 	{ "none", 0}
 };
-SrvInitParamInitUINT32List(FirmwareLogType, 0, asLogTypeTable); 
 
-static SRV_INIT_PARAM_UINT32_LOOKUP asLogGroupTable[] = { RGXFWIF_LOG_GROUP_NAME_VALUE_MAP };
-SrvInitParamInitUINT32BitField(EnableLogGroup, 0, asLogGroupTable);
+static SRV_INIT_PARAM_UINT32_LOOKUP timecorr_clk_tbl[] = {
+	{ "mono", 0 },
+	{ "mono_raw", 1 },
+	{ "sched", 2 }
+};
 
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* These functionality is n/a to guest drivers */
+static SRV_INIT_PARAM_UINT32_LOOKUP fwt_loggroup_tbl[] = { RGXFWIF_LOG_GROUP_NAME_VALUE_MAP };
+
+/*
+ * Services AppHints initialisation
+ */
+#define X(a, b, c, d, e) SrvInitParamInit ## b( a, d, e )
+APPHINT_LIST_ALL
+#undef X
+#endif /* SUPPORT_KERNEL_SRVINIT && LINUX */
+
+/*
+ * Container for all the apphints used by this module
+ */
+typedef struct _RGX_SRVINIT_APPHINTS_
+{
+	IMG_BOOL   bDustRequestInject;
+	IMG_BOOL   bEnableSignatureChecks;
+	IMG_UINT32 ui32SignatureChecksBufSize;
+
+#if defined(DEBUG)
+	IMG_BOOL   bAssertOnOutOfMem;
+	IMG_BOOL   bAssertOnHWRTrigger;
+#endif
+	IMG_BOOL   bCheckMlist;
+	IMG_BOOL   bDisableClockGating;
+	IMG_BOOL   bDisableDMOverlap;
+	IMG_BOOL   bDisableFEDLogging;
+	IMG_BOOL   bDisablePDP;
+	IMG_BOOL   bEnableCDMKillRand;
+	IMG_BOOL   bEnableFTrace;
+	IMG_BOOL   bEnableHWPerf;
+	IMG_BOOL   bEnableHWPerfHost;
+	IMG_BOOL   bEnableHWR;
+	IMG_BOOL   bEnableRTUBypass;
+	IMG_BOOL   bFilteringMode;
+	IMG_BOOL   bHWPerfDisableCustomCounterFilter;
+	IMG_BOOL   bZeroFreelist;
+	IMG_UINT32 ui32EnableFWContextSwitch;
+	IMG_UINT32 ui32FWContextSwitchProfile;
+	IMG_UINT32 ui32HWPerfFWBufSize;
+	IMG_UINT32 ui32HWPerfHostBufSize;
+	IMG_UINT32 ui32HWPerfFilter0;
+	IMG_UINT32 ui32HWPerfFilter1;
+	IMG_UINT32 ui32HWPerfHostFilter;
+	IMG_UINT32 ui32TimeCorrClock;
+	IMG_UINT32 ui32HWRDebugDumpLimit;
+	IMG_UINT32 ui32JonesDisableMask;
+	IMG_UINT32 ui32LogType;
+	IMG_UINT32 ui32TruncateMode;
+	FW_PERF_CONF eFirmwarePerf;
+	RGX_ACTIVEPM_CONF eRGXActivePMConf;
+	RGX_META_T1_CONF eUseMETAT1;
+	RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf;
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+	IMG_UINT32 aui32OSidMin[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS];
+	IMG_UINT32 aui32OSidMax[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS];
+#endif
+	IMG_BOOL   bEnableTrustedDeviceAceConfig;
+} RGX_SRVINIT_APPHINTS;
+
+
+/*!
+*******************************************************************************
+
+ @Function      GetApphints
+
+ @Description   Read init time apphints and initialise internal variables
+
+ @Input         psHints : Pointer to apphints container
+
+ @Return        void
+
+******************************************************************************/
+static INLINE void GetApphints(RGX_SRVINIT_APPHINTS *psHints, IMG_UINT64 ui64ErnsBrns, IMG_UINT64 ui64Features)
+{
+	void *pvParamState = SrvInitParamOpen();
+	IMG_UINT32 ui32ParamTemp;
+	IMG_BOOL bS7TopInfra = IMG_FALSE, bE42290 = IMG_FALSE, bTPUFiltermodeCtrl = IMG_FALSE, \
+			bE41805 = IMG_FALSE, bE42606 = IMG_FALSE, bAXIACELite = IMG_FALSE;
+
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	PVR_UNREFERENCED_PARAMETER(bE41805);
+	PVR_UNREFERENCED_PARAMETER(bE42606);
+	PVR_UNREFERENCED_PARAMETER(bE42290);
+	PVR_UNREFERENCED_PARAMETER(bS7TopInfra);
+	PVR_UNREFERENCED_PARAMETER(bTPUFiltermodeCtrl);
+#endif
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	PVR_UNREFERENCED_PARAMETER(ui64ErnsBrns);
+	PVR_UNREFERENCED_PARAMETER(ui64Features);
+	PVR_UNREFERENCED_PARAMETER(bAXIACELite);
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+	bS7TopInfra = IMG_TRUE;
+#endif
+#if defined(HW_ERN_42290)
+	bE42290 = IMG_TRUE;
+#endif
+#if defined(HW_ERN_41805)
+	bE41805 = IMG_TRUE;
+#endif
+#if defined(HW_ERN_42606)
+	bE42606 = IMG_TRUE;
+#endif
+#if defined(RGX_FEATURE_AXI_ACELITE)
+	bAXIACELite = IMG_TRUE;
+#endif
 #else
-/************************************************************************
-* Private functions
-************************************************************************/
+	if(ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+	{
+		bS7TopInfra = IMG_TRUE;
+	}
+
+	if(ui64Features & RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_BIT_MASK)
+	{
+		bTPUFiltermodeCtrl = IMG_TRUE;
+	}
+
+	if(ui64ErnsBrns & HW_ERN_42290_BIT_MASK)
+	{
+		bE42290 = IMG_TRUE;
+	}
+
+	if(ui64ErnsBrns & HW_ERN_41805_BIT_MASK)
+	{
+		bE41805 = IMG_TRUE;
+	}
+
+	if(ui64ErnsBrns & HW_ERN_42606_BIT_MASK)
+	{
+		bE42606 = IMG_TRUE;
+	}
+
+	if(ui64Features & RGX_FEATURE_AXI_ACELITE_BIT_MASK)
+	{
+		bAXIACELite = IMG_TRUE;
+	}
+#endif
+	/*
+	 * KM AppHints not passed through the srvinit interface
+	 */
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	SrvInitParamUnreferenced(FWPoisonOnFreeValue);
+	SrvInitParamUnreferenced(EnableFWPoisonOnFree);
+	SrvInitParamUnreferenced(GeneralNon4KHeapPageSize);
+	SrvInitParamUnreferenced(WatchdogThreadWeight);
+	SrvInitParamUnreferenced(WatchdogThreadPriority);
+	SrvInitParamUnreferenced(CleanupThreadWeight);
+	SrvInitParamUnreferenced(CleanupThreadPriority);
+	SrvInitParamUnreferenced(RGXBVNC);
+#endif
+
+	/*
+	 * NB AppHints initialised to a default value via SrvInitParamInit* macros above
+	 */
+
+	SrvInitParamGetBOOL(pvParamState,     DustRequestInject, psHints->bDustRequestInject);
+	SrvInitParamGetBOOL(pvParamState,     EnableSignatureChecks, psHints->bEnableSignatureChecks);
+	SrvInitParamGetUINT32(pvParamState,   SignatureChecksBufSize, psHints->ui32SignatureChecksBufSize);
+
+#if defined(DEBUG)
+	SrvInitParamGetBOOL(pvParamState,    AssertOutOfMemory, psHints->bAssertOnOutOfMem);
+	SrvInitParamGetBOOL(pvParamState,    AssertOnHWRTrigger, psHints->bAssertOnHWRTrigger);
+#endif
+	SrvInitParamGetBOOL(pvParamState,    CheckMList, psHints->bCheckMlist);
+	SrvInitParamGetBOOL(pvParamState,    DisableClockGating, psHints->bDisableClockGating);
+	SrvInitParamGetBOOL(pvParamState,    DisableDMOverlap, psHints->bDisableDMOverlap);
+	SrvInitParamGetBOOL(pvParamState,    DisableFEDLogging, psHints->bDisableFEDLogging);
+	SrvInitParamGetUINT32(pvParamState,  EnableAPM, ui32ParamTemp);
+	psHints->eRGXActivePMConf = ui32ParamTemp;
+	SrvInitParamGetBOOL(pvParamState,    EnableCDMKillingRandMode, psHints->bEnableCDMKillRand);
+	SrvInitParamGetBOOL(pvParamState,    EnableFTraceGPU, psHints->bEnableFTrace);
+	SrvInitParamGetUINT32(pvParamState,  EnableFWContextSwitch, psHints->ui32EnableFWContextSwitch);
+	SrvInitParamGetBOOL(pvParamState,    EnableHWPerf, psHints->bEnableHWPerf);
+	SrvInitParamGetBOOL(pvParamState,    EnableHWPerfHost, psHints->bEnableHWPerfHost);
+	SrvInitParamGetBOOL(pvParamState,    EnableHWR, psHints->bEnableHWR);
+	SrvInitParamGetUINT32(pvParamState,  EnableRDPowerIsland, ui32ParamTemp);
+	psHints->eRGXRDPowerIslandConf = ui32ParamTemp;
+	SrvInitParamGetBOOL(pvParamState,    EnableRTUBypass, psHints->bEnableRTUBypass);
+	SrvInitParamGetUINT32(pvParamState,  FirmwarePerf, ui32ParamTemp);
+	psHints->eFirmwarePerf = ui32ParamTemp;
+	SrvInitParamGetUINT32(pvParamState,  FWContextSwitchProfile, psHints->ui32FWContextSwitchProfile);
+	SrvInitParamGetBOOL(pvParamState,    HWPerfDisableCustomCounterFilter, psHints->bHWPerfDisableCustomCounterFilter);
+	SrvInitParamGetUINT32(pvParamState,  HWPerfHostBufSizeInKB, psHints->ui32HWPerfHostBufSize);
+	SrvInitParamGetUINT32(pvParamState,  HWPerfFWBufSizeInKB, psHints->ui32HWPerfFWBufSize);
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(LINUX)
+	/* name changes */
+	{
+		IMG_UINT64 ui64Tmp;
+		SrvInitParamGetBOOL(pvParamState,    DisablePDumpPanic, psHints->bDisablePDP);
+		SrvInitParamGetUINT64(pvParamState,  HWPerfFWFilter, ui64Tmp);
+		psHints->ui32HWPerfFilter0 = (IMG_UINT32)(ui64Tmp & 0xffffffffllu);
+		psHints->ui32HWPerfFilter1 = (IMG_UINT32)((ui64Tmp >> 32) & 0xffffffffllu);
+	}
+#else
+	SrvInitParamGetBOOL(pvParamState,    DisablePDP, psHints->bDisablePDP);
+	SrvInitParamGetUINT32(pvParamState,  HWPerfFilter0, psHints->ui32HWPerfFilter0);
+	SrvInitParamGetUINT32(pvParamState,  HWPerfFilter1, psHints->ui32HWPerfFilter1);
+	SrvInitParamUnreferenced(DisablePDumpPanic);
+	SrvInitParamUnreferenced(HWPerfFWFilter);
+	SrvInitParamUnreferenced(RGXBVNC);
+#endif
+	SrvInitParamGetUINT32(pvParamState,  HWPerfHostFilter, psHints->ui32HWPerfHostFilter);
+	SrvInitParamGetUINT32List(pvParamState,  TimeCorrClock, psHints->ui32TimeCorrClock);
+	SrvInitParamGetUINT32(pvParamState,  HWRDebugDumpLimit, ui32ParamTemp);
+	psHints->ui32HWRDebugDumpLimit = MIN(ui32ParamTemp, RGXFWIF_HWR_DEBUG_DUMP_ALL);
+
+	if(bS7TopInfra)
+	{
+	#define RGX_CR_JONES_FIX_MT_ORDER_ISP_TE_CLRMSK	(0XFFFFFFCFU)
+	#define RGX_CR_JONES_FIX_MT_ORDER_ISP_EN	(0X00000020U)
+	#define RGX_CR_JONES_FIX_MT_ORDER_TE_EN		(0X00000010U)
+
+		SrvInitParamGetUINT32(pvParamState,  JonesDisableMask, ui32ParamTemp);
+		if (((ui32ParamTemp & ~RGX_CR_JONES_FIX_MT_ORDER_ISP_TE_CLRMSK) == RGX_CR_JONES_FIX_MT_ORDER_ISP_EN) ||
+			((ui32ParamTemp & ~RGX_CR_JONES_FIX_MT_ORDER_ISP_TE_CLRMSK) == RGX_CR_JONES_FIX_MT_ORDER_TE_EN))
+		{
+			ui32ParamTemp |= (RGX_CR_JONES_FIX_MT_ORDER_TE_EN |
+							  RGX_CR_JONES_FIX_MT_ORDER_ISP_EN);
+			PVR_DPF((PVR_DBG_WARNING, "Tile reordering mode requires both TE and ISP enabled. Forcing JonesDisableMask = %d",
+					ui32ParamTemp));
+		}
+		psHints->ui32JonesDisableMask = ui32ParamTemp;
+	}
+
+	if ( (bE42290) && (bTPUFiltermodeCtrl))
+	{
+		SrvInitParamGetBOOL(pvParamState,    NewFilteringMode, psHints->bFilteringMode);
+	}
+
+	if(bE41805 || bE42606)
+	{
+		SrvInitParamGetUINT32(pvParamState,  TruncateMode, psHints->ui32TruncateMode);
+	}
+#if defined(EMULATOR)
+	if(bAXIACELite)
+	{
+		SrvInitParamGetBOOL(pvParamState, EnableTrustedDeviceAceConfig, psHints->bEnableTrustedDeviceAceConfig);
+	}
+#else
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	SrvInitParamUnreferenced(EnableTrustedDeviceAceConfig);
+#endif
+#endif	
+
+	SrvInitParamGetUINT32(pvParamState,  UseMETAT1, ui32ParamTemp);
+	psHints->eUseMETAT1 = ui32ParamTemp & RGXFWIF_INICFG_METAT1_MASK;
+
+	SrvInitParamGetBOOL(pvParamState,    ZeroFreelist, psHints->bZeroFreelist);
+
+
+	/*
+	 * HWPerf filter apphints setup
+	 */
+	if (psHints->bEnableHWPerf)
+	{
+		if (psHints->ui32HWPerfFilter0 == 0 && psHints->ui32HWPerfFilter1 == 0)
+		{
+			psHints->ui32HWPerfFilter0 = HW_PERF_FILTER_DEFAULT_ALL_ON;
+			psHints->ui32HWPerfFilter1 = HW_PERF_FILTER_DEFAULT_ALL_ON;
+		}
+	}
+	else
+	{
+		if (psHints->ui32HWPerfFilter0 != 0 || psHints->ui32HWPerfFilter1 != 0)
+		{
+			psHints->bEnableHWPerf = IMG_TRUE;
+		}
+	}
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+	if (psHints->bEnableFTrace)
+	{
+		/* In case we have not set EnableHWPerf AppHint just request creation
+		 * of certain events we need for the FTrace i.e. only the Kick/Finish
+		 * HW events */
+		if (!psHints->bEnableHWPerf)
+		{
+			psHints->ui32HWPerfFilter0 = (IMG_UINT32) (RGX_HWPERF_EVENT_MASK_HW_KICKFINISH & 0xFFFFFFFF);
+			psHints->ui32HWPerfFilter1 = (IMG_UINT32) ((RGX_HWPERF_EVENT_MASK_HW_KICKFINISH & 0xFFFFFFFF00000000) >> 32);
+		}
+		else
+		{
+			psHints->ui32HWPerfFilter0 = HW_PERF_FILTER_DEFAULT_ALL_ON;
+			psHints->ui32HWPerfFilter1 = HW_PERF_FILTER_DEFAULT_ALL_ON;
+		}
+
+	}
+#endif
+	
+	if (psHints->bEnableHWPerfHost)
+	{
+		if (psHints->ui32HWPerfHostFilter == 0)
+		{
+			psHints->ui32HWPerfHostFilter = HW_PERF_FILTER_DEFAULT_ALL_ON;
+		}
+	}
+	else
+	{
+		if (psHints->ui32HWPerfHostFilter != 0)
+		{
+			psHints->bEnableHWPerfHost = IMG_TRUE;
+		}
+	}
+
+	/*
+	 * FW logs apphints
+	 */
+	{
+		IMG_UINT32 ui32LogType;
+		IMG_BOOL bFirmwareLogTypeConfigured, bAnyLogGroupConfigured;
+
+		SrvInitParamGetUINT32BitField(pvParamState, EnableLogGroup, ui32LogType);
+		bAnyLogGroupConfigured = ui32LogType ? IMG_TRUE : IMG_FALSE;
+		bFirmwareLogTypeConfigured = SrvInitParamGetUINT32List(pvParamState, FirmwareLogType, ui32ParamTemp);
+
+		if (bFirmwareLogTypeConfigured)
+		{
+			if (ui32ParamTemp == 2 /* TRACE */)
+			{
+				if (!bAnyLogGroupConfigured)
+				{
+					/* No groups configured - defaulting to MAIN group */
+					ui32LogType |= RGXFWIF_LOG_TYPE_GROUP_MAIN;
+				}
+				ui32LogType |= RGXFWIF_LOG_TYPE_TRACE;
+			}
+			else if (ui32ParamTemp == 1 /* TBI */)
+			{
+				if (!bAnyLogGroupConfigured)
+				{
+					/* No groups configured - defaulting to MAIN group */
+					ui32LogType |= RGXFWIF_LOG_TYPE_GROUP_MAIN;
+				}
+				ui32LogType &= ~RGXFWIF_LOG_TYPE_TRACE;
+			}
+			else if (ui32ParamTemp == 0 /* NONE */)
+			{
+				ui32LogType = RGXFWIF_LOG_TYPE_NONE;
+			}
+		}
+		else
+		{
+			/* No log type configured - defaulting to TRACE */
+			ui32LogType |= RGXFWIF_LOG_TYPE_TRACE;
+		}
+
+		psHints->ui32LogType = ui32LogType;
+	}
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+	/*
+	 * GPU virtualisation validation apphints
+	 */
+	{
+		IMG_UINT uiCounter, uiRegion;
+
+		PVR_DPF((PVR_DBG_MESSAGE,"\n[GPU Virtualization Validation]: Reading OSid limits\n"));
+
+		for (uiRegion = 0; uiRegion < GPUVIRT_VALIDATION_NUM_REGIONS; uiRegion++)
+		{
+			for (uiCounter = 0; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
+			{
+				IMG_CHAR   pszHintString[GPUVIRT_VALIDATION_MAX_STRING_LENGTH];
+				IMG_UINT32 ui32Default = 0;
+
+				snprintf(pszHintString, GPUVIRT_VALIDATION_MAX_STRING_LENGTH, "OSidRegion%dMin%d", uiRegion, uiCounter);
+				PVRSRVGetAppHint(pvParamState,
+				                 pszHintString,
+				                 IMG_UINT_TYPE,
+				                 &ui32Default,
+				                 &(psHints->aui32OSidMin[uiCounter][uiRegion]));
+
+				snprintf(pszHintString, GPUVIRT_VALIDATION_MAX_STRING_LENGTH, "OSidRegion%dMax%d", uiRegion, uiCounter);
+				PVRSRVGetAppHint(pvParamState,
+				                 pszHintString,
+				                 IMG_UINT_TYPE,
+				                 &ui32Default,
+				                 &(psHints->aui32OSidMax[uiCounter][uiRegion]));
+			}
+		}
+
+		for (uiCounter = 0; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
+		{
+			for (uiRegion = 0; uiRegion < GPUVIRT_VALIDATION_NUM_REGIONS; uiRegion++)
+			{
+				PVR_DPF((PVR_DBG_MESSAGE,
+				         "\n[GPU Virtualization Validation]: Region:%d, OSid:%d, Min:%u, Max:%u\n",
+				         uiRegion, uiCounter,
+				         psHints->aui32OSidMin[uiCounter][uiRegion],
+				         psHints->aui32OSidMax[uiCounter][uiRegion]));
+			}
+		}
+	}
+#endif /* defined(SUPPORT_GPUVIRT_VALIDATION) */
+
+
+	SrvInitParamClose(pvParamState);
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      GetFWConfigFlags
+
+ @Description   Initialise and return FW config flags
+
+ @Input         psHints            : Apphints container
+ @Input         pui32FWConfigFlags : Pointer to config flags
+
+ @Return        void
+
+******************************************************************************/
+static INLINE void GetFWConfigFlags(RGX_SRVINIT_APPHINTS *psHints,
+                                    IMG_UINT32 *pui32FWConfigFlags)
+{
+	IMG_UINT32 ui32FWConfigFlags = 0;
+
+#if defined(DEBUG)
+	ui32FWConfigFlags |= psHints->bAssertOnOutOfMem ? RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY : 0;
+	ui32FWConfigFlags |= psHints->bAssertOnHWRTrigger ? RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER : 0;
+#endif
+	ui32FWConfigFlags |= psHints->bCheckMlist ? RGXFWIF_INICFG_CHECK_MLIST_EN : 0;
+	ui32FWConfigFlags |= psHints->bDisableClockGating ? RGXFWIF_INICFG_DISABLE_CLKGATING_EN : 0;
+	ui32FWConfigFlags |= psHints->bDisableDMOverlap ? RGXFWIF_INICFG_DISABLE_DM_OVERLAP : 0;
+	ui32FWConfigFlags |= psHints->bDisablePDP ? RGXFWIF_SRVCFG_DISABLE_PDP_EN : 0;
+	ui32FWConfigFlags |= psHints->bEnableCDMKillRand ? RGXFWIF_INICFG_CDM_KILL_MODE_RAND_EN : 0;
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+	/* Since FTrace GPU events depends on HWPerf, ensure it is enabled here */
+	ui32FWConfigFlags |= psHints->bEnableFTrace ? RGXFWIF_INICFG_HWPERF_EN : 0;
+#endif
+	ui32FWConfigFlags |= psHints->bEnableHWPerf ? RGXFWIF_INICFG_HWPERF_EN : 0;
+#if !defined(NO_HARDWARE)
+	ui32FWConfigFlags |= psHints->bEnableHWR ? RGXFWIF_INICFG_HWR_EN : 0;
+#endif
+	ui32FWConfigFlags |= psHints->bEnableRTUBypass ? RGXFWIF_INICFG_RTU_BYPASS_EN : 0;
+	ui32FWConfigFlags |= psHints->bHWPerfDisableCustomCounterFilter ? RGXFWIF_INICFG_HWP_DISABLE_FILTER : 0;
+	ui32FWConfigFlags |= (psHints->eFirmwarePerf == FW_PERF_CONF_CUSTOM_TIMER) ? RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN : 0;
+	ui32FWConfigFlags |= (psHints->eFirmwarePerf == FW_PERF_CONF_POLLS) ? RGXFWIF_INICFG_POLL_COUNTERS_EN : 0;
+	ui32FWConfigFlags |= psHints->eUseMETAT1 << RGXFWIF_INICFG_METAT1_SHIFT;
+	ui32FWConfigFlags |= psHints->ui32EnableFWContextSwitch & ~RGXFWIF_INICFG_CTXSWITCH_CLRMSK;
+	ui32FWConfigFlags |= (psHints->ui32FWContextSwitchProfile << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT) & RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK;
+
+	*pui32FWConfigFlags = ui32FWConfigFlags;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      GetFilterFlags
+
+ @Description   Initialise and return filter flags
+
+ @Input         psHints : Apphints container
+
+ @Return        Filter flags
+
+******************************************************************************/
+static INLINE IMG_UINT32 GetFilterFlags(RGX_SRVINIT_APPHINTS *psHints)
+{
+	IMG_UINT32 ui32FilterFlags = 0;
+
+	ui32FilterFlags |= psHints->bFilteringMode ? RGXFWIF_FILTCFG_NEW_FILTER_MODE : 0;
+	if (psHints->ui32TruncateMode == 2)
+	{
+		ui32FilterFlags |= RGXFWIF_FILTCFG_TRUNCATE_INT;
+	}
+	else if (psHints->ui32TruncateMode == 3)
+	{
+		ui32FilterFlags |= RGXFWIF_FILTCFG_TRUNCATE_HALF;
+	}
+
+	return ui32FilterFlags;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      GetDeviceFlags
+
+ @Description   Initialise and return device flags
+
+ @Input         psHints          : Apphints container
+ @Input         pui32DeviceFlags : Pointer to device flags
+
+ @Return        void
+
+******************************************************************************/
+static INLINE void GetDeviceFlags(RGX_SRVINIT_APPHINTS *psHints,
+                                  IMG_UINT32 *pui32DeviceFlags)
+{
+	IMG_UINT32 ui32DeviceFlags = 0;
+
+	ui32DeviceFlags |= psHints->bDustRequestInject? RGXKMIF_DEVICE_STATE_DUST_REQUEST_INJECT_EN : 0;
+
+	ui32DeviceFlags |= psHints->bZeroFreelist ? RGXKMIF_DEVICE_STATE_ZERO_FREELIST : 0;
+	ui32DeviceFlags |= psHints->bDisableFEDLogging ? RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN : 0;
+	ui32DeviceFlags |= psHints->bEnableHWPerfHost ? RGXKMIF_DEVICE_STATE_HWPERF_HOST_EN : 0;
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+	ui32DeviceFlags |= psHints->bEnableFTrace ? RGXKMIF_DEVICE_STATE_FTRACE_EN : 0;
+#endif
+
+	*pui32DeviceFlags = ui32DeviceFlags;
+}
+
+
 /*!
 *******************************************************************************
 
@@ -185,90 +669,230 @@
  @Return		IMG_BOOL True if it runs out of cmds when building the script
 
 ******************************************************************************/
-static IMG_BOOL PrepareDebugScript(RGX_SCRIPT_BUILD* psDbgInitScript, IMG_BOOL bFirmwarePerf)
+static IMG_BOOL PrepareDebugScript(RGX_SCRIPT_BUILD* psDbgInitScript,
+					IMG_BOOL bFirmwarePerf,
+					void *pvDeviceInfo)
 {
 #define DBG_READ(T, R, S)		if (!ScriptDBGReadRGXReg(psDbgInitScript, T, R, S)) return IMG_FALSE;
+#if defined(RGX_FEATURE_META) || defined(SUPPORT_KERNEL_SRVINIT)
 #define DBG_MSP_READ(R, S)		if (!ScriptDBGReadMetaRegThroughSP(psDbgInitScript, R, S)) return IMG_FALSE;
 #define DBG_MCR_READ(R, S)		if (!ScriptDBGReadMetaCoreReg(psDbgInitScript, R, S)) return IMG_FALSE;
-#define DBG_CALC(R, S, T, U, V)	if (!ScriptDBGCalc(psDbgInitScript, R, S, T, U, V)) return IMG_FALSE;
-#if defined(FIX_HW_BRN_44871)
-#define DBG_STRING(S)			if (!ScriptDBGString(psDbgInitScript, S)) return IMG_FALSE;
+#else
+#define DBG_MSP_READ(R, S)
+#define DBG_MCR_READ(R, S)
 #endif
+#define DBG_CALC(R, S, T, U, V)	if (!ScriptDBGCalc(psDbgInitScript, R, S, T, U, V)) return IMG_FALSE;
+#define DBG_STRING(S)			if (!ScriptDBGString(psDbgInitScript, S)) return IMG_FALSE;
 #define DBG_READ32(R, S)				DBG_READ(RGX_INIT_OP_DBG_READ32_HW_REG, R, S)
 #define DBG_READ64(R, S)				DBG_READ(RGX_INIT_OP_DBG_READ64_HW_REG, R, S)
 #define DBG_CALC_TA_AND_3D(R, S, T, U)	DBG_CALC(RGX_INIT_OP_DBG_CALC, R, S, T, U)
-
-#if defined(RGX_FEATURE_MIPS)
+	IMG_BOOL	bS7Infra, bXTInfra, e44871, bRayTracing, e47025, bVIVTSlc, bMIPS, bPBVNC;
+	IMG_UINT32	ui32SLCBanks = 0, ui32Meta = 0;
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	PVR_UNREFERENCED_PARAMETER(pvDeviceInfo);
+#else
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)pvDeviceInfo;
+#endif
 	PVR_UNREFERENCED_PARAMETER(bFirmwarePerf);
+	bS7Infra = bXTInfra = e44871 = bRayTracing = e47025 = bVIVTSlc = bMIPS = bPBVNC = IMG_FALSE;
+
+
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	#if defined(RGX_FEATURE_META)
+		ui32Meta = RGX_FEATURE_META;
+	#endif
+	#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+		bS7Infra = IMG_TRUE;
+	#endif
+
+	#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
+		bXTInfra = IMG_TRUE;
+	#endif
+
+	#if	defined(FIX_HW_BRN_44871)
+		e44871 = IMG_TRUE;
+	#endif
+
+	#if	defined(HW_ERN_47025)
+		e47025 = IMG_TRUE;
+	#endif
+
+	#if defined(RGX_FEATURE_RAY_TRACING)
+		bRayTracing = IMG_TRUE;
+	#endif
+
+	#if defined(RGX_FEATURE_SLC_BANKS)
+		ui32SLCBanks = RGX_FEATURE_SLC_BANKS;
+	#endif
+
+	#if defined(RGX_FEATURE_SLC_VIVT)
+		bVIVTSlc = IMG_TRUE;
+	#endif
+
+	#if defined(RGX_FEATURE_MIPS)
+		bMIPS = IMG_TRUE;
+	#endif
+	#if defined(RGX_FEATURE_PBVNC_COREID_REG)
+		bPBVNC = IMG_TRUE;
+	#endif
+#else
+	do{
+		if(NULL == psDevInfo)
+			break;
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_PBVNC_COREID_REG_BIT_MASK)
+		{
+			bPBVNC = IMG_TRUE;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui32META)
+		{
+			ui32Meta = psDevInfo->sDevFeatureCfg.ui32META;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+		{
+			bS7Infra = IMG_TRUE;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK)
+		{
+			bXTInfra = IMG_TRUE;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+		{
+			bRayTracing = IMG_TRUE;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SLC_VIVT_BIT_MASK)
+		{
+			bVIVTSlc = IMG_TRUE;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_MIPS_BIT_MASK)
+		{
+			bMIPS = IMG_TRUE;
+		}
+
+
+		if(psDevInfo->sDevFeatureCfg.ui32SLCBanks)
+		{
+			ui32SLCBanks = psDevInfo->sDevFeatureCfg.ui32SLCBanks;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64ErnsBrns & FIX_HW_BRN_44871_BIT_MASK)
+		{
+			e44871 = IMG_TRUE;
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64ErnsBrns & HW_ERN_47025_POS)
+		{
+			e47025 = IMG_TRUE;
+		}
+
+	}while(0);
 #endif
 
-	DBG_READ32(RGX_CR_CORE_ID,							"CORE_ID                         ");
+	if(bPBVNC)
+	{
+		DBG_READ64(RGX_CR_CORE_ID,							"CORE_ID                         ");
+	}else
+	{
+		DBG_READ32(RGX_CR_CORE_ID,							"CORE_ID                         ");
+	}
+
 	DBG_READ32(RGX_CR_CORE_REVISION,					"CORE_REVISION                   ");
 	DBG_READ32(RGX_CR_DESIGNER_REV_FIELD1,				"DESIGNER_REV_FIELD1             ");
 	DBG_READ32(RGX_CR_DESIGNER_REV_FIELD2,				"DESIGNER_REV_FIELD2             ");
 	DBG_READ64(RGX_CR_CHANGESET_NUMBER,					"CHANGESET_NUMBER                ");
-#if defined(RGX_FEATURE_META)
-	DBG_READ32(RGX_CR_META_SP_MSLVIRQSTATUS,			"META_SP_MSLVIRQSTATUS           ");
-#endif
+	if(ui32Meta)
+	{
+		DBG_READ32(RGX_CR_META_SP_MSLVIRQSTATUS,			"META_SP_MSLVIRQSTATUS           ");
+	}
 	DBG_READ64(RGX_CR_CLK_CTRL,							"CLK_CTRL                        ");
 	DBG_READ64(RGX_CR_CLK_STATUS,						"CLK_STATUS                      ");
 	DBG_READ64(RGX_CR_CLK_CTRL2,						"CLK_CTRL2                       ");
 	DBG_READ64(RGX_CR_CLK_STATUS2,						"CLK_STATUS2                     ");
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	DBG_READ64(RGX_CR_CLK_XTPLUS_CTRL,					"CLK_XTPLUS_CTRL                 ");
-	DBG_READ64(RGX_CR_CLK_XTPLUS_STATUS,				"CLK_XTPLUS_STATUS               ");
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+	if (bS7Infra)
+	{
+		DBG_READ64(RGX_CR_CLK_XTPLUS_CTRL,					"CLK_XTPLUS_CTRL                 ");
+		DBG_READ64(RGX_CR_CLK_XTPLUS_STATUS,				"CLK_XTPLUS_STATUS               ");
+	}
 	DBG_READ32(RGX_CR_EVENT_STATUS,						"EVENT_STATUS                    ");
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	DBG_READ64(RGX_CR_MMU_FAULT_STATUS,					"MMU_FAULT_STATUS                ");
-	DBG_READ64(RGX_CR_MMU_FAULT_STATUS_META,			"MMU_FAULT_STATUS_META           ");
-#else
-	DBG_READ32(RGX_CR_BIF_FAULT_BANK0_MMU_STATUS,		"BIF_FAULT_BANK0_MMU_STATUS      ");
-	DBG_READ64(RGX_CR_BIF_FAULT_BANK0_REQ_STATUS,		"BIF_FAULT_BANK0_REQ_STATUS      ");
-	DBG_READ32(RGX_CR_BIF_FAULT_BANK1_MMU_STATUS,		"BIF_FAULT_BANK1_MMU_STATUS      ");
-	DBG_READ64(RGX_CR_BIF_FAULT_BANK1_REQ_STATUS,		"BIF_FAULT_BANK1_REQ_STATUS      ");
-#endif	
+	DBG_READ64(RGX_CR_TIMER,							"TIMER                           ");
+	if (bS7Infra)
+	{
+		DBG_READ64(RGX_CR_MMU_FAULT_STATUS,					"MMU_FAULT_STATUS                ");
+		DBG_READ64(RGX_CR_MMU_FAULT_STATUS_META,			"MMU_FAULT_STATUS_META           ");
+	}
+	else
+	{
+		DBG_READ32(RGX_CR_BIF_FAULT_BANK0_MMU_STATUS,		"BIF_FAULT_BANK0_MMU_STATUS      ");
+		DBG_READ64(RGX_CR_BIF_FAULT_BANK0_REQ_STATUS,		"BIF_FAULT_BANK0_REQ_STATUS      ");
+		DBG_READ32(RGX_CR_BIF_FAULT_BANK1_MMU_STATUS,		"BIF_FAULT_BANK1_MMU_STATUS      ");
+		DBG_READ64(RGX_CR_BIF_FAULT_BANK1_REQ_STATUS,		"BIF_FAULT_BANK1_REQ_STATUS      ");
+	}
+
 	DBG_READ32(RGX_CR_BIF_MMU_STATUS,					"BIF_MMU_STATUS                  ");
 	DBG_READ32(RGX_CR_BIF_MMU_ENTRY,					"BIF_MMU_ENTRY                   ");
 	DBG_READ64(RGX_CR_BIF_MMU_ENTRY_STATUS,				"BIF_MMU_ENTRY_STATUS            ");
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	DBG_READ32(RGX_CR_BIF_JONES_OUTSTANDING_READ,		"BIF_JONES_OUTSTANDING_READ      ");
-	DBG_READ32(RGX_CR_BIF_BLACKPEARL_OUTSTANDING_READ,	"BIF_BLACKPEARL_OUTSTANDING_READ ");
-	DBG_READ32(RGX_CR_BIF_DUST_OUTSTANDING_READ,		"BIF_DUST_OUTSTANDING_READ       ");
-#else
-#if !defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
-	DBG_READ32(RGX_CR_BIF_STATUS_MMU,					"BIF_STATUS_MMU                  ");
-	DBG_READ32(RGX_CR_BIF_READS_EXT_STATUS,				"BIF_READS_EXT_STATUS            ");
-	DBG_READ32(RGX_CR_BIF_READS_INT_STATUS,				"BIF_READS_INT_STATUS            ");
-#endif
-	DBG_READ32(RGX_CR_BIFPM_STATUS_MMU,					"BIFPM_STATUS_MMU                ");
-	DBG_READ32(RGX_CR_BIFPM_READS_EXT_STATUS,			"BIFPM_READS_EXT_STATUS          ");
-	DBG_READ32(RGX_CR_BIFPM_READS_INT_STATUS,			"BIFPM_READS_INT_STATUS          ");
-#endif
-#if defined(FIX_HW_BRN_44871)
-	DBG_STRING("Warning: BRN44871 is present");
-#endif
+	if (bS7Infra)
+	{
+		DBG_READ32(RGX_CR_BIF_JONES_OUTSTANDING_READ,		"BIF_JONES_OUTSTANDING_READ      ");
+		DBG_READ32(RGX_CR_BIF_BLACKPEARL_OUTSTANDING_READ,	"BIF_BLACKPEARL_OUTSTANDING_READ ");
+		DBG_READ32(RGX_CR_BIF_DUST_OUTSTANDING_READ,		"BIF_DUST_OUTSTANDING_READ       ");
+	}else
+	{
+
+		if (!bXTInfra)
+		{
+			DBG_READ32(RGX_CR_BIF_STATUS_MMU,					"BIF_STATUS_MMU                  ");
+			DBG_READ32(RGX_CR_BIF_READS_EXT_STATUS,				"BIF_READS_EXT_STATUS            ");
+			DBG_READ32(RGX_CR_BIF_READS_INT_STATUS,				"BIF_READS_INT_STATUS            ");
+		}
+		DBG_READ32(RGX_CR_BIFPM_STATUS_MMU,					"BIFPM_STATUS_MMU                ");
+		DBG_READ32(RGX_CR_BIFPM_READS_EXT_STATUS,			"BIFPM_READS_EXT_STATUS          ");
+		DBG_READ32(RGX_CR_BIFPM_READS_INT_STATUS,			"BIFPM_READS_INT_STATUS          ");
+	}
+
+	if(e44871)
+	{
+		DBG_STRING("Warning: BRN44871 is present");
+	}
+
+	if(e47025)
+	{
+		DBG_READ64(RGX_CR_CDM_CONTEXT_LOAD_PDS0,			"CDM_CONTEXT_LOAD_PDS0           ");
+		DBG_READ64(RGX_CR_CDM_CONTEXT_LOAD_PDS1,			"CDM_CONTEXT_LOAD_PDS1           ");
+	}
+
 	DBG_READ32(RGX_CR_SLC_STATUS0,						"SLC_STATUS0                     ");
 	DBG_READ64(RGX_CR_SLC_STATUS1,						"SLC_STATUS1                     ");
-	DBG_READ64(RGX_CR_SLC_STATUS2,						"SLC_STATUS2                     ");
 
-#if defined(RGX_FEATURE_SLC_VIVT)
-	DBG_READ64(RGX_CR_CONTEXT_MAPPING0,					"CONTEXT_MAPPING0                ");
-	DBG_READ64(RGX_CR_CONTEXT_MAPPING1,					"CONTEXT_MAPPING1                ");
-	DBG_READ64(RGX_CR_CONTEXT_MAPPING2,					"CONTEXT_MAPPING2                ");
-	DBG_READ64(RGX_CR_CONTEXT_MAPPING3,					"CONTEXT_MAPPING3                ");
-	DBG_READ64(RGX_CR_CONTEXT_MAPPING4,					"CONTEXT_MAPPING4                ");
-#else
-	DBG_READ64(RGX_CR_BIF_CAT_BASE_INDEX,				"BIF_CAT_BASE_INDEX              ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE0,					"BIF_CAT_BASE0                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE1,					"BIF_CAT_BASE1                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE2,					"BIF_CAT_BASE2                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE3,					"BIF_CAT_BASE3                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE4,					"BIF_CAT_BASE4                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE5,					"BIF_CAT_BASE5                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE6,					"BIF_CAT_BASE6                   ");
-	DBG_READ64(RGX_CR_BIF_CAT_BASE7,					"BIF_CAT_BASE7                   ");
-#endif
+	if (ui32SLCBanks)
+	{
+		DBG_READ64(RGX_CR_SLC_STATUS2,						"SLC_STATUS2                     ");
+	}
+
+	if (bVIVTSlc)
+	{
+		DBG_READ64(RGX_CR_CONTEXT_MAPPING0,					"CONTEXT_MAPPING0                ");
+		DBG_READ64(RGX_CR_CONTEXT_MAPPING1,					"CONTEXT_MAPPING1                ");
+		DBG_READ64(RGX_CR_CONTEXT_MAPPING2,					"CONTEXT_MAPPING2                ");
+		DBG_READ64(RGX_CR_CONTEXT_MAPPING3,					"CONTEXT_MAPPING3                ");
+		DBG_READ64(RGX_CR_CONTEXT_MAPPING4,					"CONTEXT_MAPPING4                ");
+	}else{
+		DBG_READ64(RGX_CR_BIF_CAT_BASE_INDEX,				"BIF_CAT_BASE_INDEX              ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE0,					"BIF_CAT_BASE0                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE1,					"BIF_CAT_BASE1                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE2,					"BIF_CAT_BASE2                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE3,					"BIF_CAT_BASE3                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE4,					"BIF_CAT_BASE4                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE5,					"BIF_CAT_BASE5                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE6,					"BIF_CAT_BASE6                   ");
+		DBG_READ64(RGX_CR_BIF_CAT_BASE7,					"BIF_CAT_BASE7                   ");
+	}
 
 	DBG_READ32(RGX_CR_BIF_CTRL_INVAL,					"BIF_CTRL_INVAL                  ");
 	DBG_READ32(RGX_CR_BIF_CTRL,							"BIF_CTRL                        ");
@@ -308,47 +932,6 @@
 
 	DBG_READ32(RGX_CR_ISP_CTL,							"ISP_CTL                         ");
 	DBG_READ32(RGX_CR_ISP_STATUS,						"ISP_STATUS                      ");
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	DBG_READ32(RGX_CR_ISP_STORE0,						"ISP_STORE0                      ");
-	DBG_READ32(RGX_CR_ISP_STORE1,						"ISP_STORE1                      ");
-	DBG_READ32(RGX_CR_ISP_STORE2,						"ISP_STORE2                      ");
-	#if (RGX_FEATURE_NUM_ISP_IPP_PIPES > 3)
-	DBG_READ32(RGX_CR_ISP_STORE3,						"ISP_STORE3                      ");
-	DBG_READ32(RGX_CR_ISP_STORE4,						"ISP_STORE4                      ");
-	DBG_READ32(RGX_CR_ISP_STORE5,						"ISP_STORE5                      ");
-	#endif
-	#if (RGX_FEATURE_NUM_ISP_IPP_PIPES > 6)
-	DBG_READ32(RGX_CR_ISP_STORE6,						"ISP_STORE6                      ");
-	DBG_READ32(RGX_CR_ISP_STORE7,						"ISP_STORE7                      ");
-	#endif
-	DBG_READ32(RGX_CR_ISP_RESUME0,						"ISP_RESUME0                     ");
-	DBG_READ32(RGX_CR_ISP_RESUME1,						"ISP_RESUME1                     ");
-	DBG_READ32(RGX_CR_ISP_RESUME2,						"ISP_RESUME2                     ");
-	#if (RGX_FEATURE_NUM_ISP_IPP_PIPES > 3)
-	DBG_READ32(RGX_CR_ISP_RESUME3,						"ISP_RESUME3                     ");
-	DBG_READ32(RGX_CR_ISP_RESUME4,						"ISP_RESUME4                     ");
-	DBG_READ32(RGX_CR_ISP_RESUME5,						"ISP_RESUME5                     ");
-	#endif
-	#if (RGX_FEATURE_NUM_ISP_IPP_PIPES > 6)
-	DBG_READ32(RGX_CR_ISP_RESUME6,						"ISP_RESUME6                     ");
-	DBG_READ32(RGX_CR_ISP_RESUME7,						"ISP_RESUME7                     ");
-	#endif
-#else
-	{
-		IMG_UINT	uiPipe;
-		IMG_CHAR	pszLabel[64]; /* larger than necessary in case alignment changes */
-		for (uiPipe = 0; uiPipe < RGX_FEATURE_NUM_ISP_IPP_PIPES; uiPipe++)
-		{
-			OSSNPrintf(pszLabel, sizeof(pszLabel),		"ISP_XTP_STORE%02d                 ", uiPipe);
-			DBG_READ32(RGX_CR_ISP_XTP_STORE0 + 0x8*uiPipe, pszLabel);
-		}
-		for (uiPipe = 0; uiPipe < RGX_FEATURE_NUM_ISP_IPP_PIPES; uiPipe++)
-		{
-			OSSNPrintf(pszLabel, sizeof(pszLabel),		"ISP_XTP_RESUME%02d                ", uiPipe);
-			DBG_READ32(RGX_CR_ISP_XTP_RESUME0 + 0x8*uiPipe, pszLabel);
-		}
-	}
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
 	DBG_READ32(RGX_CR_MTS_INTCTX,						"MTS_INTCTX                      ");
 	DBG_READ32(RGX_CR_MTS_BGCTX,						"MTS_BGCTX                       ");
 	DBG_READ32(RGX_CR_MTS_BGCTX_COUNTED_SCHEDULE,		"MTS_BGCTX_COUNTED_SCHEDULE      ");
@@ -360,316 +943,715 @@
 	DBG_READ64(RGX_CR_CDM_CONTEXT_PDS1,					"CDM_CONTEXT_PDS1                ");
 	DBG_READ64(RGX_CR_CDM_TERMINATE_PDS,				"CDM_TERMINATE_PDS               ");
 	DBG_READ64(RGX_CR_CDM_TERMINATE_PDS1,				"CDM_TERMINATE_PDS1              ");
-#if defined(HW_ERN_47025)
-	DBG_READ64(RGX_CR_CDM_CONTEXT_LOAD_PDS0,			"CDM_CONTEXT_LOAD_PDS0           ");
-	DBG_READ64(RGX_CR_CDM_CONTEXT_LOAD_PDS1,			"CDM_CONTEXT_LOAD_PDS1           ");
-#endif
-	
-#if defined(RGX_FEATURE_RAY_TRACING)
-	DBG_READ32(DPX_CR_BIF_MMU_STATUS,					"DPX_CR_BIF_MMU_STATUS           ");
-	DBG_READ64(DPX_CR_BIF_FAULT_BANK_MMU_STATUS,		"DPX_CR_BIF_FAULT_BANK_MMU_STATUS");
-	DBG_READ64(DPX_CR_BIF_FAULT_BANK_REQ_STATUS,		"DPX_CR_BIF_FAULT_BANK_REQ_STATUS");
 
-	DBG_READ64(RGX_CR_RPM_SHF_FPL,						"RGX_CR_RPM_SHF_FPL	             ");
-	DBG_READ32(RGX_CR_RPM_SHF_FPL_READ,					"RGX_CR_RPM_SHF_FPL_READ         ");
-	DBG_READ32(RGX_CR_RPM_SHF_FPL_WRITE,				"RGX_CR_RPM_SHF_FPL_WRITE        ");
-	DBG_READ64(RGX_CR_RPM_SHG_FPL,   					"RGX_CR_RPM_SHG_FPL	             ");
-	DBG_READ32(RGX_CR_RPM_SHG_FPL_READ,					"RGX_CR_RPM_SHG_FPL_READ         ");
-	DBG_READ32(RGX_CR_RPM_SHG_FPL_WRITE,				"RGX_CR_RPM_SHG_FPL_WRITE        ");
+	if(e47025)
+	{
+		DBG_READ64(RGX_CR_CDM_CONTEXT_LOAD_PDS0,			"CDM_CONTEXT_LOAD_PDS0           ");
+		DBG_READ64(RGX_CR_CDM_CONTEXT_LOAD_PDS1,			"CDM_CONTEXT_LOAD_PDS1           ");
+	}
+
+	if(bRayTracing)
+	{
+#if defined(RGX_FEATURE_RAY_TRACING) || defined(SUPPORT_KERNEL_SRVINIT)
+		DBG_READ32(DPX_CR_BIF_MMU_STATUS,					"DPX_CR_BIF_MMU_STATUS           ");
+		DBG_READ64(DPX_CR_BIF_FAULT_BANK_MMU_STATUS,		"DPX_CR_BIF_FAULT_BANK_MMU_STATUS");
+		DBG_READ64(DPX_CR_BIF_FAULT_BANK_REQ_STATUS,		"DPX_CR_BIF_FAULT_BANK_REQ_STATUS");
+
+		DBG_READ64(RGX_CR_RPM_SHF_FPL,						"RGX_CR_RPM_SHF_FPL	             ");
+		DBG_READ32(RGX_CR_RPM_SHF_FPL_READ,					"RGX_CR_RPM_SHF_FPL_READ         ");
+		DBG_READ32(RGX_CR_RPM_SHF_FPL_WRITE,				"RGX_CR_RPM_SHF_FPL_WRITE        ");
+		DBG_READ64(RGX_CR_RPM_SHG_FPL,   					"RGX_CR_RPM_SHG_FPL	             ");
+		DBG_READ32(RGX_CR_RPM_SHG_FPL_READ,					"RGX_CR_RPM_SHG_FPL_READ         ");
+		DBG_READ32(RGX_CR_RPM_SHG_FPL_WRITE,				"RGX_CR_RPM_SHG_FPL_WRITE        ");
 #endif
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	DBG_READ32(RGX_CR_JONES_IDLE,						"JONES_IDLE                      ");
-#endif
+	}
+
+	if (bS7Infra)
+	{
+		DBG_READ32(RGX_CR_JONES_IDLE,						"JONES_IDLE                      ");
+	}
+
 	DBG_READ32(RGX_CR_SIDEKICK_IDLE,					"SIDEKICK_IDLE                   ");
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	DBG_READ32(RGX_CR_SLC_IDLE,							"SLC_IDLE                        ");
-#else
-	DBG_READ32(RGX_CR_SLC3_IDLE,						"SLC3_IDLE                       ");
-	DBG_READ64(RGX_CR_SLC3_STATUS,						"SLC3_STATUS                     ");
-	DBG_READ32(RGX_CR_SLC3_FAULT_STOP_STATUS,			"SLC3_FAULT_STOP_STATUS          ");
-#endif
-#if defined(RGX_FEATURE_META)
-	DBG_MSP_READ(META_CR_T0ENABLE_OFFSET,				"T0 TXENABLE                     ");
-	DBG_MSP_READ(META_CR_T0STATUS_OFFSET,				"T0 TXSTATUS                     ");
-	DBG_MSP_READ(META_CR_T0DEFR_OFFSET,					"T0 TXDEFR                       ");
-	DBG_MCR_READ(META_CR_THR0_PC,						"T0 PC                           ");
-	DBG_MCR_READ(META_CR_THR0_PCX,						"T0 PCX                          ");
-	DBG_MCR_READ(META_CR_THR0_SP,						"T0 SP                           ");
+	if (!bS7Infra)
+	{
+		DBG_READ32(RGX_CR_SLC_IDLE,							"SLC_IDLE                        ");
+	}else
+	{
+		DBG_READ32(RGX_CR_SLC3_IDLE,						"SLC3_IDLE                       ");
+		DBG_READ64(RGX_CR_SLC3_STATUS,						"SLC3_STATUS                     ");
+		DBG_READ32(RGX_CR_SLC3_FAULT_STOP_STATUS,			"SLC3_FAULT_STOP_STATUS          ");
+	}
 
-#if (RGX_FEATURE_META == MTP218) || (RGX_FEATURE_META == MTP219)
-	DBG_MSP_READ(META_CR_T1ENABLE_OFFSET,				"T1 TXENABLE                     ");
-	DBG_MSP_READ(META_CR_T1STATUS_OFFSET,				"T1 TXSTATUS                     ");
-	DBG_MSP_READ(META_CR_T1DEFR_OFFSET,					"T1 TXDEFR                       ");
-	DBG_MCR_READ(META_CR_THR1_PC,						"T1 PC                           ");
-	DBG_MCR_READ(META_CR_THR1_PCX,						"T1 PCX                          ");
-	DBG_MCR_READ(META_CR_THR1_SP,						"T1 SP                           ");
-#endif
+	if (ui32Meta)
+	{
+		DBG_MSP_READ(META_CR_T0ENABLE_OFFSET,				"T0 TXENABLE                     ");
+		DBG_MSP_READ(META_CR_T0STATUS_OFFSET,				"T0 TXSTATUS                     ");
+		DBG_MSP_READ(META_CR_T0DEFR_OFFSET,					"T0 TXDEFR                       ");
+		DBG_MCR_READ(META_CR_THR0_PC,						"T0 PC                           ");
+		DBG_MCR_READ(META_CR_THR0_PCX,						"T0 PCX                          ");
+		DBG_MCR_READ(META_CR_THR0_SP,						"T0 SP                           ");
+	}
+
+	if ((ui32Meta == MTP218) || (ui32Meta == MTP219))
+	{
+		DBG_MSP_READ(META_CR_T1ENABLE_OFFSET,				"T1 TXENABLE                     ");
+		DBG_MSP_READ(META_CR_T1STATUS_OFFSET,				"T1 TXSTATUS                     ");
+		DBG_MSP_READ(META_CR_T1DEFR_OFFSET,					"T1 TXDEFR                       ");
+		DBG_MCR_READ(META_CR_THR1_PC,						"T1 PC                           ");
+		DBG_MCR_READ(META_CR_THR1_PCX,						"T1 PCX                          ");
+		DBG_MCR_READ(META_CR_THR1_SP,						"T1 SP                           ");
+	}
 
 	if (bFirmwarePerf)
 	{
 		DBG_MSP_READ(META_CR_PERF_COUNT0,				"PERF_COUNT0                     ");
 		DBG_MSP_READ(META_CR_PERF_COUNT1,				"PERF_COUNT1                     ");
 	}
-#endif
-#if defined(RGX_FEATURE_MIPS)
-	DBG_READ32(RGX_CR_MIPS_EXCEPTION_STATUS,            "MIPS_EXCEPTION_STATUS           ");
-#endif
+
+	if (bMIPS)
+	{
+		DBG_READ32(RGX_CR_MIPS_EXCEPTION_STATUS,            "MIPS_EXCEPTION_STATUS           ");
+	}
 
 	return IMG_TRUE;
 }
 
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
+/*************************************************************************/ /*!
+ @Function       RGXTDProcessFWImage
+
+ @Description    Fetch and send data used by the trusted device to complete
+                 the FW image setup
+
+ @Input          psDeviceNode - Device node
+ @Input          psRGXFW      - Firmware blob
+
+ @Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        struct RGXFW *psRGXFW)
+{
+	PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	PVRSRV_TD_FW_PARAMS sTDFWParams;
+	PVRSRV_ERROR eError;
+
+	if (psDevConfig->pfnTDSendFWImage == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "RGXTDProcessFWImage: TDProcessFWImage not implemented!"));
+		return PVRSRV_ERROR_NOT_IMPLEMENTED;
+	}
+
+	sTDFWParams.pvFirmware = RGXFirmwareData(psRGXFW);
+	sTDFWParams.ui32FirmwareSize = RGXFirmwareSize(psRGXFW);
+	sTDFWParams.sFWCodeDevVAddrBase = psDevInfo->sFWCodeDevVAddrBase;
+	sTDFWParams.sFWDataDevVAddrBase = psDevInfo->sFWDataDevVAddrBase;
+	sTDFWParams.sFWCorememCodeFWAddr = psDevInfo->sFWCorememCodeFWAddr;
+	sTDFWParams.sFWInitFWAddr = psDevInfo->sFWInitFWAddr;
+
+	eError = psDevConfig->pfnTDSendFWImage(psDevConfig->hSysData, &sTDFWParams);
+
+	return eError;
+}
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function     AcquireHostData
+
+ @Description  Acquire Device MemDesc and CPU pointer for a given PMR
+
+ @Input        hServices      : Services connection
+ @Input        hPMR           : PMR
+ @Output       ppsHostMemDesc : Returned MemDesc
+ @Output       ppvHostAddr    : Returned CPU pointer
+
+ @Return       PVRSRV_ERROR
+
+******************************************************************************/
+static INLINE
+PVRSRV_ERROR AcquireHostData(SHARED_DEV_CONNECTION hServices,
+                             IMG_HANDLE hPMR,
+                             DEVMEM_MEMDESC **ppsHostMemDesc,
+                             void **ppvHostAddr)
+{
+	IMG_HANDLE hImportHandle;
+	IMG_DEVMEM_SIZE_T uiImportSize;
+	PVRSRV_ERROR eError;
+
+	eError = DevmemMakeLocalImportHandle(hServices,
+	                                     hPMR,
+	                                     &hImportHandle);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "AcquireHostData: DevmemMakeLocalImportHandle failed (%d)", eError));
+		goto acquire_failmakehandle;
+	}
+
+	eError = DevmemLocalImport(hServices,
+	                           hImportHandle,
+	                           PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+	                           PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+	                           PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+	                           PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
+	                           ppsHostMemDesc,
+	                           &uiImportSize,
+	                           "AcquireHostData");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "AcquireHostData: DevmemLocalImport failed (%d)", eError));
+		goto acquire_failimport;
+	}
+
+	eError = DevmemAcquireCpuVirtAddr(*ppsHostMemDesc,
+	                                  ppvHostAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "AcquireHostData: DevmemAcquireCpuVirtAddr failed (%d)", eError));
+		goto acquire_failcpuaddr;
+	}
+
+	/* We don't need the import handle anymore */
+	DevmemUnmakeLocalImportHandle(hServices, hImportHandle);
+
+	return PVRSRV_OK;
+
+
+acquire_failcpuaddr:
+	DevmemFree(*ppsHostMemDesc);
+
+acquire_failimport:
+	DevmemUnmakeLocalImportHandle(hServices, hImportHandle);
+
+acquire_failmakehandle:
+	return eError;
+}
+
 /*!
 *******************************************************************************
 
- @Function		PrepareDebugScript
+ @Function     ReleaseHostData
 
- @Description	Generates a script to dump debug info
+ @Description  Releases resources associated with a Device MemDesc
 
- @Input			psScript
+ @Input        psHostMemDesc : MemDesc to free
 
- @Return		IMG_BOOL True if it runs out of cmds when building the script
+ @Return       PVRSRV_ERROR
 
 ******************************************************************************/
-static IMG_BOOL PrepareDebugBusScript(RGX_SCRIPT_BUILD* psDbgBusScript)
+static INLINE void ReleaseHostData(DEVMEM_MEMDESC *psHostMemDesc)
 {
-#if defined(RGX_FEATURE_PERFBUS) && defined(SUPPORT_DEBUG_BUS_DUMP)
-	IMG_UINT32 i;
-#define DUMP_DEBUG_BUS(N,R,C)	if (!ScriptDBGBusReadBlock(psDbgBusScript, N, R, C)) return IMG_FALSE;
-#define DBG_WRITE(R,V)			if (!ScriptWriteRGXReg(psDbgBusScript, R, V)) return IMG_FALSE;
-									  
-	DUMP_DEBUG_BUS("TA group", RGX_CR_TA_PERF, 9);
-	DUMP_DEBUG_BUS("RAST group", RGX_CR_RASTERISATION_PERF, 10);
-	DUMP_DEBUG_BUS("HUB group", RGX_CR_HUB_BIFPMCACHE_PERF, 17);
-
-	for (i = 0; i < RGX_HWPERF_PHANTOM_INDIRECT_BY_DUST; i++)
-	{
-		IMG_CHAR aszGroupName[100];
-		DBG_WRITE(RGX_CR_TPU_MCU_L0_PERF_INDIRECT, i);
-		snprintf(aszGroupName, sizeof(aszGroupName), "TPU group %d", i);
-		DUMP_DEBUG_BUS(aszGroupName, RGX_CR_TPU_MCU_L0_PERF, 6);
-	}
-
-	for (i = 0; i < RGX_HWPERF_PHANTOM_INDIRECT_BY_CLUSTER; i++)
-	{
-		IMG_CHAR aszGroupName[100];
-		DBG_WRITE(RGX_CR_USC_PERF_INDIRECT, i);
-		snprintf(aszGroupName, sizeof(aszGroupName), "USC group %d", i);
-		DUMP_DEBUG_BUS(aszGroupName, RGX_CR_USC_PERF, 11);
-	}
-#undef DUMP_DEBUG_BUS
-#undef DBG_WRITE
-#else
-	PVR_UNREFERENCED_PARAMETER(psDbgBusScript);
-#endif /* RGX_FEATURE_PERFBUS && SUPPORT_DEBUG_BUS_DUMP*/
-
-	return IMG_TRUE;
+	DevmemReleaseCpuVirtAddr(psHostMemDesc);
+	DevmemFree(psHostMemDesc);
 }
 
 /*!
 *******************************************************************************
 
- @Function		PrepareDeinitScript
+ @Function     GetFirmwareBVNC
 
- @Description	Generates a script to suspend the hw threads
+ @Description  Retrieves FW BVNC information from binary data
 
- @Input			psScript
+ @Input        psRGXFW : Firmware binary handle to get BVNC from
 
- @Return		IMG_BOOL True if it runs out of cmds when building the script
+ @Output       psRGXFWBVNC : structure store BVNC info
+
+ @Return       IMG_TRUE upon success, IMG_FALSE otherwise
 
 ******************************************************************************/
-static IMG_BOOL PrepareDeinitScript(RGX_SCRIPT_BUILD* psScript)
+static INLINE IMG_BOOL GetFirmwareBVNC(struct RGXFW *psRGXFW,
+                                       RGXFWIF_COMPCHECKS_BVNC *psFWBVNC)
 {
-	/* Wait for Sidekick to signal IDLE except for the Garten Wrapper */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_SIDEKICK_IDLE,
-			RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
-			RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN))) return IMG_FALSE;
-#else
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_JONES_IDLE,
-			RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
-			RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN))) return IMG_FALSE;
+#if defined(LINUX)
+	const size_t FWSize = RGXFirmwareSize(psRGXFW);
+	const RGXFWIF_COMPCHECKS_BVNC * psBinBVNC;
 #endif
 
-#if !defined(SUPPORT_SHARED_SLC)
-	/* Wait for SLC to signal IDLE */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_SLC_IDLE,
-			RGX_CR_SLC_IDLE_MASKFULL,
-			RGX_CR_SLC_IDLE_MASKFULL)) return IMG_FALSE;
+#if !defined(LINUX)
+	/* Check not available in non linux OSes. Just fill the struct and return true */
+	psFWBVNC->ui32LayoutVersion = RGXFWIF_COMPCHECKS_LAYOUT_VERSION;
+	psFWBVNC->ui32VLenMax = RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX;
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	rgx_bvnc_packed(&psFWBVNC->ui64BNC, psFWBVNC->aszV, psFWBVNC->ui32VLenMax,
+	                RGX_BNC_B, RGX_BVNC_V_ST, RGX_BNC_N, RGX_BNC_C);
 #else
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_SLC3_IDLE,
-			RGX_CR_SLC3_IDLE_MASKFULL,
-			RGX_CR_SLC3_IDLE_MASKFULL)) return IMG_FALSE;
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
-#endif /* SUPPORT_SHARED_SLC */
+	rgx_bvnc_packed(&psFWBVNC->ui64BNC, psFWBVNC->aszV, psFWBVNC->ui32VLenMax,
+	                RGX_BNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BNC_KM_N, RGX_BNC_KM_C);
+#endif /* SUPPORT_KERNEL_SRVINIT */
 
-	/* unset MTS DM association with threads */
-	if(!ScriptWriteRGXReg(
-			psScript, 
-			RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC,
-			RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK & RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC_MASKFULL)) return IMG_FALSE;
-	if(!ScriptWriteRGXReg(
-			psScript, 
-			RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC,
-			RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK & RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL)) return IMG_FALSE;
-
-	if(!ScriptWriteRGXReg(
-			psScript, 
-			RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
-			RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK & RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL)) return IMG_FALSE;
-	if(!ScriptWriteRGXReg(
-			psScript, 
-			RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
-			RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK & RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL)) return IMG_FALSE;
-
-#if defined(RGX_FEATURE_META)
-	/* Disabling threads is only required for pdumps to stop the fw gracefully */
-	/* Disable thread 0 */
-	if(!ScriptWriteMetaRegThroughSP(psScript, 
-						 META_CR_T0ENABLE_OFFSET,
-						 ~META_CR_TXENABLE_ENABLE_BIT)) return IMG_FALSE;
-
-	/* Disable thread 1 */
-	if(!ScriptWriteMetaRegThroughSP(psScript, 
-						 META_CR_T1ENABLE_OFFSET,
-						 ~META_CR_TXENABLE_ENABLE_BIT)) return IMG_FALSE;
-
-	/* Only in PDUMPS: Clear down any irq raised by META 
-	   (done after disabling the FW threads to avoid a race condition) */
-	if(!ScriptWriteRGXRegPDUMPOnly(
-			psScript, 
-			RGX_CR_META_SP_MSLVIRQSTATUS,
-			0x0)) return IMG_FALSE;
-
-	/* Wait for the Slave Port to finish all the transactions */
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_META_SP_MSLVCTRL1, 
-			RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN, 
-			RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN)
-	  ) return IMG_FALSE;
-#endif
-	/* Extra Idle checks */
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_BIF_STATUS_MMU, 
-			0,
-			RGX_CR_BIF_STATUS_MMU_MASKFULL)
-	  ) return IMG_FALSE;
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_BIFPM_STATUS_MMU, 
-			0,
-			RGX_CR_BIFPM_STATUS_MMU_MASKFULL)
-	  ) return IMG_FALSE;
-#if !defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_BIF_READS_EXT_STATUS, 
-			0,
-			RGX_CR_BIF_READS_EXT_STATUS_MASKFULL)
-	  ) return IMG_FALSE;
-#endif
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_BIFPM_READS_EXT_STATUS, 
-			0,
-			RGX_CR_BIFPM_READS_EXT_STATUS_MASKFULL)
-	  ) return IMG_FALSE;
-	if(!ScriptPoll64RGXReg
-		(
-			psScript, 
-			RGX_CR_SLC_STATUS1, 
-			0,
-#if defined(FIX_HW_BRN_43276)
-			RGX_CR_SLC_STATUS1_MASKFULL & RGX_CR_SLC_STATUS1_READS1_EXT_CLRMSK & RGX_CR_SLC_STATUS1_READS0_EXT_CLRMSK)
 #else
-			RGX_CR_SLC_STATUS1_MASKFULL)
-#endif 
-	  ) return IMG_FALSE;
 
-	if(!ScriptPoll64RGXReg(
-			psScript, 
-			RGX_CR_SLC_STATUS2, 
-			0,
-			RGX_CR_SLC_STATUS2_MASKFULL)
-	  ) return IMG_FALSE;
+	if (FWSize < FW_BVNC_BACKWARDS_OFFSET)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Firmware is too small (%zu bytes)",
+		         __func__, FWSize));
+		return IMG_FALSE;
+	}
 
-#if !defined(SUPPORT_SHARED_SLC)
-	/* Wait for SLC to signal IDLE */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_SLC_IDLE,
-			RGX_CR_SLC_IDLE_MASKFULL,
-			RGX_CR_SLC_IDLE_MASKFULL)) return IMG_FALSE;
-#else
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_SLC3_IDLE,
-			RGX_CR_SLC3_IDLE_MASKFULL,
-			RGX_CR_SLC3_IDLE_MASKFULL)) return IMG_FALSE;
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
-#endif /* SUPPORT_SHARED_SLC */
+	psBinBVNC = (RGXFWIF_COMPCHECKS_BVNC *) ((IMG_UINT8 *) (RGXFirmwareData(psRGXFW)) +
+	                                         (FWSize - FW_BVNC_BACKWARDS_OFFSET));
 
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_SIDEKICK_IDLE,
-			RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
-			RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN))) return IMG_FALSE;
-#else
-	if(!ScriptPollRGXReg(
-			psScript, 
-			RGX_CR_JONES_IDLE,
-			RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
-			RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN))) return IMG_FALSE;
-#endif
+	psFWBVNC->ui32LayoutVersion = RGX_INT32_FROM_BE(psBinBVNC->ui32LayoutVersion);
 
-#if defined(RGX_FEATURE_META)
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	/* Wait for Sidekick to signal IDLE including the Garten Wrapper if
-	   there is no debugger attached (TxVECINT_BHALT = 0x0) */
-	if(!ScriptMetaRegCondPollRGXReg(
-			psScript, 
-			META_CR_TxVECINT_BHALT,
-			0x0,
-			0xFFFFFFFFU,
-			RGX_CR_SIDEKICK_IDLE,
-			RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
-			RGX_CR_SIDEKICK_IDLE_GARTEN_EN)) return IMG_FALSE;
-#else
-	/* Wait for Jone to signal IDLE including the Garten Wrapper if
-	   there is no debugger attached (TxVECINT_BHALT = 0x0) */
-	if(!ScriptMetaRegCondPollRGXReg(
-			psScript, 
-			META_CR_TxVECINT_BHALT,
-			0x0,
-			0xFFFFFFFFU,
-			RGX_CR_JONES_IDLE,
-			RGX_CR_JONES_IDLE_GARTEN_EN,
-			RGX_CR_JONES_IDLE_GARTEN_EN)) return IMG_FALSE;
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
-#else
-	if(!ScriptPollRGXReg(
-			psScript,
-			RGX_CR_SIDEKICK_IDLE,
-			RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
-			RGX_CR_SIDEKICK_IDLE_GARTEN_EN)) return IMG_FALSE;
+	psFWBVNC->ui32VLenMax = RGX_INT32_FROM_BE(psBinBVNC->ui32VLenMax);
 
-#endif
+	psFWBVNC->ui64BNC = RGX_INT64_FROM_BE(psBinBVNC->ui64BNC);
+
+	strncpy(psFWBVNC->aszV, psBinBVNC->aszV, sizeof(psFWBVNC->aszV));
+#endif /* defined(LINUX) */
 
 	return IMG_TRUE;
 }
 
+
+/*!
+*******************************************************************************
+
+ @Function     RGXInitFirmwareBridgeWrapper
+
+ @Description  Calls the proper RGXInitFirmware bridge version
+
+ @Return       PVRSRV_ERROR
+
+******************************************************************************/
+static INLINE PVRSRV_ERROR RGXInitFirmwareBridgeWrapper(SHARED_DEV_CONNECTION    hServices,
+                                                        RGXFWIF_DEV_VIRTADDR     *psRGXFwInit,
+                                                        IMG_BOOL                 bEnableSignatureChecks,
+                                                        IMG_UINT32               ui32SignatureChecksBufSize,
+                                                        IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                                                        IMG_UINT64               ui64HWPerfFilter,
+                                                        IMG_UINT32               ui32RGXFWAlignChecksArrLength,
+                                                        IMG_UINT32               *pui32RGXFWAlignChecks,
+                                                        IMG_UINT32               ui32FWConfigFlags,
+                                                        IMG_UINT32               ui32LogType,
+                                                        IMG_UINT32               ui32FilterFlags,
+                                                        IMG_UINT32               ui32JonesDisableMask,
+                                                        IMG_UINT32               ui32HWRDebugDumpLimit,
+                                                        RGXFWIF_COMPCHECKS_BVNC  *psClientBVNC,
+                                                        RGXFWIF_COMPCHECKS_BVNC  *psFirmwareBVNC,
+                                                        IMG_UINT32               ui32HWPerfCountersDataSize,
+                                                        IMG_HANDLE               *phHWPerfDataPMR,
+                                                        RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
+                                                        FW_PERF_CONF             eFirmwarePerf)
+{
+	PVRSRV_ERROR eError;
+
+	RGX_FW_INIT_IN_PARAMS sInParams = {
+		RGXFWINITPARAMS_VERSION,
+		bEnableSignatureChecks,
+		ui32SignatureChecksBufSize,
+		ui32HWPerfFWBufSizeKB,
+		ui64HWPerfFilter,
+		ui32FWConfigFlags,
+		ui32LogType,
+		ui32FilterFlags,
+		ui32JonesDisableMask,
+		ui32HWRDebugDumpLimit,
+		{ 0 },
+		{ 0 },
+		ui32HWPerfCountersDataSize,
+		eRGXRDPowerIslandConf,
+		eFirmwarePerf,
+		{ 0 }
+	};
+
+	memcpy(&(sInParams.sClientBVNC), psClientBVNC, sizeof (sInParams.sClientBVNC));
+	memcpy(&(sInParams.sFirmwareBVNC), psFirmwareBVNC, sizeof (sInParams.sFirmwareBVNC));
+
+
+	eError = BridgeRGXInitFirmwareExtended(hServices, ui32RGXFWAlignChecksArrLength,
+	                                       pui32RGXFWAlignChecks, psRGXFwInit, phHWPerfDataPMR, &sInParams);
+
+	/* Error calling the bridge could be due to old KM not implementing the extended version */
+	if ((eError == PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+	    || (eError == PVRSRV_ERROR_BRIDGE_EINVAL))
+	{
+		eError = BridgeRGXInitFirmware(hServices,
+		                               psRGXFwInit,
+		                               bEnableSignatureChecks,
+		                               ui32SignatureChecksBufSize,
+		                               ui32HWPerfFWBufSizeKB,
+		                               ui64HWPerfFilter,
+		                               ui32RGXFWAlignChecksArrLength,
+		                               pui32RGXFWAlignChecks,
+		                               ui32FWConfigFlags,
+		                               ui32LogType,
+		                               ui32FilterFlags,
+		                               ui32JonesDisableMask,
+		                               ui32HWRDebugDumpLimit,
+		                               psClientBVNC,
+		                               ui32HWPerfCountersDataSize,
+		                               phHWPerfDataPMR,
+		                               eRGXRDPowerIslandConf,
+		                               eFirmwarePerf);
+	}
+
+	return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function     InitFirmware
+
+ @Description  Allocate, initialise and pdump Firmware code and data memory
+
+ @Input        hServices       : Services connection
+ @Input        psHints         : Apphints
+ @Input        psBVNC          : Compatibility checks
+ @Output       phFWCodePMR     : FW code PMR handle
+ @Output       phFWDataPMR     : FW data PMR handle
+ @Output       phFWCorememPMR  : FW coremem code PMR handle
+ @Output       phHWPerfDataPMR : HWPerf control PMR handle
+
+ @Return       PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR InitFirmware(SHARED_DEV_CONNECTION hServices,
+                                 RGX_SRVINIT_APPHINTS *psHints,
+                                 RGXFWIF_COMPCHECKS_BVNC *psBVNC,
+                                 IMG_HANDLE *phFWCodePMR,
+                                 IMG_HANDLE *phFWDataPMR,
+                                 IMG_HANDLE *phFWCorememPMR,
+                                 IMG_HANDLE *phHWPerfDataPMR)
+{
+	struct RGXFW      *psRGXFW = NULL;
+	const IMG_BYTE    *pbRGXFirmware = NULL;
+	RGXFWIF_COMPCHECKS_BVNC sFWBVNC;
+
+	/* FW code memory */
+	IMG_DEVMEM_SIZE_T uiFWCodeAllocSize;
+	IMG_DEV_VIRTADDR  sFWCodeDevVAddrBase;
+	DEVMEM_MEMDESC    *psFWCodeHostMemDesc;
+	void              *pvFWCodeHostAddr;
+
+	/* FW data memory */
+	IMG_DEVMEM_SIZE_T uiFWDataAllocSize;
+	IMG_DEV_VIRTADDR  sFWDataDevVAddrBase;
+	DEVMEM_MEMDESC    *psFWDataHostMemDesc;
+	void              *pvFWDataHostAddr;
+
+	/* FW coremem code memory */
+	IMG_DEVMEM_SIZE_T uiFWCorememCodeAllocSize;
+	IMG_DEV_VIRTADDR  sFWCorememDevVAddrBase;
+
+	/* 
+	 * Only declare psFWCorememHostMemDesc where used (PVR_UNREFERENCED_PARAMETER doesn't
+	 * help for local vars when using certain compilers)
+	 */
+	DEVMEM_MEMDESC    *psFWCorememHostMemDesc;
+	void              *pvFWCorememHostAddr = NULL;
+
+	RGXFWIF_DEV_VIRTADDR sFWCorememFWAddr; /* FW coremem data */
+	RGXFWIF_DEV_VIRTADDR sRGXFwInit;       /* FW init struct */
+	RGX_INIT_LAYER_PARAMS sInitParams;
+#if !defined(SUPPORT_KERNEL_SRVINIT)
+	IMG_UINT32 aui32RGXFWAlignChecks[] = {RGXFW_ALIGN_CHECKS_INIT};
+#endif
+	IMG_UINT32 ui32FWConfigFlags;
+	PVRSRV_ERROR eError;
+	IMG_CHAR *pszFWFilename = NULL;
+	IMG_CHAR *pszFWpFilename = NULL;
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	IMG_CHAR aszFWFilenameStr[OSStringLength(RGX_FW_FILENAME)+MAX_BVNC_STRING_LEN+2];
+	IMG_CHAR aszFWpFilenameStr[OSStringLength(RGX_FW_FILENAME)+MAX_BVNC_STRING_LEN+3];
+	PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hServices;
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	pszFWFilename = &aszFWFilenameStr[0];
+	OSSNPrintf(pszFWFilename, OSStringLength(RGX_FW_FILENAME)+MAX_BVNC_STRING_LEN+2, "%s.%d.%d.%d.%d", RGX_FW_FILENAME,
+	           psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
+	           psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C);
+	pszFWpFilename = &aszFWpFilenameStr[0];
+	OSSNPrintf(pszFWpFilename, OSStringLength(RGX_FW_FILENAME)+MAX_BVNC_STRING_LEN+3, "%s.%d.%dp.%d.%d", RGX_FW_FILENAME,
+	           psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
+	           psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C);
+#endif /* defined(SUPPORT_KERNEL_SRVINIT) */
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+	/*
+	 * Get pointer to Firmware image
+	 */
+
+	psRGXFW = RGXLoadFirmware(hServices, pszFWFilename, pszFWpFilename);
+	if (psRGXFW == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: RGXLoadFirmware failed"));
+		eError = PVRSRV_ERROR_INIT_FAILURE;
+		goto cleanup_initfw;
+	}
+	pbRGXFirmware = RGXFirmwareData(psRGXFW);
+
+	if (!GetFirmwareBVNC(psRGXFW, &sFWBVNC))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: RGXLoadFirmware failed to get Firmware BVNC"));
+		eError = PVRSRV_ERROR_INIT_FAILURE;
+		goto cleanup_initfw;
+	}
+
+	sInitParams.hServices = hServices;
+
+	/*
+	 * Allocate Firmware memory
+	 */
+
+	eError = RGXGetFWImageAllocSize(&sInitParams,
+	                                &uiFWCodeAllocSize,
+	                                &uiFWDataAllocSize,
+	                                &uiFWCorememCodeAllocSize);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: RGXGetFWImageAllocSize failed"));
+		goto cleanup_initfw;
+	}
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	/* Disable META core memory allocation unless the META DMA is available */
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	if (!RGXDeviceHasFeatureInit(&sInitParams, RGX_FEATURE_META_DMA_BIT_MASK))
+	{
+		uiFWCorememCodeAllocSize = 0;
+	}
+#elif !defined(RGX_FEATURE_META_DMA)
+	uiFWCorememCodeAllocSize = 0;
+#endif
+#endif
+#else
+	PVR_UNREFERENCED_PARAMETER(pszFWFilename);
+	PVR_UNREFERENCED_PARAMETER(pszFWpFilename);
+	PVR_UNREFERENCED_PARAMETER(sInitParams);
+	PVR_UNREFERENCED_PARAMETER(pbRGXFirmware);
+	uiFWCodeAllocSize = 0;
+	uiFWDataAllocSize = 0;
+	uiFWCorememCodeAllocSize = 0;
+#endif
+
+	eError = BridgeRGXInitAllocFWImgMem(hServices,
+	                                    uiFWCodeAllocSize,
+	                                    uiFWDataAllocSize,
+	                                    uiFWCorememCodeAllocSize,
+	                                    phFWCodePMR,
+	                                    &sFWCodeDevVAddrBase,
+	                                    phFWDataPMR,
+	                                    &sFWDataDevVAddrBase,
+	                                    phFWCorememPMR,
+	                                    &sFWCorememDevVAddrBase,
+	                                    &sFWCorememFWAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: PVRSRVRGXInitAllocFWImgMem failed (%d)", eError));
+		goto cleanup_initfw;
+	}
+
+
+	/*
+	 * Setup Firmware initialisation data
+	 */
+
+	GetFWConfigFlags(psHints, &ui32FWConfigFlags);
+
+	eError = RGXInitFirmwareBridgeWrapper(hServices,
+	                                      &sRGXFwInit,
+	                                      psHints->bEnableSignatureChecks,
+	                                      psHints->ui32SignatureChecksBufSize,
+	                                      psHints->ui32HWPerfFWBufSize,
+	                                      (IMG_UINT64)psHints->ui32HWPerfFilter0 |
+	                                      ((IMG_UINT64)psHints->ui32HWPerfFilter1 << 32),
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	                                      0,
+	                                      NULL,
+#else
+	                                      IMG_ARR_NUM_ELEMS(aui32RGXFWAlignChecks),
+	                                      aui32RGXFWAlignChecks,
+#endif
+	                                      ui32FWConfigFlags,
+	                                      psHints->ui32LogType,
+	                                      GetFilterFlags(psHints),
+	                                      psHints->ui32JonesDisableMask,
+	                                      psHints->ui32HWRDebugDumpLimit,
+	                                      psBVNC,
+	                                      &sFWBVNC,
+	                                      sizeof(RGXFWIF_HWPERF_CTL),
+	                                      phHWPerfDataPMR,
+	                                      psHints->eRGXRDPowerIslandConf,
+	                                      psHints->eFirmwarePerf);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: PVRSRVRGXInitFirmware failed (%d)", eError));
+		goto cleanup_initfw;
+	}
+#if defined(PVRSRV_GPUVIRT_GUESTDRV)
+	PVR_UNREFERENCED_PARAMETER(pvFWCorememHostAddr);
+	PVR_UNREFERENCED_PARAMETER(psFWCorememHostMemDesc);
+	PVR_UNREFERENCED_PARAMETER(pvFWDataHostAddr);
+	PVR_UNREFERENCED_PARAMETER(psFWDataHostMemDesc);
+	PVR_UNREFERENCED_PARAMETER(pvFWCodeHostAddr);
+	PVR_UNREFERENCED_PARAMETER(psFWCodeHostMemDesc);
+#else
+	/*
+	 * Acquire pointers to Firmware allocations
+	 */
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE)
+	eError = AcquireHostData(hServices,
+	                         *phFWCodePMR,
+	                         &psFWCodeHostMemDesc,
+	                         &pvFWCodeHostAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: AcquireHostData for FW code failed (%d)", eError));
+		goto release_code;
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(psFWCodeHostMemDesc);
+
+	/* We can't get a pointer to a secure FW allocation from within the DDK */
+	pvFWCodeHostAddr = NULL;
+#endif
+
+	eError = AcquireHostData(hServices,
+	                         *phFWDataPMR,
+	                         &psFWDataHostMemDesc,
+	                         &pvFWDataHostAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: AcquireHostData for FW data failed (%d)", eError));
+		goto release_data;
+	}
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE)
+	if (uiFWCorememCodeAllocSize)
+	{
+		eError = AcquireHostData(hServices,
+								 *phFWCorememPMR,
+								 &psFWCorememHostMemDesc,
+								 &pvFWCorememHostAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "InitFirmware: AcquireHostData for FW coremem code failed (%d)", eError));
+			goto release_corememcode;
+		}
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(psFWCorememHostMemDesc);
+
+	/* We can't get a pointer to a secure FW allocation from within the DDK */
+	pvFWCorememHostAddr = NULL;
+#endif
+
+
+	/*
+	 * Process the Firmware image and setup code and data segments.
+	 *
+	 * When the trusted device is enabled and the FW code lives
+	 * in secure memory we will only setup the data segments here,
+	 * while the code segments will be loaded to secure memory
+	 * by the trusted device.
+	 */
+
+	eError = RGXProcessFWImage(&sInitParams,
+	                           pbRGXFirmware,
+	                           pvFWCodeHostAddr,
+	                           pvFWDataHostAddr,
+	                           pvFWCorememHostAddr,
+	                           &sFWCodeDevVAddrBase,
+	                           &sFWDataDevVAddrBase,
+	                           &sFWCorememDevVAddrBase,
+	                           &sFWCorememFWAddr,
+	                           &sRGXFwInit,
+#if defined(RGXFW_META_SUPPORT_2ND_THREAD)
+	                           2,
+#else
+	                           psHints->eUseMETAT1 == RGX_META_T1_OFF ? 1 : 2,
+#endif
+	                           psHints->eUseMETAT1 == RGX_META_T1_MAIN ? 1 : 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: RGXProcessFWImage failed (%d)", eError));
+		goto release_fw_allocations;
+	}
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
+	RGXTDProcessFWImage(hServices, psRGXFW);
+#endif
+
+
+	/*
+	 * Perform final steps (if any) on the kernel
+	 * before pdumping the Firmware allocations
+	 */
+	eError = BridgeRGXInitFinaliseFWImage(hServices);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "InitFirmware: RGXInitFinaliseFWImage failed (%d)", eError));
+		goto release_fw_allocations;
+	}
+
+	/*
+	 * PDump Firmware allocations
+	 */
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE)
+	SRVINITPDumpComment(hServices, "Dump firmware code image");
+	DevmemPDumpLoadMem(psFWCodeHostMemDesc,
+	                   0,
+	                   uiFWCodeAllocSize,
+	                   PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+	SRVINITPDumpComment(hServices, "Dump firmware data image");
+	DevmemPDumpLoadMem(psFWDataHostMemDesc,
+	                   0,
+	                   uiFWDataAllocSize,
+	                   PDUMP_FLAGS_CONTINUOUS);
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE)
+	if (uiFWCorememCodeAllocSize)
+	{
+		SRVINITPDumpComment(hServices, "Dump firmware coremem image");
+		DevmemPDumpLoadMem(psFWCorememHostMemDesc,
+						   0,
+						   uiFWCorememCodeAllocSize,
+						   PDUMP_FLAGS_CONTINUOUS);
+	}
+#endif
+
+
+	/*
+	 * Release Firmware allocations and clean up
+	 */
+
+release_fw_allocations:
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE)
+release_corememcode:
+	if (uiFWCorememCodeAllocSize)
+	{
+		ReleaseHostData(psFWCorememHostMemDesc);
+	}
+#endif
+
+release_data:
+	ReleaseHostData(psFWDataHostMemDesc);
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE)
+release_code:
+	ReleaseHostData(psFWCodeHostMemDesc);
+#endif
+#endif /* PVRSRV_GPUVIRT_GUESTDRV */
+cleanup_initfw:
+	if (psRGXFW != NULL)
+	{
+		RGXUnloadFirmware(psRGXFW);
+	}
+
+	return eError;
+}
+
+
 #if defined(PDUMP)
 /*!
 *******************************************************************************
@@ -693,25 +1675,34 @@
 static void InitialiseHWPerfCounters(SHARED_DEV_CONNECTION hServices, DEVMEM_MEMDESC *psHWPerfDataMemDesc, RGXFWIF_HWPERF_CTL *psHWPerfInitDataInt)
 {
 	RGXFWIF_HWPERF_CTL_BLK *psHWPerfInitBlkData;
+	IMG_UINT32 ui32CntBlkModelLen;
+	const RGXFW_HWPERF_CNTBLK_TYPE_MODEL *asCntBlkTypeModel;
 	const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc;
-	IMG_UINT32 gasCntBlkModelLen;
-	const RGXFW_HWPERF_CNTBLK_TYPE_MODEL *gasCntBlkTypeModel;
 	IMG_UINT32 ui32BlockID, ui32BlkCfgIdx, ui32CounterIdx ;
+	void *pvDev = NULL;	// Use SHARED_DEV_CONNECTION here?
+	RGX_HWPERF_CNTBLK_RT_INFO sCntBlkRtInfo;
 
-	gasCntBlkModelLen = RGXGetHWPerfBlockConfig(&gasCntBlkTypeModel);
-	for(ui32BlkCfgIdx = 0; ui32BlkCfgIdx < gasCntBlkModelLen; ui32BlkCfgIdx++)
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hServices;
+		pvDev = psDeviceNode->pvDevice;
+	}
+#endif
+	ui32CntBlkModelLen = RGXGetHWPerfBlockConfig(&asCntBlkTypeModel);
+	for(ui32BlkCfgIdx = 0; ui32BlkCfgIdx < ui32CntBlkModelLen; ui32BlkCfgIdx++)
 	{
 		/* Exit early if this core does not have any of these counter blocks
-		 * due to core type/BVNC.... */
-		psBlkTypeDesc = &gasCntBlkTypeModel[ui32BlkCfgIdx];
-		if (psBlkTypeDesc == NULL || psBlkTypeDesc->uiNumUnits == 0)
+		 * due to core type/BVNC features.... */
+		psBlkTypeDesc = &asCntBlkTypeModel[ui32BlkCfgIdx];
+		if (psBlkTypeDesc->pfnIsBlkPresent(psBlkTypeDesc, pvDev, &sCntBlkRtInfo) == IMG_FALSE)
 		{
 			continue;
 		}
+
 		/* Program all counters in one block so those already on may
 		 * be configured off and vice-a-versa. */
 		for (ui32BlockID = psBlkTypeDesc->uiCntBlkIdBase;
-					 ui32BlockID < psBlkTypeDesc->uiCntBlkIdBase+psBlkTypeDesc->uiNumUnits;
+					 ui32BlockID < psBlkTypeDesc->uiCntBlkIdBase+sCntBlkRtInfo.uiNumUnits;
 					 ui32BlockID++)
 		{
 
@@ -764,8 +1755,6 @@
 			}
 		}
 	}
-
-
 }
 /*!
 *******************************************************************************
@@ -796,66 +1785,184 @@
 
 	for( ui32CustomBlock = 0; ui32CustomBlock < RGX_HWPERF_MAX_CUSTOM_BLKS; ui32CustomBlock++ )
 	{
-			SRVINITPDumpComment(hServices, "ui32NumSelectedCounters - The Number of counters selected for this Custom Block: %d",ui32CustomBlock );
-			DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
-						offsetof(RGXFWIF_HWPERF_CTL, SelCntr[ui32CustomBlock].ui32NumSelectedCounters),
-						0,
-						PDUMP_FLAGS_CONTINUOUS);
+		/*
+		 * Some compilers cannot cope with the use of offsetof() below - the specific problem being the use of
+		 * a non-const variable in the expression, which it needs to be const. Typical compiler error produced is
+		 * "expression must have a constant value".
+		 */
+		const IMG_DEVMEM_OFFSET_T uiOffsetOfCustomBlockSelectedCounters
+		= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_HWPERF_CTL *)0)->SelCntr[ui32CustomBlock].ui32NumSelectedCounters);
+
+		SRVINITPDumpComment(hServices, "ui32NumSelectedCounters - The Number of counters selected for this Custom Block: %d",ui32CustomBlock );
+		DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+					uiOffsetOfCustomBlockSelectedCounters,
+					0,
+					PDUMP_FLAGS_CONTINUOUS);
 
 		for(ui32CounterID = 0; ui32CounterID < RGX_HWPERF_MAX_CUSTOM_CNTRS; ui32CounterID++ )
 		{
+			const IMG_DEVMEM_OFFSET_T uiOffsetOfCustomBlockSelectedCounterIDs
+			= (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_HWPERF_CTL *)0)->SelCntr[ui32CustomBlock].aui32SelectedCountersIDs[ui32CounterID]);
+
 			SRVINITPDumpComment(hServices, "CUSTOMBLK_%d_COUNTERID_%d",ui32CustomBlock, ui32CounterID);
 			DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
-					offsetof(RGXFWIF_HWPERF_CTL, SelCntr[ui32CustomBlock].aui32SelectedCountersIDs[ui32CounterID]),
+					uiOffsetOfCustomBlockSelectedCounterIDs,
 					0,
 					PDUMP_FLAGS_CONTINUOUS);
 		}
 	}
 }
-#endif
 
-#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
-/*************************************************************************/ /*!
- @Function       RGXTDProcessFWImage
+/*!
+*******************************************************************************
 
- @Description    Fetch and send data used by the trusted device to complete
-                 the FW image setup
+ @Function     InitialiseAllCounters
 
- @Input          psDeviceNode - Device node
- @Input          psRGXFW      - Firmware blob
+ @Description  Initialise HWPerf and custom counters
 
- @Return         PVRSRV_ERROR
-*/ /**************************************************************************/
-static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                        struct RGXFW *psRGXFW)
+ @Input        hServices      : Services connection
+ @Input        hHWPerfDataPMR : HWPerf control PMR handle
+
+ @Return       PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR InitialiseAllCounters(SHARED_DEV_CONNECTION hServices,
+                                          IMG_HANDLE hHWPerfDataPMR)
 {
-	PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
-	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-	PVRSRV_TD_FW_PARAMS sTDFWParams;
+	RGXFWIF_HWPERF_CTL *psHWPerfInitData;
+	DEVMEM_MEMDESC *psHWPerfDataMemDesc;
 	PVRSRV_ERROR eError;
 
-	if (psDevConfig->pfnTDSendFWImage == NULL)
+	eError = AcquireHostData(hServices,
+	                         hHWPerfDataPMR,
+	                         &psHWPerfDataMemDesc,
+	                         (void **)&psHWPerfInitData);
+
+
+	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXTDProcessFWImage: TDProcessFWImage not implemented!"));
-		return PVRSRV_ERROR_NOT_IMPLEMENTED;
+		PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", failHWPerfCountersMemDescAqCpuVirt);
 	}
 
-	sTDFWParams.pvFirmware = RGXFirmwareData(psRGXFW);
-	sTDFWParams.ui32FirmwareSize = RGXFirmwareSize(psRGXFW);
-	sTDFWParams.sFWCodeDevVAddrBase = psDevInfo->sFWCodeDevVAddrBase;
-	sTDFWParams.sFWDataDevVAddrBase = psDevInfo->sFWDataDevVAddrBase;
-	sTDFWParams.sFWCorememCodeFWAddr = psDevInfo->sFWCorememCodeFWAddr;
-	sTDFWParams.sFWInitFWAddr = psDevInfo->sFWInitFWAddr;
+	InitialiseHWPerfCounters(hServices, psHWPerfDataMemDesc, psHWPerfInitData);
+	InitialiseCustomCounters(hServices, psHWPerfDataMemDesc);
 
-	eError = psDevConfig->pfnTDSendFWImage(&sTDFWParams);
+failHWPerfCountersMemDescAqCpuVirt:
+	ReleaseHostData(psHWPerfDataMemDesc);
 
 	return eError;
 }
+#endif /* PDUMP */
+
+static void
+_ParseHTBAppHints(SHARED_DEV_CONNECTION hServices)
+{
+	PVRSRV_ERROR eError;
+	void * pvParamState = NULL;
+	IMG_UINT32 ui32LogType;
+	IMG_BOOL bAnyLogGroupConfigured;
+
+	IMG_CHAR * szBufferName = "PVRHTBuffer";
+	IMG_UINT32 ui32BufferSize;
+	HTB_OPMODE_CTRL eOpMode;
+
+	/* Services initialisation parameters */
+	pvParamState = SrvInitParamOpen();
+
+	SrvInitParamGetUINT32BitField(pvParamState, EnableHTBLogGroup, ui32LogType);
+	bAnyLogGroupConfigured = ui32LogType ? IMG_TRUE: IMG_FALSE;
+	SrvInitParamGetUINT32List(pvParamState, HTBOperationMode, eOpMode);
+	SrvInitParamGetUINT32(pvParamState, HTBufferSize, ui32BufferSize);
+
+	eError = HTBConfigure(hServices, szBufferName, ui32BufferSize);
+	PVR_LOGG_IF_ERROR(eError, "PVRSRVHTBConfigure", cleanup);
+
+	if (bAnyLogGroupConfigured)
+	{
+		eError = HTBControl(hServices, 1, &ui32LogType, 0, 0, HTB_LOGMODE_ALLPID, eOpMode);
+		PVR_LOGG_IF_ERROR(eError, "PVRSRVHTBControl", cleanup);
+	}
+
+cleanup:
+	SrvInitParamClose(pvParamState);
+}
+
+#if defined(PDUMP) && defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__)
+static void RGXInitFWSigRegisters(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	IMG_UINT32	ui32PhantomCnt = 0;
+
+	if (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_CLUSTER_GROUPING_BIT_MASK)
+	{
+		ui32PhantomCnt = RGX_GET_NUM_PHANTOMS(psDevInfo->sDevFeatureCfg.ui32NumClusters) - 1;
+	}
+
+	/*Initialise the TA related signature registers */
+	if(0 == gui32TASigRegCount)
+	{
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SCALABLE_VDM_GPP_BIT_MASK)
+		{
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVB_CHECKSUM, RGX_CR_BLACKPEARL_INDIRECT,0, ui32PhantomCnt};
+		}else
+		{
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVS0_CHECKSUM, 0, 0, 0};
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVS1_CHECKSUM, 0, 0, 0};
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVS2_CHECKSUM, 0, 0, 0};
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVS3_CHECKSUM, 0, 0, 0};
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVS4_CHECKSUM, 0, 0, 0};
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_USC_UVS5_CHECKSUM, 0, 0, 0};
+		}
+
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SCALABLE_TE_ARCH_BIT_MASK)
+		{
+			if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_SCALABLE_VDM_GPP_BIT_MASK)
+			{
+				asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_PPP_CLIP_CHECKSUM, RGX_CR_BLACKPEARL_INDIRECT,0, ui32PhantomCnt};
+			}else
+			{
+				asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_PPP, 0, 0, 0};
+			}
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_TE_CHECKSUM,0, 0, 0};
+		}else
+		{
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_PPP_SIGNATURE, 0, 0, 0};
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_TE_SIGNATURE, 0, 0, 0};
+		}
+
+		asTASigRegList[gui32TASigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_VCE_CHECKSUM, 0, 0, 0};
+
+		if(0 == (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_PDS_PER_DUST_BIT_MASK))
+		{
+			asTASigRegList[gui32TASigRegCount++] = 	(RGXFW_REGISTER_LIST){RGX_CR_PDS_DOUTM_STM_SIGNATURE,0, 0, 0};
+		}
+	}
+
+	if(0 == gui323DSigRegCount)
+	{
+		/* List of 3D signature and checksum register addresses */
+		if(0 == (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+		{
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_ISP_PDS_CHECKSUM,			0,							0, 0};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_ISP_TPF_CHECKSUM,			0,							0, 0};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_TFPU_PLANE0_CHECKSUM,		0,							0, 0};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_TFPU_PLANE1_CHECKSUM,		0,							0, 0};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_PBE_CHECKSUM,				0,							0, 0};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_IFPU_ISP_CHECKSUM,			0,							0, 0};
+		}else
+		{
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_ISP_PDS_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, ui32PhantomCnt};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_ISP_TPF_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, ui32PhantomCnt};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_TFPU_PLANE0_CHECKSUM,		RGX_CR_BLACKPEARL_INDIRECT,	0, ui32PhantomCnt};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_TFPU_PLANE1_CHECKSUM,		RGX_CR_BLACKPEARL_INDIRECT,	0, ui32PhantomCnt};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_PBE_CHECKSUM,				RGX_CR_PBE_INDIRECT,		0, psDevInfo->sDevFeatureCfg.ui32NumClusters-1};
+			as3DSigRegList[gui323DSigRegCount++] = (RGXFW_REGISTER_LIST){RGX_CR_IFPU_ISP_CHECKSUM,			RGX_CR_BLACKPEARL_INDIRECT,	0, ui32PhantomCnt};
+		};
+
+	}
+
+}
 #endif
 
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
-
-
 /*!
 *******************************************************************************
 
@@ -873,384 +1980,52 @@
 IMG_INTERNAL
 PVRSRV_ERROR RGXInit(SHARED_DEV_CONNECTION hServices)
 {
-	PVRSRV_ERROR				eError;
+	PVRSRV_ERROR eError;
 	RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
 
-	IMG_UINT32			aui32RGXFWAlignChecks[] = {RGXFW_ALIGN_CHECKS_INIT};
+	/* Services initialisation parameters */
+	RGX_SRVINIT_APPHINTS sApphints = {0};
+	IMG_UINT32 ui32DeviceFlags;
+	IMG_UINT64	ui64ErnsBrns = 0, ui64Features = 0;
 
 	/* Server scripts */
-	RGX_SCRIPT_BUILD	sDbgInitScript    = {RGX_MAX_DEBUG_COMMANDS,  0, IMG_FALSE, asDbgCommands};
-	RGX_SCRIPT_BUILD	sDbgBusInitScript = {RGX_MAX_DBGBUS_COMMANDS, 0, IMG_FALSE, asDbgBusCommands};
-	RGX_SCRIPT_BUILD	sDeinitScript     = {RGX_MAX_DEINIT_COMMANDS, 0, IMG_FALSE, asDeinitCommands};
+	RGX_SCRIPT_BUILD sDbgInitScript = {RGX_MAX_DEBUG_COMMANDS,  0, IMG_FALSE, asDbgCommands};
 
-	/* FW code memory */
-	IMG_DEVMEM_SIZE_T			uiFWCodeAllocSize = 0;	
-	void						*pvFWCodeHostAddr;
+	/* FW allocations handles */
+	IMG_HANDLE hFWCodePMR;
+	IMG_HANDLE hFWDataPMR;
+	IMG_HANDLE hFWCorememPMR;
 
-	/* FW data memory */
-	IMG_DEVMEM_SIZE_T			uiFWDataAllocSize = 0;	
-	IMG_DEV_VIRTADDR			sFWDataDevVAddrBase;
+	/* HWPerf Ctl allocation handle */
+	IMG_HANDLE hHWPerfDataPMR;
 
-	/* FW Coremem buffer */
-	IMG_DEVMEM_SIZE_T			uiFWCorememCodeAllocSize = 0;
-#if defined(RGX_META_COREMEM_CODE) || defined(RGX_META_COREMEM_DATA)
-	IMG_HANDLE 					hFWCorememImportHandle;
-	IMG_DEVMEM_SIZE_T			uiFWCorememImportSize;
-	DEVMEM_MEMDESC				*psFWCorememHostMemDesc;
-#endif
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hServices;
+	PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
 
-	IMG_DEV_VIRTADDR			sFWCorememDevVAddrBase;
-	IMG_HANDLE					hFWCorememPMR;
+	IMG_CHAR sV[RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX];
 
-	RGXFWIF_DEV_VIRTADDR		sFWCorememFWAddr;
-	/* FW code memory */
-	IMG_DEV_VIRTADDR			sFWCodeDevVAddrBase;
-	IMG_HANDLE					hFWCodePMR;
-	/* FW data memory */
-	IMG_HANDLE					hFWDataPMR;
-	RGXFWIF_DEV_VIRTADDR 		sRGXFwInit;
+	OSSNPrintf(sV, sizeof(sV), "%d", psDevInfo->sDevFeatureCfg.ui32V);
+	/*
+	 * FIXME:
+	 * Is this check redundant for the kernel mode version of srvinit?
+	 * How do we check the user mode BVNC in this case?
+	 */
+	rgx_bvnc_packed(&sBVNC.ui64BNC, sBVNC.aszV, sBVNC.ui32VLenMax, psDevInfo->sDevFeatureCfg.ui32B, \
+							sV,	\
+							psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C);
 
-	/* Services initialisation parameters*/
-	void				*pvParamState = NULL;
-	IMG_UINT32			ui32ParamTemp;
-	IMG_BOOL			bEnableSignatureChecks;
-	IMG_UINT32			ui32SignatureChecksBufSize;
-	IMG_UINT32			ui32DeviceFlags = 0;
-	IMG_UINT32			ui32FWConfigFlags = 0;
-	IMG_UINT32			ui32HWPerfFilter0, ui32HWPerfFilter1;
-	IMG_UINT32			ui32HWPerfHostFilter;
-	IMG_UINT32			ui32HWPerfFWBufSize;
-	IMG_UINT32			ui32HWRDebugDumpLimit;
-	RGX_RD_POWER_ISLAND_CONF	eRGXRDPowerIslandConf;
-	RGX_META_T1_CONF    eUseMETAT1;
-	RGX_ACTIVEPM_CONF		eRGXActivePMConf;
-	IMG_BOOL			bDustRequestInject;
 
-	IMG_UINT32			ui32LogType;
-	IMG_UINT32			ui32FilterFlags = 0;
-	IMG_UINT32			ui32JonesDisableMask = 0;	/*!< Bitfield to disable Jones ECO fixes */
-	IMG_BOOL			bFirmwareLogTypeConfigured;
-	IMG_UINT32			ui32LogTypeTemp = 0;
-	IMG_BOOL			bAnyLogGroupConfigured = IMG_FALSE;	
-
-	FW_PERF_CONF		eFirmwarePerf;
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* These variables are n/a in guest drivers */
+	ui64ErnsBrns = psDevInfo->sDevFeatureCfg.ui64ErnsBrns;
+	ui64Features = psDevInfo->sDevFeatureCfg.ui64Features;
 #else
-	/* FW code memory */
-	DEVMEM_MEMDESC		*psFWCodeHostMemDesc;
-	IMG_HANDLE 			hFWCodeImportHandle;
-	IMG_DEVMEM_SIZE_T	uiFWCodeImportSize;
-	/* FW data memory */
-	DEVMEM_MEMDESC		*psFWDataHostMemDesc;
-	IMG_HANDLE 			hFWDataImportHandle;
-	IMG_DEVMEM_SIZE_T	uiFWDataImportSize;
-	void				*pvFWDataHostAddr;
-	void                *pvFWCorememHostAddr;
-	struct RGXFW 		*psRGXFW;
-	const IMG_BYTE 		*pbRGXFirmware;
-	
-	IMG_UINT32			ui32FWContextSwitchProfile;	
-	IMG_UINT32			ui32TruncateMode = 0;
-	IMG_BOOL			bFilteringMode = IMG_FALSE;
-	IMG_BOOL			bEnable2Thrds;	
-	IMG_BOOL            bHWPerfDisableCustomCounterFilter;
-	IMG_BOOL			bEnableHWR;
-	IMG_BOOL			bEnableHWPerf;
-	IMG_BOOL			bEnableHWPerfHost;
-	IMG_UINT32			ui32EnableFWContextSwitch;
-	IMG_BOOL			bZeroFreelist;
-	IMG_BOOL			bCheckMlist;
-#if defined(DEBUG)
-	IMG_BOOL			bAssertOnOutOfMem = IMG_FALSE;
-#endif
-	IMG_BOOL			bEnableCDMKillRand = IMG_FALSE;
-	IMG_BOOL			bDisableDMOverlap = IMG_FALSE;
-	IMG_BOOL			bDisableClockGating;
-	IMG_BOOL			bDisablePDP;
-	IMG_BOOL			bEnableRTUBypass;
-#if defined(SUPPORT_GPUTRACE_EVENTS)
-	IMG_BOOL			bEnableFTrace;
-#endif
-	IMG_BOOL			bDisableFEDLogging;
-
-	RGX_INIT_LAYER_PARAMS sInitParams;
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-	IMG_UINT32			aui32OSidMin[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS];
-	IMG_UINT32			aui32OSidMax[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS];
-#endif
-#if defined(PDUMP)
-	RGXFWIF_HWPERF_CTL *psHWPerfInitData;
-	DEVMEM_MEMDESC				*psHWPerfDataMemDesc;
-	IMG_HANDLE 				hHWPerfDataImportHandle;
-	IMG_DEVMEM_SIZE_T			uiHWPerfDataImportSize;
-#endif
-#endif
-	IMG_HANDLE					hHWPerfDataPMR;
-
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest drivers do not perform firmware loading */
-	PVR_UNREFERENCED_PARAMETER(pvFWCodeHostAddr);
-#else
-	psRGXFW = RGXLoadFirmware();
-	if (psRGXFW == NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Firmware load failed"));
-		eError = PVRSRV_ERROR_INIT_FAILURE;
-		goto cleanup;
-	}
-	pbRGXFirmware = RGXFirmwareData(psRGXFW);
+	rgx_bvnc_packed(&sBVNC.ui64BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_B, RGX_BVNC_V_ST, RGX_BVNC_N, RGX_BVNC_C);
 #endif
 
 	/* Services initialisation parameters */
-	pvParamState = SrvInitParamOpen();
-
-	SrvInitParamGetUINT32(pvParamState, FirmwarePerf, ui32ParamTemp);
-	eFirmwarePerf = ui32ParamTemp;
-
-	SrvInitParamGetUINT32(pvParamState, HWRDebugDumpLimit, ui32HWRDebugDumpLimit);
-	SrvInitParamGetUINT32(pvParamState, HWPerfFWBufSizeInKB, ui32HWPerfFWBufSize);
-	SrvInitParamGetUINT32(pvParamState, SignatureChecksBufSize, ui32SignatureChecksBufSize);
-	SrvInitParamGetUINT32(pvParamState, HWPerfFilter0, ui32HWPerfFilter0);
-	SrvInitParamGetUINT32(pvParamState, HWPerfFilter1, ui32HWPerfFilter1);
-	SrvInitParamGetUINT32(pvParamState, HWPerfHostFilter, ui32HWPerfHostFilter);
-	SrvInitParamGetBOOL(pvParamState, EnableSignatureChecks, bEnableSignatureChecks);
-
-	SrvInitParamGetUINT32(pvParamState, EnableAPM, ui32ParamTemp);
-	eRGXActivePMConf = ui32ParamTemp;
-
-	SrvInitParamGetUINT32(pvParamState, EnableRDPowerIsland, ui32ParamTemp);
-	eRGXRDPowerIslandConf = ui32ParamTemp;
-
-	SrvInitParamGetUINT32(pvParamState, UseMETAT1, ui32ParamTemp);
-	eUseMETAT1 = ui32ParamTemp & RGXFWIF_INICFG_METAT1_MASK;
-
-	SrvInitParamGetBOOL(pvParamState, DustRequestInject, bDustRequestInject);
-
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* These parameter is n/a in guest drivers */
-#else
-	SrvInitParamGetBOOL(pvParamState, Enable2ndThread, bEnable2Thrds);
-	SrvInitParamGetUINT32(pvParamState, EnableFWContextSwitch, ui32EnableFWContextSwitch);
-	SrvInitParamGetUINT32(pvParamState, FWContextSwitchProfile, ui32FWContextSwitchProfile);
-
-	SrvInitParamGetBOOL(pvParamState, EnableHWPerf,	bEnableHWPerf);
-	SrvInitParamGetBOOL(pvParamState, EnableHWPerfHost, bEnableHWPerfHost);
-	SrvInitParamGetBOOL(pvParamState, HWPerfDisableCustomCounterFilter, bHWPerfDisableCustomCounterFilter);
-
-	SrvInitParamGetBOOL(pvParamState, EnableHWR, bEnableHWR);
-	SrvInitParamGetBOOL(pvParamState, CheckMList, bCheckMlist);
-	SrvInitParamGetBOOL(pvParamState, ZeroFreelist,	bZeroFreelist);
-	SrvInitParamGetBOOL(pvParamState, DisableClockGating, bDisableClockGating);
-	SrvInitParamGetBOOL(pvParamState, DisablePDP, bDisablePDP);
-#if defined(SUPPORT_GPUTRACE_EVENTS)
-	SrvInitParamGetBOOL(pvParamState, EnableFTraceGPU, bEnableFTrace);
-#endif
-#if defined(HW_ERN_41805) || defined(HW_ERN_42606)
-	SrvInitParamGetUINT32(pvParamState, TruncateMode, ui32TruncateMode);
-#endif
-#if defined(HW_ERN_42290) && defined(RGX_FEATURE_TPU_FILTERING_MODE_CONTROL)
-	SrvInitParamGetBOOL(pvParamState, NewFilteringMode, bFilteringMode);
-#endif
-	SrvInitParamGetBOOL(pvParamState, DisableFEDLogging, bDisableFEDLogging);
-	SrvInitParamGetBOOL(pvParamState, EnableRTUBypass, bEnableRTUBypass);
-
-#if defined(DEBUG)
-	SrvInitParamGetBOOL(pvParamState, AssertOutOfMemory, bAssertOnOutOfMem);
-#endif
-	SrvInitParamGetBOOL(pvParamState, EnableCDMKillingRandMode, bEnableCDMKillRand);
-	SrvInitParamGetBOOL(pvParamState, DisableDMOverlap, bDisableDMOverlap);
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	SrvInitParamGetUINT32(pvParamState, JonesDisableMask, ui32JonesDisableMask);
-	ui32JonesDisableMask = ui32JonesDisableMask & ~RGX_CR_JONES_FIX_DISABLE_CLRMSK;
-#endif
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-{
-	IMG_UINT	uiCounter, uiRegion;
-	void		*pvHintState = NULL;
-
-	PVR_DPF((PVR_DBG_MESSAGE,"\n[GPU Virtualization Validation]: Reading OSid limits\n"));
-
-	PVRSRVCreateAppHintState(IMG_SRVCLIENT, 0, &pvHintState);
-
-	for (uiRegion = 0; uiRegion < GPUVIRT_VALIDATION_NUM_REGIONS; uiRegion++)
-	{
-		for (uiCounter = 0; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
-		{
-			IMG_CHAR	pszHintString[GPUVIRT_VALIDATION_MAX_STRING_LENGTH];
-			IMG_UINT32	ui32Default = 0;
-
-			snprintf(pszHintString, GPUVIRT_VALIDATION_MAX_STRING_LENGTH, "OSidRegion%dMin%d", uiRegion, uiCounter );
-
-			PVRSRVGetAppHint(pvHintState, pszHintString, IMG_UINT_TYPE, &ui32Default, &(aui32OSidMin[uiCounter][uiRegion]));
-
-			snprintf(pszHintString, GPUVIRT_VALIDATION_MAX_STRING_LENGTH, "OSidRegion%dMax%d", uiRegion, uiCounter );
-
-			PVRSRVGetAppHint(pvHintState, pszHintString, IMG_UINT_TYPE, &ui32Default, &(aui32OSidMax[uiCounter][uiRegion]));
-		}
-	}
-
-	for (uiCounter = 0; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
-	{
-		for (uiRegion = 0; uiRegion < GPUVIRT_VALIDATION_NUM_REGIONS; uiRegion++)
-		{
-			PVR_DPF((PVR_DBG_MESSAGE,"\n[GPU Virtualization Validation]: Region:%d, OSid:%d, Min:%u, Max:%u\n",uiRegion, uiCounter, aui32OSidMin[uiCounter][uiRegion], aui32OSidMax[uiCounter][uiRegion]));
-		}
-	}
-
-	PVRSRVFreeAppHintState(IMG_SRVCLIENT, pvHintState);
-}
-#endif
-
-	ui32HWRDebugDumpLimit = MIN(ui32HWRDebugDumpLimit, RGXFWIF_HWR_DEBUG_DUMP_ALL);
-#endif
-
-	bFirmwareLogTypeConfigured = SrvInitParamGetUINT32List(pvParamState, FirmwareLogType, ui32LogTypeTemp);
-	bAnyLogGroupConfigured = SrvInitParamGetUINT32BitField(pvParamState, EnableLogGroup, ui32LogType);
-
-	if (bFirmwareLogTypeConfigured)
-	{
-		if (ui32LogTypeTemp == 2 /* TRACE */)
-		{
-			if (!bAnyLogGroupConfigured)
-			{
-				/* no groups configured - defaulting to MAIN group */
-				ui32LogType |= RGXFWIF_LOG_TYPE_GROUP_MAIN;
-			}
-			ui32LogType |= RGXFWIF_LOG_TYPE_TRACE;
-		}
-		else if (ui32LogTypeTemp == 1 /* TBI */)
-		{
-			if (!bAnyLogGroupConfigured)
-			{
-				/* no groups configured - defaulting to MAIN group */
-				ui32LogType |= RGXFWIF_LOG_TYPE_GROUP_MAIN;
-			}
-			ui32LogType &= ~RGXFWIF_LOG_TYPE_TRACE;
-		}
-		else if (ui32LogTypeTemp == 0 /* NONE */)
-		{
-			ui32LogType = RGXFWIF_LOG_TYPE_NONE;
-		}
-	}
-	else
-	{
-		/* no log type configured - defaulting to TRACE */
-		ui32LogType |= RGXFWIF_LOG_TYPE_TRACE;
-	}
-
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* These functionality is n/a to guest drivers */
-#else
-	if (bEnable2Thrds)
-	{
-		eError = PVRSRV_ERROR_NOT_SUPPORTED;
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Enable2ndThread parameter not supported (%d)", eError));
-#if defined(FIX_HW_BRN_40298)
-		/* If the second thread needs to be enabled, then we need a proper WA for this BRN */
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: 2nd Thread Enabled but WA not implemented (%d)", eError));
-#endif
-		goto cleanup;
-	}
-	ui32FWConfigFlags |= (ui32EnableFWContextSwitch & ~RGXFWIF_INICFG_CTXSWITCH_CLRMSK);
-	ui32FWConfigFlags |= ((ui32FWContextSwitchProfile << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT) & RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK);
-	ui32FWConfigFlags |= bEnableHWPerf? RGXFWIF_INICFG_HWPERF_EN : 0;
-	ui32FWConfigFlags |= bHWPerfDisableCustomCounterFilter ? RGXFWIF_INICFG_HWP_DISABLE_FILTER : 0;
-	ui32FWConfigFlags |= bCheckMlist? RGXFWIF_INICFG_CHECK_MLIST_EN : 0;
-#if !defined(NO_HARDWARE)
-	ui32FWConfigFlags |= bEnableHWR? RGXFWIF_INICFG_HWR_EN : 0;
-#endif
-	ui32FWConfigFlags |= bDisableClockGating? RGXFWIF_INICFG_DISABLE_CLKGATING_EN : 0;
-
-	ui32FWConfigFlags |= (eFirmwarePerf==FW_PERF_CONF_POLLS)? RGXFWIF_INICFG_POLL_COUNTERS_EN : 0;
-	ui32FWConfigFlags |= (eFirmwarePerf==FW_PERF_CONF_CUSTOM_TIMER)? RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN : 0;
-
-	ui32FWConfigFlags |= bDisablePDP? RGXFWIF_SRVCFG_DISABLE_PDP_EN : 0;
-	ui32FWConfigFlags |= bEnableCDMKillRand? RGXFWIF_INICFG_CDM_KILL_MODE_RAND_EN : 0;
-#if defined(DEBUG)
-	ui32FWConfigFlags |= bAssertOnOutOfMem? RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY : 0;
-#endif
-	ui32FWConfigFlags |= bDisableDMOverlap? RGXFWIF_INICFG_DISABLE_DM_OVERLAP : 0;
-
-	ui32DeviceFlags |= bZeroFreelist ? RGXKMIF_DEVICE_STATE_ZERO_FREELIST : 0;
-	ui32DeviceFlags |= bDisableFEDLogging ? RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN : 0;
-	ui32DeviceFlags |= bDustRequestInject? RGXKMIF_DEVICE_STATE_DUST_REQUEST_INJECT_EN : 0;
-
-	if (bEnableHWPerfHost)
-	{
-		if (ui32HWPerfHostFilter == 0)
-		{
-			ui32HWPerfHostFilter = HW_PERF_FILTER_DEFAULT_ALL_ON;
-		}
-	}
-	else
-	{
-		if (ui32HWPerfHostFilter != 0)
-		{
-			bEnableHWPerfHost = IMG_TRUE;
-		}
-	}
-	ui32DeviceFlags |= bEnableHWPerfHost ? RGXKMIF_DEVICE_STATE_HWPERF_HOST_EN : 0;
-	if (bEnableHWPerf && (ui32HWPerfFilter0 == 0 && ui32HWPerfFilter1 == 0))
-	{
-		ui32HWPerfFilter0 = HW_PERF_FILTER_DEFAULT_ALL_ON;
-		ui32HWPerfFilter1 = HW_PERF_FILTER_DEFAULT_ALL_ON;
-	}
-#if defined(SUPPORT_GPUTRACE_EVENTS)
-	if (bEnableFTrace)
-	{
-		ui32DeviceFlags |= RGXKMIF_DEVICE_STATE_FTRACE_EN;
-		/* Since FTrace GPU events depends on HWPerf, ensure it is enabled here */
-		ui32FWConfigFlags |= RGXFWIF_INICFG_HWPERF_EN;
-
-		/* In case we have not set EnableHWPerf AppHint just request creation
-		 * of certain events we need for the FTrace.
-		 */
-		if (!bEnableHWPerf)
-		{
-			ui32HWPerfFilter0 = 0x007BFF00;
-			ui32HWPerfFilter1 = 0x0;
-		}
-		else
-		{
-			ui32HWPerfFilter0 = HW_PERF_FILTER_DEFAULT_ALL_ON;
-			ui32HWPerfFilter1 = HW_PERF_FILTER_DEFAULT_ALL_ON;
-		}
-
-	}
-#endif
-
-#if defined(RGX_FEATURE_RAY_TRACING)
-	ui32FWConfigFlags |= bEnableRTUBypass ? RGXFWIF_INICFG_RTU_BYPASS_EN : 0;
-#endif
-
-	ui32FWConfigFlags |= (eUseMETAT1 << RGXFWIF_INICFG_METAT1_SHIFT);
-
-	ui32FilterFlags |= bFilteringMode ? RGXFWIF_FILTCFG_NEW_FILTER_MODE : 0;
-	if(ui32TruncateMode == 2)
-	{
-		ui32FilterFlags |= RGXFWIF_FILTCFG_TRUNCATE_INT;
-	}
-	else if(ui32TruncateMode == 3)
-	{
-		ui32FilterFlags |= RGXFWIF_FILTCFG_TRUNCATE_HALF;
-	}
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
-	
-	/* Require a minimum amount of memory for the signature buffers */
-	if (ui32SignatureChecksBufSize < RGXFW_SIG_BUFFER_SIZE_DEFAULT)
-	{
-		ui32SignatureChecksBufSize = RGXFW_SIG_BUFFER_SIZE_DEFAULT;
-	}
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C); 
-#else
-	rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_B, RGX_BVNC_V_ST, RGX_BVNC_N, RGX_BVNC_C); 
-#endif
-
+	_ParseHTBAppHints(hServices);
+	GetApphints(&sApphints, ui64ErnsBrns, ui64Features);
+	GetDeviceFlags(&sApphints, &ui32DeviceFlags);
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 {
@@ -1262,326 +2037,67 @@
 	{
 		for (uiRegion = 0; uiRegion < GPUVIRT_VALIDATION_NUM_REGIONS; uiRegion++)
 		{
-			aui32Buffer[ui32Counter++] = aui32OSidMin[uiOS][uiRegion];
-			aui32Buffer[ui32Counter++] = aui32OSidMax[uiOS][uiRegion];
+			aui32Buffer[ui32Counter++] = sApphints.aui32OSidMin[uiOS][uiRegion];
+			aui32Buffer[ui32Counter++] = sApphints.aui32OSidMax[uiOS][uiRegion];
 		}
 	}
 
-	BridgeGPUVIRTPopulateLMASubArenas(hServices, ui32Counter, aui32Buffer);
+	BridgeGPUVIRTPopulateLMASubArenas(hServices, ui32Counter, aui32Buffer, sApphints.bEnableTrustedDeviceAceConfig);
 }
 #endif
 
 
-	/*
-	 * FW Memory allocation
-	 */
-	RGXGetFWImageAllocSize(&uiFWCodeAllocSize,
-	                       &uiFWDataAllocSize,
-	                       &uiFWCorememCodeAllocSize);
-
-	/* Do firmware memory allocations that back its code and data sections */
-	eError = BridgeRGXInitAllocFWImgMem(hServices,
-	                                    uiFWCodeAllocSize,
-	                                    uiFWDataAllocSize,
-	                                    uiFWCorememCodeAllocSize,
-	                                    &hFWCodePMR,
-	                                    &sFWCodeDevVAddrBase,
-	                                    &hFWDataPMR,
-	                                    &sFWDataDevVAddrBase,
-	                                    &hFWCorememPMR,
-	                                    &sFWCorememDevVAddrBase,
-	                                    &sFWCorememFWAddr);
-	if(eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: PVRSRVRGXInitAllocFWImgMemfailed (%d)", eError));
-		goto cleanup;
-	}
-
-	/* Initialize firmware configuration */
-	eError = BridgeRGXInitFirmware(hServices,
-	                               &sRGXFwInit,
-	                               bEnableSignatureChecks,
-	                               ui32SignatureChecksBufSize,
-	                               ui32HWPerfFWBufSize,
-	                               (IMG_UINT64)ui32HWPerfFilter0|((IMG_UINT64)ui32HWPerfFilter1<<32),
-	                               sizeof(aui32RGXFWAlignChecks),
-	                               aui32RGXFWAlignChecks,
-	                               ui32FWConfigFlags,
-	                               ui32LogType,
-	                               ui32FilterFlags,
-	                               ui32JonesDisableMask,
-	                               ui32HWRDebugDumpLimit,
-	                               &sBVNC,
-	                               sizeof(RGXFWIF_HWPERF_CTL),
-	                               &hHWPerfDataPMR,
-	                               eRGXRDPowerIslandConf,
-	                               eFirmwarePerf);
-
-	if(eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: PVRSRVRGXInitFirmware failed (%d)", eError));
-		goto cleanup;
-	}
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRLock();
-#endif
-
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* These functionality is n/a to guest drivers */
-#else
-#if !defined(SUPPORT_TRUSTED_DEVICE)
-	DevmemMakeLocalImportHandle(hServices,
-	                            hFWCodePMR,
-	                            &hFWCodeImportHandle);
-
-	DevmemLocalImport(hServices,
-	                  hFWCodeImportHandle,
-	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
-	                  &psFWCodeHostMemDesc,
-	                  &uiFWCodeImportSize);
-
-	DevmemAcquireCpuVirtAddr(psFWCodeHostMemDesc,
-	                         &pvFWCodeHostAddr);
-#else
-	PVR_UNREFERENCED_PARAMETER(hFWCodeImportHandle);
-	PVR_UNREFERENCED_PARAMETER(psFWCodeHostMemDesc);
-	PVR_UNREFERENCED_PARAMETER(uiFWCodeImportSize);
-
-	/* We can't get a pointer to a secure FW allocation from within the DDK */
-	pvFWCodeHostAddr = NULL;
-#endif
-
-	DevmemMakeLocalImportHandle(hServices,
-	                            hFWDataPMR,
-	                            &hFWDataImportHandle);
-
-	DevmemLocalImport(hServices,
-	                  hFWDataImportHandle,
-	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
-	                  &psFWDataHostMemDesc,
-	                  &uiFWDataImportSize);
-
-	DevmemAcquireCpuVirtAddr(psFWDataHostMemDesc,
-	                         &pvFWDataHostAddr);
-
-
-	/* Map FW coremem buffer to copy the coremem contents on it */
-#if defined(RGX_META_COREMEM_CODE) || defined(RGX_META_COREMEM_DATA)
-	DevmemMakeLocalImportHandle(hServices,
-	                            hFWCorememPMR,
-	                            &hFWCorememImportHandle);
-
-	DevmemLocalImport(hServices,
-	                  hFWCorememImportHandle,
-	                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-	                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-	                  PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
-	                  &psFWCorememHostMemDesc,
-	                  &uiFWCorememImportSize);
-
-	DevmemAcquireCpuVirtAddr(psFWCorememHostMemDesc,
-	                         &pvFWCorememHostAddr);
-#else
-	pvFWCorememHostAddr = NULL;
-#endif
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRUnlock();
-#endif
-
-	/*
-	 * Process the FW image and setup code and data segments.
-	 *
-	 * When the trusted device is enabled and the FW image lives
-	 * in secure memory we will only setup the data segments here,
-	 * while the code segments will be loaded to secure memory
-	 * by the trusted device.
-	 */
-	sInitParams.hServices = hServices;
-
-	eError = RGXProcessFWImage(&sInitParams,
-	                           pbRGXFirmware,
-	                           pvFWCodeHostAddr,
-	                           pvFWDataHostAddr,
-	                           pvFWCorememHostAddr,
-	                           &sFWCodeDevVAddrBase,
-	                           &sFWDataDevVAddrBase,
-	                           &sFWCorememDevVAddrBase,
-	                           &sFWCorememFWAddr,
-	                           &sRGXFwInit,
-	                           eUseMETAT1 == RGX_META_T1_OFF ? 1 : 2,
-	                           eUseMETAT1 == RGX_META_T1_MAIN ? 1 : 0);
+	eError = InitFirmware(hServices,
+	                      &sApphints,
+	                      &sBVNC,
+	                      &hFWCodePMR,
+	                      &hFWDataPMR,
+	                      &hFWCorememPMR,
+	                      &hHWPerfDataPMR);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: RGXProcessFWImage failed (%d)", eError));
+		PVR_DPF((PVR_DBG_ERROR, "RGXInit: InitFirmware failed (%d)", eError));
 		goto cleanup;
 	}
 
-#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE)
-	RGXTDProcessFWImage(hServices, psRGXFW);
-#endif
-
-	/*
-	 * FW image processing complete, perform final steps
-	 * (if any) on the kernel before pdumping the FW code
-	 */
-	eError = BridgeRGXInitFinaliseFWImage(hServices,
-	                                      hFWCodePMR,
-	                                      uiFWCodeAllocSize);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: RGXInitFinaliseFWImage failed (%d)", eError));
-		goto cleanup;
-	}
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRLock();
-#endif
-
-#if !defined(SUPPORT_TRUSTED_DEVICE)
-	/* dump the fw code */
-	SRVINITPDumpComment(hServices, "Dump firmware code image");
-	DevmemPDumpLoadMem(psFWCodeHostMemDesc,
-							 0,
-							 uiFWCodeAllocSize,
-							 PDUMP_FLAGS_CONTINUOUS);
-#endif
-	SRVINITPDumpComment(hServices, "Dump firmware data image");
-	DevmemPDumpLoadMem(psFWDataHostMemDesc,
-							 0,
-							 uiFWDataAllocSize,
-							 PDUMP_FLAGS_CONTINUOUS);
-
-
-#if defined(RGX_META_COREMEM_CODE) && !defined(SUPPORT_TRUSTED_DEVICE)
-	SRVINITPDumpComment(hServices, "Dump firmware coremem image");
-	DevmemPDumpLoadMem(psFWCorememHostMemDesc,
-							 0,
-							 RGX_META_COREMEM_CODE_SIZE,
-							 PDUMP_FLAGS_CONTINUOUS);
-
-	/* clean the mappings that are not required anymore */
-	DevmemReleaseCpuVirtAddr(psFWCorememHostMemDesc);
-	DevmemFree(psFWCorememHostMemDesc);
-	DevmemUnmakeLocalImportHandle(hServices,
-	                              hFWCorememImportHandle);
-#endif
-	
-	/* clean the mappings that are not required anymore */
-	DevmemReleaseCpuVirtAddr(psFWDataHostMemDesc);
-	DevmemFree(psFWDataHostMemDesc);
-	DevmemUnmakeLocalImportHandle(hServices,
-	                              hFWDataImportHandle);
-
-#if !defined(SUPPORT_TRUSTED_DEVICE)
-	DevmemReleaseCpuVirtAddr(psFWCodeHostMemDesc);
-	DevmemFree(psFWCodeHostMemDesc);
-	DevmemUnmakeLocalImportHandle(hServices,
-	                              hFWCodeImportHandle);
-#endif
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRUnlock();
-#endif
-
 	/*
 	 * Build Debug info script
 	 */
 	sDbgInitScript.psCommands = asDbgCommands;
 
-	if(!PrepareDebugScript(&sDbgInitScript, eFirmwarePerf != FW_PERF_CONF_NONE))
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	if(!PrepareDebugScript(&sDbgInitScript, sApphints.eFirmwarePerf != FW_PERF_CONF_NONE, psDevInfo))
+#else
+	if(!PrepareDebugScript(&sDbgInitScript, sApphints.eFirmwarePerf != FW_PERF_CONF_NONE, NULL))
+#endif
 	{
 		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Run out of mem for the dbg commands"));
 	}
 
-
 	/* finish the script */
 	if(!ScriptHalt(&sDbgInitScript))
 	{
 		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Run out of mem for the terminating dbg script"));
 	}
 
-	/*
-	 * Build Debugbus script
-	 */
-	sDbgBusInitScript.psCommands = asDbgBusCommands;
-
-	if(!PrepareDebugBusScript(&sDbgBusInitScript))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Run out of mem for the dbg commands"));
-	}
-
-	/* finish the script */
-	if(!ScriptHalt(&sDbgBusInitScript))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Run out of mem for the terminating dbg script"));
-	}
-
-	/*
-	 * Build deinit script
-	 */
-	sDeinitScript.psCommands = asDeinitCommands;
-
-	if(!PrepareDeinitScript(&sDeinitScript))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Run out of mem for the deinit commands"));
-	}
-
-	/* finish the script */
-	if(!ScriptHalt(&sDeinitScript))
-	{
-		PVR_DPF((PVR_DBG_ERROR, "RGXInit: Run out of mem for the terminating deinit script"));
-	}
 #if defined(PDUMP)
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRLock();
-#endif
-	/* Acquire HWPerf data mem handle to be able to fill it later */
-	DevmemMakeLocalImportHandle(hServices,
-	                            hHWPerfDataPMR,
-	                            &hHWPerfDataImportHandle);
-
-	DevmemLocalImport(hServices,
-	                        hHWPerfDataImportHandle,
-	                        PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-	                        PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-	                        PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-	                        PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
-	                        &psHWPerfDataMemDesc,
-	                        &uiHWPerfDataImportSize);
-	eError = DevmemAcquireCpuVirtAddr(psHWPerfDataMemDesc, (void **)&psHWPerfInitData);
+	eError = InitialiseAllCounters(hServices, hHWPerfDataPMR);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", failHWPerfCountersMemDescAqCpuVirt);
+		PVR_DPF((PVR_DBG_ERROR, "RGXInit: InitialiseAllCounters failed (%d)", eError));
+		goto cleanup;
 	}
-
-	InitialiseHWPerfCounters(hServices, psHWPerfDataMemDesc, psHWPerfInitData);
-	InitialiseCustomCounters(hServices, psHWPerfDataMemDesc);
-
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRUnlock();
 #endif
-#endif
-#endif /* defined(PVRSRV_GPUVIRT_GUESTDRV) */
 
 	/*
 	 * Perform second stage of RGX initialisation
 	 */
 	eError = BridgeRGXInitDevPart2(hServices,
 	                               sDbgInitScript.psCommands,
-	                               sDbgBusInitScript.psCommands,
-	                               sDeinitScript.psCommands,
 	                               ui32DeviceFlags,
-	                               ui32HWPerfHostFilter,
-	                               eRGXActivePMConf,
+	                               sApphints.ui32HWPerfHostBufSize,
+	                               sApphints.ui32HWPerfHostFilter,
+	                               sApphints.eRGXActivePMConf,
 	                               hFWCodePMR,
 	                               hFWDataPMR,
 	                               hFWCorememPMR,
@@ -1593,18 +2109,51 @@
 		goto cleanup;
 	}
 
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* These functionality is n/a to guest drivers */
-#else
-#if !defined(SUPPORT_KERNEL_SRVINIT) && defined(PDUMP)
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(SUPPORT_VALIDATION)
+	PVRSRVAppHintDumpState();
+#endif
+
+#if defined(PDUMP)
 	/*
 	 * Dump the list of signature registers
 	 */
 	{
 		IMG_UINT32 i;
+		IMG_UINT32 ui32TASigRegCount = 0, ui323DSigRegCount= 0;
+		IMG_BOOL	bRayTracing = IMG_FALSE;
+
+#if defined(SUPPORT_KERNEL_SRVINIT) && defined(__KERNEL__)
+		RGXInitFWSigRegisters(psDevInfo);
+		ui32TASigRegCount = gui32TASigRegCount;
+		ui323DSigRegCount = gui323DSigRegCount;
+		if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_RAY_TRACING_BIT_MASK)
+		{
+			bRayTracing = IMG_TRUE;
+		}
+#if defined(DEBUG)
+		if (gui32TASigRegCount > SIG_REG_TA_MAX_COUNT)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: TA signature registers max count exceeded",__func__));
+			PVR_ASSERT(0);
+		}
+		if (gui323DSigRegCount > SIG_REG_3D_MAX_COUNT)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: 3D signature registers max count exceeded",__func__));
+			PVR_ASSERT(0);
+		}
+#endif
+#else
+		ui32TASigRegCount = sizeof(asTASigRegList)/sizeof(RGXFW_REGISTER_LIST);
+		ui323DSigRegCount = sizeof(as3DSigRegList)/sizeof(RGXFW_REGISTER_LIST);
+#if defined(RGX_FEATURE_RAY_TRACING)
+		bRayTracing = IMG_TRUE;
+#endif
+#endif
+
+
 
 		SRVINITPDumpComment(hServices, "Signature TA registers: ");
-		for (i = 0; i < sizeof(asTASigRegList)/sizeof(RGXFW_REGISTER_LIST); i++)
+		for (i = 0; i < ui32TASigRegCount; i++)
 		{
 			if (asTASigRegList[i].ui16IndirectRegNum != 0)
 			{
@@ -1619,7 +2168,7 @@
 		}
 
 		SRVINITPDumpComment(hServices, "Signature 3D registers: ");
-		for (i = 0; i < sizeof(as3DSigRegList)/sizeof(RGXFW_REGISTER_LIST); i++)
+		for (i = 0; i < ui323DSigRegCount; i++)
 		{
 			if (as3DSigRegList[i].ui16IndirectRegNum != 0)
 			{
@@ -1633,67 +2182,47 @@
 			}
 		}
 
-#if defined(RGX_FEATURE_RAY_TRACING)
-		SRVINITPDumpComment(hServices, "Signature RTU registers: ");
-		for (i = 0; i < sizeof(asRTUSigRegList)/sizeof(RGXFW_REGISTER_LIST); i++)
+		if(bRayTracing)
 		{
-			if (asRTUSigRegList[i].ui16IndirectRegNum != 0)
+#if defined (RGX_FEATURE_RAY_TRACING) || defined(SUPPORT_KERNEL_SRVINIT)
+			SRVINITPDumpComment(hServices, "Signature RTU registers: ");
+			for (i = 0; i < sizeof(asRTUSigRegList)/sizeof(RGXFW_REGISTER_LIST); i++)
 			{
-				SRVINITPDumpComment(hServices, " * 0x%8.8X (indirect via 0x%8.8X %d to %d)",
-				              asRTUSigRegList[i].ui16RegNum, asRTUSigRegList[i].ui16IndirectRegNum,
-				              asRTUSigRegList[i].ui16IndirectStartVal, asRTUSigRegList[i].ui16IndirectEndVal);
+				if (asRTUSigRegList[i].ui16IndirectRegNum != 0)
+				{
+					SRVINITPDumpComment(hServices, " * 0x%8.8X (indirect via 0x%8.8X %d to %d)",
+								  asRTUSigRegList[i].ui16RegNum, asRTUSigRegList[i].ui16IndirectRegNum,
+								  asRTUSigRegList[i].ui16IndirectStartVal, asRTUSigRegList[i].ui16IndirectEndVal);
+				}
+				else
+				{
+					SRVINITPDumpComment(hServices, " * 0x%8.8X", asRTUSigRegList[i].ui16RegNum);
+				}
 			}
-			else
+
+			SRVINITPDumpComment(hServices, "Signature SHG registers: ");
+			for (i = 0; i < sizeof(asSHGSigRegList)/sizeof(RGXFW_REGISTER_LIST); i++)
 			{
-				SRVINITPDumpComment(hServices, " * 0x%8.8X", asRTUSigRegList[i].ui16RegNum);
+				if (asSHGSigRegList[i].ui16IndirectRegNum != 0)
+				{
+					SRVINITPDumpComment(hServices, " * 0x%8.8X (indirect via 0x%8.8X %d to %d)",
+								  asSHGSigRegList[i].ui16RegNum, asSHGSigRegList[i].ui16IndirectRegNum,
+								  asSHGSigRegList[i].ui16IndirectStartVal, asSHGSigRegList[i].ui16IndirectEndVal);
+				}
+				else
+				{
+					SRVINITPDumpComment(hServices, " * 0x%8.8X", asSHGSigRegList[i].ui16RegNum);
+				}
 			}
+#endif
 		}
 
-		SRVINITPDumpComment(hServices, "Signature SHG registers: ");
-		for (i = 0; i < sizeof(asSHGSigRegList)/sizeof(RGXFW_REGISTER_LIST); i++)
-		{
-			if (asSHGSigRegList[i].ui16IndirectRegNum != 0)
-			{
-				SRVINITPDumpComment(hServices, " * 0x%8.8X (indirect via 0x%8.8X %d to %d)",
-				              asSHGSigRegList[i].ui16RegNum, asSHGSigRegList[i].ui16IndirectRegNum,
-				              asSHGSigRegList[i].ui16IndirectStartVal, asSHGSigRegList[i].ui16IndirectEndVal);
-			}
-			else
-			{
-				SRVINITPDumpComment(hServices, " * 0x%8.8X", asSHGSigRegList[i].ui16RegNum);
-			}
-		}
-#endif
 	}
 #endif	/* !defined(SUPPORT_KERNEL_SRVINIT) && defined(PDUMP) */
-#endif /*   defined(PVRSRV_GPUVIRT_GUESTDRV) */
 
 	eError = PVRSRV_OK;
-#if defined(PDUMP)
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRLock();
-#endif
 
-	DevmemReleaseCpuVirtAddr(psHWPerfDataMemDesc);
-	DevmemFree(psHWPerfDataMemDesc);
-	DevmemUnmakeLocalImportHandle(hServices,
-	                              hHWPerfDataImportHandle);
-#if defined(SUPPORT_KERNEL_SRVINIT)
-	PMRUnlock();
-#endif
-failHWPerfCountersMemDescAqCpuVirt:
-#endif
 cleanup:
-	SrvInitParamClose(pvParamState);
-
-#if	defined(PVRSRV_GPUVIRT_GUESTDRV)
-	/* Guest driver do not unload firmware */
-#else
-	if (psRGXFW != NULL)
-	{
-		RGXUnloadFirmware(psRGXFW);
-	}
-#endif
 	return eError;
 }
 
diff --git a/drivers/staging/imgtec/rogue/rgxsrvinit_script.c b/drivers/staging/imgtec/rogue/rgxsrvinit_script.c
index e1d9bc8..8870de9 100644
--- a/drivers/staging/imgtec/rogue/rgxsrvinit_script.c
+++ b/drivers/staging/imgtec/rogue/rgxsrvinit_script.c
@@ -207,7 +207,7 @@
 }
 
 
-#if defined(RGX_FEATURE_META)
+#if defined(RGX_FEATURE_META) || defined(SUPPORT_KERNEL_SRVINIT)
 IMG_BOOL ScriptWriteRGXRegPDUMPOnly(RGX_SCRIPT_BUILD *psScript,
                                     IMG_UINT32 ui32Offset,
                                     IMG_UINT32 ui32Value)
@@ -510,7 +510,6 @@
 #endif /* RGX_FEATURE_META */
 
 
-#if defined(FIX_HW_BRN_44871)
 IMG_BOOL ScriptDBGString(RGX_SCRIPT_BUILD *psScript,
                          const IMG_CHAR *aszString)
 {
@@ -529,114 +528,6 @@
 
 	return IMG_FALSE;
 }
-#endif /* FIX_HW_BRN_44871 */
-
-
-#if defined(RGX_FEATURE_PERFBUS) && defined(SUPPORT_DEBUG_BUS_DUMP)
-/*!
-*******************************************************************************
-
- @Function      ScriptWaitUs
-
- @Description   Adds wait to the script
-
- @Input         psScript
-
- @Input         ui32WaitInUs
-
- @Return        IMG_BOOL
-
-******************************************************************************/
-static IMG_BOOL ScriptWaitUs(RGX_SCRIPT_BUILD *psScript,
-                             IMG_UINT32 ui32WaitInUs)
-{
-	RGX_INIT_COMMAND *psComm = NextScriptCommand(psScript);
-
-	if (psComm != NULL)
-	{
-		psComm->sDBGWait.eOp = RGX_INIT_OP_DBG_WAIT;
-		psComm->sDBGWait.ui32WaitInUs = ui32WaitInUs;
-		return IMG_TRUE;
-	}
-
-	return IMG_FALSE;
-}
-
-
-IMG_BOOL ScriptDBGBusReadBlock(RGX_SCRIPT_BUILD *psScript,
-                               const IMG_CHAR *pszGroupName,
-                               IMG_UINT32 ui32BaseAddrOffset,
-                               IMG_UINT32 ui32GroupCount)
-{
-	IMG_UINT32 i;
-	IMG_CHAR szBlockOffset[100];
-
-#define REG_WRITE(R, V)      if (!ScriptWriteRGXReg(psScript, R, V)) return IMG_FALSE;
-#define DBG_READ(T, R, S)    if (!ScriptDBGReadRGXReg(psScript, T, R, S)) return IMG_FALSE;
-#define DBG_STRING(S)        if (!ScriptDBGString(psScript, S)) return IMG_FALSE;
-#define DBG_WAITUS(T)        if (!ScriptWaitUs(psScript, T)) return IMG_FALSE;
-#define DBG_BUS_READ(R, S) \
-	DBG_READ(RGX_INIT_OP_DBG_READ64_HW_REG, R, S); \
-	DBG_WAITUS(10);
-
-/* Workout the generic register offsets based on RGX_CR_TA_PERF */
-#define RGX_CR_N_PERF                0
-#define RGX_CR_N_PERF_SELECT0        (RGX_CR_TA_PERF_SELECT0 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_SELECT1        (RGX_CR_TA_PERF_SELECT1 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_SELECT2        (RGX_CR_TA_PERF_SELECT2 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_SELECT3        (RGX_CR_TA_PERF_SELECT3 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_SELECTED_BITS  (RGX_CR_TA_PERF_SELECTED_BITS - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_COUNTER_0      (RGX_CR_TA_PERF_COUNTER_0 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_COUNTER_1      (RGX_CR_TA_PERF_COUNTER_1 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_COUNTER_2      (RGX_CR_TA_PERF_COUNTER_2 - RGX_CR_TA_PERF)
-#define RGX_CR_N_PERF_COUNTER_3      (RGX_CR_TA_PERF_COUNTER_3 - RGX_CR_TA_PERF)
-
-	/*
-	 * Note:
-	 * Although we use RGX_CR_TA_* here the control registers are the
-	 * same for all the perf register banks, but there is no generic
-	 * RGX_CR_N_* register definition to use.
-	 */
-	
-	DBG_STRING(pszGroupName);
-
-	/* Enable debug bus */
-	REG_WRITE(ui32BaseAddrOffset + RGX_CR_N_PERF, RGX_CR_TA_PERF_CTRL_ENABLE_EN);
-
-	/*
-	 *Loop across all the groups in the block, reading the values 4 at a time
-	 */
-	for (i=0;i<ui32GroupCount;i+=4)
-	{
-		REG_WRITE(ui32BaseAddrOffset + RGX_CR_N_PERF_SELECT0,
-		          (i << RGX_CR_TA_PERF_SELECT0_GROUP_SELECT_SHIFT) |
-		           ~RGX_CR_TA_PERF_SELECT0_BIT_SELECT_CLRMSK);
-
-		REG_WRITE(ui32BaseAddrOffset + RGX_CR_N_PERF_SELECT1,
-		          ((i+1) << RGX_CR_TA_PERF_SELECT1_GROUP_SELECT_SHIFT) |
-		           ~RGX_CR_TA_PERF_SELECT1_BIT_SELECT_CLRMSK);
-		
-		REG_WRITE(ui32BaseAddrOffset + RGX_CR_N_PERF_SELECT2,
-		          ((i+2) << RGX_CR_TA_PERF_SELECT2_GROUP_SELECT_SHIFT) |
-		          ~RGX_CR_TA_PERF_SELECT2_BIT_SELECT_CLRMSK);
-		
-		REG_WRITE(ui32BaseAddrOffset + RGX_CR_N_PERF_SELECT3,
-		          ((i+3) << RGX_CR_TA_PERF_SELECT3_GROUP_SELECT_SHIFT) |
-		          ~RGX_CR_TA_PERF_SELECT3_BIT_SELECT_CLRMSK);
-
-		snprintf(szBlockOffset, sizeof(szBlockOffset), "BlockOffset 0x%08x", i);
-		DBG_BUS_READ(ui32BaseAddrOffset + RGX_CR_N_PERF_SELECTED_BITS, szBlockOffset);
-	}
-
-#undef REG_WRITE
-#undef DBG_READ
-#undef DBG_STRING
-#undef DBG_WAITUS
-#undef DBG_BUS_READ
-
-	return IMG_TRUE;
-}
-#endif /* RGX_FEATURE_PERFBUS && SUPPORT_DEBUG_BUS_DUMP */
 
 
 IMG_BOOL ScriptHalt(RGX_SCRIPT_BUILD *psScript)
diff --git a/drivers/staging/imgtec/rogue/rgxsrvinit_script.h b/drivers/staging/imgtec/rogue/rgxsrvinit_script.h
index eb34e7f..44aa1af 100644
--- a/drivers/staging/imgtec/rogue/rgxsrvinit_script.h
+++ b/drivers/staging/imgtec/rogue/rgxsrvinit_script.h
@@ -170,7 +170,7 @@
                        IMG_CHAR *pszName);
 
 
-#if defined(RGX_FEATURE_META)
+#if defined(RGX_FEATURE_META) || defined(SUPPORT_KERNEL_SRVINIT)
 /*!
 *******************************************************************************
 
@@ -290,7 +290,6 @@
 #endif /* RGX_FEATURE_META */
 
 
-#if defined(FIX_HW_BRN_44871)
 /*!
 *******************************************************************************
 
@@ -308,32 +307,6 @@
 IMG_INTERNAL
 IMG_BOOL ScriptDBGString(RGX_SCRIPT_BUILD *psScript,
                          const IMG_CHAR *aszString);
-#endif /* FIX_HW_BRN_44871 */
-
-
-#if defined(RGX_FEATURE_PERFBUS) && defined(SUPPORT_DEBUG_BUS_DUMP)
-/*!
-*******************************************************************************
-
- @Function      ScriptDBGBusReadBlock
-
- @Description   Adds script entries reading a reg through the debug bus interface
-
- @Input         psScript
- @Input         pszGroupName
- @Input         ui32BaseAddrOffset
- @Input         ui32GroupCount
-
- @Return        IMG_BOOL
-
-******************************************************************************/
-
-IMG_INTERNAL
-IMG_BOOL ScriptDBGBusReadBlock(RGX_SCRIPT_BUILD *psScript,
-                               const IMG_CHAR *pszGroupName,
-                               IMG_UINT32 ui32BaseAddrOffset,
-                               IMG_UINT32 ui32GroupCount);
-#endif /* RGX_FEATURE_PERFBUS && SUPPORT_DEBUG_BUS_DUMP */
 
 
 /*!
diff --git a/drivers/staging/imgtec/rogue/rgxstartstop.c b/drivers/staging/imgtec/rogue/rgxstartstop.c
index 8c66631..f6a656a 100644
--- a/drivers/staging/imgtec/rogue/rgxstartstop.c
+++ b/drivers/staging/imgtec/rogue/rgxstartstop.c
@@ -44,22 +44,18 @@
 /* The routines implemented here are built on top of an abstraction layer to
  * hide DDK/OS-specific details in case they are used outside of the DDK
  * (e.g. when trusted device is enabled).
- * Any new dependency should be added to rgxlayer_km.h. */
+ * Any new dependency should be added to rgxlayer_km.h.
+ * Any new code should be built on top of the existing abstraction layer,
+ * which should be extended when necessary. */
 #include "rgxstartstop.h"
 
-#if defined(RGX_FEATURE_MIPS)
-#include "devicemem_utils.h"
-#include "osfunc.h"
-#include "pdump_km.h"
-#include "physheap.h"
-#include "rgxfwutils.h"
-#endif
-
 #if defined(SUPPORT_SHARED_SLC)
 #include "rgxapi_km.h"
 #include "rgxdevice.h"
 #endif
 
+#define SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING
+
 
 #if !defined(FIX_HW_BRN_37453)
 /*!
@@ -81,8 +77,6 @@
 #endif
 
 
-#if defined(RGX_FEATURE_META)
-#if defined(PDUMP)
 static PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
@@ -100,8 +94,6 @@
 
 	return eError;
 }
-#endif /* PDUMP */
-
 
 static PVRSRV_ERROR RGXReadMetaRegThroughSP(const void *hPrivate,
                                             IMG_UINT32 ui32RegAddr,
@@ -126,14 +118,65 @@
 	                      RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
 	if (eError != PVRSRV_OK) return eError;
 
+#if !defined(NO_HARDWARE)
 	*ui32RegValue = RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAX);
+#else
+	*ui32RegValue = 0xFFFFFFFF;
+#endif
 
 	return eError;
 }
-#endif /* RGX_FEATURE_META */
 
+static PVRSRV_ERROR RGXWriteMetaCoreRegThoughSP(const void *hPrivate,
+                                                IMG_UINT32 ui32CoreReg,
+                                                IMG_UINT32 ui32Value)
+{
+	IMG_UINT32 i = 0;
 
-#if defined(RGX_FEATURE_META)
+	RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXUXXRXDT_OFFSET, ui32Value);
+	RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXUXXRXRQ_OFFSET, ui32CoreReg & ~META_CR_TXUXXRXRQ_RDnWR_BIT);
+
+	do
+	{
+		RGXReadMetaRegThroughSP(hPrivate, META_CR_TXUXXRXRQ_OFFSET, &ui32Value);
+	} while (((ui32Value & META_CR_TXUXXRXRQ_DREADY_BIT) != META_CR_TXUXXRXRQ_DREADY_BIT) && (i++ < 1000));
+
+	if (i == 1000)
+	{
+		RGXCommentLogPower(hPrivate, "RGXWriteMetaCoreRegThoughSP: Timeout");
+		return PVRSRV_ERROR_TIMEOUT;
+	}
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR RGXStartFirmware(const void *hPrivate)
+{
+	PVRSRV_ERROR eError;
+
+	/* Give privilege to debug and slave port */
+	RGXWriteMetaRegThroughSP(hPrivate, META_CR_SYSC_JTAG_THREAD, META_CR_SYSC_JTAG_THREAD_PRIV_EN);
+
+	/* Point Meta to the bootloader address, global (uncached) range */
+	eError = RGXWriteMetaCoreRegThoughSP(hPrivate,
+	                                     PC_ACCESS(0),
+	                                     RGXFW_BOOTLDR_META_ADDR | META_MEM_GLOBAL_RANGE_BIT);
+
+	if (eError != PVRSRV_OK)
+	{
+		RGXCommentLogPower(hPrivate, "RGXStart: RGX Firmware Slave boot Start failed!");
+		return eError;
+	}
+
+	/* Enable minim encoding */
+	RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXPRIVEXT, META_CR_TXPRIVEXT_MINIM_EN);
+
+	/* Enable Meta thread */
+	RGXWriteMetaRegThroughSP(hPrivate, META_CR_T0ENABLE_OFFSET, META_CR_TXENABLE_ENABLE_BIT);
+
+	return PVRSRV_OK;
+}
+
 /*!
 *******************************************************************************
 
@@ -146,43 +189,46 @@
  @Return        void
 
 ******************************************************************************/
-static PVRSRV_ERROR RGXInitMetaProcWrapper(const void *hPrivate)
+static void RGXInitMetaProcWrapper(const void *hPrivate)
 {
 	IMG_UINT64 ui64GartenConfig;
-	PVRSRV_ERROR eError = PVRSRV_OK;
 
 	/* Set Garten IDLE to META idle and Set the Garten Wrapper BIF Fence address */
 
 	/* Garten IDLE bit controlled by META */
 	ui64GartenConfig = RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META;
 
-	/* The fence addr is set here and then re-initialised at the fw init sequence. 
-     The following assignment is deprecated and will be removed in future */
-	ui64GartenConfig |= (RGXFW_BOOTLDR_DEVV_ADDR & ~RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_CLRMSK);
+	/* The fence addr is set at the fw init sequence */
 
-	/* Set PC = 0 for fences */
-	ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK;
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		/* Set PC = 0 for fences */
+		ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_CLRMSK;
+		ui64GartenConfig |= (IMG_UINT64)META_MMU_CONTEXT_MAPPING
+		                    << RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_SHIFT;
 
-#if defined(RGX_FEATURE_SLC_VIVT)
-#if !defined(FIX_HW_BRN_51281)
-	/* Ensure the META fences go all the way to external memory */
-	ui64GartenConfig |= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_SLC_COHERENT_EN;    /* SLC Coherent 1 */
-	ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PERSISTENCE_CLRMSK; /* SLC Persistence 0 */
-#endif /* FIX_HW_BRN_51281 */
+		if (!RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_51281_BIT_MASK))
+		{
+			/* Ensure the META fences go all the way to external memory */
+			ui64GartenConfig |= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_SLC_COHERENT_EN;    /* SLC Coherent 1 */
+			ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PERSISTENCE_CLRMSK; /* SLC Persistence 0 */
+		}
+	}
+	else
+	{
+		/* Set PC = 0 for fences */
+		ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK;
+		ui64GartenConfig |= (IMG_UINT64)META_MMU_CONTEXT_MAPPING
+		                    << RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT;
 
-#else
-	/* Set SLC DM=META */
-	ui64GartenConfig |= ((IMG_UINT64) RGXFW_SEGMMU_META_DM_ID) << RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_SHIFT;
-
-#endif /* RGX_FEATURE_SLC_VIVT */
+		/* Set SLC DM=META */
+		ui64GartenConfig |= ((IMG_UINT64) RGXFW_SEGMMU_META_DM_ID) << RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_SHIFT;
+	}
 
 	RGXCommentLogPower(hPrivate, "RGXStart: Configure META wrapper");
 	RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui64GartenConfig);
-
-	return eError;
 }
 
-#else  /* RGX_FEATURE_META */
 
 /*!
 *******************************************************************************
@@ -191,160 +237,125 @@
 
  @Description   Configures the hardware wrapper of the MIPS processor
 
- @Input         psDeviceNode    : Device node structure
- @Input         psDeviceConfig  : Device config structure
-
- @Return        void
-
-******************************************************************************/
-static PVRSRV_ERROR RGXInitMipsProcWrapper(PVRSRV_RGXDEV_INFO *psDevInfo,
-                                           PVRSRV_DEVICE_CONFIG *psDevConfig)
-{
-	PVRSRV_ERROR eError = PVRSRV_OK;
-
-#if !defined(NO_HARDWARE) || defined(PDUMP)
-	/* Garten IDLE bit controlled by MIPS */
-	IMG_UINT64 ui64GartenConfig = RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META;
-	IMG_UINT32 ui32BootCodeOffset = (IMG_UINT32)RGXMIPSFW_BOOTCODE_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
-	PMR *psPMR = (PMR *)(psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR);
-#endif
-
-	/* We need to setup the MIPS wrapper register in case of a MIPS-based BVNC*/
-#if !defined(NO_HARDWARE)
-	IMG_UINT32 ui32NMIOffset = (IMG_UINT32)RGXMIPSFW_NMI_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
-	IMG_DEV_PHYADDR sDevAddrPtr;
-	IMG_DEV_PHYADDR sPhyRegAddr;
-	void *pvRegsBaseKM;
-	IMG_BOOL bValid;
-
-	eError = RGXGetPhyAddr(psPMR, &sDevAddrPtr, ui32BootCodeOffset, (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE, 1, &bValid);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXGetPhyAddr failed (%u)",
-                        eError));
-		return eError;
-	}
-
-	/* Write into the RGX_CR_MTS_MIPS_WRAPPER_CONFIG to set the register transactions ID */
-	/* The physical address needs to be translate in case we are in a LMA scenario*/
-	PhysHeapCpuPAddrToDevPAddr(psDevInfo->psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL],
-	                           1, &sPhyRegAddr, &(psDevConfig->sRegsCpuPBase));
-
-	pvRegsBaseKM = OSMapPhysToLin(psDevConfig->sRegsCpuPBase, psDevConfig->ui32RegsSize, 0);
-	OSWriteHWReg64(pvRegsBaseKM,
-	               RGX_CR_MIPS_WRAPPER_CONFIG,
-	               (sPhyRegAddr.uiAddr >> RGXMIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) | (RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS));
-
-	/* Write the register Boot remap registers */
-	OSWriteHWReg64(pvRegsBaseKM,
-	               RGX_CR_MIPS_ADDR_REMAP1_CONFIG1,
-	               RGXMIPSFW_BOOTLDR_ADDR_PHY | 1);
-
-	/* only 0xC bits of the original address survive (4K bootloader), we take the low 32-bits (12 bits aligned) of the physAddr*/
-	OSWriteHWReg64(pvRegsBaseKM,
-	               RGX_CR_MIPS_ADDR_REMAP1_CONFIG2,
-	               (sDevAddrPtr.uiAddr & ~RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK) | RGXMIPSFW_LOG2_REMAP1_SEGMENT_SIZE);
-
-	eError = RGXGetPhyAddr(psPMR, &sDevAddrPtr, ui32NMIOffset, (IMG_UINT32)RGXMIPSFW_LOG2_PAGE_SIZE, 1, &bValid);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR,"RGXGetPhyAddr failed (%u)",
-                         eError));
-		return eError;
-	}
-
-	/* Write the register remap registers for NMI code and data */
-	OSWriteHWReg64(pvRegsBaseKM,
-	               RGX_CR_MIPS_ADDR_REMAP3_CONFIG1,
-	               RGXMIPSFW_NMI_ADDR_PHY | 1);
-
-	/* only 0xC bits of the original address survive, we take the low 32-bits (12 bits aligned) of the physAddr*/
-	OSWriteHWReg64(pvRegsBaseKM,
-	               RGX_CR_MIPS_ADDR_REMAP3_CONFIG2,
-	               (sDevAddrPtr.uiAddr & ~RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK) | RGXMIPSFW_LOG2_REMAP3_SEGMENT_SIZE);
-
-	/* Set the garten idle bit to be driven by the MIPS cpu_idle signal */
-	OSWriteHWReg64(pvRegsBaseKM, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui64GartenConfig);
-
-	/* Turn on the EJTAG probe */
-	OSWriteHWReg32(pvRegsBaseKM, RGX_CR_MIPS_DEBUG_CONFIG, 0);
-
-	OSUnMapPhysToLin(pvRegsBaseKM, psDevConfig->ui32RegsSize, 0);
-#endif
-
-#if defined(PDUMP)
-	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Configure MIPS wrapper");
-	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Write the register transaction ID");
-	PDumpRegLabelToInternalVar(RGX_PDUMPREG_NAME, RGX_CR_MIPS_WRAPPER_CONFIG, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
-	/* The register transactions identifier is 16-bit aligned */
-	PDumpWriteVarSHRValueOp(":SYSMEM:$1", RGXMIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN, PDUMP_FLAGS_CONTINUOUS);
-	/* Enable micromips instruction encoding */
-	PDumpWriteVarORValueOp(":SYSMEM:$1", RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS, PDUMP_FLAGS_CONTINUOUS);
-	/* Do the actual register write */
-	PDumpInternalVarToReg64(RGX_PDUMPREG_NAME,
-	                        RGX_CR_MIPS_WRAPPER_CONFIG,
-	                        ":SYSMEM:$1",
-	                        0);
-
-	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Write the register Boot remap registers");
-	PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_MIPS_ADDR_REMAP1_CONFIG1, RGXMIPSFW_BOOTLDR_ADDR_PHY | 1, PDUMP_FLAGS_CONTINUOUS);
-	PDumpMemLabelToInternalVar(":SYSMEM:$1",
-	                           psPMR,
-	                           psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32BootCodeOffset,
-	                           PDUMP_FLAGS_CONTINUOUS);
-	PDumpWriteVarANDValueOp(":SYSMEM:$1",
-	                        ~RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK,
-	                        PDUMP_FLAGS_CONTINUOUS);
-	PDumpWriteVarORValueOp(":SYSMEM:$1",
-	                       RGXMIPSFW_LOG2_REMAP1_SEGMENT_SIZE,
-	                       PDUMP_FLAGS_CONTINUOUS);
-	PDumpInternalVarToReg32(RGX_PDUMPREG_NAME,
-	                        RGX_CR_MIPS_ADDR_REMAP1_CONFIG2,
-	                        ":SYSMEM:$1",
-	                        PDUMP_FLAGS_CONTINUOUS);
-	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Set the GARTEN_IDLE type to MIPS");
-	PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui64GartenConfig, PDUMP_FLAGS_CONTINUOUS);
-#endif /* PDUMP */
-	return eError;
-}
-#endif /* RGX_FEATURE_META */
-
-
-/*!
-*******************************************************************************
-
- @Function      RGXInitFWProcWrapper
-
- @Description   Configures the hardware wrapper of the Firmware processor
-
  @Input         hPrivate  : Implementation specific data
 
  @Return        void
 
 ******************************************************************************/
-static PVRSRV_ERROR RGXInitFWProcWrapper(const void *hPrivate)
+static void RGXInitMipsProcWrapper(const void *hPrivate)
 {
-#if defined(RGX_FEATURE_META)
-	return RGXInitMetaProcWrapper(hPrivate);
-#else
-	PVRSRV_RGXDEV_INFO *psDevInfo;
-	PVRSRV_DEVICE_CONFIG *psDevConfig;
+	IMG_DEV_PHYADDR sPhyAddr;
+	IMG_UINT64 ui64RemapSettings = RGXMIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE; /* Same for all remap registers */
 
-	PVR_ASSERT(hPrivate != NULL);
-	psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
-	psDevConfig = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevConfig;
-	return RGXInitMipsProcWrapper(psDevInfo, psDevConfig);
+	RGXCommentLogPower(hPrivate, "RGXStart: Configure MIPS wrapper");
+
+	/*
+	 * MIPS wrapper (registers transaction ID and ISA mode) setup
+	 */
+
+	RGXAcquireGPURegsAddr(hPrivate, &sPhyAddr);
+
+	RGXCommentLogPower(hPrivate, "RGXStart: Write wrapper config register");
+	RGXMIPSWrapperConfig(hPrivate,
+	                     RGX_CR_MIPS_WRAPPER_CONFIG,
+	                     sPhyAddr.uiAddr,
+	                     RGXMIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN,
+	                     RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS);
+
+	/*
+	 * Boot remap setup
+	 */
+
+	RGXAcquireBootRemapAddr(hPrivate, &sPhyAddr);
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	/* Do not mark accesses to a FW code remap region as DRM accesses */
+	ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
 #endif
+
+	RGXCommentLogPower(hPrivate, "RGXStart: Write boot remap registers");
+	RGXBootRemapConfig(hPrivate,
+	                   RGX_CR_MIPS_ADDR_REMAP1_CONFIG1,
+	                   RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN | RGX_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN,
+	                   RGX_CR_MIPS_ADDR_REMAP1_CONFIG2,
+	                   sPhyAddr.uiAddr,
+	                   ~RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK,
+	                   ui64RemapSettings);
+
+	/*
+	 * Data remap setup
+	 */
+
+	RGXAcquireDataRemapAddr(hPrivate, &sPhyAddr);
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	/* Remapped data in non-secure memory */
+	ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
+#endif
+
+	RGXCommentLogPower(hPrivate, "RGXStart: Write data remap registers");
+	RGXDataRemapConfig(hPrivate,
+	                   RGX_CR_MIPS_ADDR_REMAP2_CONFIG1,
+	                   RGXMIPSFW_DATA_REMAP_PHYS_ADDR_IN | RGX_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN,
+	                   RGX_CR_MIPS_ADDR_REMAP2_CONFIG2,
+	                   sPhyAddr.uiAddr,
+	                   ~RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK,
+	                   ui64RemapSettings);
+
+	/*
+	 * Code remap setup
+	 */
+
+	RGXAcquireCodeRemapAddr(hPrivate, &sPhyAddr);
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	/* Do not mark accesses to a FW code remap region as DRM accesses */
+	ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
+#endif
+
+	RGXCommentLogPower(hPrivate, "RGXStart: Write exceptions remap registers");
+	RGXCodeRemapConfig(hPrivate,
+	                   RGX_CR_MIPS_ADDR_REMAP3_CONFIG1,
+	                   RGXMIPSFW_CODE_REMAP_PHYS_ADDR_IN | RGX_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN,
+	                   RGX_CR_MIPS_ADDR_REMAP3_CONFIG2,
+	                   sPhyAddr.uiAddr,
+	                   ~RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK,
+	                   ui64RemapSettings);
+
+	/*
+	 * Trampoline remap setup
+	 */
+
+	RGXAcquireTrampolineRemapAddr(hPrivate, &sPhyAddr);
+	ui64RemapSettings = RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE;
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	/* Remapped data in non-secure memory */
+	ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
+#endif
+
+	RGXCommentLogPower(hPrivate, "RGXStart: Write trampoline remap registers");
+	RGXTrampolineRemapConfig(hPrivate,
+	                   RGX_CR_MIPS_ADDR_REMAP4_CONFIG1,
+	                   sPhyAddr.uiAddr | RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MODE_ENABLE_EN,
+	                   RGX_CR_MIPS_ADDR_REMAP4_CONFIG2,
+	                   RGXMIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR,
+	                   ~RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_ADDR_OUT_CLRMSK,
+	                   ui64RemapSettings);
+
+	/* Garten IDLE bit controlled by MIPS */
+	RGXCommentLogPower(hPrivate, "RGXStart: Set GARTEN_IDLE type to MIPS");
+	RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
+
+	/* Turn on the EJTAG probe (only useful driver live) */
+	RGXWriteReg32(hPrivate, RGX_CR_MIPS_DEBUG_CONFIG, 0);
 }
 
 
-#if !defined(RGX_FEATURE_S7_CACHE_HIERARCHY)
-#define RGX_INIT_SLC _RGXInitSLC
-
 /*!
 *******************************************************************************
 
- @Function      _RGXInitSLC
+ @Function      __RGXInitSLC
 
  @Description   Initialise RGX SLC
 
@@ -353,128 +364,157 @@
  @Return        void
 
 ******************************************************************************/
-static void _RGXInitSLC(const void *hPrivate)
+static void __RGXInitSLC(const void *hPrivate)
 {
-	IMG_UINT32 ui32Reg;
-	IMG_UINT32 ui32RegVal;
-
-#if defined(FIX_HW_BRN_36492)
-	/* Because the WA for this BRN forbids using SLC reset, need to inval it instead */
-	RGXCommentLogPower(hPrivate, "Invalidate the SLC");
-	RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_FLUSH_INVAL, RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_EN);
-
-	/* Poll for completion */
-	RGXPollReg32(hPrivate, RGX_CR_SLC_STATUS0, 0x0, RGX_CR_SLC_STATUS0_MASKFULL);
-#endif
-
-#if (RGX_FEATURE_SLC_SIZE_IN_BYTES < (128*1024))
-	/*
-	 * SLC Bypass control
-	 */
-	ui32Reg = RGX_CR_SLC_CTRL_BYPASS;
-	ui32RegVal = RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_EN;
-
-	/* Bypass SLC for textures if the SLC size is less than 128kB */
-	RGXCommentLogPower(hPrivate, "Bypass SLC for TPU");
-	RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
-#endif
-
-	/*
-	 * SLC Bypass control
-	 */
-	ui32Reg = RGX_CR_SLC_CTRL_MISC;
-	ui32RegVal = RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
-
-	/* Bypass burst combiner if SLC line size is smaller than 1024 bits */
-#if (RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS < 1024)
-	ui32RegVal |= RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;
-#endif
-
-	RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
-}
-
-#else /* RGX_FEATURE_S7_CACHE_HIERARCHY */
-#define RGX_INIT_SLC _RGXInitSLC3
-
-/*!
-*******************************************************************************
-
- @Function      RGXInitSLC3
-
- @Description   Initialise RGX SLC3
-
- @Input         hPrivate  : Implementation specific data
-
- @Return        void
-
-******************************************************************************/
-static void _RGXInitSLC3(const void *hPrivate)
-{
-	IMG_UINT32 ui32Reg;
-	IMG_UINT32 ui32RegVal;
-
-#if defined(HW_ERN_51468)
-	/*
-	 * SLC control
-	 */
-	ui32Reg = RGX_CR_SLC3_CTRL_MISC;
-	ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_WEAVED_HASH;
-	RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
-#else
-	/*
-	 * SLC control
-	 */
-	ui32Reg = RGX_CR_SLC3_CTRL_MISC;
-	ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_SCRAMBLE_PVR_HASH;
-	RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
-
-	/*
-	 * SLC scramble bits
-	 */
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK))
 	{
-		IMG_UINT32 i;
-		IMG_UINT32 aui32ScrambleRegs[] = {
-		    RGX_CR_SLC3_SCRAMBLE,
-		    RGX_CR_SLC3_SCRAMBLE2,
-		    RGX_CR_SLC3_SCRAMBLE3,
-		    RGX_CR_SLC3_SCRAMBLE4
-		};
+		IMG_UINT32 ui32Reg;
+		IMG_UINT32 ui32RegVal;
 
-		IMG_UINT64 aui64ScrambleValues[] = {
-#if (RGX_FEATURE_SLC_BANKS == 2)
-		   IMG_UINT64_C(0x6965a99a55696a6a),
-		   IMG_UINT64_C(0x6aa9aa66959aaa9a),
-		   IMG_UINT64_C(0x9a5665965a99a566),
-		   IMG_UINT64_C(0x5aa69596aa66669a)
-#elif (RGX_FEATURE_SLC_BANKS == 4)
-		   IMG_UINT64_C(0xc6788d722dd29ce4),
-		   IMG_UINT64_C(0x7272e4e11b279372),
-		   IMG_UINT64_C(0x87d872d26c6c4be1),
-		   IMG_UINT64_C(0xe1b4878d4b36e478)
-#elif (RGX_FEATURE_SLC_BANKS == 8)
-		   IMG_UINT64_C(0x859d6569e8fac688),
-		   IMG_UINT64_C(0xf285e1eae4299d33),
-		   IMG_UINT64_C(0x1e1af2be3c0aa447)
-#endif
-		};
-
-		for (i = 0; i < sizeof(aui64ScrambleValues)/sizeof(IMG_UINT64); i++)
+		if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_51468_BIT_MASK))
 		{
-			IMG_UINT32 ui32Reg = aui32ScrambleRegs[i];
-			IMG_UINT64 ui64Value = aui64ScrambleValues[i];
+			/*
+			 * SLC control
+			 */
+			ui32Reg = RGX_CR_SLC3_CTRL_MISC;
+			ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_WEAVED_HASH |
+			             RGX_CR_SLC3_CTRL_MISC_WRITE_COMBINER_EN;
+			RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
+		}
+		else
+		{
+			/*
+			 * SLC control
+			 */
+			ui32Reg = RGX_CR_SLC3_CTRL_MISC;
+			ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_SCRAMBLE_PVR_HASH |
+			             RGX_CR_SLC3_CTRL_MISC_WRITE_COMBINER_EN;
+			RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
 
-			RGXWriteReg64(hPrivate, ui32Reg, ui64Value);
+			/*
+			 * SLC scramble bits
+			 */
+			{
+				IMG_UINT32 i;
+				IMG_UINT32 ui32Count=0;
+				IMG_UINT32 ui32SLCBanks = RGXGetDeviceSLCBanks(hPrivate);
+				IMG_UINT64 aui64ScrambleValues[4];
+				IMG_UINT32 aui32ScrambleRegs[] = {
+					RGX_CR_SLC3_SCRAMBLE,
+					RGX_CR_SLC3_SCRAMBLE2,
+					RGX_CR_SLC3_SCRAMBLE3,
+					RGX_CR_SLC3_SCRAMBLE4
+				};
+
+				if (2 == ui32SLCBanks)
+				{
+					aui64ScrambleValues[0] = IMG_UINT64_C(0x6965a99a55696a6a);
+					aui64ScrambleValues[1] = IMG_UINT64_C(0x6aa9aa66959aaa9a);
+					aui64ScrambleValues[2] = IMG_UINT64_C(0x9a5665965a99a566);
+					aui64ScrambleValues[3] = IMG_UINT64_C(0x5aa69596aa66669a);
+					ui32Count = 4;
+				}
+				else if (4 == ui32SLCBanks)
+				{
+					aui64ScrambleValues[0] = IMG_UINT64_C(0xc6788d722dd29ce4);
+					aui64ScrambleValues[1] = IMG_UINT64_C(0x7272e4e11b279372);
+					aui64ScrambleValues[2] = IMG_UINT64_C(0x87d872d26c6c4be1);
+					aui64ScrambleValues[3] = IMG_UINT64_C(0xe1b4878d4b36e478);
+					ui32Count = 4;
+
+				}
+				else if (8 == ui32SLCBanks)
+				{
+					aui64ScrambleValues[0] = IMG_UINT64_C(0x859d6569e8fac688);
+					aui64ScrambleValues[1] = IMG_UINT64_C(0xf285e1eae4299d33);
+					aui64ScrambleValues[2] = IMG_UINT64_C(0x1e1af2be3c0aa447);
+					ui32Count = 3;
+				}
+
+				for (i = 0; i < ui32Count; i++)
+				{
+					IMG_UINT32 ui32Reg = aui32ScrambleRegs[i];
+					IMG_UINT64 ui64Value = aui64ScrambleValues[i];
+					RGXWriteReg64(hPrivate, ui32Reg, ui64Value);
+				}
+			}
+		}
+
+		if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_45914_BIT_MASK))
+		{
+			/* Disable the forced SLC coherency which the hardware enables for compatibility with older pdumps */
+			RGXCommentLogPower(hPrivate, "Disable forced SLC coherency");
+			RGXWriteReg64(hPrivate, RGX_CR_GARTEN_SLC, 0);
 		}
 	}
+	else
+	{
+		IMG_UINT32 ui32Reg;
+		IMG_UINT32 ui32RegVal;
+
+#if defined(FIX_HW_BRN_36492)
+		/* Because the WA for this BRN forbids using SLC reset, need to inval it instead */
+		RGXCommentLogPower(hPrivate, "Invalidate the SLC");
+		RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_FLUSH_INVAL, RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_EN);
+
+		/* Poll for completion */
+		RGXPollReg32(hPrivate, RGX_CR_SLC_STATUS0, 0x0, RGX_CR_SLC_STATUS0_MASKFULL);
 #endif
 
-#if defined(HW_ERN_45914)
-	/* Disable the forced SLC coherency which the hardware enables for compatibility with older pdumps */
-	RGXCommentLogPower(hPrivate, "RGXStart: disable forced SLC coherency");
-	RGXWriteReg64(hPrivate, RGX_CR_GARTEN_SLC, 0);
+		/*
+		 * SLC Bypass control
+		 */
+		ui32Reg = RGX_CR_SLC_CTRL_BYPASS;
+		ui32RegVal = 0;
+
+		if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SLCSIZE8_BIT_MASK)  ||
+		    RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_61450_BIT_MASK))
+		{
+			RGXCommentLogPower(hPrivate, "Bypass SLC for IPF_OBJ and IPF_CPF");
+			ui32RegVal |= RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_EN | RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_EN;
+		}
+
+		if (RGXGetDeviceSLCSize(hPrivate) < (128*1024))
+		{
+			/* Bypass SLC for textures if the SLC size is less than 128kB */
+			RGXCommentLogPower(hPrivate, "Bypass SLC for TPU");
+			ui32RegVal |= RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_EN;
+		}
+
+		if (ui32RegVal != 0)
+		{
+			RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
+		}
+
+		/*
+		 * SLC Misc control.
+		 *
+		 * Note: This is a 64bit register and we set only the lower 32bits leaving the top
+		 *       32bits (RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS) unchanged from the HW default.
+		 */
+		ui32Reg = RGX_CR_SLC_CTRL_MISC;
+		ui32RegVal = (RGXReadReg32(hPrivate, ui32Reg) & RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN) |		
+		             RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
+		if (RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_60084_BIT_MASK))
+		{
+#if !defined(SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING)
+			ui32RegVal |= RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN;
+#else
+			if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_61389_BIT_MASK))
+			{
+				ui32RegVal |= RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN;
+			}
 #endif
+		}
+		/* Bypass burst combiner if SLC line size is smaller than 1024 bits */
+		if (RGXGetDeviceCacheLineSize(hPrivate) < 1024)
+		{
+			ui32RegVal |= RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;
+		}
+
+		RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
+	}
 }
-#endif /* RGX_FEATURE_S7_CACHE_HIERARCHY */
 
 
 /*!
@@ -491,57 +531,78 @@
 ******************************************************************************/
 static void RGXInitBIF(const void *hPrivate)
 {
-#if !defined(RGX_FEATURE_MIPS)
-	IMG_DEV_PHYADDR sPCAddr;
+	if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		IMG_DEV_PHYADDR sPCAddr;
 
-	/*
-	 * Acquire the address of the Kernel Page Catalogue.
-	 */
-	RGXAcquireKernelMMUPC(hPrivate, &sPCAddr);
+		/*
+		 * Acquire the address of the Kernel Page Catalogue.
+		 */
+		RGXAcquireKernelMMUPC(hPrivate, &sPCAddr);
 
-	/*
-	 * Write the kernel catalogue base.
-	 */
-	RGXCommentLogPower(hPrivate, "RGX firmware MMU Page Catalogue");
+		/*
+		 * Write the kernel catalogue base.
+		 */
+		RGXCommentLogPower(hPrivate, "RGX firmware MMU Page Catalogue");
 
-#if !defined(RGX_FEATURE_SLC_VIVT)
-	/* Write the cat-base address */
-	RGXWriteKernelMMUPC64(hPrivate,
-	                      RGX_CR_BIF_CAT_BASE0,
-	                      RGX_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT,
-	                      RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT,
-	                      ((sPCAddr.uiAddr
-	                      >> RGX_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT)
-	                      << RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT)
-	                      & ~RGX_CR_BIF_CAT_BASE0_ADDR_CLRMSK);
-#else
-	/* Set the mapping context */
-	RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, 0);
-
-	/* Write the cat-base address */
-	RGXWriteKernelMMUPC32(hPrivate,
-	                      RGX_CR_MMU_CBASE_MAPPING,
-	                      RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
-	                      RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
-	                      (IMG_UINT32)(((sPCAddr.uiAddr
-	                      >> RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT)
-	                      << RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT)
-	                      & ~RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_CLRMSK));
-#endif /* RGX_FEATURE_SLC_VIVT */
-
-	/*
-	 * Trusted META boot
-	 */
+		if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SLC_VIVT_BIT_MASK))
+		{
+			/* Write the cat-base address */
+			RGXWriteKernelMMUPC64(hPrivate,
+			                      RGX_CR_BIF_CAT_BASE0,
+			                      RGX_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT,
+			                      RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT,
+			                      ((sPCAddr.uiAddr
+			                      >> RGX_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT)
+			                      << RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT)
+			                      & ~RGX_CR_BIF_CAT_BASE0_ADDR_CLRMSK);
+			/*
+			 * Trusted Firmware boot
+			 */
 #if defined(SUPPORT_TRUSTED_DEVICE)
-	RGXCommentLogPower(hPrivate, "RGXInitBIF: Trusted Device enabled");
-	RGXWriteReg32(hPrivate, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN);
+			RGXCommentLogPower(hPrivate, "RGXInitBIF: Trusted Device enabled");
+			RGXWriteReg32(hPrivate, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN);
 #endif
+		}
+		else
+		{
+			IMG_UINT32 uiPCAddr;
+			uiPCAddr = (((sPCAddr.uiAddr >> RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT)
+			             << RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT)
+			            & ~RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_CLRMSK);
+			/* Set the mapping context */
+			RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, 0);
 
-#endif /* RGX_FEATURE_MIPS */
+			/* Write the cat-base address */
+			RGXWriteKernelMMUPC32(hPrivate,
+			                      RGX_CR_MMU_CBASE_MAPPING,
+			                      RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
+			                      RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
+			                      uiPCAddr);
+#if defined(SUPPORT_TRUSTED_DEVICE)
+			/* Set-up MMU ID 1 mapping to the same PC used by MMU ID 0 */
+			RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, 1);
+			RGXWriteKernelMMUPC32(hPrivate,
+			                      RGX_CR_MMU_CBASE_MAPPING,
+			                      RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
+			                      RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
+			                      uiPCAddr);
+#endif /* SUPPORT_TRUSTED_DEVICE */
+		}
+	}
+	else
+	{
+		/*
+		 * Trusted Firmware boot
+		 */
+#if defined(SUPPORT_TRUSTED_DEVICE)
+		RGXCommentLogPower(hPrivate, "RGXInitBIF: Trusted Device enabled");
+		RGXWriteReg32(hPrivate, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN);
+#endif
+	}
 }
 
 
-#if defined(RGX_FEATURE_AXI_ACELITE)
 /*!
 *******************************************************************************
 
@@ -567,22 +628,56 @@
 	             (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_CACHE_MAINTENANCE_SHIFT)  |
 	             (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_COHERENT_SHIFT) |
 	             (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_COHERENT_SHIFT) |
-#if defined(FIX_HW_BRN_42321)
-	             (((IMG_UINT64) 1) << RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT) |
-#endif
 	             (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_COHERENT_SHIFT) |
 	             (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_SHIFT) |
 	             (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_SHIFT);
 
+	if (RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_42321_BIT_MASK))
+	{
+		ui64RegVal |= (((IMG_UINT64) 1) << RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT);
+	}
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SLC_VIVT_BIT_MASK))
+	{
+		RGXCommentLogPower(hPrivate, "OSID 0 and 1 are trusted");
+		ui64RegVal |= IMG_UINT64_C(0xFC)
+	              << RGX_CR_AXI_ACE_LITE_CONFIGURATION_OSID_SECURITY_SHIFT;
+	}
+#endif
+
 	RGXCommentLogPower(hPrivate, "Init AXI-ACE interface");
 	RGXWriteReg64(hPrivate, ui32RegAddr, ui64RegVal);
 }
-#endif
 
 
 PVRSRV_ERROR RGXStart(const void *hPrivate)
 {
 	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_BOOL bDoFWSlaveBoot;
+	IMG_CHAR *pcRGXFW_PROCESSOR;
+	IMG_BOOL bMetaFW;
+
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_MIPS_BIT_MASK))
+	{
+		pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
+		bMetaFW = IMG_FALSE;
+		bDoFWSlaveBoot = IMG_FALSE;
+	}
+	else
+	{
+		pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
+		bMetaFW = IMG_TRUE;
+		bDoFWSlaveBoot = RGXDoFWSlaveBoot(hPrivate);
+	}
+
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SYS_BUS_SECURE_RESET_BIT_MASK))
+	{
+		/* Disable the default sys_bus_secure protection to perform minimal setup */
+		RGXCommentLogPower(hPrivate, "RGXStart: Disable sys_bus_secure");
+		RGXWriteReg32(hPrivate, RGX_CR_SYS_BUS_SECURE, 0);
+		(void) RGXReadReg32(hPrivate, RGX_CR_SYS_BUS_SECURE); /* Fence write */
+	}
 
 #if defined(FIX_HW_BRN_37453)
 	/* Force all clocks on*/
@@ -601,45 +696,49 @@
 #define RGX_CR_SOFT_RESET_ALL  (RGX_CR_SOFT_RESET_MASKFULL)
 #endif
 
-#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	/* Set RGX in soft-reset */
-	RGXCommentLogPower(hPrivate, "RGXStart: soft reset assert step 1");
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS);
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		/* Set RGX in soft-reset */
+		RGXCommentLogPower(hPrivate, "RGXStart: soft reset assert step 1");
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS);
 
-	RGXCommentLogPower(hPrivate, "RGXStart: soft reset assert step 2");
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_JONES_ALL | RGX_S7_SOFT_RESET_DUSTS);
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET2, RGX_S7_SOFT_RESET2);
+		RGXCommentLogPower(hPrivate, "RGXStart: soft reset assert step 2");
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_JONES_ALL | RGX_S7_SOFT_RESET_DUSTS);
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET2, RGX_S7_SOFT_RESET2);
 
-	/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
-	(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+		/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+		(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
 
-	/* Take everything out of reset but META/MIPS */
-	RGXCommentLogPower(hPrivate, "RGXStart: soft reset de-assert step 1 excluding %s", RGXFW_PROCESSOR);
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS | RGX_CR_SOFT_RESET_GARTEN_EN);
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET2, 0x0);
+		/* Take everything out of reset but META/MIPS */
+		RGXCommentLogPower(hPrivate, "RGXStart: soft reset de-assert step 1 excluding %s", pcRGXFW_PROCESSOR);
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS | RGX_CR_SOFT_RESET_GARTEN_EN);
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET2, 0x0);
 
-	(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+		(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
 
-	RGXCommentLogPower(hPrivate, "RGXStart: soft reset de-assert step 2 excluding %s", RGXFW_PROCESSOR);
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
+		RGXCommentLogPower(hPrivate, "RGXStart: soft reset de-assert step 2 excluding %s", pcRGXFW_PROCESSOR);
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
 
-	(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
-#else
-	/* Set RGX in soft-reset */
-	RGXCommentLogPower(hPrivate, "RGXStart: soft reset everything");
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL);
+		(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+	}
+	else
+	{
+		/* Set RGX in soft-reset */
+		RGXCommentLogPower(hPrivate, "RGXStart: soft reset everything");
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL);
 
-	/* Take Rascal and Dust out of reset */
-	RGXCommentLogPower(hPrivate, "RGXStart: Rascal and Dust out of reset");
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL ^ RGX_CR_SOFT_RESET_RASCALDUSTS_EN);
+		/* Take Rascal and Dust out of reset */
+		RGXCommentLogPower(hPrivate, "RGXStart: Rascal and Dust out of reset");
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL ^ RGX_CR_SOFT_RESET_RASCALDUSTS_EN);
 
-	/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
-	(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+		/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+		(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
 
-	/* Take everything out of reset but META/MIPS */
-	RGXCommentLogPower(hPrivate, "RGXStart: Take everything out of reset but %s", RGXFW_PROCESSOR);
-	RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
-#endif
+		/* Take everything out of reset but META/MIPS */
+		RGXCommentLogPower(hPrivate, "RGXStart: Take everything out of reset but %s", pcRGXFW_PROCESSOR);
+		RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
+	}
+
 
 #if !defined(FIX_HW_BRN_37453)
 	/* Enable clocks */
@@ -650,29 +749,50 @@
 	 * Initialise SLC.
 	 */
 #if !defined(SUPPORT_SHARED_SLC)
-	RGX_INIT_SLC(hPrivate);
+	__RGXInitSLC(hPrivate);
 #endif
 
-#if defined(RGX_FEATURE_META)
-	/* Configure META to Master boot */
-	RGXCommentLogPower(hPrivate, "RGXStart: META Master boot");
-	RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN);
-#endif
+	if (bMetaFW)
+	{
+		if (bDoFWSlaveBoot)
+		{
+			/* Configure META to Slave boot */
+			RGXCommentLogPower(hPrivate, "RGXStart: META Slave boot");
+			RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, 0);
 
-	/* Initialises META/MIPS wrapper */
-	RGXInitFWProcWrapper(hPrivate);
+		}
+		else
+		{
+			/* Configure META to Master boot */
+			RGXCommentLogPower(hPrivate, "RGXStart: META Master boot");
+			RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN);
+		}
+	}
 
-#if defined(RGX_FEATURE_AXI_ACELITE)
-	/* We must init the AXI-ACE interface before 1st BIF transaction */
-	RGXAXIACELiteInit(hPrivate);
-#endif
+	/*
+	 * Initialise Firmware wrapper
+	 */
+	if (bMetaFW)
+	{
+		RGXInitMetaProcWrapper(hPrivate);
+	}
+	else
+	{
+		RGXInitMipsProcWrapper(hPrivate);
+	}
+
+	if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_AXI_ACELITE_BIT_MASK))
+	{
+		/* We must init the AXI-ACE interface before 1st BIF transaction */
+		RGXAXIACELiteInit(hPrivate);
+	}
 
 	/*
 	 * Initialise BIF.
 	 */
 	RGXInitBIF(hPrivate);
 
-	RGXCommentLogPower(hPrivate, "RGXStart: Take %s out of reset", RGXFW_PROCESSOR);
+	RGXCommentLogPower(hPrivate, "RGXStart: Take %s out of reset", pcRGXFW_PROCESSOR);
 
 	/* Need to wait for at least 16 cycles before taking META/MIPS out of reset ... */
 	RGXWaitCycles(hPrivate, 32, 3);
@@ -691,49 +811,95 @@
 	RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_AUTO);
 #endif
 
-	RGXCommentLogPower(hPrivate, "RGXStart: RGX Firmware Master boot Start");
+	if (bMetaFW && bDoFWSlaveBoot)
+	{
+		eError = RGXIOCoherencyTest(hPrivate);
+		if (eError != PVRSRV_OK) return eError;
+
+		RGXCommentLogPower(hPrivate, "RGXStart: RGX Firmware Slave boot Start");
+		eError = RGXStartFirmware(hPrivate);
+		if (eError != PVRSRV_OK) return eError;
+	}
+	else
+	{
+		RGXCommentLogPower(hPrivate, "RGXStart: RGX Firmware Master boot Start");
+	}
 
 	/* Enable Sys Bus security */
 #if defined(SUPPORT_TRUSTED_DEVICE)
+	RGXCommentLogPower(hPrivate, "RGXStart: Enable sys_bus_secure");
 	RGXWriteReg32(hPrivate, RGX_CR_SYS_BUS_SECURE, RGX_CR_SYS_BUS_SECURE_ENABLE_EN);
+	(void) RGXReadReg32(hPrivate, RGX_CR_SYS_BUS_SECURE); /* Fence write */
 #endif
 
 	return eError;
 }
 
+static INLINE void ClearIRQStatusRegister(const void *hPrivate, IMG_BOOL bMetaFW)
+{
+	IMG_UINT32 ui32IRQClearReg;
+	IMG_UINT32 ui32IRQClearMask;
+
+	if(bMetaFW)
+	{
+		ui32IRQClearReg = RGX_CR_META_SP_MSLVIRQSTATUS;
+		ui32IRQClearMask = RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK;
+	}
+	else
+	{
+		ui32IRQClearReg = RGX_CR_MIPS_WRAPPER_IRQ_CLEAR;
+		ui32IRQClearMask = RGX_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN;
+	}
+
+	RGXWriteReg32(hPrivate, ui32IRQClearReg, ui32IRQClearMask);
+
+#if defined(RGX_FEATURE_OCPBUS)
+	RGXWriteReg32(hPrivate, RGX_CR_OCP_IRQSTATUS_2, RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN);
+#endif
+}
 
 PVRSRV_ERROR RGXStop(const void *hPrivate)
 {
+	IMG_BOOL bMetaFW = !RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_MIPS_BIT_MASK);
 	PVRSRV_ERROR eError;
 
+	ClearIRQStatusRegister(hPrivate, bMetaFW);
+
 	/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SIDEKICK_IDLE,
-	                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
-	                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
-#else
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_JONES_IDLE,
-	                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
-	                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
-#endif
+	if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SIDEKICK_IDLE,
+		                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
+		                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
+	}
+	else
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_JONES_IDLE,
+		                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
+		                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
+	}
+
 	if (eError != PVRSRV_OK) return eError;
 
 
 #if !defined(SUPPORT_SHARED_SLC)
 	/* Wait for SLC to signal IDLE */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SLC_IDLE,
-	                      RGX_CR_SLC_IDLE_MASKFULL,
-	                      RGX_CR_SLC_IDLE_MASKFULL);
-#else
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SLC3_IDLE,
-	                      RGX_CR_SLC3_IDLE_MASKFULL,
-	                      RGX_CR_SLC3_IDLE_MASKFULL);
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+	if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SLC_IDLE,
+		                      RGX_CR_SLC_IDLE_MASKFULL,
+		                      RGX_CR_SLC_IDLE_MASKFULL);
+	}
+	else
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SLC3_IDLE,
+		                      RGX_CR_SLC3_IDLE_MASKFULL,
+		                      RGX_CR_SLC3_IDLE_MASKFULL);
+	}
 #endif /* SUPPORT_SHARED_SLC */
 	if (eError != PVRSRV_OK) return eError;
 
@@ -757,33 +923,36 @@
 	              & RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL);
 
 
-#if defined(RGX_FEATURE_META) && defined(PDUMP)
-	/* Disabling threads is only required for pdumps to stop the fw gracefully */
+#if defined(PDUMP)
+	if (bMetaFW)
+	{
+		/* Disabling threads is only required for pdumps to stop the fw gracefully */
 
-	/* Disable thread 0 */
-	eError = RGXWriteMetaRegThroughSP(hPrivate,
-	                                  META_CR_T0ENABLE_OFFSET,
-	                                  ~META_CR_TXENABLE_ENABLE_BIT);
-	if (eError != PVRSRV_OK) return eError;
+		/* Disable thread 0 */
+		eError = RGXWriteMetaRegThroughSP(hPrivate,
+		                                  META_CR_T0ENABLE_OFFSET,
+		                                  ~META_CR_TXENABLE_ENABLE_BIT);
+		if (eError != PVRSRV_OK) return eError;
 
-	/* Disable thread 1 */
-	eError = RGXWriteMetaRegThroughSP(hPrivate,
-	                                  META_CR_T1ENABLE_OFFSET,
-	                                  ~META_CR_TXENABLE_ENABLE_BIT);
-	if (eError != PVRSRV_OK) return eError;
+		/* Disable thread 1 */
+		eError = RGXWriteMetaRegThroughSP(hPrivate,
+		                                  META_CR_T1ENABLE_OFFSET,
+		                                  ~META_CR_TXENABLE_ENABLE_BIT);
+		if (eError != PVRSRV_OK) return eError;
 
-	/* Clear down any irq raised by META (done after disabling the FW
-	 * threads to avoid a race condition).
-	 * This is only really needed for PDumps but we do it anyway driver-live.
-	 */
-	RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS, 0x0);
+		/* Clear down any irq raised by META (done after disabling the FW
+		 * threads to avoid a race condition).
+		 * This is only really needed for PDumps but we do it anyway driver-live.
+		 */
+		RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS, 0x0);
 
-	/* Wait for the Slave Port to finish all the transactions */
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_META_SP_MSLVCTRL1,
-	                      RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-	                      RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
-	if (eError != PVRSRV_OK) return eError;
+		/* Wait for the Slave Port to finish all the transactions */
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_META_SP_MSLVCTRL1,
+		                      RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+		                      RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
+		if (eError != PVRSRV_OK) return eError;
+	}
 #endif
 
 
@@ -800,13 +969,16 @@
 	                      RGX_CR_BIFPM_STATUS_MMU_MASKFULL);
 	if (eError != PVRSRV_OK) return eError;
 
-#if !defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE) && !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_BIF_READS_EXT_STATUS,
-	                      0,
-	                      RGX_CR_BIF_READS_EXT_STATUS_MASKFULL);
-	if (eError != PVRSRV_OK) return eError;
-#endif
+	if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK) &&
+	    !RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_BIF_READS_EXT_STATUS,
+		                      0,
+		                      RGX_CR_BIF_READS_EXT_STATUS_MASKFULL);
+		if (eError != PVRSRV_OK) return eError;
+	}
+
 
 	eError = RGXPollReg32(hPrivate,
 	                      RGX_CR_BIFPM_READS_EXT_STATUS,
@@ -814,56 +986,67 @@
 	                      RGX_CR_BIFPM_READS_EXT_STATUS_MASKFULL);
 	if (eError != PVRSRV_OK) return eError;
 
-	eError = RGXPollReg64(hPrivate,
-	                      RGX_CR_SLC_STATUS1,
-	                      0,
-#if defined(FIX_HW_BRN_43276)
-	                      RGX_CR_SLC_STATUS1_MASKFULL & RGX_CR_SLC_STATUS1_READS1_EXT_CLRMSK & RGX_CR_SLC_STATUS1_READS0_EXT_CLRMSK);
-#else
-	                      RGX_CR_SLC_STATUS1_MASKFULL);
-#endif
-	if (eError != PVRSRV_OK) return eError;
+	{
+		IMG_UINT64 ui64SLCMask = RGX_CR_SLC_STATUS1_MASKFULL;
+		eError = RGXPollReg64(hPrivate,
+		                      RGX_CR_SLC_STATUS1,
+		                      0,
+		                      ui64SLCMask);
+		if (eError != PVRSRV_OK) return eError;
+	}
 
-	eError = RGXPollReg64(hPrivate,
-	                      RGX_CR_SLC_STATUS2,
-	                      0,
-	                      RGX_CR_SLC_STATUS2_MASKFULL);
-	if (eError != PVRSRV_OK) return eError;
-
+	if (4 == RGXGetDeviceSLCBanks(hPrivate))
+	{
+		eError = RGXPollReg64(hPrivate,
+		                      RGX_CR_SLC_STATUS2,
+		                      0,
+		                      RGX_CR_SLC_STATUS2_MASKFULL);
+		if (eError != PVRSRV_OK) return eError;
+	}
 
 #if !defined(SUPPORT_SHARED_SLC)
 	/* Wait for SLC to signal IDLE */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SLC_IDLE,
-	                      RGX_CR_SLC_IDLE_MASKFULL,
-	                      RGX_CR_SLC_IDLE_MASKFULL);
-#else
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SLC3_IDLE,
-	                      RGX_CR_SLC3_IDLE_MASKFULL,
-	                      RGX_CR_SLC3_IDLE_MASKFULL);
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+	if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SLC_IDLE,
+		                      RGX_CR_SLC_IDLE_MASKFULL,
+		                      RGX_CR_SLC_IDLE_MASKFULL);
+	}
+	else
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SLC3_IDLE,
+		                      RGX_CR_SLC3_IDLE_MASKFULL,
+		                      RGX_CR_SLC3_IDLE_MASKFULL);
+	}
 #endif /* SUPPORT_SHARED_SLC */
 	if (eError != PVRSRV_OK) return eError;
 
 
 	/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SIDEKICK_IDLE,
-	                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
-	                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
-#else
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_JONES_IDLE,
-	                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
-	                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
-#endif
+	if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SIDEKICK_IDLE,
+		                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
+		                      RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
+	}
+	else
+	{
+		if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
+		{
+			eError = RGXPollReg32(hPrivate,
+			                      RGX_CR_JONES_IDLE,
+			                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
+			                      RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
+		}
+	}
+
 	if (eError != PVRSRV_OK) return eError;
 
 
-#if defined(RGX_FEATURE_META)
+	if (bMetaFW)
 	{
 		IMG_UINT32 ui32RegValue;
 
@@ -877,28 +1060,32 @@
 			/* Wait for Sidekick/Jones to signal IDLE including
 			 * the Garten Wrapper if there is no debugger attached
 			 * (TxVECINT_BHALT = 0x0) */
-#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
-			eError = RGXPollReg32(hPrivate,
-			                      RGX_CR_SIDEKICK_IDLE,
-			                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
-			                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
-			if (eError != PVRSRV_OK) return eError;
-#else
-			eError = RGXPollReg32(hPrivate,
-			                      RGX_CR_JONES_IDLE,
-			                      RGX_CR_JONES_IDLE_GARTEN_EN,
-			                      RGX_CR_JONES_IDLE_GARTEN_EN);
-			if (eError != PVRSRV_OK) return eError;
-#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+			if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
+			{
+				eError = RGXPollReg32(hPrivate,
+				                      RGX_CR_SIDEKICK_IDLE,
+				                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
+				                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
+				if (eError != PVRSRV_OK) return eError;
+			}
+			else
+			{
+				eError = RGXPollReg32(hPrivate,
+				                      RGX_CR_JONES_IDLE,
+				                      RGX_CR_JONES_IDLE_GARTEN_EN,
+				                      RGX_CR_JONES_IDLE_GARTEN_EN);
+				if (eError != PVRSRV_OK) return eError;
+			}
 		}
 	}
-#else /* defined(RGX_FEATURE_META) */
-	eError = RGXPollReg32(hPrivate,
-	                      RGX_CR_SIDEKICK_IDLE,
-	                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
-	                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
-	if (eError != PVRSRV_OK) return eError;
-#endif /* RGX_FEATURE_META */
+	else
+	{
+		eError = RGXPollReg32(hPrivate,
+		                      RGX_CR_SIDEKICK_IDLE,
+		                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
+		                      RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
+		if (eError != PVRSRV_OK) return eError;
+	}
 
 	return eError;
 }
@@ -933,7 +1120,7 @@
 	RGXWriteReg64(pvPowerParams, RGX_CR_SOFT_RESET, 0x0);
 #endif
 
-	RGX_INIT_SLC(pvPowerParams);
+	__RGXInitSLC(pvPowerParams);
 
 	return PVRSRV_OK;
 }
diff --git a/drivers/staging/imgtec/rogue/rgxstartstop.h b/drivers/staging/imgtec/rogue/rgxstartstop.h
index 85d79d9..3b4e785 100644
--- a/drivers/staging/imgtec/rogue/rgxstartstop.h
+++ b/drivers/staging/imgtec/rogue/rgxstartstop.h
@@ -46,8 +46,10 @@
 
 /* The routines declared here are built on top of an abstraction layer to
  * hide DDK/OS-specific details in case they are used outside of the DDK
- * (e.g. when trusted device is enabled).
- * Any new dependency should be added to rgxlayer_km.h. */
+ * (e.g. when DRM security is enabled).
+ * Any new dependency should be added to rgxlayer_km.h.
+ * Any new code should be built on top of the existing abstraction layer,
+ * which should be extended when necessary. */
 #include "rgxlayer_km.h"
 
 /*!
@@ -79,3 +81,4 @@
 PVRSRV_ERROR RGXStop(const void *hPrivate);
 
 #endif /* __RGXSTARTSTOP_H__ */
+
diff --git a/drivers/staging/imgtec/rogue/rgxsync.c b/drivers/staging/imgtec/rogue/rgxsync.c
deleted file mode 100644
index d7a0fed..0000000
--- a/drivers/staging/imgtec/rogue/rgxsync.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX sync kick routines
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX sync kick routines
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include "srvkm.h"
-#include "pdump_km.h"
-#include "pvr_debug.h"
-#include "rgxutils.h"
-#include "rgxfwutils.h"
-#include "rgxmem.h"
-#include "allocmem.h"
-#include "devicemem.h"
-#include "devicemem_pdump.h"
-#include "osfunc.h"
-#include "rgxccb.h"
-
-#include "sync_server.h"
-#include "sync_internal.h"
-
-#include "rgxsync.h"
-
-PVRSRV_ERROR RGXKickSyncKM(PVRSRV_DEVICE_NODE        *psDeviceNode,
-                           RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
-						   RGXFWIF_DM                eDM,
-						   IMG_CHAR                  *pszCommandName,
-                           IMG_UINT32                ui32ClientFenceCount,
-                           PRGXFWIF_UFO_ADDR         *pauiClientFenceUFOAddress,
-                           IMG_UINT32                *paui32ClientFenceValue,
-                           IMG_UINT32                ui32ClientUpdateCount,
-                           PRGXFWIF_UFO_ADDR         *pauiClientUpdateUFOAddress,
-                           IMG_UINT32                *paui32ClientUpdateValue,
-                           IMG_UINT32                ui32ServerSyncPrims,
-                           IMG_UINT32                *paui32ServerSyncFlags,
-                           SERVER_SYNC_PRIMITIVE     **pasServerSyncs,
-                           IMG_BOOL                  bPDumpContinuous,
-                           IMG_UINT32                ui32ExtJobRef,
-                           IMG_UINT32                ui32JobId)
-{
-	RGXFWIF_KCCB_CMD		sCmpKCCBCmd;
-	RGX_CCB_CMD_HELPER_DATA	asCmdHelperData[1];
-	PVRSRV_ERROR			eError;
-	PVRSRV_ERROR			eError2;
-	IMG_UINT32				i;
-
-	/* Sanity check the server fences */
-	for (i=0;i<ui32ServerSyncPrims;i++)
-	{
-		if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
-		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on %s) must fence", __FUNCTION__, pszCommandName));
-			return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
-		}
-	}
-
-	eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psServerCommonContext),
-									  ui32ClientFenceCount,
-									  pauiClientFenceUFOAddress,
-									  paui32ClientFenceValue,
-									  ui32ClientUpdateCount,
-									  pauiClientUpdateUFOAddress,
-									  paui32ClientUpdateValue,
-									  ui32ServerSyncPrims,
-									  paui32ServerSyncFlags,
-									  pasServerSyncs,
-									  0,         /* ui32CmdSize */
-									  NULL,  /* pui8DMCmd */
-									  NULL,  /* ppPreAddr */
-									  NULL,  /* ppPostAddr */
-									  NULL,  /* ppRMWUFOAddr */
-									  RGXFWIF_CCB_CMD_TYPE_NULL,
-									  ui32ExtJobRef,
-									  ui32JobId,
-									  bPDumpContinuous,
-									  pszCommandName,
-									  asCmdHelperData);
-	if (eError != PVRSRV_OK)
-	{
-		goto fail_cmdinit;
-	}
-
-	eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asCmdHelperData),
-	                                   asCmdHelperData);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire space for client CCB command", __FUNCTION__));
-		goto fail_cmdaquire;
-	}
-
-
-	/*
-		We should reserved space in the kernel CCB here and fill in the command
-		directly.
-		This is so if there isn't space in the kernel CCB we can return with
-		retry back to services client before we take any operations
-	*/
-
-	/*
-		We might only be kicking for flush out a padding packet so only submit
-		the command if the create was successful
-	*/
-	if (eError == PVRSRV_OK)
-	{
-		/*
-			All the required resources are ready at this point, we can't fail so
-			take the required server sync operations and commit all the resources
-		*/
-		RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, pszCommandName, FWCommonContextGetFWAddress(psServerCommonContext).ui32Addr);
-	}
-
-	/* Construct the kernel compute CCB command. */
-	sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
-	sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psServerCommonContext);
-	sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psServerCommonContext));
-	sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
-
-	/*
-	 * Submit the compute command to the firmware.
-	 */
-	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
-	{
-		eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
-									eDM,
-									&sCmpKCCBCmd,
-									sizeof(sCmpKCCBCmd),
-									bPDumpContinuous);
-		if (eError2 != PVRSRV_ERROR_RETRY)
-		{
-			break;
-		}
-		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-	} END_LOOP_UNTIL_TIMEOUT();
-	
-	if (eError2 != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s failed to schedule kernel CCB command. (0x%x)", __FUNCTION__, eError));
-	}
-	/*
-	 * Now check eError (which may have returned an error from our earlier call
-	 * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
-	 * so we check it now...
-	 */
-	if (eError != PVRSRV_OK )
-	{
-		goto fail_cmdaquire;
-	}
-
-	return PVRSRV_OK;
-
-fail_cmdaquire:
-fail_cmdinit:
-
-	return eError;
-}
-
-/******************************************************************************
- End of file (rgxsync.c)
-******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxsync.h b/drivers/staging/imgtec/rogue/rgxsync.h
deleted file mode 100644
index 7a10239..0000000
--- a/drivers/staging/imgtec/rogue/rgxsync.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          RGX sync kick functionality
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Header for the RGX sync kick functionality
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#if !defined(__RGXSYNC__)
-#define __RGXSYNC_H__
-
-#include "devicemem.h"
-#include "device.h"
-#include "rgxfwutils.h"
-#include "rgx_fwif_resetframework.h"
-#include "rgxdebug.h"
-
-#include "sync_server.h"
-#include "sync_internal.h"
-#include "connection_server.h"
-
-/*!
-*******************************************************************************
- @Function	RGXKickSyncKM
-
- @Description Send a sync kick command to the FW
-	
- @Return   PVRSRV_ERROR
-******************************************************************************/
-PVRSRV_ERROR RGXKickSyncKM(PVRSRV_DEVICE_NODE        *psDeviceNode,
-						   RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
-						   RGXFWIF_DM                eDM,
-						   IMG_CHAR                  *pszCommandName,
-						   IMG_UINT32                ui32ClientFenceCount,
-						   PRGXFWIF_UFO_ADDR         *pauiClientFenceUFOAddress,
-						   IMG_UINT32                *paui32ClientFenceValue,
-						   IMG_UINT32                ui32ClientUpdateCount,
-						   PRGXFWIF_UFO_ADDR         *pauiClientUpdateUFOAddress,
-						   IMG_UINT32                *paui32ClientUpdateValue,
-						   IMG_UINT32                ui32ServerSyncPrims,
-						   IMG_UINT32                *paui32ServerSyncFlags,
-						   SERVER_SYNC_PRIMITIVE     **pasServerSyncs,
-						   IMG_BOOL                  bPDumpContinuous,
-						   IMG_UINT32                ui32ExtJobRef,
-						   IMG_UINT32                ui32JobId);
-
-#endif /* __RGXSYNC_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxta3d.c b/drivers/staging/imgtec/rogue/rgxta3d.c
index eb81721..6ff9192 100644
--- a/drivers/staging/imgtec/rogue/rgxta3d.c
+++ b/drivers/staging/imgtec/rogue/rgxta3d.c
@@ -52,13 +52,13 @@
 #include "allocmem.h"
 #include "devicemem.h"
 #include "devicemem_pdump.h"
+#include "ri_server.h"
 #include "osfunc.h"
 #include "pvrsrv.h"
 #include "rgx_memallocflags.h"
 #include "rgxccb.h"
 #include "rgxhwperf.h"
 #include "rgxtimerquery.h"
-#include "rgxsync.h"
 #include "htbuffer.h"
 
 #include "rgxdefs_km.h"
@@ -66,6 +66,7 @@
 #include "physmem.h"
 #include "sync_server.h"
 #include "sync_internal.h"
+#include "sync.h"
 #include "process_stats.h"
 
 #if defined(SUPPORT_BUFFER_SYNC)
@@ -76,6 +77,17 @@
 #include "pvr_sync.h"
 #endif
 
+#if defined(SUPPORT_PDVFS)
+#include "rgxpdvfs.h"
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "hash.h"
+#include "rgxworkest.h"
+
+#define HASH_CLEAN_LIMIT 6
+#endif
+
 typedef struct _DEVMEM_REF_LOOKUP_
 {
 	IMG_UINT32 ui32ZSBufferID;
@@ -111,14 +123,18 @@
 #define RC_CLEANUP_3D_COMPLETE		(1 << 1)
 	PVRSRV_CLIENT_SYNC_PRIM		*psCleanupSync;
 	DLLIST_NODE					sListNode;
-	SYNC_ADDR_LIST			sSyncAddrListTAFence;
-	SYNC_ADDR_LIST			sSyncAddrListTAUpdate;
-	SYNC_ADDR_LIST			sSyncAddrList3DFence;
-	SYNC_ADDR_LIST			sSyncAddrList3DUpdate;
-	ATOMIC_T				hJobId;
+	SYNC_ADDR_LIST				sSyncAddrListTAFence;
+	SYNC_ADDR_LIST				sSyncAddrListTAUpdate;
+	SYNC_ADDR_LIST				sSyncAddrList3DFence;
+	SYNC_ADDR_LIST				sSyncAddrList3DUpdate;
+	ATOMIC_T					hJobId;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	WORKEST_HOST_DATA			sWorkEstData;
+#endif
 };
 
 
+#if ! defined(NO_HARDWARE)
 static
 #ifdef __GNUC__
 	__attribute__((noreturn))
@@ -134,6 +150,7 @@
 	}
 #endif
 }
+#endif
 
 
 /*
@@ -151,7 +168,8 @@
 	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
 											  psTAData->psServerCommonContext,
 											  psCleanupSync,
-											  RGXFWIF_DM_TA);
+											  RGXFWIF_DM_TA,
+											  PDUMP_FLAGS_NONE);
 	if (eError == PVRSRV_ERROR_RETRY)
 	{
 		return eError;
@@ -185,7 +203,7 @@
 	}
 #endif
 	FWCommonContextFree(psTAData->psServerCommonContext);
-	DevmemFwFree(psTAData->psContextStateMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, psTAData->psContextStateMemDesc);
 	psTAData->psServerCommonContext = NULL;
 	return PVRSRV_OK;
 }
@@ -201,7 +219,8 @@
 	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
 											  ps3DData->psServerCommonContext,
 											  psCleanupSync,
-											  RGXFWIF_DM_3D);
+											  RGXFWIF_DM_3D,
+											  PDUMP_FLAGS_NONE);
 	if (eError == PVRSRV_ERROR_RETRY)
 	{
 		return eError;
@@ -236,7 +255,7 @@
 #endif
 
 	FWCommonContextFree(ps3DData->psServerCommonContext);
-	DevmemFwFree(ps3DData->psContextStateMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, ps3DData->psContextStateMemDesc);
 	ps3DData->psServerCommonContext = NULL;
 	return PVRSRV_OK;
 }
@@ -303,7 +322,8 @@
 									RGXFWIF_DM_GP,
 									&sGPCCBCmd,
 									sizeof(sGPCCBCmd),
-									IMG_TRUE);
+									0,
+									PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_ERROR_RETRY)
 		{
 			break;
@@ -391,7 +411,7 @@
 											ui32Entry,
 											ui32Entry2,
 											psFreeList->ui32CurrentFLPages));
-				bFreelistBad = IMG_FALSE;
+				bFreelistBad = IMG_TRUE;
 			}
     	}
     }
@@ -428,6 +448,7 @@
 	IMG_DEVMEM_SIZE_T uiLength;
 	IMG_DEVMEM_SIZE_T uistartPage;
 	PVRSRV_ERROR eError;
+	const IMG_CHAR * pszAllocName = "Free List";
 
 	/* Are we allowed to grow ? */
 	if ((psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) < ui32NumPages)
@@ -472,6 +493,8 @@
 									&ui32MappingTable,
 									RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
 									PVRSRV_MEMALLOCFLAG_GPU_READABLE,
+									OSStringLength(pszAllocName) + 1,
+									pszAllocName,
 									&psPMRNode->psPMR);
 	if(eError != PVRSRV_OK)
 	{
@@ -499,6 +522,40 @@
 	uistartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
 	uiOffset = psFreeList->uiFreeListPMROffset + (uistartPage * sizeof(IMG_UINT32));
 
+#if defined(PVR_RI_DEBUG)
+
+	eError = RIWritePMREntryKM(psPMRNode->psPMR,
+	                           OSStringNLength(pszAllocName, RI_MAX_TEXT_LEN),
+	                           pszAllocName,
+	                           uiSize);
+	if( eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: call to RIWritePMREntryKM failed (eError=%d)",
+				__func__,
+				eError));
+	}
+
+	 /* Attach RI information */
+	eError = RIWriteMEMDESCEntryKM(psPMRNode->psPMR,
+	                               OSStringNLength(pszAllocName, RI_MAX_TEXT_LEN),
+	                               pszAllocName,
+	                               0,
+	                               uiSize,
+	                               uiSize,
+	                               IMG_FALSE,
+	                               IMG_FALSE,
+	                               &psPMRNode->hRIHandle);
+	if( eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"%s: call to RIWriteMEMDESCEntryKM failed (eError=%d)",
+				__func__,
+				eError));
+	}
+
+#endif /* if defined(PVR_RI_DEBUG) */
+
 	/* write Freelist with Memory Block physical addresses */
 	eError = PMRWritePMPageList(
 						/* Target PMR, offset, and length */
@@ -606,6 +663,21 @@
 			PVR_ASSERT(IMG_FALSE);
 		}
 
+#if defined(PVR_RI_DEBUG)
+
+		if (psPMRNode->hRIHandle)
+		{
+		    PVRSRV_ERROR eError;
+
+		    eError = RIDeleteMEMDESCEntryKM(psPMRNode->hRIHandle);
+			if( eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: call to RIDeleteMEMDESCEntryKM failed (eError=%d)", __func__, eError));
+			}
+		}
+
+#endif  /* if defined(PVR_RI_DEBUG) */
+
 		/* Free PMR (We should be the only one that holds a ref on the PMR) */
 		eError = PMRUnrefPMR(psPMRNode->psPMR);
 		if (eError != PVRSRV_OK)
@@ -682,11 +754,9 @@
 	if (psFreeList)
 	{
 		/* Try to grow the freelist */
-		PMRLock();
 		eError = RGXGrowFreeList(psFreeList,
 								psFreeList->ui32GrowFLPages,
 								&psFreeList->sMemoryBlockHead);
-		PMRUnlock();
 		if (eError == PVRSRV_OK)
 		{
 			/* Grow successful, return size of grow size */
@@ -722,23 +792,12 @@
 
 		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 		{
-#if defined(PDUMP)
-			/* RGXScheduleCommand leads to PMRPDumpLoadMem.
-			 * This call originates from the MISR so the PMR lock can't be taken at
-			 * the bridge level, and the PMR lock can't be taken inside RGXScheduleCommand
-			 * because this would lead to bridge calls which acquire the PMR lock in the bridge
-			 * trying to acquire the lock twice
-			 */
-			PMRLock();
-#endif
 			eError = RGXScheduleCommand(psDevInfo,
-												RGXFWIF_DM_3D,
-												&s3DCCBCmd,
-												sizeof(s3DCCBCmd),
-												IMG_FALSE);
-#if defined(PDUMP)
-			PMRUnlock();
-#endif
+										RGXFWIF_DM_3D,
+										&s3DCCBCmd,
+										sizeof(s3DCCBCmd),
+										0,
+										PDUMP_FLAGS_NONE);
 			if (eError != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -778,8 +837,6 @@
 	ui32StartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
 	uiOffset = psFreeList->uiFreeListPMROffset + (ui32StartPage * sizeof(IMG_UINT32));
 
-	PMRLock();
-
 	PMRUnwritePMPageList(psPMRNode->psPageList);
 	psPMRNode->psPageList = NULL;
 	eError = PMRWritePMPageList(
@@ -811,132 +868,155 @@
 		}
 	}
 
-	PMRUnlock();
-
 	psFreeList->ui32CurrentFLPages += psPMRNode->ui32NumPages;
 }
 
+
+static PVRSRV_ERROR RGXReconstructFreeList(RGX_FREELIST *psFreeList)
+{
+	DLLIST_NODE       *psNode, *psNext;
+	RGXFWIF_FREELIST  *psFWFreeList;
+	PVRSRV_ERROR      eError;
+
+	//PVR_DPF((PVR_DBG_ERROR, "FreeList RECONSTRUCTION: Reconstructing freelist %p (ID=%u)", psFreeList, psFreeList->ui32FreelistID));
+
+	/* Do the FreeList Reconstruction */
+	psFreeList->ui32CurrentFLPages = 0;
+
+	/* Reconstructing Init FreeList pages */
+	dllist_foreach_node(&psFreeList->sMemoryBlockInitHead, psNode, psNext)
+	{
+		_RGXCheckFreeListReconstruction(psNode);
+	}
+
+	/* Reconstructing Grow FreeList pages */
+	dllist_foreach_node(&psFreeList->sMemoryBlockHead, psNode, psNext)
+	{
+		_RGXCheckFreeListReconstruction(psNode);
+	}
+
+	/* Reset the firmware freelist structure */
+	eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	psFWFreeList->ui32CurrentStackTop       = psFWFreeList->ui32CurrentPages - 1;
+	psFWFreeList->ui32AllocatedPageCount    = 0;
+	psFWFreeList->ui32AllocatedMMUPageCount = 0;
+	psFWFreeList->ui32HWRCounter++;
+
+	DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+
+	/* Check the Freelist checksum if required (as the list is fully populated) */
+	if (psFreeList->bCheckFreelist)
+	{
+		IMG_UINT64  ui64CheckSum;
+		
+		_CheckFreelist(psFreeList, psFreeList->ui32CurrentFLPages, psFreeList->ui64FreelistChecksum, &ui64CheckSum);
+	}
+
+	return eError;
+}
+
+
 void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
                                               IMG_UINT32 ui32FreelistsCount,
                                               IMG_UINT32 *paui32Freelists)
 {
-	PVRSRV_ERROR eError;
-	RGX_FREELIST *psFreeList;
-	IMG_UINT32 ui32Loop, ui32Loop2;
-	RGXFWIF_KCCB_CMD sTACCBCmd;
-	IMG_UINT64 ui64CheckSum;
-
-	PVR_ASSERT(psDevInfo);
+	PVRSRV_ERROR      eError = PVRSRV_OK;
+	DLLIST_NODE       *psNode, *psNext;
+	IMG_UINT32        ui32Loop;
+	RGXFWIF_KCCB_CMD  sTACCBCmd;
+	
+	PVR_ASSERT(psDevInfo != NULL);
 	PVR_ASSERT(ui32FreelistsCount <= (MAX_HW_TA3DCONTEXTS * RGXFW_MAX_FREELISTS));
 
-	//PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Reconstructing %u freelist(s)", ui32FreelistsCount));
+	//PVR_DPF((PVR_DBG_ERROR, "FreeList RECONSTRUCTION: %u freelist(s) requested for reconstruction", ui32FreelistsCount));
 
-	/* initialise the command */
+	/*
+	 *  Initialise the response command (in case we don't find a freelist ID)...
+	 */
 	sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE;
-	sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount = 0;
+	sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount = ui32FreelistsCount;
 
 	for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
 	{
-		/* check if there is more than one occurrence of FL on the list */
-		for (ui32Loop2 = ui32Loop + 1; ui32Loop2 < ui32FreelistsCount; ui32Loop2++)
+		sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] = paui32Freelists[ui32Loop] |
+		                                                                             RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
+	}
+
+	/*
+	 *  The list of freelists we have been given for reconstruction will
+	 *  consist of local and global freelists (maybe MMU as well). Any
+	 *  local freelists will have their global list specified as well.
+	 *  However there may be other local freelists not listed, which are
+	 *  going to have their global freelist reconstructed. Therefore we
+	 *  have to find those freelists as well meaning we will have to
+	 *  iterate the entire list of freelists to find which must be reconstructed.
+	 */
+	OSLockAcquire(psDevInfo->hLockFreeList);
+	dllist_foreach_node(&psDevInfo->sFreeListHead, psNode, psNext)
+	{
+		RGX_FREELIST  *psFreeList  = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
+		IMG_BOOL      bReconstruct = IMG_FALSE;
+
+		/*
+		 *  Check if this freelist needs to be reconstructed (was it requested
+		 *  or was its global freelist requested)...
+		 */
+		for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
 		{
-			if (paui32Freelists[ui32Loop] == paui32Freelists[ui32Loop2])
+			if (paui32Freelists[ui32Loop] == psFreeList->ui32FreelistID  ||
+			    paui32Freelists[ui32Loop] == psFreeList->ui32FreelistGlobalID)
 			{
-				/* There is a duplicate on a list, skip current Freelist */
+				bReconstruct = IMG_TRUE;
 				break;
 			}
 		}
 
-		if (ui32Loop2 < ui32FreelistsCount)
+		if (bReconstruct)
 		{
-			/* There is a duplicate on the list, skip current Freelist */
-			continue;
-		}
-
-		/* find the freelist with the corresponding ID */
-		psFreeList = FindFreeList(psDevInfo, paui32Freelists[ui32Loop]);
-
-		if (psFreeList)
-		{
-			DLLIST_NODE *psNode, *psNext;
-			//PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Reconstructing freelist %08X", (IMG_UINT32)psFreeList));
-
-			/* Do the FreeList Reconstruction */
-
-			psFreeList->ui32CurrentFLPages = 0;
-
-			/* Reconstructing Init FreeList pages */
-			dllist_foreach_node(&psFreeList->sMemoryBlockInitHead, psNode, psNext)
-			{
-				_RGXCheckFreeListReconstruction(psNode);
-			}
-
-			/* Reconstructing Grow FreeList pages */
-			dllist_foreach_node(&psFreeList->sMemoryBlockHead, psNode, psNext)
-			{
-				_RGXCheckFreeListReconstruction(psNode);
-			}
-
-			if (psFreeList->bCheckFreelist)
-			{
-				/* Check the Freelist checksum (as the list is fully populated) */
-				_CheckFreelist(psFreeList, psFreeList->ui32CurrentFLPages, psFreeList->ui64FreelistChecksum, &ui64CheckSum);
-			}
-
-			eError = PVRSRV_OK;
-
+			eError = RGXReconstructFreeList(psFreeList);
 			if (eError == PVRSRV_OK)
 			{
-				/* Freelist reconstruction successful */
-				sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount] =
-				                    paui32Freelists[ui32Loop];
+				for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
+				{
+					if (paui32Freelists[ui32Loop] == psFreeList->ui32FreelistID)
+					{
+						/* Reconstruction of this requested freelist was successful... */
+						sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] &= ~RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
+						break;
+					}
+				}
 			}
-#if 0
 			else
 			{
-				/* Freelist reconstruction failed */
-				sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount] =
-				                    paui32Freelists[ui32Loop] | RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
-
 				PVR_DPF((PVR_DBG_ERROR,"Reconstructing of FreeList %p failed (error %u)",
-				         psFreeList,
-				         eError));
+						 psFreeList,
+						 eError));
 			}
-#endif
-			sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount++;
 		}
-		else
-		{
-			/* Should never happen */
-			PVR_DPF((PVR_DBG_ERROR,"RGXProcessRequestFreelistsReconstruction: FreeList Lookup for FreeList ID 0x%08X failed. "
-										"Last allocated FreeList ID: 0x%08X",
-										paui32Freelists[ui32Loop],
-										psDevInfo->ui32FreelistCurrID - 1));
-			PVR_ASSERT(IMG_FALSE);
-		}
+	}
+	OSLockRelease(psDevInfo->hLockFreeList);
+
+	/* Check that all freelists were found and reconstructed... */
+	for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
+	{
+		PVR_ASSERT((sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] &
+		            RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG) == 0);
 	}
 
 	/* send feedback */
-
 	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 	{
-#if defined(PDUMP)
-			/* RGXScheduleCommand leads to PMRPDumpLoadMem.
-			 * This call originates from the MISR so the PMR lock can't be taken at
-			 * the bridge level, and the PMR lock can't be taken inside RGXScheduleCommand
-			 * because this would lead to bridge calls which acquire the PMR lock in the bridge
-			 * trying to acquire the lock twice
-			 */
-		PMRLock();
-#endif
 		eError = RGXScheduleCommand(psDevInfo,
 		                            RGXFWIF_DM_TA,
 		                            &sTACCBCmd,
 		                            sizeof(sTACCBCmd),
-		                            IMG_FALSE);
-#if defined(PDUMP)
-		PMRUnlock();
-#endif
+		                            0,
+		                            PDUMP_FLAGS_NONE);
 		if (eError != PVRSRV_ERROR_RETRY)
 		{
 			break;
@@ -952,7 +1032,7 @@
 IMG_EXPORT
 PVRSRV_ERROR RGXCreateHWRTData(CONNECTION_DATA      *psConnection,
                                PVRSRV_DEVICE_NODE	*psDeviceNode,
-                               IMG_UINT32			psRenderTarget,
+							   IMG_UINT32			psRenderTarget, /* FIXME this should not be IMG_UINT32 */
 							   IMG_DEV_VIRTADDR		psPMMListDevVAddr,
 							   IMG_DEV_VIRTADDR		psVFPPageTableAddr,
 							   RGX_FREELIST			*apsFreeLists[RGXFW_MAX_FREELISTS],
@@ -990,14 +1070,13 @@
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	
 	/* Prepare cleanup struct */
-	psTmpCleanup = OSAllocMem(sizeof(*psTmpCleanup));
+	psTmpCleanup = OSAllocZMem(sizeof(*psTmpCleanup));
 	if (psTmpCleanup == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto AllocError;
 	}
 
-	OSMemSet(psTmpCleanup, 0, sizeof(*psTmpCleanup));
 	*ppsCleanupData = psTmpCleanup;
 
 	/* Allocate cleanup sync */
@@ -1049,6 +1128,8 @@
 	eError = DevmemAcquireCpuVirtAddr(*ppsMemDesc, (void **)&psHWRTData);
 	PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTDataCpuMapError);
 
+	/* FIXME: MList is something that that PM writes physical addresses to,
+	 * so ideally its best allocated in kernel */
 	psHWRTData->psPMMListDevVAddr = psPMMListDevVAddr;
 	psHWRTData->psParentRenderTarget.ui32Addr = psRenderTarget;
 	#if defined(SUPPORT_VFP)
@@ -1080,7 +1161,7 @@
 		psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount++;
 		psHWRTData->apsFreeLists[ui32Loop].ui32Addr = psTmpCleanup->apsFreeLists[ui32Loop]->sFreeListFWDevVAddr.ui32Addr;		
 		/* invalid initial snapshot value, the snapshot is always taken during first kick
-		 * and hence the value get replaced during the first kick anyway. So its safe to set it 0.
+		 * and hence the value get replaced during the first kick anyway. So it's safe to set it 0.
 		*/
 		psHWRTData->aui32FreeListHWRSnapshot[ui32Loop] = 0;
 	}
@@ -1136,7 +1217,7 @@
 			goto FWAllocateRTArryError;
 		}
 
-		RGXSetFirmwareAddress(&psRTACtl->paui32ValidRenderTargets,
+		RGXSetFirmwareAddress(&psRTACtl->sValidRenderTargets,
 										psTmpCleanup->psRTArrayMemDesc,
 										0, RFW_FWADDR_FLAG_NONE);
 
@@ -1160,15 +1241,15 @@
 			goto FWAllocateRTAccArryError;
 		}
 
-		RGXSetFirmwareAddress(&psRTACtl->paui32NumRenders,
+		RGXSetFirmwareAddress(&psRTACtl->sNumRenders,
                                                 psTmpCleanup->psRendersAccArrayMemDesc,
                                                 0, RFW_FWADDR_FLAG_NONE);
 		psRTACtl->ui16MaxRTs = ui16MaxRTs;
 	}
 	else
 	{
-		psRTACtl->paui32ValidRenderTargets.ui32Addr = 0;
-		psRTACtl->paui32NumRenders.ui32Addr = 0;
+		psRTACtl->sValidRenderTargets.ui32Addr = 0;
+		psRTACtl->sNumRenders.ui32Addr = 0;
 		psRTACtl->ui16MaxRTs = 1;
 	}
 		
@@ -1182,12 +1263,12 @@
 	return PVRSRV_OK;
 
 FWAllocateRTAccArryError:
-	DevmemFwFree(psTmpCleanup->psRTArrayMemDesc);
+	DevmemFwFree(psDevInfo, psTmpCleanup->psRTArrayMemDesc);
 FWAllocateRTArryError:
 	DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
 FWRTACpuMapError:
 	RGXUnsetFirmwareAddress(*ppsRTACtlMemDesc);
-	DevmemFwFree(*ppsRTACtlMemDesc);
+	DevmemFwFree(psDevInfo, *ppsRTACtlMemDesc);
 FWRTAAllocateError:
 	OSLockAcquire(psDevInfo->hLockFreeList);
 	for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
@@ -1199,7 +1280,7 @@
 	DevmemReleaseCpuVirtAddr(*ppsMemDesc);
 FWRTDataCpuMapError:
 	RGXUnsetFirmwareAddress(*ppsMemDesc);
-	DevmemFwFree(*ppsMemDesc);
+	DevmemFwFree(psDevInfo, *ppsMemDesc);
 FWRTDataAllocateError:
 	SyncPrimFree(psTmpCleanup->psCleanupSync);
 SyncAlloc:
@@ -1249,24 +1330,24 @@
 	if(psCleanupData->psRTACtlMemDesc)
 	{
 		RGXUnsetFirmwareAddress(psCleanupData->psRTACtlMemDesc);
-		DevmemFwFree(psCleanupData->psRTACtlMemDesc);
+		DevmemFwFree(psDevInfo, psCleanupData->psRTACtlMemDesc);
 	}
 	
 	RGXUnsetFirmwareAddress(psCleanupData->psFWHWRTDataMemDesc);
-	DevmemFwFree(psCleanupData->psFWHWRTDataMemDesc);
+	DevmemFwFree(psDevInfo, psCleanupData->psFWHWRTDataMemDesc);
 	
 	if(psCleanupData->psRTArrayMemDesc)
 	{
 		RGXUnsetFirmwareAddress(psCleanupData->psRTArrayMemDesc);
-		DevmemFwFree(psCleanupData->psRTArrayMemDesc);
+		DevmemFwFree(psDevInfo, psCleanupData->psRTArrayMemDesc);
 	}
+
 	if(psCleanupData->psRendersAccArrayMemDesc)
 	{
 		RGXUnsetFirmwareAddress(psCleanupData->psRendersAccArrayMemDesc);
-		DevmemFwFree(psCleanupData->psRendersAccArrayMemDesc);
+		DevmemFwFree(psDevInfo, psCleanupData->psRendersAccArrayMemDesc);
 	}
 
-
 	SyncPrimFree(psCleanupData->psCleanupSync);
 
 	/* decrease freelist refcount */
@@ -1289,6 +1370,7 @@
 							   IMG_UINT32			ui32MaxFLPages,
 							   IMG_UINT32			ui32InitFLPages,
 							   IMG_UINT32			ui32GrowFLPages,
+							   RGX_FREELIST			*psGlobalFreeList,
 							   IMG_BOOL				bCheckFreelist,
 							   IMG_DEV_VIRTADDR		sFreeListDevVAddr,
 							   PMR					*psFreeListPMR,
@@ -1302,14 +1384,13 @@
 	PVRSRV_RGXDEV_INFO			*psDevInfo = psDeviceNode->pvDevice;
 
 	/* Allocate kernel freelist struct */
-	psFreeList = OSAllocMem(sizeof(*psFreeList));
+	psFreeList = OSAllocZMem(sizeof(*psFreeList));
 	if (psFreeList == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: failed to allocate host data structure"));
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto ErrorAllocHost;
 	}
-	OSMemSet(psFreeList, 0, sizeof(*psFreeList));
 
 	/* Allocate cleanup sync */
 	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
@@ -1323,10 +1404,10 @@
 	}
 
 	/*
-	 * This FW FreeList context is only mapped into kernel for initialisation.
-	 * Otherwise this allocation is only used by the FW.
-	 * Therefore the GPU cache doesn't need coherency,
-	 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
+	 * This FW FreeList context is only mapped into kernel for initialisation
+	 * and reconstruction (at other times it is not mapped and only used by
+	 * the FW. Therefore the GPU cache doesn't need coherency, and write-combine
+	 * is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
 	 */
 	eError = DevmemFwAllocate(psDevInfo,
 							sizeof(*psFWFreeList),
@@ -1354,6 +1435,7 @@
 	psFreeList->psFWFreelistMemDesc = psFWFreelistMemDesc;
 	RGXSetFirmwareAddress(&psFreeList->sFreeListFWDevVAddr, psFWFreelistMemDesc, 0, RFW_FWADDR_FLAG_NONE);
 	psFreeList->ui32FreelistID = psDevInfo->ui32FreelistCurrID++;
+	psFreeList->ui32FreelistGlobalID = (psGlobalFreeList ? psGlobalFreeList->ui32FreelistID : 0);
 	psFreeList->ui32MaxFLPages = ui32MaxFLPages;
 	psFreeList->ui32InitFLPages = ui32InitFLPages;
 	psFreeList->ui32GrowFLPages = ui32GrowFLPages;
@@ -1449,7 +1531,7 @@
 	OSLockRelease(psDevInfo->hLockFreeList);
 
 	RGXUnsetFirmwareAddress(psFWFreelistMemDesc);
-	DevmemFwFree(psFWFreelistMemDesc);
+	DevmemFwFree(psDevInfo, psFWFreelistMemDesc);
 
 FWFreeListAlloc:
 	SyncPrimFree(psFreeList->psCleanupSync);
@@ -1490,6 +1572,11 @@
 		return eError;
 	}
 
+	/* Remove FreeList from linked list before we destroy it... */
+	OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
+	dllist_remove_node(&psFreeList->sNode);
+	OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
 	if (psFreeList->bCheckFreelist)
 	{
 		RGXFWIF_FREELIST  *psFWFreeList;
@@ -1515,7 +1602,7 @@
 
 	/* Destroy FW structures */
 	RGXUnsetFirmwareAddress(psFreeList->psFWFreelistMemDesc);
-	DevmemFwFree(psFreeList->psFWFreelistMemDesc);
+	DevmemFwFree(psFreeList->psDevInfo, psFreeList->psFWFreelistMemDesc);
 
 	/* Remove grow shrink blocks */
 	while (!dllist_is_empty(&psFreeList->sMemoryBlockHead))
@@ -1532,11 +1619,6 @@
 	PVR_ASSERT(dllist_is_empty(&psFreeList->sMemoryBlockInitHead));
 	PVR_ASSERT(psFreeList->ui32CurrentFLPages == 0);
 
-	/* Remove FreeList from list */
-	OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
-	dllist_remove_node(&psFreeList->sNode);
-	OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
-
 	SyncPrimFree(psFreeList->psCleanupSync);
 
 	/* free Freelist */
@@ -1628,14 +1710,13 @@
 
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	
-	psCleanupData = OSAllocMem(sizeof(*psCleanupData));
+	psCleanupData = OSAllocZMem(sizeof(*psCleanupData));
 	if (psCleanupData == NULL)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto err_out;
 	}
 
-	OSMemSet(psCleanupData, 0, sizeof(*psCleanupData));
 	psCleanupData->psDeviceNode = psDeviceNode;
 	/*
 	 * This FW render target context is only mapped into kernel for initialisation.
@@ -1683,7 +1764,7 @@
 	goto err_out;
 
 err_fwalloc:
-	DevmemFwFree(psCleanupData->psRenderTargetMemDesc);
+	DevmemFwFree(psDevInfo, psCleanupData->psRenderTargetMemDesc);
 	goto err_free;
 
 }
@@ -1695,6 +1776,8 @@
 IMG_EXPORT
 PVRSRV_ERROR RGXDestroyRenderTarget(RGX_RT_CLEANUP_DATA *psCleanupData)
 {
+	PVRSRV_DEVICE_NODE *psDeviceNode = psCleanupData->psDeviceNode;
+
 	RGXUnsetFirmwareAddress(psCleanupData->psRenderTargetMemDesc);
 
 	/*
@@ -1705,7 +1788,6 @@
 	{
 		RGXFWIF_KCCB_CMD sFlushInvalCmd;
 		PVRSRV_ERROR eError;
-		PVRSRV_DEVICE_NODE *psDeviceNode = psCleanupData->psDeviceNode;
 
 		/* Schedule the SLC flush command ... */
 #if defined(PDUMP)
@@ -1721,7 +1803,7 @@
 											RGXFWIF_DM_GP,
 											&sFlushInvalCmd,
 											sizeof(sFlushInvalCmd),
-											IMG_TRUE);
+											PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: Failed to schedule SLC flush command with error (%u)", eError));
@@ -1729,7 +1811,7 @@
 		else
 		{
 			/* Wait for the SLC flush to complete */
-			eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+			eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
 			if (eError != PVRSRV_OK)
 			{
 				PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: SLC flush and invalidate aborted with error (%u)", eError));
@@ -1737,7 +1819,7 @@
 		}
 	}
 
-	DevmemFwFree(psCleanupData->psRenderTargetMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, psCleanupData->psRenderTargetMemDesc);
 	OSFreeMem(psCleanupData);
 	return PVRSRV_OK;
 }
@@ -1759,17 +1841,16 @@
 	RGXFWIF_FWZSBUFFER			*psFWZSBuffer;
 	RGX_ZSBUFFER_DATA			*psZSBuffer;
 	DEVMEM_MEMDESC				*psFWZSBufferMemDesc;
-	IMG_BOOL					bOnDemand = ((uiMapFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
+	IMG_BOOL					bOnDemand = PVRSRV_CHECK_ON_DEMAND(uiMapFlags) ? IMG_TRUE : IMG_FALSE;
 
 	/* Allocate host data structure */
-	psZSBuffer = OSAllocMem(sizeof(*psZSBuffer));
+	psZSBuffer = OSAllocZMem(sizeof(*psZSBuffer));
 	if (psZSBuffer == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup data structure for ZS-Buffer"));
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto ErrorAllocCleanup;
 	}
-	OSMemSet(psZSBuffer, 0, sizeof(*psZSBuffer));
 
 	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
 						   &psZSBuffer->psCleanupSync,
@@ -1860,7 +1941,7 @@
 	/* error handling */
 
 ErrorAcquireFWZSBuffer:
-	DevmemFwFree(psFWZSBufferMemDesc);
+	DevmemFwFree(psDevInfo, psFWZSBufferMemDesc);
 
 ErrorAllocFWZSBuffer:
 	SyncPrimFree(psZSBuffer->psCleanupSync);
@@ -1894,7 +1975,7 @@
 	{
 		/* Free the firmware render context. */
     	RGXUnsetFirmwareAddress(psZSBuffer->psZSBufferMemDesc);
-		DevmemFwFree(psZSBuffer->psZSBufferMemDesc);
+		DevmemFwFree(psZSBuffer->psDevInfo, psZSBuffer->psZSBufferMemDesc);
 
 	    /* Remove Deferred Allocation from list */
 		if (psZSBuffer->bOnDemand)
@@ -1930,7 +2011,7 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	if ((psZSBuffer->uiMapFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) == 0)
+	if (!psZSBuffer->bOnDemand)
 	{
 		/* Only deferred allocations can be populated */
 		return PVRSRV_ERROR_INVALID_PARAMS;
@@ -2140,12 +2221,10 @@
 		IMG_BOOL bBackingDone = IMG_TRUE;
 
 		/* Populate ZLS */
-		PMRLock();
 		eError = RGXBackingZSBuffer(psZSBuffer);
-		PMRUnlock();
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR,"Populating ZS-Buffer failed failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
+			PVR_DPF((PVR_DBG_ERROR,"Populating ZS-Buffer failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
 			bBackingDone = IMG_FALSE;
 		}
 
@@ -2157,10 +2236,11 @@
 		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 		{
 			eError = RGXScheduleCommand(psDevInfo,
-												RGXFWIF_DM_TA,
-												&sTACCBCmd,
-												sizeof(sTACCBCmd),
-												IMG_FALSE);
+										RGXFWIF_DM_TA,
+										&sTACCBCmd,
+										sizeof(sTACCBCmd),
+										0,
+										PDUMP_FLAGS_NONE);
 			if (eError != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -2199,9 +2279,7 @@
 	if (psZSBuffer)
 	{
 		/* Unpopulate ZLS */
-		PMRLock();
 		eError = RGXUnbackingZSBuffer(psZSBuffer);
-		PMRUnlock();
 		if (eError != PVRSRV_OK)
 		{
 			PVR_DPF((PVR_DBG_ERROR,"UnPopulating ZS-Buffer failed failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
@@ -2216,10 +2294,11 @@
 		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
 		{
 			eError = RGXScheduleCommand(psDevInfo,
-												RGXFWIF_DM_TA,
-												&sTACCBCmd,
-												sizeof(sTACCBCmd),
-												IMG_FALSE);
+										RGXFWIF_DM_TA,
+										&sTACCBCmd,
+										sizeof(sTACCBCmd),
+										0,
+										PDUMP_FLAGS_NONE);
 			if (eError != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -2313,7 +2392,7 @@
 
 fail_tacommoncontext:
 fail_suspendcpuvirtacquire:
-	DevmemFwFree(psTAData->psContextStateMemDesc);
+	DevmemFwFree(psDevInfo, psTAData->psContextStateMemDesc);
 fail_tacontextsuspendalloc:
 	PVR_ASSERT(eError != PVRSRV_OK);
 
@@ -2383,7 +2462,7 @@
 	return PVRSRV_OK;
 
 fail_3dcommoncontext:
-	DevmemFwFree(ps3DData->psContextStateMemDesc);
+	DevmemFwFree(psDevInfo, ps3DData->psContextStateMemDesc);
 fail_3dcontextsuspendalloc:
 	PVR_ASSERT(eError != PVRSRV_OK);
 
@@ -2413,13 +2492,12 @@
 
 	/* Prepare cleanup structure */
 	*ppsRenderContext = NULL;
-	psRenderContext = OSAllocMem(sizeof(*psRenderContext));
+	psRenderContext = OSAllocZMem(sizeof(*psRenderContext));
 	if (psRenderContext == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	OSMemSet(psRenderContext, 0, sizeof(*psRenderContext));
 	psRenderContext->psDeviceNode = psDeviceNode;
 
 	/*
@@ -2436,16 +2514,9 @@
 		goto fail_fwrendercontext;
 	}
 
-	/*
-		As the common context alloc will dump the TA and 3D common contexts
-		after the've been setup we skip of the 2 common contexts and dump the
-		rest of the structure
-	*/
-	PDUMPCOMMENT("Dump shared part of render context context");
-	DevmemPDumpLoadMem(psRenderContext->psFWRenderContextMemDesc,
-					   (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
-					   sizeof(RGXFWIF_FWRENDERCONTEXT) - (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
-					   PDUMP_FLAGS_CONTINUOUS);
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	WorkEstRCInit(&(psRenderContext->sWorkEstData));
+#endif
 
 	/* Allocate cleanup sync */
 	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
@@ -2534,11 +2605,11 @@
 					  psRenderContext->psCleanupSync);
 fail_tacontext:
 fail_frameworkcopy:
-	DevmemFwFree(psRenderContext->psFWFrameworkMemDesc);
+	DevmemFwFree(psDevInfo, psRenderContext->psFWFrameworkMemDesc);
 fail_frameworkcreate:
 	SyncPrimFree(psRenderContext->psCleanupSync);
 fail_syncalloc:
-	DevmemFwFree(psRenderContext->psFWRenderContextMemDesc);
+	DevmemFwFree(psDevInfo, psRenderContext->psFWRenderContextMemDesc);
 fail_fwrendercontext:
 	OSFreeMem(psRenderContext);
 	PVR_ASSERT(eError != PVRSRV_OK);
@@ -2554,6 +2625,10 @@
 {
 	PVRSRV_ERROR				eError;
 	PVRSRV_RGXDEV_INFO 	*psDevInfo = psRenderContext->psDeviceNode->pvDevice;
+	RGXFWIF_FWRENDERCONTEXT	*psFWRenderContext;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	IMG_UINT32 ui32WorkEstCCBSubmitted;
+#endif
 
 	/* remove node from list before calling destroy - as destroy, if successful
 	 * will invalidate the node
@@ -2569,7 +2644,7 @@
 		eError = _DestroyTAContext(&psRenderContext->sTAData,
 								   psRenderContext->psDeviceNode,
 								   psRenderContext->psCleanupSync);
-		if (eError != PVRSRV_ERROR_RETRY)
+		if (eError == PVRSRV_OK)
 		{
 			psRenderContext->ui32CleanupStatus |= RC_CLEANUP_TA_COMPLETE;
 		}
@@ -2585,7 +2660,7 @@
 		eError = _Destroy3DContext(&psRenderContext->s3DData,
 								   psRenderContext->psDeviceNode,
 								   psRenderContext->psCleanupSync);
-		if (eError != PVRSRV_ERROR_RETRY)
+		if (eError == PVRSRV_OK)
 		{
 			psRenderContext->ui32CleanupStatus |= RC_CLEANUP_3D_COMPLETE;
 		}
@@ -2595,13 +2670,36 @@
 		}
 	}
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
+	                                  (void **)&psFWRenderContext);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDestroyRenderContextKM: Failed to map firmware render context (%u)",
+		         eError));
+		goto e0;
+	}
+
+	ui32WorkEstCCBSubmitted = psFWRenderContext->ui32WorkEstCCBSubmitted;
+
+	DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
+
+	/* Check if all of the workload estimation CCB commands for this workload
+	 * are read
+	 */
+	if(ui32WorkEstCCBSubmitted != psRenderContext->sWorkEstData.ui32WorkEstCCBReceived)
+	{
+		eError = PVRSRV_ERROR_RETRY;
+		goto e0;
+	}
+#endif
+
 	/*
 		Only if both TA and 3D contexts have been cleaned up can we
 		free the shared resources
 	*/
 	if (psRenderContext->ui32CleanupStatus == (RC_CLEANUP_3D_COMPLETE | RC_CLEANUP_TA_COMPLETE))
 	{
-		RGXFWIF_FWRENDERCONTEXT	*psFWRenderContext;
 
 		/* Update SPM statistics */
 		eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
@@ -2617,10 +2715,10 @@
 		}
 
 		/* Free the framework buffer */
-		DevmemFwFree(psRenderContext->psFWFrameworkMemDesc);
+		DevmemFwFree(psDevInfo, psRenderContext->psFWFrameworkMemDesc);
 	
 		/* Free the firmware render context */
-		DevmemFwFree(psRenderContext->psFWRenderContextMemDesc);
+		DevmemFwFree(psDevInfo, psRenderContext->psFWRenderContextMemDesc);
 
 		/* Free the cleanup sync */
 		SyncPrimFree(psRenderContext->psCleanupSync);
@@ -2630,6 +2728,11 @@
 		SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DFence);
 		SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DUpdate);
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		WorkEstRCDeInit(&(psRenderContext->sWorkEstData),
+                        psDevInfo);
+#endif
+
 		OSFreeMem(psRenderContext);
 	}
 
@@ -2643,6 +2746,9 @@
 }
 
 
+/* TODO !!! this was local on the stack, and we managed to blow the stack for the kernel. 
+ * THIS - 46 argument function needs to be sorted out.
+ */
 /* 1 command for the TA */
 static RGX_CCB_CMD_HELPER_DATA asTACmdHelperData[1];
 /* Up to 3 commands for the 3D (partial render fence, partial reader, and render) */
@@ -2653,6 +2759,7 @@
  */
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT	*psRenderContext,
+								 IMG_UINT32					ui32ClientCacheOpSeqNum,
 								 IMG_UINT32					ui32ClientTAFenceCount,
 								 SYNC_PRIMITIVE_BLOCK				**apsClientTAFenceSyncPrimBlock,
 								 IMG_UINT32					*paui32ClientTAFenceSyncOffset,
@@ -2689,13 +2796,12 @@
 								 IMG_UINT32					ui323DCmdSize,
 								 IMG_PBYTE					pui83DDMCmd,
 								 IMG_UINT32					ui32ExtJobRef,
-								 IMG_UINT32					ui32IntJobRef,
 								 IMG_BOOL					bLastTAInScene,
 								 IMG_BOOL					bKickTA,
 								 IMG_BOOL					bKickPR,
 								 IMG_BOOL					bKick3D,
 								 IMG_BOOL					bAbort,
-								 IMG_BOOL					bPDumpContinuous,
+								 IMG_UINT32					ui32PDumpFlags,
 								 RGX_RTDATA_CLEANUP_DATA	*psRTDataCleanup,
 								 RGX_ZSBUFFER_DATA		*psZBuffer,
 								 RGX_ZSBUFFER_DATA		*psSBuffer,
@@ -2705,7 +2811,12 @@
 								 IMG_BOOL			*pbCommittedRefCounts3D,
 								 IMG_UINT32			ui32SyncPMRCount,
 								 IMG_UINT32			*paui32SyncPMRFlags,
-								 PMR				**ppsSyncPMRs)
+								 PMR				**ppsSyncPMRs,
+								 IMG_UINT32			ui32RenderTargetSize,
+								 IMG_UINT32			ui32NumberOfDrawCalls,
+								 IMG_UINT32			ui32NumberOfIndices,
+								 IMG_UINT32			ui32NumberOfMRTs,
+								 IMG_UINT64			ui64DeadlineInus)
 {
 
 	IMG_UINT32				ui32TACmdCount=0;
@@ -2713,8 +2824,6 @@
 	IMG_UINT32				ui32TACmdOffset=0;
 	IMG_UINT32				ui323DCmdOffset=0;
 	RGXFWIF_UFO				sPRUFO;
-	IMG_UINT32				*paui32Server3DSyncFlagsPR = NULL;
-	IMG_UINT32				*paui32Server3DSyncFlags3D = NULL;
 	IMG_UINT32				i;
 	PVRSRV_ERROR			eError = PVRSRV_OK;
 	PVRSRV_ERROR			eError2;
@@ -2735,6 +2844,18 @@
 	PRGXFWIF_UFO_ADDR			*pauiClient3DUpdateUFOAddress;
 	PRGXFWIF_UFO_ADDR			uiPRFenceUFOAddress;
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	RGXFWIF_WORKEST_KICK_DATA sWorkloadKickDataTA;
+	RGXFWIF_WORKEST_KICK_DATA sWorkloadKickData3D;
+	IMG_UINT32 ui32TACommandOffset = 0;
+	IMG_UINT32 ui323DCommandOffset = 0;
+	IMG_UINT32 ui32TACmdHeaderOffset = 0;
+	IMG_UINT32 ui323DCmdHeaderOffset = 0;
+	IMG_UINT32 ui323DFullRenderCommandOffset = 0;
+	IMG_UINT32 ui32TACmdOffsetWrapCheck = 0;
+	IMG_UINT32 ui323DCmdOffsetWrapCheck = 0;
+#endif
+
 #if defined(SUPPORT_BUFFER_SYNC)
 	struct pvr_buffer_sync_append_data *psAppendData = NULL;
 #endif
@@ -2758,7 +2879,11 @@
 			__func__, i32CheckFenceFD));
 	}
 #endif
-	PVR_UNREFERENCED_PARAMETER(ui32IntJobRef);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	sWorkloadKickDataTA.ui64ReturnDataIndex = 0;
+	sWorkloadKickData3D.ui64ReturnDataIndex = 0;
+#endif
 
 	ui32JobId = OSAtomicIncrement(&psRenderContext->hJobId);
 
@@ -2849,7 +2974,7 @@
 	/*
 		Sanity check we have a PR kick if there are client or server fences
 	*/
-	if (!bKickPR & ((ui32Client3DFenceCount != 0) || (ui32Server3DSyncPrims != 0)))
+	if (!bKickPR && ((ui32Client3DFenceCount != 0) || (ui32Server3DSyncPrims != 0)))
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: 3D fence (client or server) passed without a PR kick", __FUNCTION__));
 		return PVRSRV_ERROR_INVALID_PARAMS;
@@ -2858,6 +2983,7 @@
 	if (ui32SyncPMRCount)
 	{
 #if defined(SUPPORT_BUFFER_SYNC)
+		PVRSRV_DEVICE_NODE *psDeviceNode = psRenderContext->psDeviceNode;
 		IMG_UINT32 ui32ClientIntUpdateCount = 0;
 		PRGXFWIF_UFO_ADDR *pauiClientIntUpdateUFOAddress = NULL;
 		IMG_UINT32 *paui32ClientIntUpdateValue = NULL;
@@ -2890,7 +3016,8 @@
 			paui32ClientIntUpdateValue = paui32ClientPRUpdateValue;
 		}
 
-		err = pvr_buffer_sync_append_start(ui32SyncPMRCount,
+		err = pvr_buffer_sync_append_start(psDeviceNode->psBufferSyncContext,
+										   ui32SyncPMRCount,
 										   ppsSyncPMRs,
 										   paui32SyncPMRFlags,
 										   ui32ClientTAFenceCount,
@@ -3026,6 +3153,19 @@
 	{
 		RGX_SERVER_RC_TA_DATA *psTAData = &psRenderContext->sTAData;
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		/* Prepare workload estimation */
+		WorkEstPrepare(psRenderContext->psDeviceNode->pvDevice,
+		               &(psRenderContext->sWorkEstData),
+		               &(psRenderContext->sWorkEstData.sWorkloadMatchingDataTA),
+		               ui32RenderTargetSize,
+		               ui32NumberOfDrawCalls,
+		               ui32NumberOfIndices,
+		               ui32NumberOfMRTs,
+		               ui64DeadlineInus,
+		               &sWorkloadKickDataTA);
+#endif
+
 		/* Init the TA command helper */
 		eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psTAData->psServerCommonContext),
 		                                ui32ClientTAFenceCount,
@@ -3036,6 +3176,7 @@
 		                                paui32ClientTAUpdateValue,
 		                                ui32ServerTASyncPrims,
 		                                paui32ServerTASyncFlags,
+		                                SYNC_FLAG_MASK_ALL,
 		                                pasServerTASyncs,
 		                                ui32TACmdSize,
 		                                pui8TADMCmd,
@@ -3045,7 +3186,12 @@
 		                                RGXFWIF_CCB_CMD_TYPE_TA,
 		                                ui32ExtJobRef,
 		                                ui32JobId,
-		                                bPDumpContinuous,
+		                                ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		                                &sWorkloadKickDataTA,
+#else
+										NULL,
+#endif
 		                                "TA",
 		                                asTACmdHelperData);
 		if (eError != PVRSRV_OK)
@@ -3053,6 +3199,14 @@
 			goto fail_tacmdinit;
 		}
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		/* The following is used to determine the offset of the command header
+		 * containing the workload estimation data so that can be accessed when
+		 * the KCCB is read.
+		 */
+		ui32TACmdHeaderOffset = RGXCmdHelperGetDMCommandHeaderOffset(asTACmdHelperData);
+#endif
+
 		eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asTACmdHelperData),
 		                                   asTACmdHelperData);
 		if (eError != PVRSRV_OK)
@@ -3070,29 +3224,6 @@
 	{
 		RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
 
-		if (ui32Server3DSyncPrims)
-		{
-			/*
-				The fence (and possible update) straddle multiple commands so
-				we have to modify the flags to do the right things at the right
-				time.
-				At this stage we should only fence, any updates will happen with
-				the normal 3D command.
-			*/
-			paui32Server3DSyncFlagsPR = OSAllocMem(sizeof(IMG_UINT32) * ui32Server3DSyncPrims);
-			if (paui32Server3DSyncFlagsPR == NULL)
-			{
-				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-				goto fail_prserversyncflagsallocpr;
-			}
-
-			/* Copy only the fence flag across */
-			for (i=0;i<ui32Server3DSyncPrims;i++)
-			{
-				paui32Server3DSyncFlagsPR[i] = paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK;
-			}
-		}
-
 		/*
 			The command helper doesn't know about the PR fence so create
 			the command with all the fences against it and later create
@@ -3110,7 +3241,8 @@
 										NULL,
 										NULL,
 										(bKick3D ? ui32Server3DSyncPrims : 0),
-										paui32Server3DSyncFlagsPR,
+										paui32Server3DSyncFlags,
+										PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK,
 										pasServer3DSyncs,
 										sizeof(sPRUFO),
 										(IMG_UINT8*) &sPRUFO,
@@ -3120,7 +3252,8 @@
 										RGXFWIF_CCB_CMD_TYPE_FENCE_PR,
 										ui32ExtJobRef,
 										ui32JobId,
-										bPDumpContinuous,
+										ui32PDumpFlags,
+										NULL,
 										"3D-PR-Fence",
 										&as3DCmdHelperData[ui323DCmdCount++]);
 		if (eError != PVRSRV_OK)
@@ -3142,6 +3275,7 @@
 										paui32ClientPRUpdateValue,
 										0,
 										NULL,
+										SYNC_FLAG_MASK_ALL,
 										NULL,
 										ui323DPRCmdSize,
 										pui83DPRDMCmd,
@@ -3151,7 +3285,8 @@
 										RGXFWIF_CCB_CMD_TYPE_3D_PR,
 										ui32ExtJobRef,
 										ui32JobId,
-										bPDumpContinuous,
+										ui32PDumpFlags,
+										NULL,
 										"3D-PR",
 										&as3DCmdHelperData[ui323DCmdCount++]);
 		if (eError != PVRSRV_OK)
@@ -3164,26 +3299,18 @@
 	{
 		RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
 
-		if (ui32Server3DSyncPrims)
-		{
-			/*
-				Copy only the update flags for the 3D as the fences will be in
-				the PR command created above
-			*/
-			paui32Server3DSyncFlags3D = OSAllocMem(sizeof(IMG_UINT32) * ui32Server3DSyncPrims);
-			if (paui32Server3DSyncFlags3D == NULL)
-			{
-				eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-				goto fail_prserversyncflagsalloc3d;
-			}
-
-			/* Copy only the update flag across */
-			for (i=0;i<ui32Server3DSyncPrims;i++)
-			{
-				paui32Server3DSyncFlags3D[i] = paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE;
-			}
-		}
-
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		/* Prepare workload estimation */
+		WorkEstPrepare(psRenderContext->psDeviceNode->pvDevice,
+		               &(psRenderContext->sWorkEstData),
+		               &(psRenderContext->sWorkEstData.sWorkloadMatchingData3D),
+		               ui32RenderTargetSize,
+		               ui32NumberOfDrawCalls,
+		               ui32NumberOfIndices,
+		               ui32NumberOfMRTs,
+		               ui64DeadlineInus,
+		               &sWorkloadKickData3D);
+#endif
 		/* Init the 3D command helper */
 		eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
 										0,
@@ -3193,7 +3320,8 @@
 										pauiClient3DUpdateUFOAddress,
 										paui32Client3DUpdateValue,
 										ui32Server3DSyncPrims,
-										paui32Server3DSyncFlags3D,
+										paui32Server3DSyncFlags,
+										PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE,
 										pasServer3DSyncs,
 										ui323DCmdSize,
 										pui83DDMCmd,
@@ -3203,13 +3331,30 @@
 										RGXFWIF_CCB_CMD_TYPE_3D,
 										ui32ExtJobRef,
 										ui32JobId,
-										bPDumpContinuous,
+										ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+										&sWorkloadKickData3D,
+#else
+										NULL,
+#endif
 										"3D",
 										&as3DCmdHelperData[ui323DCmdCount++]);
 		if (eError != PVRSRV_OK)
 		{
 			goto fail_3dcmdinit;
 		}
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		/* The following are used to determine the offset of the command header
+		 * containing the workload estimation data so that can be accessed when
+		 * the KCCB is read.
+		 */
+		ui323DCmdHeaderOffset =
+			RGXCmdHelperGetDMCommandHeaderOffset(&as3DCmdHelperData[ui323DCmdCount - 1]);
+		ui323DFullRenderCommandOffset =
+			RGXCmdHelperGetCommandOffset(as3DCmdHelperData,
+			                             ui323DCmdCount - 1);
+#endif
 	}
 
 	/* Protect against array overflow in RGXCmdHelperAcquireCmdCCB() */
@@ -3250,6 +3395,24 @@
 								  asTACmdHelperData,
 								  "TA",
 								  FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		ui32TACmdOffsetWrapCheck =
+			RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
+
+		/* This checks if the command would wrap around at the end of the CCB
+		 * and therefore would start at an offset of 0 rather than the current
+		 * command offset.
+		 */
+		if(ui32TACmdOffset < ui32TACmdOffsetWrapCheck)
+		{
+			ui32TACommandOffset = ui32TACmdOffset;
+		}
+		else
+		{
+			ui32TACommandOffset = 0;
+		}
+#endif
 	}
 
 	if (ui323DCmdCount)
@@ -3259,6 +3422,18 @@
 								  as3DCmdHelperData,
 								  "3D",
 								  FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext).ui32Addr);
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		ui323DCmdOffsetWrapCheck = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
+
+		if(ui323DCmdOffset < ui323DCmdOffsetWrapCheck)
+		{
+			ui323DCommandOffset = ui323DCmdOffset;
+		}
+		else
+		{
+			ui323DCommandOffset = 0;
+		}
+#endif
 	}
 
 	if (ui32TACmdCount)
@@ -3271,6 +3446,18 @@
 		sTAKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext);
 		sTAKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
 
+		/* Add the Workload data into the KCCB kick */
+		sTAKCCBCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
+		sTAKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		/* Store the offset to the CCCB command header so that it can be
+		 * referenced when the KCCB command reaches the FW
+		 */
+		sTAKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset =
+			ui32TACommandOffset + ui32TACmdHeaderOffset;
+#endif
+
 		if(bCommitRefCountsTA)
 		{
 			AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &sTAKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
@@ -3301,7 +3488,8 @@
 										RGXFWIF_DM_TA,
 										&sTAKCCBCmd,
 										sizeof(sTAKCCBCmd),
-										bPDumpContinuous);
+										ui32ClientCacheOpSeqNum,
+										ui32PDumpFlags);
 			if (eError2 != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -3324,6 +3512,17 @@
 		s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext);
 		s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
 
+		/* Add the Workload data into the KCCB kick */
+		s3DKCCBCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
+		s3DKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+		/* Store the offset to the CCCB command header so that it can be
+		 * referenced when the KCCB command reaches the FW
+		 */
+		s3DKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = ui323DCommandOffset + ui323DCmdHeaderOffset + ui323DFullRenderCommandOffset;
+#endif
+
 		if(bCommitRefCounts3D)
 		{
 			AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &s3DKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
@@ -3351,7 +3550,8 @@
 										RGXFWIF_DM_3D,
 										&s3DKCCBCmd,
 										sizeof(s3DKCCBCmd),
-										bPDumpContinuous);
+										ui32ClientCacheOpSeqNum,
+										ui32PDumpFlags);
 			if (eError2 != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -3402,34 +3602,14 @@
 	}
 #endif
 
-	if(paui32Server3DSyncFlags3D)
-	{
-		OSFreeMem(paui32Server3DSyncFlags3D);
-	}
-
-	if(paui32Server3DSyncFlagsPR)
-	{
-		OSFreeMem(paui32Server3DSyncFlagsPR);
-	}
-
 	*pi32UpdateFenceFD = i32UpdateFenceFD;
 
 	return PVRSRV_OK;
 
 fail_3dacquirecmd:
 fail_3dcmdinit:
-	if (paui32Server3DSyncFlags3D)
-	{
-		OSFreeMem(paui32Server3DSyncFlags3D);
-	}
-fail_prserversyncflagsalloc3d:
 fail_prcmdinit:
 fail_prfencecmdinit:
-	if (paui32Server3DSyncFlagsPR)
-	{
-		OSFreeMem(paui32Server3DSyncFlagsPR);
-	}
-fail_prserversyncflagsallocpr:
 fail_taacquirecmd:
 fail_tacmdinit:
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
@@ -3580,37 +3760,36 @@
 	OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
 }
 
-IMG_BOOL CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+IMG_UINT32 CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 	DLLIST_NODE *psNode, *psNext;
-	IMG_BOOL bStalled = IMG_FALSE;
+	IMG_UINT32 ui32ContextBitMask = 0;
 
 	OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock);
 
 	dllist_foreach_node(&psDevInfo->sRenderCtxtListHead, psNode, psNext)
 	{
-		IMG_BOOL bTAStalled=IMG_FALSE, b3DStalled = IMG_FALSE;
 		RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx =
 			IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
 		if(NULL != psCurrentServerRenderCtx->sTAData.psServerCommonContext)
 		{
-			bTAStalled = CheckStalledClientCommonContext(psCurrentServerRenderCtx->sTAData.psServerCommonContext) == PVRSRV_ERROR_CCCB_STALLED;
+			if (CheckStalledClientCommonContext(psCurrentServerRenderCtx->sTAData.psServerCommonContext, RGX_KICK_TYPE_DM_TA) == PVRSRV_ERROR_CCCB_STALLED)
+			{
+				ui32ContextBitMask |= RGX_KICK_TYPE_DM_TA;
+			}
 		}
 
 		if(NULL != psCurrentServerRenderCtx->s3DData.psServerCommonContext)
 		{
-			b3DStalled = CheckStalledClientCommonContext(psCurrentServerRenderCtx->s3DData.psServerCommonContext) == PVRSRV_ERROR_CCCB_STALLED;
-		}
-
-		if (bTAStalled || b3DStalled)
-		{
-			bStalled = IMG_TRUE;
-			break;
+			if (CheckStalledClientCommonContext(psCurrentServerRenderCtx->s3DData.psServerCommonContext, RGX_KICK_TYPE_DM_3D) == PVRSRV_ERROR_CCCB_STALLED)
+			{
+				ui32ContextBitMask |= RGX_KICK_TYPE_DM_3D;
+			}
 		}
 	}
 
 	OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
-	return bStalled;
+	return ui32ContextBitMask;
 }
 
 /******************************************************************************
diff --git a/drivers/staging/imgtec/rogue/rgxta3d.h b/drivers/staging/imgtec/rogue/rgxta3d.h
index f04f00e..bab2f41 100644
--- a/drivers/staging/imgtec/rogue/rgxta3d.h
+++ b/drivers/staging/imgtec/rogue/rgxta3d.h
@@ -53,6 +53,7 @@
 #include "sync_server.h"
 #include "connection_server.h"
 #include "rgxdebug.h"
+#include "pvr_notifier.h"
 
 typedef struct _RGX_SERVER_RENDER_CONTEXT_ RGX_SERVER_RENDER_CONTEXT;
 typedef struct _RGX_FREELIST_ RGX_FREELIST;
@@ -81,6 +82,7 @@
 	IMG_UINT32				ui32CurrentFLPages;
 	IMG_UINT32				ui32GrowFLPages;
 	IMG_UINT32				ui32FreelistID;
+	IMG_UINT32				ui32FreelistGlobalID;	/* related global freelist for this freelist */
 	IMG_UINT64				ui64FreelistChecksum;	/* checksum over freelist content */
 	IMG_BOOL				bCheckFreelist;			/* freelist check enabled */
 	IMG_UINT32				ui32RefCount;			/* freelist reference counting */
@@ -101,6 +103,10 @@
 	RGXFWIF_DEV_VIRTADDR	sFreeListFWDevVAddr;
 
 	PVRSRV_CLIENT_SYNC_PRIM	*psCleanupSync;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	HASH_TABLE*				psWorkloadHashTable;
+#endif
 } ;
 
 struct _RGX_PMR_NODE_ {
@@ -110,6 +116,9 @@
 	DLLIST_NODE				sMemoryBlock;
 	IMG_UINT32				ui32NumPages;
 	IMG_BOOL				bInternal;
+#if defined(PVR_RI_DEBUG)
+	RI_HANDLE				hRIHandle;
+#endif
 } ;
 
 typedef struct {
@@ -277,6 +286,7 @@
 							   IMG_UINT32			ui32MaxFLPages,
 							   IMG_UINT32			ui32InitFLPages,
 							   IMG_UINT32			ui32GrowFLPages,
+							   RGX_FREELIST			*psGlobalFreeList,
 							   IMG_BOOL				bCheckFreelist,
 							   IMG_DEV_VIRTADDR		sFreeListDevVAddr,
 							   PMR					*psFreeListPMR,
@@ -382,6 +392,7 @@
 ******************************************************************************/
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT	*psRenderContext,
+								 IMG_UINT32					ui32ClientCacheOpSeqNum,
 								 IMG_UINT32					ui32ClientTAFenceCount,
 								 SYNC_PRIMITIVE_BLOCK				**apsClientTAFenceSyncPrimBlock,
 								 IMG_UINT32					*paui32ClientTAFenceSyncOffset,
@@ -418,23 +429,27 @@
 								 IMG_UINT32					ui323DCmdSize,
 								 IMG_PBYTE					pui83DDMCmd,
 								 IMG_UINT32					ui32ExtJobRef,
-								 IMG_UINT32					ui32IntJobRef,
 								 IMG_BOOL					bLastTAInScene,
 								 IMG_BOOL					bKickTA,
 								 IMG_BOOL					bKickPR,
 								 IMG_BOOL					bKick3D,
 								 IMG_BOOL					bAbort,
-								 IMG_BOOL					bPDumpContinuous,
-								 RGX_RTDATA_CLEANUP_DATA        *psRTDataCleanup,
-								 RGX_ZSBUFFER_DATA              *psZBuffer,
-								 RGX_ZSBUFFER_DATA               *psSBuffer,
-								 IMG_BOOL						bCommitRefCountsTA,
-								 IMG_BOOL						bCommitRefCounts3D,
-								 IMG_BOOL						*pbCommittedRefCountsTA,
-								 IMG_BOOL						*pbCommittedRefCounts3D,
+								 IMG_UINT32					ui32PDumpFlags,
+								 RGX_RTDATA_CLEANUP_DATA	*psRTDataCleanup,
+								 RGX_ZSBUFFER_DATA			*psZBuffer,
+								 RGX_ZSBUFFER_DATA			*psSBuffer,
+								 IMG_BOOL					bCommitRefCountsTA,
+								 IMG_BOOL					bCommitRefCounts3D,
+								 IMG_BOOL					*pbCommittedRefCountsTA,
+								 IMG_BOOL					*pbCommittedRefCounts3D,
 								 IMG_UINT32					ui32SyncPMRCount,
 								 IMG_UINT32					*paui32SyncPMRFlags,
-								 PMR						**ppsSyncPMRs);
+								 PMR						**ppsSyncPMRs,
+								 IMG_UINT32					ui32RenderTargetSize,
+								 IMG_UINT32					ui32NumberOfDrawCalls,
+								 IMG_UINT32					ui32NumberOfIndices,
+								 IMG_UINT32					ui32NumberOfMRTs,
+								 IMG_UINT64					ui64DeadlineInus);
 
 
 PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
@@ -455,6 +470,6 @@
 				void *pvDumpDebugFile);
 
 /* Debug/Watchdog - check if client contexts are stalled */
-IMG_BOOL CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+IMG_UINT32 CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
 
 #endif /* __RGXTA3D_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxtdmtransfer.c b/drivers/staging/imgtec/rogue/rgxtdmtransfer.c
new file mode 100644
index 0000000..40f87a9
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxtdmtransfer.c
@@ -0,0 +1,814 @@
+/*************************************************************************/ /*!
+@File           rgxtdmtransfer.c
+@Title          Device specific TDM transfer queue routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "pdump_km.h"
+#include "rgxdevice.h"
+#include "rgxccb.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxtdmtransfer.h"
+#include "rgx_tq_shared.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "pvrsrv.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgx_memallocflags.h"
+#include "rgxtimerquery.h"
+#include "rgxhwperf.h"
+#include "htbuffer.h"
+
+#include "pdump_km.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "sync.h"
+
+#if defined(SUPPORT_BUFFER_SYNC)
+#include "pvr_buffer_sync.h"
+#endif
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+#include "pvr_sync.h"
+#endif
+
+
+typedef struct {
+	RGX_SERVER_COMMON_CONTEXT * psServerCommonContext;
+	IMG_UINT32                  ui32Priority;
+} RGX_SERVER_TQ_TDM_DATA;
+
+
+struct _RGX_SERVER_TQ_TDM_CONTEXT_ {
+	PVRSRV_DEVICE_NODE      *psDeviceNode;
+	DEVMEM_MEMDESC          *psFWFrameworkMemDesc;
+	IMG_UINT32              ui32Flags;
+	RGX_SERVER_TQ_TDM_DATA  sTDMData;
+	PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
+	DLLIST_NODE             sListNode;
+	SYNC_ADDR_LIST          sSyncAddrListFence;
+	SYNC_ADDR_LIST          sSyncAddrListUpdate;
+	ATOMIC_T                hJobId;
+};
+
+static PVRSRV_ERROR _CreateTDMTransferContext(
+	CONNECTION_DATA         * psConnection,
+	PVRSRV_DEVICE_NODE      * psDeviceNode,
+	DEVMEM_MEMDESC          * psFWMemContextMemDesc,
+	IMG_UINT32                ui32Priority,
+	RGX_COMMON_CONTEXT_INFO * psInfo,
+	RGX_SERVER_TQ_TDM_DATA  * psTDMData)
+{
+	PVRSRV_ERROR eError;
+
+	eError = FWCommonContextAllocate(
+		psConnection,
+		psDeviceNode,
+		REQ_TYPE_TQ_TDM,
+		RGXFWIF_DM_TDM,
+		NULL,
+		0,
+		psFWMemContextMemDesc,
+		NULL,
+		RGX_TQ2D_CCB_SIZE_LOG2,
+		ui32Priority,
+		psInfo,
+		&psTDMData->psServerCommonContext);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_contextalloc;
+	}
+
+	psTDMData->ui32Priority = ui32Priority;
+	return PVRSRV_OK;
+
+fail_contextalloc:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+
+static PVRSRV_ERROR _DestroyTDMTransferContext(
+	RGX_SERVER_TQ_TDM_DATA  * psTDMData,
+	PVRSRV_DEVICE_NODE      * psDeviceNode,
+	PVRSRV_CLIENT_SYNC_PRIM * psCleanupSync)
+{
+	PVRSRV_ERROR eError;
+
+	/* Check if the FW has finished with this resource ... */
+	eError = RGXFWRequestCommonContextCleanUp(
+		psDeviceNode,
+		psTDMData->psServerCommonContext,
+		psCleanupSync,
+		RGXFWIF_DM_TDM,
+		PDUMP_FLAGS_NONE);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		return eError;
+	}
+	else if (eError != PVRSRV_OK)
+	{
+		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+				 __FUNCTION__,
+				 PVRSRVGetErrorStringKM(eError)));
+		return eError;
+	}
+
+	/* ... it has so we can free it's resources */
+	FWCommonContextFree(psTDMData->psServerCommonContext);
+	return PVRSRV_OK;
+}
+
+/*
+ * PVRSRVCreateTransferContextKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
+	CONNECTION_DATA            * psConnection,
+	PVRSRV_DEVICE_NODE         * psDeviceNode,
+	IMG_UINT32                   ui32Priority,
+	IMG_DEV_VIRTADDR             sMCUFenceAddr,
+	IMG_UINT32                   ui32FrameworkCommandSize,
+	IMG_PBYTE                    pabyFrameworkCommand,
+	IMG_HANDLE                   hMemCtxPrivData,
+	RGX_SERVER_TQ_TDM_CONTEXT ** ppsTransferContext)
+{
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext;
+
+	DEVMEM_MEMDESC          * psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+	RGX_COMMON_CONTEXT_INFO   sInfo;
+	PVRSRV_ERROR              eError = PVRSRV_OK;
+	PVRSRV_RGXDEV_INFO        *psDevInfo = psDeviceNode->pvDevice;
+
+	/* Allocate the server side structure */
+	*ppsTransferContext = NULL;
+	psTransferContext = OSAllocZMem(sizeof(*psTransferContext));
+	if (psTransferContext == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psTransferContext->psDeviceNode = psDeviceNode;
+
+	/* Allocate cleanup sync */
+	eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+						   &psTransferContext->psCleanupSync,
+						   "transfer context cleanup");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate cleanup sync (0x%x)",
+				eError));
+		goto fail_syncalloc;
+	}
+
+	/* 
+	 * Create the FW framework buffer
+	 */
+	eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+										&psTransferContext->psFWFrameworkMemDesc,
+										ui32FrameworkCommandSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate firmware GPU framework state (%u)",
+				eError));
+		goto fail_frameworkcreate;
+	}
+
+	/* Copy the Framework client data into the framework buffer */
+	eError = PVRSRVRGXFrameworkCopyCommand(psTransferContext->psFWFrameworkMemDesc,
+										   pabyFrameworkCommand,
+										   ui32FrameworkCommandSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to populate the framework buffer (%u)",
+				eError));
+		goto fail_frameworkcopy;
+	}
+
+	sInfo.psFWFrameworkMemDesc = psTransferContext->psFWFrameworkMemDesc;
+	sInfo.psMCUFenceAddr = &sMCUFenceAddr;
+
+	eError = _CreateTDMTransferContext(psConnection,
+									  psDeviceNode,
+									  psFWMemContextMemDesc,
+									  ui32Priority,
+									  &sInfo,
+									  &psTransferContext->sTDMData);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_tdmtransfercontext;
+	}
+
+	SyncAddrListInit(&psTransferContext->sSyncAddrListFence);
+	SyncAddrListInit(&psTransferContext->sSyncAddrListUpdate);
+
+	{
+		OSWRLockAcquireWrite(psDevInfo->hTDMCtxListLock);
+		dllist_add_to_tail(&(psDevInfo->sTDMCtxtListHead), &(psTransferContext->sListNode));
+		OSWRLockReleaseWrite(psDevInfo->hTDMCtxListLock);
+		*ppsTransferContext = psTransferContext;
+	}
+
+	*ppsTransferContext = psTransferContext;
+	
+	return PVRSRV_OK;
+	
+fail_tdmtransfercontext:
+fail_frameworkcopy:
+	DevmemFwFree(psDevInfo, psTransferContext->psFWFrameworkMemDesc);
+fail_frameworkcreate:
+	SyncPrimFree(psTransferContext->psCleanupSync);
+fail_syncalloc:
+	OSFreeMem(psTransferContext);
+	PVR_ASSERT(eError != PVRSRV_OK);
+	*ppsTransferContext = NULL;
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMDestroyTransferContextKM(RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psTransferContext->psDeviceNode->pvDevice;
+
+	/* remove node from list before calling destroy - as destroy, if successful
+	 * will invalidate the node
+	 * must be re-added if destroy fails
+	 */
+	OSWRLockAcquireWrite(psDevInfo->hTDMCtxListLock);
+	dllist_remove_node(&(psTransferContext->sListNode));
+	OSWRLockReleaseWrite(psDevInfo->hTDMCtxListLock);
+
+
+	eError = _DestroyTDMTransferContext(&psTransferContext->sTDMData,
+	                                    psTransferContext->psDeviceNode,
+	                                    psTransferContext->psCleanupSync);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_destroyTDM;
+	}
+
+	DevmemFwFree(psDevInfo, psTransferContext->psFWFrameworkMemDesc);
+	SyncPrimFree(psTransferContext->psCleanupSync);
+
+	SyncAddrListDeinit(&psTransferContext->sSyncAddrListFence);
+	SyncAddrListDeinit(&psTransferContext->sSyncAddrListUpdate);
+
+	OSFreeMem(psTransferContext);
+
+	return PVRSRV_OK;
+
+  fail_destroyTDM:
+
+	OSWRLockAcquireWrite(psDevInfo->hTDMCtxListLock);
+	dllist_add_to_tail(&(psDevInfo->sTDMCtxtListHead), &(psTransferContext->sListNode));
+	OSWRLockReleaseWrite(psDevInfo->hTDMCtxListLock);
+	PVR_ASSERT(eError != PVRSRV_OK);
+	return eError;
+}
+
+
+/*
+ * PVRSRVSubmitTQ3DKickKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext,
+	IMG_UINT32                  ui32PDumpFlags,
+	IMG_UINT32                  ui32ClientCacheOpSeqNum,
+	IMG_UINT32                  ui32ClientFenceCount,
+	SYNC_PRIMITIVE_BLOCK     ** pauiClientFenceUFOSyncPrimBlock,
+	IMG_UINT32                * paui32ClientFenceSyncOffset,
+	IMG_UINT32                * paui32ClientFenceValue,
+	IMG_UINT32                  ui32ClientUpdateCount,
+	SYNC_PRIMITIVE_BLOCK     ** pauiClientUpdateUFOSyncPrimBlock,
+	IMG_UINT32                * paui32ClientUpdateSyncOffset,
+	IMG_UINT32                * paui32ClientUpdateValue,
+	IMG_UINT32                  ui32ServerSyncCount,
+	IMG_UINT32                * paui32ServerSyncFlags,
+	SERVER_SYNC_PRIMITIVE    ** papsServerSyncs,
+	IMG_INT32                   i32CheckFenceFD,
+	IMG_INT32                   i32UpdateTimelineFD,
+	IMG_INT32                 * pi32UpdateFenceFD,
+	IMG_CHAR                    szFenceName[32],
+	IMG_UINT32                  ui32FWCommandSize,
+	IMG_UINT8                 * pui8FWCommand,
+	IMG_UINT32                  ui32ExtJobRef,
+	IMG_UINT32                  ui32SyncPMRCount,
+	IMG_UINT32                * paui32SyncPMRFlags,
+	PMR                      ** ppsSyncPMRs)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode = psTransferContext->psDeviceNode;
+	RGX_CCB_CMD_HELPER_DATA *psCmdHelper;
+	PRGXFWIF_UFO_ADDR * pauiIntFenceUFOAddress   = NULL;
+	PRGXFWIF_UFO_ADDR * pauiIntUpdateUFOAddress  = NULL;
+	IMG_UINT32        * paui32IntFenceValue      = paui32ClientFenceValue;
+	IMG_UINT32          ui32IntClientFenceCount  = ui32ClientFenceCount;
+	IMG_UINT32        * paui32IntUpdateValue     = paui32ClientUpdateValue;
+	IMG_UINT32          ui32IntClientUpdateCount = ui32ClientUpdateCount;
+	PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError2;
+	IMG_INT32 i32UpdateFenceFD = -1;
+	IMG_UINT32 ui32JobId;
+
+	IMG_UINT32 ui32CmdOffset = 0;
+
+	PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+	PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+	PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+
+#if defined(SUPPORT_BUFFER_SYNC)
+	struct pvr_buffer_sync_append_data *psAppendData = NULL;
+#endif
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	struct pvr_sync_append_data *psFDFenceData = NULL;
+
+	if (i32UpdateTimelineFD >= 0 && !pi32UpdateFenceFD)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+#else
+	if (i32UpdateTimelineFD >= 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Providing native sync timeline (%d) in non native sync enabled driver",
+			__func__, i32UpdateTimelineFD));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	if (i32CheckFenceFD >= 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Providing native check sync (%d) in non native sync enabled driver",
+			__func__, i32CheckFenceFD));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+#endif
+
+	ui32JobId = OSAtomicIncrement(&psTransferContext->hJobId);
+
+	/* Ensure the string is null-terminated (Required for safety) */
+	szFenceName[31] = '\0';
+
+	if (ui32SyncPMRCount != 0)
+	{
+		if (!ppsSyncPMRs)
+		{
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	}
+
+	/* We can't allocate the required amount of stack space on all consumer architectures */
+	psCmdHelper = OSAllocMem(sizeof(RGX_CCB_CMD_HELPER_DATA));
+	if (psCmdHelper == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto fail_allochelper;
+	}
+
+
+	/*
+		Init the command helper commands for all the prepares
+	*/
+	{
+		RGX_CLIENT_CCB *psClientCCB;
+		RGX_SERVER_COMMON_CONTEXT *psServerCommonCtx;
+		IMG_CHAR *pszCommandName;
+		RGXFWIF_CCB_CMD_TYPE eType;
+
+		psServerCommonCtx = psTransferContext->sTDMData.psServerCommonContext;
+		psClientCCB = FWCommonContextGetClientCCB(psServerCommonCtx);
+		pszCommandName = "TQ-TDM";
+		eType = (ui32FWCommandSize == 0) ? RGXFWIF_CCB_CMD_TYPE_NULL : RGXFWIF_CCB_CMD_TYPE_TQ_TDM;
+
+		eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListFence,
+		                              ui32ClientFenceCount,
+		                              pauiClientFenceUFOSyncPrimBlock,
+		                              paui32ClientFenceSyncOffset);
+		if(eError != PVRSRV_OK)
+		{
+			goto fail_populate_sync_addr_list;
+		}
+		pauiIntFenceUFOAddress = psTransferContext->sSyncAddrListFence.pasFWAddrs;
+
+		eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListUpdate,
+										ui32ClientUpdateCount,
+										pauiClientUpdateUFOSyncPrimBlock,
+										paui32ClientUpdateSyncOffset);
+		if(eError != PVRSRV_OK)
+		{
+			goto fail_populate_sync_addr_list;
+		}
+		pauiIntUpdateUFOAddress = psTransferContext->sSyncAddrListUpdate.pasFWAddrs;
+
+
+#if defined(SUPPORT_BUFFER_SYNC)
+		if (ui32SyncPMRCount)
+		{
+			int err;
+
+			err = pvr_buffer_sync_append_start(psDeviceNode->psBufferSyncContext,
+											   ui32SyncPMRCount,
+											   ppsSyncPMRs,
+											   paui32SyncPMRFlags,
+											   ui32IntClientFenceCount,
+											   pauiIntFenceUFOAddress,
+											   paui32IntFenceValue,
+											   ui32IntClientUpdateCount,
+											   pauiIntUpdateUFOAddress,
+											   paui32IntUpdateValue,
+											   &psAppendData);
+			if (err)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to append buffer syncs (errno=%d)", __FUNCTION__, err));
+				eError = (err == -ENOMEM) ? PVRSRV_ERROR_OUT_OF_MEMORY : PVRSRV_ERROR_INVALID_PARAMS;
+				goto fail_sync_append;
+			}
+
+			pvr_buffer_sync_append_checks_get(psAppendData,
+											  &ui32IntClientFenceCount,
+											  &pauiIntFenceUFOAddress,
+											  &paui32IntFenceValue);
+
+			pvr_buffer_sync_append_updates_get(psAppendData,
+											   &ui32IntClientUpdateCount,
+											   &pauiIntUpdateUFOAddress,
+											   &paui32IntUpdateValue);
+		}
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	if (i32CheckFenceFD >= 0 || i32UpdateTimelineFD >= 0)
+	{
+		eError =
+		  pvr_sync_append_fences(szFenceName,
+		                               i32CheckFenceFD,
+		                               i32UpdateTimelineFD,
+		                               ui32IntClientUpdateCount,
+		                               pauiIntUpdateUFOAddress,
+		                               paui32IntUpdateValue,
+		                               ui32IntClientFenceCount,
+		                               pauiIntFenceUFOAddress,
+		                               paui32IntFenceValue,
+		                               &psFDFenceData);
+		if (eError != PVRSRV_OK)
+		{
+			goto fail_syncinit;
+		}
+		pvr_sync_get_updates(psFDFenceData, &ui32IntClientUpdateCount,
+			&pauiIntUpdateUFOAddress, &paui32IntUpdateValue);
+		pvr_sync_get_checks(psFDFenceData, &ui32IntClientFenceCount,
+			&pauiIntFenceUFOAddress, &paui32IntFenceValue);
+	}
+#endif
+
+		RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psTransferContext->psDeviceNode->pvDevice,
+		                          & pPreAddr,
+		                          & pPostAddr,
+		                          & pRMWUFOAddr);
+
+		/*
+			Create the command helper data for this command
+		*/
+		eError = RGXCmdHelperInitCmdCCB(psClientCCB,
+		                                ui32IntClientFenceCount,
+		                                pauiIntFenceUFOAddress,
+		                                paui32IntFenceValue,
+		                                ui32IntClientUpdateCount,
+		                                pauiIntUpdateUFOAddress,
+		                                paui32IntUpdateValue,
+		                                ui32ServerSyncCount,
+		                                paui32ServerSyncFlags,
+		                                SYNC_FLAG_MASK_ALL,
+		                                papsServerSyncs,
+		                                ui32FWCommandSize,
+		                                pui8FWCommand,
+		                                & pPreAddr,
+		                                & pPostAddr,
+		                                & pRMWUFOAddr,
+		                                eType,
+		                                ui32ExtJobRef,
+		                                ui32JobId,
+		                                ui32PDumpFlags,
+		                                NULL,
+		                                pszCommandName,
+		                                psCmdHelper);
+		if (eError != PVRSRV_OK)
+		{
+			goto fail_initcmd;
+		}
+	}
+
+	/*
+		Acquire space for all the commands in one go
+	*/
+	
+	eError = RGXCmdHelperAcquireCmdCCB(1, psCmdHelper);
+	if (eError != PVRSRV_OK)
+	{
+			goto fail_3dcmdacquire;
+	}
+
+
+	/*
+		We should acquire the kernel CCB(s) space here as the schedule could fail
+		and we would have to roll back all the syncs
+	*/
+
+	/*
+		Only do the command helper release (which takes the server sync
+		operations if the acquire succeeded
+	*/
+	ui32CmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->sTDMData.psServerCommonContext));
+	RGXCmdHelperReleaseCmdCCB(1,
+	                          psCmdHelper,
+	                          "TQ_TDM",
+	                          FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext).ui32Addr);
+
+
+	/*
+		Even if we failed to acquire the client CCB space we might still need
+		to kick the HW to process a padding packet to release space for us next
+		time round
+	*/
+	{
+		RGXFWIF_KCCB_CMD sTDMKCCBCmd;
+
+		/* Construct the kernel 3D CCB command. */
+		sTDMKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+		sTDMKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext);
+		sTDMKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->sTDMData.psServerCommonContext));
+		sTDMKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+		/* HTBLOGK(HTB_SF_MAIN_KICK_TDM, */
+		/* 		s3DKCCBCmd.uCmdData.sCmdKickData.psContext, */
+		/* 		ui323DCmdOffset); */
+		RGX_HWPERF_HOST_ENQ(psTransferContext, OSGetCurrentClientProcessIDKM(),
+		                    FWCommonContextGetFWAddress(psTransferContext->
+		                    sTDMData.psServerCommonContext).ui32Addr,
+		                    ui32ExtJobRef, ui32JobId, RGX_HWPERF_KICK_TYPE_TQTDM);
+
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
+										RGXFWIF_DM_TDM,
+			                            & sTDMKCCBCmd,
+										sizeof(sTDMKCCBCmd),
+										ui32ClientCacheOpSeqNum,
+										ui32PDumpFlags);
+			if (eError2 != PVRSRV_ERROR_RETRY)
+			{
+				break;
+			}
+			OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+		} END_LOOP_UNTIL_TIMEOUT();
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+		RGXHWPerfFTraceGPUEnqueueEvent(psDeviceNode->pvDevice,
+ 			FWCommonContextGetFWAddress(psTransferContext->
+ 				sTDMData.psServerCommonContext).ui32Addr,
+			ui32JobId, RGX_HWPERF_KICK_TYPE_TQTDM);
+#endif
+	}
+
+	/*
+	 * Now check eError (which may have returned an error from our earlier calls
+	 * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
+	 * so we check it now...
+	 */
+	if (eError != PVRSRV_OK )
+	{
+		goto fail_2dcmdacquire;
+	}
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+	if (i32UpdateTimelineFD >= 0)
+	{
+		/* If we get here, this should never fail. Hitting that likely implies
+		 * a code error above */
+		i32UpdateFenceFD = pvr_sync_get_update_fd(psFDFenceData);
+		if (i32UpdateFenceFD < 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get install update sync fd",
+				__FUNCTION__));
+			/* If we fail here, we cannot rollback the syncs as the hw already
+			 * has references to resources they may be protecting in the kick
+			 * so fallthrough */
+
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto fail_free_append_data;
+		}
+	}
+#if defined(NO_HARDWARE)
+	pvr_sync_nohw_complete_fences(psFDFenceData);
+#endif
+	/*
+		Free the merged sync memory if required
+	*/
+	pvr_sync_free_append_fences_data(psFDFenceData);
+#endif
+
+#if defined(SUPPORT_BUFFER_SYNC)
+	if (psAppendData)
+	{
+		pvr_buffer_sync_append_finish(psAppendData);
+	}
+#endif
+
+	* pi32UpdateFenceFD = i32UpdateFenceFD;
+
+	OSFreeMem(psCmdHelper);
+
+	return PVRSRV_OK;
+
+/*
+	No resources are created in this function so there is nothing to free
+	unless we had to merge syncs.
+	If we fail after the client CCB acquire there is still nothing to do
+	as only the client CCB release will modify the client CCB
+*/
+fail_2dcmdacquire:
+fail_3dcmdacquire:
+
+fail_initcmd:
+
+/* fail_pdumpcheck: */
+/* fail_cmdtype: */
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+fail_syncinit:
+	/* Relocated cleanup here as the loop could fail after the first iteration
+	 * at the above goto tags at which point the psFDCheckData memory would
+	 * have been allocated.
+	 */
+	pvr_sync_rollback_append_fences(psFDFenceData);
+fail_free_append_data:
+	pvr_sync_free_append_fences_data(psFDFenceData);
+#endif
+#if defined(SUPPORT_BUFFER_SYNC)
+	pvr_buffer_sync_append_abort(psAppendData);
+fail_sync_append:
+#endif
+fail_populate_sync_addr_list:
+	PVR_ASSERT(eError != PVRSRV_OK);
+	OSFreeMem(psCmdHelper);
+fail_allochelper:
+	return eError;
+	
+
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMNotifyWriteOffsetUpdateKM(
+	RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+	IMG_UINT32                 ui32PDumpFlags)
+{
+	RGXFWIF_KCCB_CMD  sKCCBCmd;
+	PVRSRV_ERROR      eError;
+
+	/* Schedule the firmware command */
+	sKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE;
+	sKCCBCmd.uCmdData.sWriteOffsetUpdateData.psContext = FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext);
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		eError = RGXScheduleCommand(psTransferContext->psDeviceNode->pvDevice,
+		                            RGXFWIF_DM_TDM,
+		                            &sKCCBCmd,
+		                            sizeof(sKCCBCmd),
+		                            0,
+		                            ui32PDumpFlags);
+		if (eError != PVRSRV_ERROR_RETRY)
+		{
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXTDMNotifyWriteOffsetUpdateKM: Failed to schedule the FW command %d (%s)",
+				eError, PVRSRVGETERRORSTRING(eError)));
+	}
+
+	return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXTDMSetTransferContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                   PVRSRV_DEVICE_NODE * psDeviceNode,
+												   RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+												   IMG_UINT32 ui32Priority)
+{
+	PVRSRV_ERROR eError;
+	
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	
+	if (psTransferContext->sTDMData.ui32Priority != ui32Priority)
+	{
+		eError = ContextSetPriority(psTransferContext->sTDMData.psServerCommonContext,
+									psConnection,
+									psTransferContext->psDeviceNode->pvDevice,
+									ui32Priority,
+									RGXFWIF_DM_TDM);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+void CheckForStalledTDMTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	DLLIST_NODE *psNode, *psNext;
+
+	OSWRLockAcquireRead(psDevInfo->hTDMCtxListLock);
+
+	dllist_foreach_node(&psDevInfo->sTDMCtxtListHead, psNode, psNext)
+	{
+		RGX_SERVER_TQ_TDM_CONTEXT *psCurrentServerTransferCtx =
+			IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_TDM_CONTEXT, sListNode);
+
+		DumpStalledFWCommonContext(psCurrentServerTransferCtx->sTDMData.psServerCommonContext,
+		                           pfnDumpDebugPrintf, pvDumpDebugFile);
+	}
+
+	OSWRLockReleaseRead(psDevInfo->hTDMCtxListLock);
+}
+
+
+IMG_UINT32 CheckForStalledClientTDMTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	DLLIST_NODE *psNode, *psNext;
+	IMG_UINT32 ui32ContextBitMask = 0;
+
+	OSWRLockAcquireRead(psDevInfo->hTDMCtxListLock);
+
+	dllist_foreach_node(&psDevInfo->sTDMCtxtListHead, psNode, psNext)
+	{
+		RGX_SERVER_TQ_TDM_CONTEXT *psCurrentServerTransferCtx =
+			IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_TDM_CONTEXT, sListNode);
+
+		if (CheckStalledClientCommonContext(
+			             psCurrentServerTransferCtx->sTDMData.psServerCommonContext, RGX_KICK_TYPE_DM_TDM_2D)
+			         == PVRSRV_ERROR_CCCB_STALLED) {
+			ui32ContextBitMask = RGX_KICK_TYPE_DM_TDM_2D;
+		}
+	}
+
+	OSWRLockReleaseRead(psDevInfo->hTDMCtxListLock);
+	return ui32ContextBitMask;
+}
+
+
+
+/**************************************************************************//**
+ End of file (rgxtdmtransfer.c)
+******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxtdmtransfer.h b/drivers/staging/imgtec/rogue/rgxtdmtransfer.h
new file mode 100644
index 0000000..8ebbbb50
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxtdmtransfer.h
@@ -0,0 +1,123 @@
+/*************************************************************************/ /*!
+@File           rgxtdmtransfer.h
+@Title          RGX Transfer queue 2 Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX Transfer queue Functionality
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__RGXTDMTRANSFER_H__)
+#define __RGXTDMTRANSFER_H__
+
+#include "devicemem.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgxdebug.h"
+#include "pvr_notifier.h"
+
+#include "sync_server.h"
+#include "connection_server.h"
+
+typedef struct _RGX_SERVER_TQ_TDM_CONTEXT_ RGX_SERVER_TQ_TDM_CONTEXT;
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
+	CONNECTION_DATA           * psConnection,
+	PVRSRV_DEVICE_NODE        * psDeviceNode,
+	IMG_UINT32                  ui32Priority,
+	IMG_DEV_VIRTADDR            sMCUFenceAddr,
+	IMG_UINT32                  ui32FrameworkCommandSize,
+	IMG_PBYTE                   pabyFrameworkCommand,
+	IMG_HANDLE                  hMemCtxPrivData,
+	RGX_SERVER_TQ_TDM_CONTEXT **ppsTransferContext);
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMDestroyTransferContextKM(RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext);
+
+
+PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
+	RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext,
+	IMG_UINT32                  ui32PDumpFlags,
+	IMG_UINT32                  ui32ClientCacheOpSeqNum,
+	IMG_UINT32                  ui32ClientFenceCount,
+	SYNC_PRIMITIVE_BLOCK     ** pauiClientFenceUFOSyncPrimBlock,
+	IMG_UINT32                * paui32ClientFenceSyncOffset,
+	IMG_UINT32                * paui32ClientFenceValue,
+	IMG_UINT32                  ui32ClientUpdateCount,
+	SYNC_PRIMITIVE_BLOCK     ** pauiClientUpdateUFOSyncPrimBlock,
+	IMG_UINT32                * paui32ClientUpdateSyncOffset,
+	IMG_UINT32                * paui32ClientUpdateValue,
+	IMG_UINT32                  ui32ServerSyncCount,
+	IMG_UINT32                * paui32ServerSyncFlags,
+	SERVER_SYNC_PRIMITIVE    ** papsServerSyncs,
+	IMG_INT32                   i32CheckFenceFD,
+	IMG_INT32                   i32UpdateTimelineFD,
+	IMG_INT32                 * pi32UpdateFenceFD,
+	IMG_CHAR                    szFenceName[32],
+	IMG_UINT32                  ui32FWCommandSize,
+	IMG_UINT8                 * pui8FWCommand,
+	IMG_UINT32                  ui32ExtJobRef,
+	IMG_UINT32                  ui32SyncPMRCount,
+	IMG_UINT32                * pui32SyncPMRFlags,
+	PMR                      ** ppsSyncPMRs);
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMNotifyWriteOffsetUpdateKM(
+	RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+	IMG_UINT32                 ui32PDumpFlags);
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXTDMSetTransferContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                   PVRSRV_DEVICE_NODE * psDeviceNode,
+												   RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+												   IMG_UINT32 ui32Priority);
+
+/* Debug - check if transfer context is waiting on a fence */
+void CheckForStalledTDMTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile);
+
+/* Debug/Watchdog - check if client transfer contexts are stalled */
+IMG_UINT32 CheckForStalledClientTDMTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+
+#endif /* __RGXTDMTRANSFER_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxtimecorr.c b/drivers/staging/imgtec/rogue/rgxtimecorr.c
index 45bc390..7d595eb 100644
--- a/drivers/staging/imgtec/rogue/rgxtimecorr.c
+++ b/drivers/staging/imgtec/rogue/rgxtimecorr.c
@@ -44,6 +44,7 @@
 #include "rgxtimecorr.h"
 #include "rgxfwutils.h"
 #include "htbserver.h"
+#include "pvrsrv_apphint.h"
 
 /******************************************************************************
  *
@@ -65,6 +66,89 @@
  *
  *****************************************************************************/
 
+static IMG_UINT32 g_ui32ClockSource = PVRSRV_APPHINT_TIMECORRCLOCK;
+
+/*
+	AppHint interfaces
+*/
+
+static PVRSRV_ERROR _SetClock(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const void *psPrivate,
+                              IMG_UINT32 ui32Value)
+{
+	static const IMG_CHAR *apszClocks[] = {
+		"mono", "mono_raw", "sched"
+	};
+
+	if (ui32Value >= RGXTIMECORR_CLOCK_LAST)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Invalid clock source type (%u)", ui32Value));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	g_ui32ClockSource = ui32Value;
+
+	PVR_DPF((PVR_DBG_WARNING, "Time correlation clock set to \"%s\"",
+			apszClocks[g_ui32ClockSource]));
+
+	if (psDeviceNode)
+	{
+		/* update correlation data, and unfortunately we have to remove
+		* 'const' to do so */
+		RGXGPUFreqCalibrateCorrelatePeriodic((PVRSRV_DEVICE_NODE *) psDeviceNode);
+	}
+
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+	PVR_UNREFERENCED_PARAMETER(apszClocks);
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _GetClock(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const void *psPrivate,
+                              IMG_UINT32 *pui32Value)
+{
+	*pui32Value = g_ui32ClockSource;
+
+	PVR_UNREFERENCED_PARAMETER(psPrivate);
+
+	return PVRSRV_OK;
+}
+
+void RGXGPUFreqCalibrationInitAppHintCallbacks(
+                                         const PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_TimeCorrClock, _GetClock,
+	                                    _SetClock, psDeviceNode, NULL);
+}
+
+/*
+	End of AppHint interface
+*/
+
+IMG_UINT64 RGXGPUFreqCalibrateClockns64(void)
+{
+	IMG_UINT64 ui64Clock;
+
+	switch (g_ui32ClockSource) {
+		case RGXTIMECORR_CLOCK_MONO:
+			return ((void) OSClockMonotonicns64(&ui64Clock), ui64Clock);
+		case RGXTIMECORR_CLOCK_MONO_RAW:
+			return OSClockMonotonicRawns64();
+		case RGXTIMECORR_CLOCK_SCHED:
+			return OSClockns64();
+		default:
+			PVR_ASSERT(IMG_FALSE);
+			return 0;
+	}
+}
+
+IMG_UINT64 RGXGPUFreqCalibrateClockus64(void)
+{
+	IMG_UINT32 rem;
+	return OSDivide64r64(RGXGPUFreqCalibrateClockns64(), 1000, &rem);
+}
+
 static void _RGXMakeTimeCorrData(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_BOOL bLogToHTB)
 {
 	PVRSRV_RGXDEV_INFO    *psDevInfo     = psDeviceNode->pvDevice;
@@ -74,15 +158,33 @@
 	IMG_UINT32            ui32NewSeqCount;
 	IMG_UINT32            ui32CoreClockSpeed;
 	IMG_UINT32            ui32Remainder;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	IMG_UINT64            ui64OSMonoTime = 0;
+#endif
 
 	ui32CoreClockSpeed = psGpuDVFSTable->aui32DVFSClock[psGpuDVFSTable->ui32CurrentDVFSId];
 
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	{
+		PVRSRV_ERROR eError;
+		eError = OSClockMonotonicns64(&ui64OSMonoTime);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"_RGXMakeTimeCorrData: System Monotonic Clock not available."));
+			PVR_ASSERT(eError == PVRSRV_OK);
+		}
+	}
+#endif
+
 	ui32NewSeqCount = psGpuUtilFWCB->ui32TimeCorrSeqCount + 1;
 	psTimeCorr = &psGpuUtilFWCB->sTimeCorr[RGXFWIF_TIME_CORR_CURR_INDEX(ui32NewSeqCount)];
 
-	psTimeCorr->ui64CRTimeStamp    = RGXReadHWTimerReg(psDevInfo);
-	psTimeCorr->ui64OSTimeStamp    = OSClockns64();
-	psTimeCorr->ui32CoreClockSpeed = ui32CoreClockSpeed;
+	psTimeCorr->ui64CRTimeStamp     = RGXReadHWTimerReg(psDevInfo);
+	psTimeCorr->ui64OSTimeStamp     = RGXGPUFreqCalibrateClockns64();
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	psTimeCorr->ui64OSMonoTimeStamp = ui64OSMonoTime;
+#endif
+	psTimeCorr->ui32CoreClockSpeed  = ui32CoreClockSpeed;
 	psTimeCorr->ui32CRDeltaToOSDeltaKNs =
 	    RGXFWIF_GET_CRDELTA_TO_OSDELTA_K_NS(ui32CoreClockSpeed, ui32Remainder);
 
@@ -111,21 +213,21 @@
 	IMG_UINT32         ui32Index          = RGX_GPU_DVFS_GET_INDEX(ui32CoreClockSpeed);
 
 	IMG_UINT64 ui64CRTimestamp = RGXReadHWTimerReg(psDevInfo);
-	IMG_UINT64 ui64OSTimestamp = OSClockus64();
+	IMG_UINT64 ui64OSTimestamp = RGXGPUFreqCalibrateClockus64();
 
 	psGpuDVFSTable->ui64CalibrationCRTimestamp = ui64CRTimestamp;
 	psGpuDVFSTable->ui64CalibrationOSTimestamp = ui64OSTimestamp;
 
 	/* Set the time needed to (re)calibrate the GPU frequency */
-	if((psGpuDVFSTable->aui32DVFSClock[ui32Index] == 0) ||                /* We never met this frequency */
-	   (psGpuDVFSTable->aui32DVFSClock[ui32Index] == ui32CoreClockSpeed)) /* We weren't able to calibrate this frequency previously */
+	if ((psGpuDVFSTable->aui32DVFSClock[ui32Index] == 0) ||                /* We never met this frequency */
+	    (psGpuDVFSTable->aui32DVFSClock[ui32Index] == ui32CoreClockSpeed)) /* We weren't able to calibrate this frequency previously */
 	{
 		psGpuDVFSTable->aui32DVFSClock[ui32Index] = ui32CoreClockSpeed;
 		psGpuDVFSTable->ui32CalibrationPeriod     = RGX_GPU_DVFS_FIRST_CALIBRATION_TIME_US;
 
 		PVR_DPF((PVR_DBG_MESSAGE, "RGXGPUFreqCalibrationStart: using uncalibrated GPU frequency %u", ui32CoreClockSpeed));
 	}
-	else if(psGpuDVFSTable->ui32CalibrationPeriod == RGX_GPU_DVFS_FIRST_CALIBRATION_TIME_US)
+	else if (psGpuDVFSTable->ui32CalibrationPeriod == RGX_GPU_DVFS_FIRST_CALIBRATION_TIME_US)
 	{
 		psGpuDVFSTable->ui32CalibrationPeriod = RGX_GPU_DVFS_TRANSITION_CALIBRATION_TIME_US;
 	}
@@ -145,9 +247,9 @@
 	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
 	IMG_UINT64 ui64CRTimestamp = RGXReadHWTimerReg(psDevInfo);
-	IMG_UINT64 ui64OSTimestamp = OSClockus64();
+	IMG_UINT64 ui64OSTimestamp = RGXGPUFreqCalibrateClockus64();
 
-	if(!psGpuDVFSTable->bAccumulatePeriod)
+	if (!psGpuDVFSTable->bAccumulatePeriod)
 	{
 		psGpuDVFSTable->ui64CalibrationCRTimediff = 0;
 		psGpuDVFSTable->ui64CalibrationOSTimediff = 0;
@@ -193,9 +295,9 @@
 
 
 /*
-	RGXGPUFreqCalibratePrePowerState
+	RGXGPUFreqCalibratePrePowerOff
 */
-void RGXGPUFreqCalibratePrePowerState(IMG_HANDLE hDevHandle)
+void RGXGPUFreqCalibratePrePowerOff(IMG_HANDLE hDevHandle)
 {
 	PVRSRV_DEVICE_NODE  *psDeviceNode   = hDevHandle;
 	PVRSRV_RGXDEV_INFO  *psDevInfo      = psDeviceNode->pvDevice;
@@ -203,7 +305,7 @@
 
 	_RGXGPUFreqCalibrationPeriodStop(psDeviceNode, psGpuDVFSTable);
 
-	if(psGpuDVFSTable->ui64CalibrationOSTimediff >= psGpuDVFSTable->ui32CalibrationPeriod)
+	if (psGpuDVFSTable->ui64CalibrationOSTimediff >= psGpuDVFSTable->ui32CalibrationPeriod)
 	{
 		_RGXGPUFreqCalibrationCalculate(psDeviceNode, psGpuDVFSTable);
 	}
@@ -211,9 +313,9 @@
 
 
 /*
-	RGXGPUFreqCalibratePostPowerState
+	RGXGPUFreqCalibratePostPowerOn
 */
-void RGXGPUFreqCalibratePostPowerState(IMG_HANDLE hDevHandle)
+void RGXGPUFreqCalibratePostPowerOn(IMG_HANDLE hDevHandle)
 {
 	PVRSRV_DEVICE_NODE  *psDeviceNode      = hDevHandle;
 	PVRSRV_RGXDEV_INFO  *psDevInfo         = psDeviceNode->pvDevice;
@@ -263,10 +365,10 @@
 	RGX_GPU_DVFS_TABLE  *psGpuDVFSTable        = psDevInfo->psGpuDVFSTable;
 	IMG_UINT32          ui32ReturnedClockSpeed = ui32NewClockSpeed;
 
-	if(RGX_GPU_DVFS_GET_INDEX(ui32NewClockSpeed) != psGpuDVFSTable->ui32CurrentDVFSId)
+	if (RGX_GPU_DVFS_GET_INDEX(ui32NewClockSpeed) != psGpuDVFSTable->ui32CurrentDVFSId)
 	{
 		/* Only calibrate if the last period was long enough */
-		if(psGpuDVFSTable->ui64CalibrationOSTimediff >= RGX_GPU_DVFS_TRANSITION_CALIBRATION_TIME_US)
+		if (psGpuDVFSTable->ui64CalibrationOSTimediff >= RGX_GPU_DVFS_TRANSITION_CALIBRATION_TIME_US)
 		{
 			ui32ReturnedClockSpeed = _RGXGPUFreqCalibrationCalculate(psDeviceNode, psGpuDVFSTable);
 		}
@@ -294,24 +396,23 @@
 	PVRSRV_DEVICE_NODE     *psDeviceNode   = hDevHandle;
 	PVRSRV_RGXDEV_INFO     *psDevInfo      = psDeviceNode->pvDevice;
 	RGX_GPU_DVFS_TABLE     *psGpuDVFSTable = psDevInfo->psGpuDVFSTable;
-	PVRSRV_DATA            *psPVRSRVData;
-	IMG_UINT64             ui64TimeNow     = OSClockus64();
+	IMG_UINT64             ui64TimeNow     = RGXGPUFreqCalibrateClockus64();
 	PVRSRV_DEV_POWER_STATE ePowerState;
 
 	/* Check if it's the right time to recalibrate the GPU clock frequency */
-	if((ui64TimeNow - psGpuDVFSTable->ui64CalibrationOSTimestamp) < psGpuDVFSTable->ui32CalibrationPeriod) return;
+	if ((ui64TimeNow - psGpuDVFSTable->ui64CalibrationOSTimestamp) < psGpuDVFSTable->ui32CalibrationPeriod) return;
 
 	/* Try to acquire the powerlock, if not possible then don't wait */
-	psPVRSRVData     = PVRSRVGetPVRSRVData();
-	if (OSLockIsLocked(psPVRSRVData->hPowerLock)) return; /* Better to not wait here if possible */
-	/* There's a chance that the powerlock could be taken here, it's not that bad even if not desirable */
-	if (PVRSRVPowerLock() != PVRSRV_OK) return;
+	if (OSLockIsLocked(psDeviceNode->hPowerLock)) return; /* Better to not wait here if possible */
+	/* There's a chance that the powerlock could be taken here, it's not that bad even if not desirable
+	   (TODO use OSTryLockAcquire, currently implemented under Linux only) */
+	if (PVRSRVPowerLock(psDeviceNode) != PVRSRV_OK) return;
 
 	/* If the GPU is off then we can't do anything */
-	PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
+	PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 	if (ePowerState != PVRSRV_DEV_POWER_STATE_ON)
 	{
-		PVRSRVPowerUnlock();
+		PVRSRVPowerUnlock(psDeviceNode);
 		return;
 	}
 
@@ -321,7 +422,24 @@
 	_RGXGPUFreqCalibrationPeriodStart(psDeviceNode, psGpuDVFSTable);
 	_RGXMakeTimeCorrData(psDeviceNode, IMG_TRUE);
 
-	PVRSRVPowerUnlock();
+	PVRSRVPowerUnlock(psDeviceNode);
+}
+
+/*
+	RGXGPUFreqCalibrateClockSource
+*/
+RGXTIMECORR_CLOCK_TYPE RGXGPUFreqCalibrateGetClockSource(void)
+{
+	return g_ui32ClockSource;
+}
+
+/*
+	RGXGPUFreqCalibrateClockSource
+*/
+PVRSRV_ERROR RGXGPUFreqCalibrateSetClockSource(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               RGXTIMECORR_CLOCK_TYPE eClockType)
+{
+	return _SetClock(psDeviceNode, NULL, eClockType);
 }
 
 
diff --git a/drivers/staging/imgtec/rogue/rgxtimecorr.h b/drivers/staging/imgtec/rogue/rgxtimecorr.h
index 8a1b7bb..b307056 100644
--- a/drivers/staging/imgtec/rogue/rgxtimecorr.h
+++ b/drivers/staging/imgtec/rogue/rgxtimecorr.h
@@ -45,11 +45,20 @@
 #define __RGXTIMECORR_H__
 
 #include "img_types.h"
+#include "device.h"
+
+typedef enum {
+    RGXTIMECORR_CLOCK_MONO,
+    RGXTIMECORR_CLOCK_MONO_RAW,
+    RGXTIMECORR_CLOCK_SCHED,
+
+    RGXTIMECORR_CLOCK_LAST
+} RGXTIMECORR_CLOCK_TYPE;
 
 /*!
 ******************************************************************************
 
- @Function    RGXGPUFreqCalibratePrePowerState
+ @Function    RGXGPUFreqCalibratePrePowerOff
 
  @Description Manage GPU frequency and timer correlation data
               before a power off.
@@ -59,12 +68,12 @@
  @Return      void
 
 ******************************************************************************/
-void RGXGPUFreqCalibratePrePowerState(IMG_HANDLE hDevHandle);
+void RGXGPUFreqCalibratePrePowerOff(IMG_HANDLE hDevHandle);
 
 /*!
 ******************************************************************************
 
- @Function    RGXGPUFreqCalibratePostPowerState
+ @Function    RGXGPUFreqCalibratePostPowerOn
 
  @Description Manage GPU frequency and timer correlation data
               after a power on.
@@ -74,7 +83,7 @@
  @Return      void
 
 ******************************************************************************/
-void RGXGPUFreqCalibratePostPowerState(IMG_HANDLE hDevHandle);
+void RGXGPUFreqCalibratePostPowerOn(IMG_HANDLE hDevHandle);
 
 /*!
 ******************************************************************************
@@ -122,4 +131,59 @@
 ******************************************************************************/
 void RGXGPUFreqCalibrateCorrelatePeriodic(IMG_HANDLE hDevHandle);
 
+/*!
+******************************************************************************
+
+ @Function    RGXGPUFreqCalibrateClockns64
+
+ @Description Returns value of currently selected clock (in ns).
+
+ @Return      clock value from currently selected clock source
+
+******************************************************************************/
+IMG_UINT64 RGXGPUFreqCalibrateClockns64(void);
+
+/*!
+******************************************************************************
+
+ @Function    RGXGPUFreqCalibrateClockns64
+
+ @Description Returns value of currently selected clock (in us).
+
+ @Return      clock value from currently selected clock source
+
+******************************************************************************/
+IMG_UINT64 RGXGPUFreqCalibrateClockus64(void);
+
+/*!
+******************************************************************************
+
+ @Function    RGXGPUFreqCalibrateClockSource
+
+ @Description Returns currently selected clock source
+
+ @Return      clock source type
+
+******************************************************************************/
+RGXTIMECORR_CLOCK_TYPE RGXGPUFreqCalibrateGetClockSource(void);
+
+/*!
+******************************************************************************
+
+ @Function    RGXGPUFreqCalibrateSetClockSource
+
+ @Description Sets clock source for correlation data.
+
+ @Input       psDeviceNode : RGX Device Node
+ @Input       eClockType : clock source type
+
+ @Return      error code
+
+******************************************************************************/
+PVRSRV_ERROR RGXGPUFreqCalibrateSetClockSource(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                             RGXTIMECORR_CLOCK_TYPE eClockType);
+
+void RGXGPUFreqCalibrationInitAppHintCallbacks(
+                                        const PVRSRV_DEVICE_NODE *psDeviceNode);
+
 #endif /* __RGXTIMECORR_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxtimerquery.c b/drivers/staging/imgtec/rogue/rgxtimerquery.c
index 8170e3e..bb4f4a5 100644
--- a/drivers/staging/imgtec/rogue/rgxtimerquery.c
+++ b/drivers/staging/imgtec/rogue/rgxtimerquery.c
@@ -43,6 +43,7 @@
 
 #include "rgxtimerquery.h"
 #include "rgxdevice.h"
+#include "rgxtimecorr.h"
 
 #include "rgxfwutils.h"
 #include "pdump_km.h"
@@ -140,7 +141,7 @@
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 
-	*pui64Time = OSClockns64();
+	*pui64Time = RGXGPUFreqCalibrateClockns64();
 
 	return PVRSRV_OK;
 }
diff --git a/drivers/staging/imgtec/rogue/rgxtransfer.c b/drivers/staging/imgtec/rogue/rgxtransfer.c
index 390c665..839c5df 100644
--- a/drivers/staging/imgtec/rogue/rgxtransfer.c
+++ b/drivers/staging/imgtec/rogue/rgxtransfer.c
@@ -59,11 +59,14 @@
 #include "rgx_memallocflags.h"
 #include "rgxtimerquery.h"
 #include "rgxhwperf.h"
-#include "rgxsync.h"
 #include "htbuffer.h"
 
+#include "pdump_km.h"
+
 #include "sync_server.h"
 #include "sync_internal.h"
+#include "sync.h"
+#include "rgx_bvnc_defs_km.h"
 
 #if defined(SUPPORT_BUFFER_SYNC)
 #include "pvr_buffer_sync.h"
@@ -79,6 +82,7 @@
 	IMG_UINT32					ui32Priority;
 } RGX_SERVER_TQ_3D_DATA;
 
+
 typedef struct {
 	RGX_SERVER_COMMON_CONTEXT	*psServerCommonContext;
 	IMG_UINT32					ui32Priority;
@@ -94,15 +98,16 @@
 	RGX_SERVER_TQ_2D_DATA		s2DData;
 	PVRSRV_CLIENT_SYNC_PRIM		*psCleanupSync;
 	DLLIST_NODE					sListNode;
-	SYNC_ADDR_LIST			sSyncAddrListFence;
-	SYNC_ADDR_LIST			sSyncAddrListUpdate;
-	ATOMIC_T				hJobId;
+	ATOMIC_T			hJobId;
+	IMG_UINT32			ui32PDumpFlags;
+	/* per-prepare sync address lists */
+	SYNC_ADDR_LIST			asSyncAddrListFence[TQ_MAX_PREPARES_PER_SUBMIT];
+	SYNC_ADDR_LIST			asSyncAddrListUpdate[TQ_MAX_PREPARES_PER_SUBMIT];
 };
 
 /*
 	Static functions used by transfer context code
 */
-
 static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection,
 											 PVRSRV_DEVICE_NODE *psDeviceNode,
 											 DEVMEM_MEMDESC *psFWMemContextMemDesc,
@@ -154,12 +159,13 @@
 	return PVRSRV_OK;
 
 fail_contextalloc:
-	DevmemFwFree(ps3DData->psFWContextStateMemDesc);
+	DevmemFwFree(psDevInfo, ps3DData->psFWContextStateMemDesc);
 fail_contextswitchstate:
 	PVR_ASSERT(eError != PVRSRV_OK);
 	return eError;
 }
 
+
 static PVRSRV_ERROR _Create2DTransferContext(CONNECTION_DATA *psConnection,
 											 PVRSRV_DEVICE_NODE *psDeviceNode,
 											 DEVMEM_MEMDESC *psFWMemContextMemDesc,
@@ -197,7 +203,8 @@
 
 static PVRSRV_ERROR _Destroy2DTransferContext(RGX_SERVER_TQ_2D_DATA *ps2DData,
 											  PVRSRV_DEVICE_NODE *psDeviceNode,
-											  PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+											  PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync,
+											  IMG_UINT32 ui32PDumpFlags)
 {
 	PVRSRV_ERROR eError;
 
@@ -205,7 +212,8 @@
 	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
 											  ps2DData->psServerCommonContext,
 											  psCleanupSync,
-											  RGXFWIF_DM_2D);
+											  RGXFWIF_DM_2D,
+											  ui32PDumpFlags);
 	if (eError == PVRSRV_ERROR_RETRY)
 	{
 		return eError;
@@ -215,6 +223,7 @@
 		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
 				 __FUNCTION__,
 				 PVRSRVGetErrorStringKM(eError)));
+		return eError;
 	}
 
 	/* ... it has so we can free it's resources */
@@ -225,7 +234,8 @@
 
 static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData,
 											  PVRSRV_DEVICE_NODE *psDeviceNode,
-											  PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+											  PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync,
+											  IMG_UINT32 ui32PDumpFlags)
 {
 	PVRSRV_ERROR eError;
 
@@ -233,7 +243,8 @@
 	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
 											  ps3DData->psServerCommonContext,
 											  psCleanupSync,
-											  RGXFWIF_DM_3D);
+											  RGXFWIF_DM_3D,
+											  ui32PDumpFlags);
 	if (eError == PVRSRV_ERROR_RETRY)
 	{
 		return eError;
@@ -243,15 +254,17 @@
 		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
 				 __FUNCTION__,
 				 PVRSRVGetErrorStringKM(eError)));
+		return eError;
 	}
 
 	/* ... it has so we can free it's resources */
-	DevmemFwFree(ps3DData->psFWContextStateMemDesc);
+	DevmemFwFree(psDeviceNode->pvDevice, ps3DData->psFWContextStateMemDesc);
 	FWCommonContextFree(ps3DData->psServerCommonContext);
 	ps3DData->psServerCommonContext = NULL;
 	return PVRSRV_OK;
 }
 
+
 /*
  * PVRSRVCreateTransferContextKM
  */
@@ -266,20 +279,19 @@
 										   RGX_SERVER_TQ_CONTEXT	**ppsTransferContext)
 {
 	RGX_SERVER_TQ_CONTEXT	*psTransferContext;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 	DEVMEM_MEMDESC			*psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
 	RGX_COMMON_CONTEXT_INFO	sInfo;
 	PVRSRV_ERROR			eError = PVRSRV_OK;
 
 	/* Allocate the server side structure */
 	*ppsTransferContext = NULL;
-	psTransferContext = OSAllocMem(sizeof(*psTransferContext));
+	psTransferContext = OSAllocZMem(sizeof(*psTransferContext));
 	if (psTransferContext == NULL)
 	{
 		return PVRSRV_ERROR_OUT_OF_MEMORY;
 	}
 
-	OSMemSet(psTransferContext, 0, sizeof(*psTransferContext));
-
 	psTransferContext->psDeviceNode = psDeviceNode;
 
 	/* Allocate cleanup sync */
@@ -332,20 +344,20 @@
 	}
 	psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_3D;
 
-	eError = _Create2DTransferContext(psConnection,
-									  psDeviceNode,
-									  psFWMemContextMemDesc,
-									  ui32Priority,
-									  &sInfo,
-									  &psTransferContext->s2DData);
-	if (eError != PVRSRV_OK)
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK)
 	{
-		goto fail_2dtransfercontext;
+		eError = _Create2DTransferContext(psConnection,
+										  psDeviceNode,
+										  psFWMemContextMemDesc,
+										  ui32Priority,
+										  &sInfo,
+										  &psTransferContext->s2DData);
+		if (eError != PVRSRV_OK)
+		{
+			goto fail_2dtransfercontext;
+		}
+		psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_2D;
 	}
-	psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_2D;
-
-	SyncAddrListInit(&psTransferContext->sSyncAddrListFence);
-	SyncAddrListInit(&psTransferContext->sSyncAddrListUpdate);
 
 	{
 		PVRSRV_RGXDEV_INFO			*psDevInfo = psDeviceNode->pvDevice;
@@ -357,15 +369,22 @@
 	}
 
 	*ppsTransferContext = psTransferContext;
+	
 	return PVRSRV_OK;
 
+
 fail_2dtransfercontext:
-	_Destroy3DTransferContext(&psTransferContext->s3DData,
-							  psTransferContext->psDeviceNode,
-							  psTransferContext->psCleanupSync);
+	if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK)
+	{
+		_Destroy3DTransferContext(&psTransferContext->s3DData,
+								  psTransferContext->psDeviceNode,
+								  psTransferContext->psCleanupSync,
+								  psTransferContext->ui32PDumpFlags);
+	}
+
 fail_3dtransfercontext:
 fail_frameworkcopy:
-	DevmemFwFree(psTransferContext->psFWFrameworkMemDesc);
+	DevmemFwFree(psDevInfo, psTransferContext->psFWFrameworkMemDesc);
 fail_frameworkcreate:
 	SyncPrimFree(psTransferContext->psCleanupSync);
 fail_syncalloc:
@@ -380,6 +399,7 @@
 {
 	PVRSRV_ERROR eError;
 	PVRSRV_RGXDEV_INFO *psDevInfo = psTransferContext->psDeviceNode->pvDevice;
+	IMG_UINT32 i;
 
 	/* remove node from list before calling destroy - as destroy, if successful
 	 * will invalidate the node
@@ -389,11 +409,13 @@
 	dllist_remove_node(&(psTransferContext->sListNode));
 	OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
 
-	if (psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D)
+	if ((psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) && \
+			(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 	{
 		eError = _Destroy2DTransferContext(&psTransferContext->s2DData,
 										   psTransferContext->psDeviceNode,
-										   psTransferContext->psCleanupSync);
+										   psTransferContext->psCleanupSync,
+										   PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			goto fail_destroy2d;
@@ -406,7 +428,8 @@
 	{
 		eError = _Destroy3DTransferContext(&psTransferContext->s3DData,
 										   psTransferContext->psDeviceNode,
-										   psTransferContext->psCleanupSync);
+										   psTransferContext->psCleanupSync,
+										   PDUMP_FLAGS_CONTINUOUS);
 		if (eError != PVRSRV_OK)
 		{
 			goto fail_destroy3d;
@@ -415,18 +438,23 @@
 		psTransferContext->ui32Flags &= ~RGX_SERVER_TQ_CONTEXT_FLAGS_3D;
 	}
 
-	DevmemFwFree(psTransferContext->psFWFrameworkMemDesc);
-	SyncPrimFree(psTransferContext->psCleanupSync);
+	/* free any resources within the per-prepare UFO address stores */
+	for(i = 0; i < TQ_MAX_PREPARES_PER_SUBMIT; i++)
+	{
+		SyncAddrListDeinit(&psTransferContext->asSyncAddrListFence[i]);
+		SyncAddrListDeinit(&psTransferContext->asSyncAddrListUpdate[i]);
+	}
 
-	SyncAddrListDeinit(&psTransferContext->sSyncAddrListFence);
-	SyncAddrListDeinit(&psTransferContext->sSyncAddrListUpdate);
+	DevmemFwFree(psDevInfo, psTransferContext->psFWFrameworkMemDesc);
+	SyncPrimFree(psTransferContext->psCleanupSync);
 
 	OSFreeMem(psTransferContext);
 
 	return PVRSRV_OK;
 
-fail_destroy2d:
 fail_destroy3d:
+
+fail_destroy2d:
 	OSWRLockAcquireWrite(psDevInfo->hTransferCtxListLock);
 	dllist_add_to_tail(&(psDevInfo->sTransferCtxtListHead), &(psTransferContext->sListNode));
 	OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
@@ -439,6 +467,7 @@
  */
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT	*psTransferContext,
+									   IMG_UINT32				ui32ClientCacheOpSeqNum,
 									   IMG_UINT32				ui32PrepareCount,
 									   IMG_UINT32				*paui32ClientFenceCount,
 									   SYNC_PRIMITIVE_BLOCK		***papauiClientFenceUFOSyncPrimBlock,
@@ -459,19 +488,19 @@
 									   IMG_UINT8				**papaui8FWCommand,
 									   IMG_UINT32				*pui32TQPrepareFlags,
 									   IMG_UINT32				ui32ExtJobRef,
-									   IMG_UINT32				ui32IntJobRef,
 									   IMG_UINT32				ui32SyncPMRCount,
 									   IMG_UINT32				*paui32SyncPMRFlags,
 									   PMR						**ppsSyncPMRs)
 {
 	PVRSRV_DEVICE_NODE *psDeviceNode = psTransferContext->psDeviceNode;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 	RGX_CCB_CMD_HELPER_DATA *pas3DCmdHelper;
 	RGX_CCB_CMD_HELPER_DATA *pas2DCmdHelper;
 	IMG_UINT32 ui323DCmdCount = 0;
 	IMG_UINT32 ui322DCmdCount = 0;
 	IMG_UINT32 ui323DCmdOffset = 0;
 	IMG_UINT32 ui322DCmdOffset = 0;
-	IMG_BOOL bPDumpContinuous = IMG_FALSE;
+	IMG_UINT32 ui32PDumpFlags = PDUMP_FLAGS_NONE;
 	IMG_UINT32 i;
 	IMG_UINT32 ui32IntClientFenceCount = 0;
 	PRGXFWIF_UFO_ADDR *pauiIntFenceUFOAddress = NULL;
@@ -513,14 +542,13 @@
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 #endif
-	PVR_UNREFERENCED_PARAMETER(ui32IntJobRef);
 
 	ui32JobId = OSAtomicIncrement(&psTransferContext->hJobId);
 
 	/* Ensure the string is null-terminated (Required for safety) */
 	szFenceName[31] = '\0';
 
-	if (ui32PrepareCount == 0)
+	if ((ui32PrepareCount == 0) || (ui32PrepareCount > TQ_MAX_PREPARES_PER_SUBMIT))
 	{
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
@@ -571,7 +599,7 @@
 	}
 
 	/*
-		Ensure we do the right thing for server syncs which cross call bounderies
+		Ensure we do the right thing for server syncs which cross call boundaries
 	*/
 	for (i=0;i<ui32PrepareCount;i++)
 	{
@@ -622,6 +650,8 @@
 		IMG_CHAR *pszCommandName;
 		RGX_CCB_CMD_HELPER_DATA *psCmdHelper;
 		RGXFWIF_CCB_CMD_TYPE eType;
+		SYNC_ADDR_LIST *psSyncAddrListFence;
+		SYNC_ADDR_LIST *psSyncAddrListUpdate;
 
 		if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 3D))
 		{
@@ -631,7 +661,8 @@
 			psCmdHelper = &pas3DCmdHelper[ui323DCmdCount++];
 			eType = RGXFWIF_CCB_CMD_TYPE_TQ_3D;
 		}
-		else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D))
+		else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D) && \
+				(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 		{
 			psServerCommonCtx = psTransferContext->s2DData.psServerCommonContext;
 			psClientCCB = FWCommonContextGetClientCCB(psServerCommonCtx);
@@ -647,15 +678,15 @@
 
 		if (i == 0)
 		{
-			bPDumpContinuous = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS);
-			PDUMPCOMMENTWITHFLAGS((bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0,
+			ui32PDumpFlags = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) != 0) ? PDUMP_FLAGS_CONTINUOUS : PDUMP_FLAGS_NONE;
+			PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
 					"%s Command Server Submit on FWCtx %08x", pszCommandName, FWCommonContextGetFWAddress(psServerCommonCtx).ui32Addr);
+			psTransferContext->ui32PDumpFlags |= ui32PDumpFlags;
 		}
 		else
 		{
-			IMG_BOOL bNewPDumpContinuous = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS);
-
-			if (bNewPDumpContinuous != bPDumpContinuous)
+			IMG_UINT32 ui32NewPDumpFlags = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) != 0) ? PDUMP_FLAGS_CONTINUOUS : PDUMP_FLAGS_NONE;
+			if (ui32NewPDumpFlags != ui32PDumpFlags)
 			{
 				eError = PVRSRV_ERROR_INVALID_PARAMS;
 				PVR_DPF((PVR_DBG_ERROR, "%s: Mixing of continuous and non-continuous command in a batch is not permitted", __FUNCTION__));
@@ -663,8 +694,9 @@
 			}
 		}
 
+		psSyncAddrListFence = &psTransferContext->asSyncAddrListFence[i];
 		ui32IntClientFenceCount  = paui32ClientFenceCount[i];
-		eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListFence,
+		eError = SyncAddrListPopulate(psSyncAddrListFence,
 										ui32IntClientFenceCount,
 										papauiClientFenceUFOSyncPrimBlock[i],
 										papaui32ClientFenceSyncOffset[i]);
@@ -672,11 +704,12 @@
 		{
 			goto fail_populate_sync_addr_list;
 		}
-		pauiIntFenceUFOAddress = psTransferContext->sSyncAddrListFence.pasFWAddrs;
+		pauiIntFenceUFOAddress = psSyncAddrListFence->pasFWAddrs;
 
 		paui32IntFenceValue      = papaui32ClientFenceValue[i];
+		psSyncAddrListUpdate = &psTransferContext->asSyncAddrListUpdate[i];
 		ui32IntClientUpdateCount = paui32ClientUpdateCount[i];
-		eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListUpdate,
+		eError = SyncAddrListPopulate(psSyncAddrListUpdate,
 										ui32IntClientUpdateCount,
 										papauiClientUpdateUFOSyncPrimBlock[i],
 										papaui32ClientUpdateSyncOffset[i]);
@@ -684,7 +717,7 @@
 		{
 			goto fail_populate_sync_addr_list;
 		}
-		pauiIntUpdateUFOAddress = psTransferContext->sSyncAddrListUpdate.pasFWAddrs;
+		pauiIntUpdateUFOAddress = psSyncAddrListUpdate->pasFWAddrs;
 		paui32IntUpdateValue     = papaui32ClientUpdateValue[i];
 
 #if defined(SUPPORT_BUFFER_SYNC)
@@ -692,7 +725,8 @@
 		{
 			int err;
 
-			err = pvr_buffer_sync_append_start(ui32SyncPMRCount,
+			err = pvr_buffer_sync_append_start(psDeviceNode->psBufferSyncContext,
+											   ui32SyncPMRCount,
 											   ppsSyncPMRs,
 											   paui32SyncPMRFlags,
 											   ui32IntClientFenceCount,
@@ -763,6 +797,7 @@
 		                                paui32IntUpdateValue,
 		                                paui32ServerSyncCount[i],
 		                                papaui32ServerSyncFlags[i],
+		                                SYNC_FLAG_MASK_ALL,
 		                                papapsServerSyncs[i],
 		                                paui32FWCommandSize[i],
 		                                papaui8FWCommand[i],
@@ -772,7 +807,8 @@
 		                                eType,
 		                                ui32ExtJobRef,
 		                                ui32JobId,
-		                                bPDumpContinuous,
+		                                ui32PDumpFlags,
+		                                NULL,
 		                                pszCommandName,
 		                                psCmdHelper);
 		if (eError != PVRSRV_OK)
@@ -831,7 +867,7 @@
 		
 	}
 
-	if (ui322DCmdCount)
+	if ((ui322DCmdCount) && (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 	{
 		ui322DCmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s2DData.psServerCommonContext));
 		RGXCmdHelperReleaseCmdCCB(ui322DCmdCount,
@@ -855,7 +891,8 @@
 		s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext);
 		s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s3DData.psServerCommonContext));
 		s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
-
+		s3DKCCBCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
+		s3DKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
 		HTBLOGK(HTB_SF_MAIN_KICK_3D,
 				s3DKCCBCmd.uCmdData.sCmdKickData.psContext,
 				ui323DCmdOffset);
@@ -869,7 +906,8 @@
 										RGXFWIF_DM_3D,
 										&s3DKCCBCmd,
 										sizeof(s3DKCCBCmd),
-										bPDumpContinuous);
+										ui32ClientCacheOpSeqNum,
+										ui32PDumpFlags);
 			if (eError2 != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -883,7 +921,7 @@
 #endif
 	}
 
-	if (ui322DCmdCount)
+	if ((ui322DCmdCount) && (psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 	{
 		RGXFWIF_KCCB_CMD s2DKCCBCmd;
 		IMG_UINT32 ui32FWCtx = FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext).ui32Addr;
@@ -907,7 +945,8 @@
 										RGXFWIF_DM_2D,
 										&s2DKCCBCmd,
 										sizeof(s2DKCCBCmd),
-										bPDumpContinuous);
+										ui32ClientCacheOpSeqNum,
+										ui32PDumpFlags);
 			if (eError2 != PVRSRV_ERROR_RETRY)
 			{
 				break;
@@ -986,6 +1025,7 @@
 fail_pdumpcheck:
 fail_cmdtype:
 
+fail_populate_sync_addr_list:
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 fail_syncinit:
 	/* Relocated cleanup here as the loop could fail after the first iteration
@@ -1000,7 +1040,6 @@
 	pvr_buffer_sync_append_abort(psAppendData);
 fail_sync_append:
 #endif
-fail_populate_sync_addr_list:
 	PVR_ASSERT(eError != PVRSRV_OK);
 	OSFreeMem(pas2DCmdHelper);
 fail_alloc2dhelper:
@@ -1009,16 +1048,19 @@
 	return eError;
 }
 
+
 PVRSRV_ERROR PVRSRVRGXSetTransferContextPriorityKM(CONNECTION_DATA *psConnection,
                                                    PVRSRV_DEVICE_NODE * psDevNode,
 												   RGX_SERVER_TQ_CONTEXT *psTransferContext,
 												   IMG_UINT32 ui32Priority)
 {
 	PVRSRV_ERROR eError;
+	PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice;
 
 	PVR_UNREFERENCED_PARAMETER(psDevNode);
 
-	if (psTransferContext->s2DData.ui32Priority != ui32Priority)
+	if ((psTransferContext->s2DData.ui32Priority != ui32Priority)  && \
+			(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 	{
 		eError = ContextSetPriority(psTransferContext->s2DData.psServerCommonContext,
 									psConnection,
@@ -1027,7 +1069,10 @@
 									RGXFWIF_DM_2D);
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 2D part of the transfercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			if(eError != PVRSRV_ERROR_RETRY)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 2D part of the transfercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			}
 			goto fail_2dcontext;
 		}
 		psTransferContext->s2DData.ui32Priority = ui32Priority;
@@ -1042,14 +1087,19 @@
 									RGXFWIF_DM_3D);
 		if (eError != PVRSRV_OK)
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 3D part of the transfercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			if(eError != PVRSRV_ERROR_RETRY)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 3D part of the transfercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+			}
 			goto fail_3dcontext;
 		}
 		psTransferContext->s3DData.ui32Priority = ui32Priority;
 	}
+	
 	return PVRSRV_OK;
 
 fail_3dcontext:
+
 fail_2dcontext:
 	PVR_ASSERT(eError != PVRSRV_OK);
 	return eError;
@@ -1068,7 +1118,8 @@
 		RGX_SERVER_TQ_CONTEXT *psCurrentServerTransferCtx =
 			IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_CONTEXT, sListNode);
 
-		if (psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D)
+		if ((psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) && \
+				(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 		{
 			DumpStalledFWCommonContext(psCurrentServerTransferCtx->s2DData.psServerCommonContext,
 									   pfnDumpDebugPrintf, pvDumpDebugFile);
@@ -1084,212 +1135,39 @@
 	OSWRLockReleaseRead(psDevInfo->hTransferCtxListLock);
 }
 
-IMG_BOOL CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+IMG_UINT32 CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 	DLLIST_NODE *psNode, *psNext;
-	IMG_BOOL bStalled = IMG_FALSE;
+	IMG_UINT32 ui32ContextBitMask = 0;
 
 	OSWRLockAcquireRead(psDevInfo->hTransferCtxListLock);
 
 	dllist_foreach_node(&psDevInfo->sTransferCtxtListHead, psNode, psNext)
 	{
-		IMG_BOOL bTQ2DStalled = IMG_FALSE, bTQ3DStalled = IMG_FALSE;
 		RGX_SERVER_TQ_CONTEXT *psCurrentServerTransferCtx =
 			IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_CONTEXT, sListNode);
-		if(NULL != psCurrentServerTransferCtx->s2DData.psServerCommonContext)
+
+		if ((psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) && \
+				(NULL != psCurrentServerTransferCtx->s2DData.psServerCommonContext) && \
+				(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_TLA_BIT_MASK))
 		{
-			bTQ2DStalled = CheckStalledClientCommonContext(psCurrentServerTransferCtx->s2DData.psServerCommonContext) == PVRSRV_ERROR_CCCB_STALLED;
+			if (CheckStalledClientCommonContext(psCurrentServerTransferCtx->s2DData.psServerCommonContext, RGX_KICK_TYPE_DM_TQ2D) == PVRSRV_ERROR_CCCB_STALLED)
+			{
+				ui32ContextBitMask |= RGX_KICK_TYPE_DM_TQ2D;
+			}
 		}
 
-		if(NULL != psCurrentServerTransferCtx->s3DData.psServerCommonContext)
+		if ((psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_3D) && (NULL != psCurrentServerTransferCtx->s3DData.psServerCommonContext))
 		{
-			bTQ3DStalled = CheckStalledClientCommonContext(psCurrentServerTransferCtx->s3DData.psServerCommonContext) == PVRSRV_ERROR_CCCB_STALLED;
-		}
-
-		if (bTQ2DStalled || bTQ3DStalled)
-		{
-			bStalled = IMG_TRUE;
-			break;
+			if ((CheckStalledClientCommonContext(psCurrentServerTransferCtx->s3DData.psServerCommonContext, RGX_KICK_TYPE_DM_TQ3D) == PVRSRV_ERROR_CCCB_STALLED))
+			{
+				ui32ContextBitMask |= RGX_KICK_TYPE_DM_TQ3D;
+			}
 		}
 	}
 
 	OSWRLockReleaseRead(psDevInfo->hTransferCtxListLock);
-	return bStalled;
-}
-
-PVRSRV_ERROR PVRSRVRGXKickSyncTransferKM(RGX_SERVER_TQ_CONTEXT	*psTransferContext,
-									   IMG_UINT32				ui32ClientFenceCount,
-									   SYNC_PRIMITIVE_BLOCK		**pauiClientFenceUFOSyncPrimBlock,
-									   IMG_UINT32				*paui32ClientFenceSyncOffset,
-									   IMG_UINT32				*paui32ClientFenceValue,
-									   IMG_UINT32				ui32ClientUpdateCount,
-									   SYNC_PRIMITIVE_BLOCK		**pauiClientUpdateUFOSyncPrimBlock,
-									   IMG_UINT32				*paui32ClientUpdateSyncOffset,
-									   IMG_UINT32				*paui32ClientUpdateValue,
-									   IMG_UINT32				ui32ServerSyncCount,
-									   IMG_UINT32				*pui32ServerSyncFlags,
-									   SERVER_SYNC_PRIMITIVE	**pasServerSyncs,
-									   IMG_INT32				i32CheckFenceFD,
-									   IMG_INT32				i32UpdateTimelineFD,
-									   IMG_INT32				*pi32UpdateFenceFD,
-									   IMG_CHAR			        szFenceName[32],
-									   IMG_UINT32				ui32TQPrepareFlags,
-									   IMG_UINT32				ui32ExtJobRef,
-									   IMG_UINT32				ui32IntJobRef)
-{
-	PVRSRV_ERROR                eError;
-	RGX_SERVER_COMMON_CONTEXT   *psServerCommonCtx;
-	IMG_CHAR                    *pszCommandName;
-	RGXFWIF_DM                  eDM;
-	IMG_BOOL                    bPDumpContinuous;
-	IMG_INT32					i32UpdateFenceFD = -1;
-	IMG_UINT32					ui32JobId;
-
-	PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress;
-	PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress;
-
-#if defined(SUPPORT_NATIVE_FENCE_SYNC)
-	/* Android fd sync update info */
-	struct pvr_sync_append_data *psFDFenceData = NULL;
-#endif
-	PVR_UNREFERENCED_PARAMETER(ui32IntJobRef);
-
-	ui32JobId = OSAtomicIncrement(&psTransferContext->hJobId);
-
-	/* Ensure the string is null-terminated (Required for safety) */
-	szFenceName[31] = '\0';
-
-	eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListFence,
-									ui32ClientFenceCount,
-									pauiClientFenceUFOSyncPrimBlock,
-									paui32ClientFenceSyncOffset);
-	if(eError != PVRSRV_OK)
-	{
-		goto err_populate_sync_addr_list;
-	}
-
-	pauiClientFenceUFOAddress = psTransferContext->sSyncAddrListFence.pasFWAddrs;
-
-	eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListUpdate,
-									ui32ClientUpdateCount,
-									pauiClientUpdateUFOSyncPrimBlock,
-									paui32ClientUpdateSyncOffset);
-	if(eError != PVRSRV_OK)
-	{
-		goto err_populate_sync_addr_list;
-	}
-
-	pauiClientUpdateUFOAddress = psTransferContext->sSyncAddrListUpdate.pasFWAddrs;
-
-	bPDumpContinuous = ((ui32TQPrepareFlags & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS);
-
-	if (TQ_PREP_FLAGS_COMMAND_IS(ui32TQPrepareFlags, 3D))
-	{
-		psServerCommonCtx = psTransferContext->s3DData.psServerCommonContext;
-		pszCommandName = "SyncTQ-3D";
-		eDM = RGXFWIF_DM_3D;
-	}
-	else if (TQ_PREP_FLAGS_COMMAND_IS(ui32TQPrepareFlags, 2D))
-	{
-		psServerCommonCtx = psTransferContext->s2DData.psServerCommonContext;
-		pszCommandName = "SyncTQ-2D";
-		eDM = RGXFWIF_DM_2D;
-	}
-	else
-	{
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-
-#if defined(SUPPORT_NATIVE_FENCE_SYNC)
-	/* Android FD fences are hardcoded to updates (IMG_TRUE below), Fences go to the TA and updates to the 3D */
-	if (i32UpdateTimelineFD >= 0 && !pi32UpdateFenceFD)
-	{
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
-	if (i32CheckFenceFD >= 0 || i32UpdateTimelineFD >= 0)
-	{
-		eError =
-		  pvr_sync_append_fences(szFenceName,
-		                         i32CheckFenceFD,
-		                         i32UpdateTimelineFD,
-		                         ui32ClientUpdateCount,
-		                         pauiClientUpdateUFOAddress,
-		                         paui32ClientUpdateValue,
-		                         ui32ClientFenceCount,
-		                         pauiClientFenceUFOAddress,
-		                         paui32ClientFenceValue,
-		                         &psFDFenceData);
-		if (eError != PVRSRV_OK)
-		{
-			goto fail_fdsync;
-		}
-		pvr_sync_get_updates(psFDFenceData, &ui32ClientUpdateCount,
-			&pauiClientUpdateUFOAddress, &paui32ClientUpdateValue);
-		pvr_sync_get_checks(psFDFenceData, &ui32ClientFenceCount,
-			&pauiClientFenceUFOAddress, &paui32ClientFenceValue);
-	}
-#endif /* defined(SUPPORT_NATIVE_FENCE_SYNC) */
-
-	eError = 
-		RGXKickSyncKM(psTransferContext->psDeviceNode,
-				      psServerCommonCtx,
-				      eDM,
-				      pszCommandName,
-				      ui32ClientFenceCount,
-				      pauiClientFenceUFOAddress,
-				      paui32ClientFenceValue,
-				      ui32ClientUpdateCount,
-				      pauiClientUpdateUFOAddress,
-				      paui32ClientUpdateValue,
-				      ui32ServerSyncCount,
-				      pui32ServerSyncFlags,
-				      pasServerSyncs,
-				      bPDumpContinuous,
-				      ui32ExtJobRef,
-				      ui32JobId);
-
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Error calling RGXKickSyncKM (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
-		goto fail_kicksync;
-	}
-
-#if defined(SUPPORT_NATIVE_FENCE_SYNC)
-	if (i32UpdateTimelineFD >= 0)
-	{
-		/* If we get here, this should never fail. Hitting that likely implies
-		 * a code error above */
-		i32UpdateFenceFD = pvr_sync_get_update_fd(psFDFenceData);
-		if (i32UpdateFenceFD < 0)
-		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get install update sync fd",
-				__FUNCTION__));
-			/* If we fail here, we cannot rollback the syncs as the hw already
-			 * has references to resources they may be protecting in the kick
-			 * so fallthrough */
-
-			eError = PVRSRV_ERROR_INVALID_PARAMS;
-			goto fail_free_append_data;
-		}
-	}
-#if defined(NO_HARDWARE)
-	pvr_sync_nohw_complete_fences(psFDFenceData);
-#endif
-	pvr_sync_free_append_fences_data(psFDFenceData);
-#endif
-	*pi32UpdateFenceFD = i32UpdateFenceFD;
-
-	return eError;
-
-fail_kicksync:
-#if defined(SUPPORT_NATIVE_FENCE_SYNC)
-	pvr_sync_rollback_append_fences(psFDFenceData);
-fail_free_append_data:
-	pvr_sync_free_append_fences_data(psFDFenceData);
-fail_fdsync:
-#endif
-err_populate_sync_addr_list:
-	return eError;
+	return ui32ContextBitMask;
 }
 
 /**************************************************************************//**
diff --git a/drivers/staging/imgtec/rogue/rgxtransfer.h b/drivers/staging/imgtec/rogue/rgxtransfer.h
index 3699f4d..ac89f34 100644
--- a/drivers/staging/imgtec/rogue/rgxtransfer.h
+++ b/drivers/staging/imgtec/rogue/rgxtransfer.h
@@ -50,6 +50,7 @@
 #include "rgxfwutils.h"
 #include "rgx_fwif_resetframework.h"
 #include "rgxdebug.h"
+#include "pvr_notifier.h"
 
 #include "sync_server.h"
 #include "connection_server.h"
@@ -66,6 +67,8 @@
 
  @Input pvDeviceNode - device node
  
+FIXME fill this in
+
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
@@ -110,6 +113,7 @@
 ******************************************************************************/
 IMG_EXPORT
 PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT	*psTransferContext,
+									IMG_UINT32				ui32ClientCacheOpSeqNum,
 									IMG_UINT32				ui32PrepareCount,
 									IMG_UINT32				*paui32ClientFenceCount,
 									SYNC_PRIMITIVE_BLOCK		***papauiClientFenceUFOSyncPrimBlock,
@@ -130,7 +134,6 @@
 									IMG_UINT8				**papaui8FWCommand,
 									IMG_UINT32				*pui32TQPrepareFlags,
 									IMG_UINT32				ui32ExtJobRef,
-									IMG_UINT32				ui32IntJobRef,
 									IMG_UINT32				ui32SyncPMRCount,
 									IMG_UINT32				*paui32SyncPMRFlags,
 									PMR						**ppsSyncPMRs);
@@ -147,25 +150,6 @@
 					void *pvDumpDebugFile);
 
 /* Debug/Watchdog - check if client transfer contexts are stalled */
-IMG_BOOL CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+IMG_UINT32 CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
 
-PVRSRV_ERROR PVRSRVRGXKickSyncTransferKM(RGX_SERVER_TQ_CONTEXT	*psTransferContext,
-									   IMG_UINT32				ui32ClientFenceCount,
-									   SYNC_PRIMITIVE_BLOCK		**pauiClientFenceUFOSyncPrimBlock,
-									   IMG_UINT32				*paui32ClientFenceSyncOffset,
-									   IMG_UINT32				*paui32ClientFenceValue,
-									   IMG_UINT32				ui32ClientUpdateCount,
-									   SYNC_PRIMITIVE_BLOCK		**pauiClientUpdateUFOSyncPrimBlock,
-									   IMG_UINT32				*paui32ClientUpdateSyncOffset,
-									   IMG_UINT32				*paui32ClientUpdateValue,
-									   IMG_UINT32				ui32ServerSyncCount,
-									   IMG_UINT32				*pui32ServerSyncFlags,
-									   SERVER_SYNC_PRIMITIVE	**pasServerSyncs,
-									   IMG_INT32				i32CheckFenceFD,
-									   IMG_INT32				i32UpdateTimelineFD,
-									   IMG_INT32				*pi32UpdateFenceFD,
-									   IMG_CHAR					szFenceName[32],
-									   IMG_UINT32				ui32TQPrepareFlags,
-									   IMG_UINT32				ui32ExtJobRef,
-									   IMG_UINT32				ui32IntJobRef);
 #endif /* __RGXTRANSFER_H__ */
diff --git a/drivers/staging/imgtec/rogue/rgxutils.c b/drivers/staging/imgtec/rogue/rgxutils.c
index 588195a..8b01a05 100644
--- a/drivers/staging/imgtec/rogue/rgxutils.c
+++ b/drivers/staging/imgtec/rogue/rgxutils.c
@@ -54,6 +54,151 @@
 #include "sync_internal.h"
 #include "rgxfwutils.h"
 
+
+PVRSRV_ERROR RGXQueryAPMState(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_UINT32 *pui32State)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_UNREFERENCED_PARAMETER(pvPrivateData);
+
+	if (!psDeviceNode)
+		return PVRSRV_ERROR_INVALID_PARAMS;
+
+	psDevInfo = psDeviceNode->pvDevice;
+	*pui32State = psDevInfo->eActivePMConf;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXSetAPMState(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_UINT32 ui32State)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_UNREFERENCED_PARAMETER(pvPrivateData);
+
+	if (!psDeviceNode || !psDeviceNode->pvDevice)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	if (RGX_ACTIVEPM_FORCE_OFF != ui32State
+		|| !psDevInfo->pvAPMISRData)
+	{
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+
+#if !defined(NO_HARDWARE)
+	eError = OSUninstallMISR(psDevInfo->pvAPMISRData);
+	if (PVRSRV_OK == eError)
+	{
+		psDevInfo->eActivePMConf = RGX_ACTIVEPM_FORCE_OFF;
+		psDevInfo->pvAPMISRData = NULL;
+		eError = PVRSRVSetDeviceDefaultPowerState(psDeviceNode,
+		                                          PVRSRV_DEV_POWER_STATE_ON);
+	}
+#endif
+
+	return eError;
+}
+
+PVRSRV_ERROR RGXQueryPdumpPanicEnable(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_BOOL *pbEnabled)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_UNREFERENCED_PARAMETER(pvPrivateData);
+
+	if (!psDeviceNode || !psDeviceNode->pvDevice)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	*pbEnabled = psDevInfo->bPDPEnabled;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXSetPdumpPanicEnable(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_BOOL bEnable)
+{
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	PVR_UNREFERENCED_PARAMETER(pvPrivateData);
+
+	if (!psDeviceNode || !psDeviceNode->pvDevice)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	psDevInfo->bPDPEnabled = bEnable;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXGetDeviceFlags(PVRSRV_RGXDEV_INFO *psDevInfo,
+				IMG_UINT32 *pui32DeviceFlags)
+{
+	if (!pui32DeviceFlags || !psDevInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	*pui32DeviceFlags = psDevInfo->ui32DeviceFlags;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXSetDeviceFlags(PVRSRV_RGXDEV_INFO *psDevInfo,
+				IMG_UINT32 ui32Config,
+				IMG_BOOL bSetNotClear)
+{
+	IMG_UINT32 ui32DeviceFlags = 0;
+
+	if (!psDevInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (ui32Config & RGXKMIF_DEVICE_STATE_ZERO_FREELIST)
+	{
+		ui32DeviceFlags |= RGXKM_DEVICE_STATE_ZERO_FREELIST;
+	}
+
+	if (ui32Config & RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN)
+	{
+		ui32DeviceFlags |= RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN;
+	}
+
+	if (ui32Config & RGXKMIF_DEVICE_STATE_DUST_REQUEST_INJECT_EN)
+	{
+		ui32DeviceFlags |= RGXKM_DEVICE_STATE_DUST_REQUEST_INJECT_EN;
+	}
+
+	if (bSetNotClear)
+	{
+		psDevInfo->ui32DeviceFlags |= ui32DeviceFlags;
+	}
+	else
+	{
+		psDevInfo->ui32DeviceFlags &= ~ui32DeviceFlags;
+	}
+
+	return PVRSRV_OK;
+}
+
 /*
  * RGXRunScript
  */
@@ -283,6 +428,53 @@
 	return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
 }
 
+inline const char * RGXStringifyKickTypeDM(RGX_KICK_TYPE_DM eKickTypeDM)
+{
+	/*      
+	 *  This is based on the currently defined DMs.             
+	 *  If you need to modify the enum in include/rgx_common.h
+	 *  please keep this function up-to-date too.
+	 *
+	 *       typedef enum _RGXFWIF_DM_
+	 *       {
+	 *           RGXFWIF_DM_GP        = 0,
+	 *           RGXFWIF_DM_2D        = 1, 
+	 *           RGXFWIF_DM_TDM       = 1,
+	 *           RGXFWIF_DM_TA        = 2,
+	 *           RGXFWIF_DM_3D        = 3,
+	 *           RGXFWIF_DM_CDM       = 4,
+	 *           RGXFWIF_DM_RTU       = 5,
+	 *           RGXFWIF_DM_SHG       = 6,
+	 *           RGXFWIF_DM_LAST,
+	 *           RGXFWIF_DM_FORCE_I32 = 0x7fffffff   
+	 *       } RGXFWIF_DM;
+	 */
+	PVR_ASSERT(eKickTypeDM < RGX_KICK_TYPE_DM_LAST);
+
+	switch(eKickTypeDM) {
+		case RGX_KICK_TYPE_DM_GP:
+			return "GP ";
+		case RGX_KICK_TYPE_DM_TDM_2D:   
+			return "TDM/2D ";
+		case RGX_KICK_TYPE_DM_TA:   
+			return "TA ";
+		case RGX_KICK_TYPE_DM_3D:
+			return "3D ";
+		case RGX_KICK_TYPE_DM_CDM:
+			return "CDM ";
+		case RGX_KICK_TYPE_DM_RTU:
+			return "RTU ";
+		case RGX_KICK_TYPE_DM_SHG:
+			return "SHG ";
+		case RGX_KICK_TYPE_DM_TQ2D:
+			return "TQ2D ";
+		case RGX_KICK_TYPE_DM_TQ3D:
+			return "TQ3D ";
+		default:
+			return "Invalid DM ";
+	}
+}
+
 /******************************************************************************
  End of file (rgxutils.c)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxutils.h b/drivers/staging/imgtec/rogue/rgxutils.h
index 718f70c..693563d 100644
--- a/drivers/staging/imgtec/rogue/rgxutils.h
+++ b/drivers/staging/imgtec/rogue/rgxutils.h
@@ -44,11 +44,130 @@
 #include "device.h"
 #include "rgxdevice.h"
 #include "rgxdebug.h"
+#include "pvr_notifier.h"
 #include "pvrsrv.h"
 
 /*!
 ******************************************************************************
 
+ @Function      RGXQueryAPMState
+
+ @Description   Query the state of the APM configuration
+
+ @Input         psDeviceNode : The device node
+
+ @Input         pvPrivateData: Unused (required for AppHint callback)
+
+ @Output        pui32State   : The APM configuration state
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXQueryAPMState(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_UINT32 *pui32State);
+
+/*!
+******************************************************************************
+
+ @Function      RGXSetAPMState
+
+ @Description   Set the APM configuration state. Currently only 'OFF' is
+                supported
+
+ @Input         psDeviceNode : The device node
+
+ @Input         pvPrivateData: Unused (required for AppHint callback)
+
+ @Input         ui32State    : The requested APM configuration state
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXSetAPMState(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_UINT32 ui32State);
+
+/*!
+******************************************************************************
+
+ @Function      RGXQueryPdumpPanicEnable
+
+ @Description   Get the PDump Panic Enable configuration state.
+
+ @Input         psDeviceNode : The device node
+
+ @Input         pvPrivateData: Unused (required for AppHint callback)
+
+ @Input         pbEnabled    : IMG_TRUE if PDump Panic is enabled
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXQueryPdumpPanicEnable(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_BOOL *pbEnabled);
+
+/*!
+******************************************************************************
+
+ @Function      RGXSetPdumpPanicEnable
+
+ @Description   Set the PDump Panic Enable flag
+
+ @Input         psDeviceNode : The device node
+
+ @Input         pvPrivateData: Unused (required for AppHint callback)
+
+ @Input         bEnable      : The requested configuration state
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXSetPdumpPanicEnable(const PVRSRV_DEVICE_NODE *psDeviceNode,
+	const void *pvPrivateData,
+	IMG_BOOL bEnable);
+
+/*!
+******************************************************************************
+
+ @Function      RGXGetDeviceFlags
+
+ @Description   Get the device flags for a given device
+
+ @Input         psDevInfo        : The device descriptor query
+
+ @Output        pui32DeviceFlags : The current state of the device flags
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXGetDeviceFlags(PVRSRV_RGXDEV_INFO *psDevInfo,
+				IMG_UINT32 *pui32DeviceFlags);
+
+/*!
+******************************************************************************
+
+ @Function      RGXSetDeviceFlags
+
+ @Description   Set the device flags for a given device
+
+ @Input         psDevInfo : The device descriptor to modify
+
+ @Input         ui32Config : The device flags to modify
+
+ @Input         bSetNotClear : Set or clear the specified flags
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXSetDeviceFlags(PVRSRV_RGXDEV_INFO *psDevInfo,
+				IMG_UINT32 ui32Config,
+				IMG_BOOL bSetNotClear);
+
+/*!
+******************************************************************************
+
  @Function	RGXRunScript
 
  @Description Execute the commands in the script
@@ -65,6 +184,21 @@
 				DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 				void *pvDumpDebugFile);
 
+/*!
+******************************************************************************
+
+ @Function    RGXStringifyKickTypeDM
+
+ @Description Gives the kick type DM name stringified
+
+ @Input       Kick type DM
+
+ @Return      Array containing the kick type DM name
+
+******************************************************************************/
+const char* RGXStringifyKickTypeDM(RGX_KICK_TYPE_DM eKickTypeDM);
+                                                                             
+#define RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(bitmask, eKickTypeDM) bitmask & eKickTypeDM ? RGXStringifyKickTypeDM(eKickTypeDM) : ""
 /******************************************************************************
  End of file (rgxutils.h)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/rgxworkest.c b/drivers/staging/imgtec/rogue/rgxworkest.c
new file mode 100644
index 0000000..362d4ee
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxworkest.c
@@ -0,0 +1,517 @@
+/*************************************************************************/ /*!
+@File           rgxworkest.c
+@Title          RGX Workload Estimation Functionality
+@Codingstyle    IMG
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Kernel mode workload estimation functionality.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "rgxworkest.h"
+#include "rgxfwutils.h"
+#include "rgxdevice.h"
+#include "rgxpdvfs.h"
+#include "device.h"
+#include "pvr_debug.h"
+
+#define ROUND_DOWN_TO_NEAREST_1024(number) (((number) >> 10) << 10)
+
+void WorkEstRCInit(WORKEST_HOST_DATA *psWorkEstData)
+{
+	/* Create hash tables for workload matching */
+	psWorkEstData->sWorkloadMatchingDataTA.psWorkloadDataHash =
+		HASH_Create_Extended(WORKLOAD_HASH_SIZE,
+							 sizeof(RGX_WORKLOAD_TA3D *),
+							 &WorkEstHashFuncTA3D,
+							 (HASH_KEY_COMP *)&WorkEstHashCompareTA3D);
+
+	/* Create a lock to protect the hash table */
+	WorkEstHashLockCreate(&(psWorkEstData->sWorkloadMatchingDataTA.psWorkEstHashLock));
+
+	psWorkEstData->sWorkloadMatchingData3D.psWorkloadDataHash =
+		HASH_Create_Extended(WORKLOAD_HASH_SIZE,
+							 sizeof(RGX_WORKLOAD_TA3D *),
+							 &WorkEstHashFuncTA3D,
+							 (HASH_KEY_COMP *)&WorkEstHashCompareTA3D);
+
+	/* Create a lock to protect the hash tables */
+	WorkEstHashLockCreate(&(psWorkEstData->sWorkloadMatchingData3D.psWorkEstHashLock));
+}
+
+void WorkEstRCDeInit(WORKEST_HOST_DATA *psWorkEstData,
+                     PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	HASH_TABLE        *psWorkloadDataHash;
+	RGX_WORKLOAD_TA3D *pasWorkloadHashKeys;
+	RGX_WORKLOAD_TA3D *psWorkloadHashKey;
+	IMG_UINT32        ui32i;
+	IMG_UINT64        *paui64WorkloadCycleData;
+
+	pasWorkloadHashKeys = psWorkEstData->sWorkloadMatchingDataTA.asWorkloadHashKeys;
+	paui64WorkloadCycleData = psWorkEstData->sWorkloadMatchingDataTA.aui64HashCycleData;
+	psWorkloadDataHash = psWorkEstData->sWorkloadMatchingDataTA.psWorkloadDataHash;
+
+	if(psWorkloadDataHash)
+	{
+		for(ui32i = 0; ui32i < WORKLOAD_HASH_SIZE; ui32i++)
+		{
+			if(paui64WorkloadCycleData[ui32i] > 0)
+			{
+				psWorkloadHashKey = &pasWorkloadHashKeys[ui32i];
+				HASH_Remove_Extended(psWorkloadDataHash,
+									 (uintptr_t*)&psWorkloadHashKey);
+			}
+		}
+
+		HASH_Delete(psWorkloadDataHash);
+	}
+
+	/* Remove the hash lock */
+	WorkEstHashLockDestroy(psWorkEstData->sWorkloadMatchingDataTA.psWorkEstHashLock);
+
+	pasWorkloadHashKeys = psWorkEstData->sWorkloadMatchingData3D.asWorkloadHashKeys;
+	paui64WorkloadCycleData = psWorkEstData->sWorkloadMatchingData3D.aui64HashCycleData;
+	psWorkloadDataHash = psWorkEstData->sWorkloadMatchingData3D.psWorkloadDataHash;
+
+	if(psWorkloadDataHash)
+	{
+		for(ui32i = 0; ui32i < WORKLOAD_HASH_SIZE; ui32i++)
+		{
+			if(paui64WorkloadCycleData[ui32i] > 0)
+			{
+				psWorkloadHashKey = &pasWorkloadHashKeys[ui32i];
+				HASH_Remove_Extended(psWorkloadDataHash,
+									 (uintptr_t*)&psWorkloadHashKey);
+			}
+		}
+
+		HASH_Delete(psWorkloadDataHash);
+	}
+
+	/* Remove the hash lock */
+	WorkEstHashLockDestroy(psWorkEstData->sWorkloadMatchingData3D.psWorkEstHashLock);
+
+	return;
+}
+
+IMG_BOOL WorkEstHashCompareTA3D(size_t uKeySize,
+								void *pKey1,
+								void *pKey2)
+{
+	RGX_WORKLOAD_TA3D *psWorkload1;
+	RGX_WORKLOAD_TA3D *psWorkload2;
+
+	if(pKey1 && pKey2)
+	{
+		psWorkload1 = *((RGX_WORKLOAD_TA3D **)pKey1);
+		psWorkload2 = *((RGX_WORKLOAD_TA3D **)pKey2);
+
+		PVR_ASSERT(psWorkload1);
+		PVR_ASSERT(psWorkload2);
+
+		if(psWorkload1->ui32RenderTargetSize == psWorkload2->ui32RenderTargetSize
+		   && psWorkload1->ui32NumberOfDrawCalls == psWorkload2->ui32NumberOfDrawCalls
+		   && psWorkload1->ui32NumberOfIndices == psWorkload2->ui32NumberOfIndices
+		   && psWorkload1->ui32NumberOfMRTs == psWorkload2->ui32NumberOfMRTs)
+		{
+			/* This is added to allow this memory to be freed */
+			*(uintptr_t*)pKey2 = *(uintptr_t*)pKey1;
+			return IMG_TRUE;
+		}
+	}
+	return IMG_FALSE;
+}
+
+static inline IMG_UINT32 WorkEstDoHash(IMG_UINT32 ui32Input)
+{
+	IMG_UINT32 ui32HashPart;
+
+	ui32HashPart = ui32Input;
+	ui32HashPart += (ui32HashPart << 12);
+	ui32HashPart ^= (ui32HashPart >> 22);
+	ui32HashPart += (ui32HashPart << 4);
+	ui32HashPart ^= (ui32HashPart >> 9);
+	ui32HashPart += (ui32HashPart << 10);
+	ui32HashPart ^= (ui32HashPart >> 2);
+	ui32HashPart += (ui32HashPart << 7);
+	ui32HashPart ^= (ui32HashPart >> 12);
+
+	return ui32HashPart;
+}
+
+IMG_UINT32 WorkEstHashFuncTA3D(size_t uKeySize, void *pKey, IMG_UINT32 uHashTabLen)
+{
+	RGX_WORKLOAD_TA3D *psWorkload = *((RGX_WORKLOAD_TA3D**)pKey);
+	IMG_UINT32 ui32HashKey = 0;
+	PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+	PVR_UNREFERENCED_PARAMETER(uKeySize);
+
+	ui32HashKey += WorkEstDoHash(psWorkload->ui32RenderTargetSize);
+	ui32HashKey += WorkEstDoHash(psWorkload->ui32NumberOfDrawCalls);
+	ui32HashKey += WorkEstDoHash(psWorkload->ui32NumberOfIndices);
+	ui32HashKey += WorkEstDoHash(psWorkload->ui32NumberOfMRTs);
+
+	return ui32HashKey;
+}
+
+PVRSRV_ERROR WorkEstPrepare(PVRSRV_RGXDEV_INFO        *psDevInfo,
+                            WORKEST_HOST_DATA         *psWorkEstHostData,
+                            WORKLOAD_MATCHING_DATA    *psWorkloadMatchingData,
+                            IMG_UINT32                ui32RenderTargetSize,
+                            IMG_UINT32                ui32NumberOfDrawCalls,
+                            IMG_UINT32                ui32NumberOfIndices,
+                            IMG_UINT32                ui32NumberOfMRTs,
+                            IMG_UINT64                ui64DeadlineInus,
+                            RGXFWIF_WORKEST_KICK_DATA *psWorkEstKickData)
+{
+	PVRSRV_ERROR          eError;
+	RGX_WORKLOAD_TA3D     *psWorkloadCharacteristics;
+	IMG_UINT64            *pui64CyclePrediction;
+	POS_LOCK              psWorkEstHashLock;
+	IMG_UINT64            ui64WorkloadDeadlineInus = ui64DeadlineInus;
+	IMG_UINT64            ui64CurrentTime;
+	HASH_TABLE            *psWorkloadDataHash;
+	WORKEST_RETURN_DATA   *psReturnData;
+
+	if(psDevInfo == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"WorkEstPrepare: Device Info not available"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(psDevInfo->bWorkEstEnabled != IMG_TRUE)
+	{
+		/* No error message to avoid excessive messages */
+		return PVRSRV_OK;
+	}
+
+	if(psWorkEstHostData == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "WorkEstPrepare: Host data not available"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(psWorkloadMatchingData == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "WorkEstPrepare: Workload Matching Data not available"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psWorkloadDataHash = psWorkloadMatchingData->psWorkloadDataHash;
+	if(psWorkloadDataHash == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"WorkEstPrepare: Hash Table not available"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psWorkEstHashLock = psWorkloadMatchingData->psWorkEstHashLock;
+	if(psWorkEstHashLock == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstPrepare: Hash lock not available"
+		        ));
+		eError = PVRSRV_ERROR_UNABLE_TO_RETRIEVE_HASH_VALUE;
+		return eError;
+	}
+
+	eError = OSClockMonotonicus64(&ui64CurrentTime);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		         "WorkEstPrepare: Unable to access System Monotonic clock"));
+		PVR_ASSERT(eError == PVRSRV_OK);
+		return eError;
+	}
+
+#if defined(SUPPORT_PDVFS)
+	psDevInfo->psDeviceNode->psDevConfig->sDVFS.sPDVFSData.bWorkInFrame = IMG_TRUE;
+#endif
+
+	/* Set up data for the return path to process the workload */
+
+	/* Any host side data needed for the return path is stored in an array and
+	 * only the array's index is passed to and from the firmware. This is a
+	 * similar abstraction to using handles but is optimised for this case.
+	 */
+	psReturnData =
+		&psDevInfo->asReturnData[psDevInfo->ui32ReturnDataWO];
+
+	/* The index for the specific data is passed to the FW */
+	psWorkEstKickData->ui64ReturnDataIndex = psDevInfo->ui32ReturnDataWO;
+
+	psDevInfo->ui32ReturnDataWO =
+		(psDevInfo->ui32ReturnDataWO + 1) & RETURN_DATA_ARRAY_WRAP_MASK;
+
+	/* The workload characteristics are needed in the return data for the
+	 * matching of future workloads via the hash.
+	 */
+	psWorkloadCharacteristics = &psReturnData->sWorkloadCharacteristics;
+	psWorkloadCharacteristics->ui32RenderTargetSize = ui32RenderTargetSize;
+	psWorkloadCharacteristics->ui32NumberOfDrawCalls = ui32NumberOfDrawCalls;
+	psWorkloadCharacteristics->ui32NumberOfIndices = ui32NumberOfIndices;
+	psWorkloadCharacteristics->ui32NumberOfMRTs = ui32NumberOfMRTs;
+
+	/* The matching data is needed as it holds the hash data. */
+	psReturnData->psWorkloadMatchingData = psWorkloadMatchingData;
+
+	/* The host data for the completion updates */
+	psReturnData->psWorkEstHostData = psWorkEstHostData;
+	if(ui64WorkloadDeadlineInus > ui64CurrentTime)
+	{
+		/* This is rounded to reduce multiple deadlines with a minor spread
+		 * flooding the fw workload array.
+		 */
+		psWorkEstKickData->ui64DeadlineInus =
+			ROUND_DOWN_TO_NEAREST_1024(ui64WorkloadDeadlineInus);
+	}
+	else
+	{
+		/* If the deadline has already passed assign as zero to suggest full
+		 * frequency
+		 */
+		psWorkEstKickData->ui64DeadlineInus = 0;
+	}
+
+	/* Acquire the lock to access hash */
+	OSLockAcquire(psWorkEstHashLock);
+
+	/* Check if there is a prediction for this workload */
+	pui64CyclePrediction =
+		(IMG_UINT64*) HASH_Retrieve(psWorkloadDataHash,
+		                            (uintptr_t)psWorkloadCharacteristics);
+
+	/* Release lock */
+	OSLockRelease(psWorkEstHashLock);
+
+	if(pui64CyclePrediction != NULL)
+	{
+		/* Cycle prediction is available, store this prediction */
+		psWorkEstKickData->ui64CyclesPrediction = *pui64CyclePrediction;
+	}
+	else
+	{
+		/* There is no prediction */
+		psWorkEstKickData->ui64CyclesPrediction = 0;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR WorkEstWorkloadFinished(PVRSRV_RGXDEV_INFO        *psDevInfo,
+                                     RGXFWIF_WORKEST_FWCCB_CMD *psReturnCmd)
+{
+	RGX_WORKLOAD_TA3D           *psWorkloadCharacteristics;
+	RGX_WORKLOAD_TA3D           *pasWorkloadHashKeys;
+	IMG_UINT64                  *paui64HashCycleData;
+	IMG_UINT32                  *pui32HashArrayWO;
+	RGX_WORKLOAD_TA3D           *psWorkloadHashKey;
+	IMG_UINT64                  *pui64CyclesTaken;
+	HASH_TABLE                  *psWorkloadHash;
+	WORKLOAD_MATCHING_DATA      *psWorkloadMatchingData;
+	POS_LOCK                    psWorkEstHashLock;
+	IMG_BOOL                    bHashSucess;
+	WORKEST_RETURN_DATA         *psReturnData;
+	WORKEST_HOST_DATA           *psWorkEstHostData;
+	PVRSRV_ERROR                eError = PVRSRV_OK;
+
+	if(psDevInfo->bWorkEstEnabled != IMG_TRUE)
+	{
+		/* No error message to avoid excessive messages */
+		return PVRSRV_OK;
+	}
+
+	if(psReturnCmd == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstFinished: Missing Return Command"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(psReturnCmd->ui64ReturnDataIndex >= RETURN_DATA_ARRAY_SIZE)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstFinished: Handle Reference Out of Bounds"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Retrieve the return data for this workload */
+	psReturnData = &psDevInfo->asReturnData[psReturnCmd->ui64ReturnDataIndex];
+
+	psWorkEstHostData = psReturnData->psWorkEstHostData;
+
+	if(psWorkEstHostData == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstFinished: Missing host data"));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return eError;
+	}
+
+	psWorkloadCharacteristics = &psReturnData->sWorkloadCharacteristics;
+
+	if(psWorkloadCharacteristics == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstFinished: Missing workload characteristics"));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto hasherror;
+	}
+
+	psWorkloadMatchingData = psReturnData->psWorkloadMatchingData;
+
+	psWorkloadHash = psWorkloadMatchingData->psWorkloadDataHash;
+	if(psWorkloadHash == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstFinished: Missing hash"));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto hasherror;
+	}
+
+	psWorkEstHashLock = psWorkloadMatchingData->psWorkEstHashLock;
+	if(psWorkEstHashLock == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+		        "WorkEstFinished: Missing hash lock"));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto hasherror;
+	}
+
+	OSLockAcquire(psWorkEstHashLock);
+
+	pui64CyclesTaken =
+		(IMG_UINT64*) HASH_Remove_Extended(psWorkloadHash,
+		                                   (uintptr_t*)&psWorkloadCharacteristics);
+
+	pui32HashArrayWO = &(psWorkloadMatchingData->ui32HashArrayWO);
+	paui64HashCycleData = psWorkloadMatchingData->aui64HashCycleData;
+	pasWorkloadHashKeys = psWorkloadMatchingData->asWorkloadHashKeys;
+
+	/* Remove the oldest Hash data before it becomes overwritten */
+	if(paui64HashCycleData[*pui32HashArrayWO] > 0)
+	{
+		psWorkloadHashKey = &pasWorkloadHashKeys[*pui32HashArrayWO];
+		HASH_Remove_Extended(psWorkloadHash,
+		                     (uintptr_t*)&psWorkloadHashKey);
+	}
+
+	if(pui64CyclesTaken == NULL)
+	{
+		/* There is no existing entry for these characteristics. */
+		pasWorkloadHashKeys[*pui32HashArrayWO] = *psWorkloadCharacteristics;
+
+		paui64HashCycleData[*pui32HashArrayWO] = psReturnCmd->ui64CyclesTaken;
+	}
+	else
+	{
+		*pui64CyclesTaken =
+			(*pui64CyclesTaken + psReturnCmd->ui64CyclesTaken)/2;
+
+		pasWorkloadHashKeys[*pui32HashArrayWO] = *psWorkloadCharacteristics;
+
+		paui64HashCycleData[*pui32HashArrayWO] = *pui64CyclesTaken;
+
+		/* Set the old value to 0 so it is known to be invalid */
+		*pui64CyclesTaken = 0;
+	}
+
+
+	bHashSucess = HASH_Insert((HASH_TABLE*)(psWorkloadHash),
+			(uintptr_t)&pasWorkloadHashKeys[*pui32HashArrayWO],
+			(uintptr_t)&paui64HashCycleData[*pui32HashArrayWO]);
+	PVR_ASSERT(bHashSucess);
+
+	if(*pui32HashArrayWO == WORKLOAD_HASH_SIZE-1)
+	{
+		*pui32HashArrayWO = 0;
+	}
+	else
+	{
+		(*pui32HashArrayWO)++;
+	}
+
+	OSLockRelease(psWorkEstHashLock);
+
+hasherror:
+
+	/* Update the received counter so that the FW is able to check as to whether
+	 * all the workloads connected to a render context are finished.
+	 */
+	psWorkEstHostData->ui32WorkEstCCBReceived++;
+	return eError;
+}
+
+void WorkEstHashLockCreate(POS_LOCK *psWorkEstHashLock)
+{
+	if(*psWorkEstHashLock == NULL)
+	{
+		OSLockCreate(psWorkEstHashLock, LOCK_TYPE_DISPATCH);
+	}
+	return;
+}
+
+void WorkEstHashLockDestroy(POS_LOCK sWorkEstHashLock)
+{
+	if(sWorkEstHashLock != NULL)
+	{
+		OSLockDestroy(sWorkEstHashLock);
+		sWorkEstHashLock = NULL;
+	}
+	return;
+}
+
+void WorkEstCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+	RGXFWIF_WORKEST_FWCCB_CMD *psFwCCBCmd;
+
+	RGXFWIF_CCB_CTL *psFWCCBCtl = psDevInfo->psWorkEstFirmwareCCBCtl;
+	IMG_UINT8 *psFWCCB = psDevInfo->psWorkEstFirmwareCCB;
+
+	while (psFWCCBCtl->ui32ReadOffset != psFWCCBCtl->ui32WriteOffset)
+	{
+		/* Point to the next command */
+		psFwCCBCmd = ((RGXFWIF_WORKEST_FWCCB_CMD *)psFWCCB) + psFWCCBCtl->ui32ReadOffset;
+
+		WorkEstWorkloadFinished(psDevInfo, psFwCCBCmd);
+
+		/* Update read offset */
+		psFWCCBCtl->ui32ReadOffset = (psFWCCBCtl->ui32ReadOffset + 1) & psFWCCBCtl->ui32WrapMask;
+	}
+}
diff --git a/drivers/staging/imgtec/rogue/rgxworkest.h b/drivers/staging/imgtec/rogue/rgxworkest.h
new file mode 100644
index 0000000..cda2250
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/rgxworkest.h
@@ -0,0 +1,96 @@
+/*************************************************************************/ /*!
+@File           rgxworkest.h
+@Title          RGX Workload Estimation Functionality
+@Codingstyle    IMG
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the kernel mode workload estimation functionality.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef RGXWORKEST_H
+#define RGXWORKEST_H
+
+#include "img_types.h"
+#include "hash.h"
+#include "rgxta3d.h"
+
+
+IMG_INTERNAL
+void WorkEstRCInit(WORKEST_HOST_DATA *psWorkEstData);
+
+IMG_INTERNAL
+void WorkEstRCDeInit(WORKEST_HOST_DATA *psWorkEstData,
+                     PVRSRV_RGXDEV_INFO *psDevInfo);
+IMG_INTERNAL
+PVRSRV_ERROR WorkEstEmptyWorkloadHash(	HASH_TABLE* psHash,
+										uintptr_t k,
+										uintptr_t v);
+
+IMG_INTERNAL
+IMG_BOOL WorkEstHashCompareTA3D(size_t uKeySize,
+								 void *pKey1,
+								 void *pKey2);
+
+IMG_INTERNAL
+IMG_UINT32 WorkEstHashFuncTA3D(size_t uKeySize, void *pKey, IMG_UINT32 uHashTabLen);
+
+IMG_INTERNAL
+PVRSRV_ERROR WorkEstPrepare(PVRSRV_RGXDEV_INFO        *psDevInfo,
+                            WORKEST_HOST_DATA         *psWorkEstHostData,
+                            WORKLOAD_MATCHING_DATA    *psWorkloadMatchingData,
+                            IMG_UINT32                ui32RenderTargetSize,
+                            IMG_UINT32                ui32NumberOfDrawCalls,
+                            IMG_UINT32                ui32NumberOfIndices,
+                            IMG_UINT32                ui32NumberOfMRTs,
+                            IMG_UINT64                ui64DeadlineInus,
+                            RGXFWIF_WORKEST_KICK_DATA *psWorkEstKickData);
+
+IMG_INTERNAL
+PVRSRV_ERROR WorkEstWorkloadFinished(PVRSRV_RGXDEV_INFO        *psDevInfo,
+                                     RGXFWIF_WORKEST_FWCCB_CMD *psReturnCmd);
+
+IMG_INTERNAL
+void WorkEstHashLockCreate(POS_LOCK *psWorkEstHashLock);
+
+IMG_INTERNAL
+void WorkEstHashLockDestroy(POS_LOCK sWorkEstHashLock);
+
+IMG_INTERNAL
+void WorkEstCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+#endif /* RGXWORKEST_H */
diff --git a/drivers/staging/imgtec/rogue/ri_server.c b/drivers/staging/imgtec/rogue/ri_server.c
index a56b688..4ab4f05 100644
--- a/drivers/staging/imgtec/rogue/ri_server.c
+++ b/drivers/staging/imgtec/rogue/ri_server.c
@@ -1197,7 +1197,9 @@
 
 		if (psRISubEntry->bIsImport)
 		{
-			ui64TotalImport += psRISubEntry->ui64Size;
+			/* If it is a local import we set backed size to 0
+			 * so we don't account twice for the same allocation */
+			ui64TotalImport += psRISubEntry->ui64BackedSize;
 		}
 		else
 		{
@@ -1281,7 +1283,7 @@
 
 	OSSNPrintf(pszEntryString,
 	           ui16MaxStrLen,
-	           "%s 0x%010llx\t%-80s %s\t0x%10llx [0x%10llx] %s%s%c",
+	           "%s 0x%010llx\t%-80s %s\t0x%010llx [0x%010llx] %s%s%c",
 	           (bDebugFs ? "" : "  "),
 	           (unsigned long long) (psRISubEntry->sVAddr.uiAddr + psRISubEntry->ui64Offset),
 	           pszAnnotationText,
@@ -1293,7 +1295,6 @@
 	           (bDebugFs ? '\n' : ' '));
 }
 
-
 /*!
 ******************************************************************************
 
@@ -1520,6 +1521,124 @@
 	return eError;
 }
 
+#if defined(DEBUG)
+/*!
+******************************************************************************
+
+ @Function	_DumpList
+ @Description
+            Dumps out RI List entries according to parameters passed.
+
+ @input     hPMR - If not NULL, function will output the RI entries for
+                   the specified PMR only
+ @input     pid - If non-zero, the function will only output MEMDESC RI
+  	  	  	  	  entries made by the process with ID pid.
+                  If zero, all MEMDESC RI entries will be output.
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR _DumpProcessList(PMR *hPMR,
+									 IMG_PID pid,
+									 IMG_UINT64 ui64Offset,
+									 IMG_DEV_VIRTADDR *psDevVAddr)
+{
+	RI_LIST_ENTRY *psRIEntry = NULL;
+	RI_SUBLIST_ENTRY *psRISubEntry = NULL;
+	IMG_UINT16 ui16SubEntriesParsed = 0;
+	uintptr_t hashData = 0;
+	PMR *pPMRHashKey = hPMR;
+	PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+	psDevVAddr->uiAddr = 0;
+
+	if (!hPMR)
+	{
+		/* NULL handle provided */
+		return eError;
+	}
+
+	if (g_pRIHashTable && g_pProcHashTable)
+	{
+		PVR_ASSERT(hPMR && pid);
+
+		/* look-up hPMR in Hash Table */
+		hashData = HASH_Retrieve_Extended (g_pRIHashTable, (void *)&pPMRHashKey);
+		psRIEntry = (RI_LIST_ENTRY *)hashData;
+
+		if (!psRIEntry)
+		{
+			/* No entry found in hash table */
+			return PVRSRV_ERROR_NOT_FOUND;
+		}
+
+		if (psRIEntry->ui16SubListCount)
+		{
+			psRISubEntry = IMG_CONTAINER_OF(dllist_get_next_node(&(psRIEntry->sSubListFirst)),
+											RI_SUBLIST_ENTRY, sListNode);
+
+			/* Traverse RI sublist and output details for each entry */
+			while (psRISubEntry && (ui16SubEntriesParsed < psRIEntry->ui16SubListCount))
+			{
+				if (pid == psRISubEntry->pid)
+				{
+					IMG_UINT64 ui64StartOffset = psRISubEntry->ui64Offset;
+					IMG_UINT64 ui64EndOffset = psRISubEntry->ui64Offset + psRISubEntry->ui64Size;
+
+					if (ui64Offset >= ui64StartOffset && ui64Offset < ui64EndOffset)
+					{
+						psDevVAddr->uiAddr = psRISubEntry->sVAddr.uiAddr;
+						return PVRSRV_OK;
+					}
+				}
+
+				ui16SubEntriesParsed++;
+				psRISubEntry = IMG_CONTAINER_OF(dllist_get_next_node(&(psRISubEntry->sListNode)),
+												RI_SUBLIST_ENTRY, sListNode);
+			}
+		}
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	RIDumpProcessListKM
+
+ @Description
+            Dumps out selected contents of all MEMDESC RI List entries (for a
+            PMR) which have been allocate by the specified process only.
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDumpProcessListKM(PMR *hPMR,
+								 IMG_PID pid,
+								 IMG_UINT64 ui64Offset,
+								 IMG_DEV_VIRTADDR *psDevVAddr)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (g_pProcHashTable)
+	{
+		/* Acquire RI lock*/
+		_RILock();
+
+		eError = _DumpProcessList(hPMR,
+								  pid,
+								  ui64Offset,
+								  psDevVAddr);
+
+		/* Release RI lock*/
+		_RIUnlock();
+	}
+
+	return eError;
+}
+#endif
+
 static PVRSRV_ERROR _DumpAllEntries (uintptr_t k, uintptr_t v)
 {
 	RI_LIST_ENTRY *psRIEntry = (RI_LIST_ENTRY *)v;
diff --git a/drivers/staging/imgtec/rogue/ri_server.h b/drivers/staging/imgtec/rogue/ri_server.h
index 692ad01..102cc9a 100644
--- a/drivers/staging/imgtec/rogue/ri_server.h
+++ b/drivers/staging/imgtec/rogue/ri_server.h
@@ -94,6 +94,13 @@
 
 PVRSRV_ERROR RIDumpProcessKM(IMG_PID pid);
 
+#if defined(DEBUG)
+PVRSRV_ERROR RIDumpProcessListKM(PMR *hPMR,
+								 IMG_PID pid,
+								 IMG_UINT64 ui64Offset,
+								 IMG_DEV_VIRTADDR *psDevVAddr);
+#endif
+
 IMG_BOOL RIGetListEntryKM(IMG_PID pid,
 						  IMG_HANDLE **ppHandle,
 						  IMG_CHAR **ppszEntryString);
diff --git a/drivers/staging/imgtec/rogue/rogue_trace_events.h b/drivers/staging/imgtec/rogue/rogue_trace_events.h
index 34df614..227621a 100644
--- a/drivers/staging/imgtec/rogue/rogue_trace_events.h
+++ b/drivers/staging/imgtec/rogue/rogue_trace_events.h
@@ -44,6 +44,7 @@
 #if !defined(_ROGUE_TRACE_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _ROGUE_TRACE_EVENTS_H
 
+#include <linux/version.h>
 #include <linux/tracepoint.h>
 #include <linux/time.h>
 
@@ -62,7 +63,14 @@
 		rem = do_div(t, USEC_PER_SEC); \
 	})
 
-TRACE_EVENT(rogue_fence_update,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+int trace_fence_update_enabled_callback(void);
+#else
+void trace_fence_update_enabled_callback(void);
+#endif
+void trace_fence_update_disabled_callback(void);
+
+TRACE_EVENT_FN(rogue_fence_update,
 
 	TP_PROTO(const char *comm, const char *cmd, const char *dm, u32 ctx_id, u32 offset,
 		u32 sync_fwaddr, u32 sync_value),
@@ -96,10 +104,20 @@
 		(unsigned long)__entry->ctx_id,
 		(unsigned long)__entry->offset,
 		(unsigned long)__entry->sync_fwaddr,
-		(unsigned long)__entry->sync_value)
+		(unsigned long)__entry->sync_value),
+
+	trace_fence_update_enabled_callback,
+	trace_fence_update_disabled_callback
 );
 
-TRACE_EVENT(rogue_fence_check,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+int trace_fence_check_enabled_callback(void);
+#else
+void trace_fence_check_enabled_callback(void);
+#endif
+void trace_fence_check_disabled_callback(void);
+
+TRACE_EVENT_FN(rogue_fence_check,
 
 	TP_PROTO(const char *comm, const char *cmd, const char *dm, u32 ctx_id, u32 offset,
 		u32 sync_fwaddr, u32 sync_value),
@@ -133,7 +151,10 @@
 		(unsigned long)__entry->ctx_id,
 		(unsigned long)__entry->offset,
 		(unsigned long)__entry->sync_fwaddr,
-		(unsigned long)__entry->sync_value)
+		(unsigned long)__entry->sync_value),
+
+	trace_fence_check_enabled_callback,
+	trace_fence_check_disabled_callback
 );
 
 TRACE_EVENT(rogue_create_fw_context,
@@ -164,6 +185,12 @@
 
 void PVRGpuTraceEnableUfoCallback(void);
 void PVRGpuTraceDisableUfoCallback(void);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+int PVRGpuTraceEnableUfoCallbackWrapper(void);
+#else
+#define PVRGpuTraceEnableUfoCallbackWrapper \
+		PVRGpuTraceEnableUfoCallback
+#endif
 
 TRACE_EVENT_FN(rogue_ufo_update,
 
@@ -199,7 +226,7 @@
 		(unsigned long)__entry->fwaddr,
 		(unsigned long)__entry->old_value,
 		(unsigned long)__entry->new_value),
-	PVRGpuTraceEnableUfoCallback,
+	PVRGpuTraceEnableUfoCallbackWrapper,
 	PVRGpuTraceDisableUfoCallback
 );
 
@@ -237,7 +264,7 @@
 		(unsigned long)__entry->fwaddr,
 		(unsigned long)__entry->value,
 		(unsigned long)__entry->required),
-	PVRGpuTraceEnableUfoCallback,
+	PVRGpuTraceEnableUfoCallbackWrapper,
 	PVRGpuTraceDisableUfoCallback
 );
 
@@ -275,7 +302,7 @@
 		(unsigned long)__entry->fwaddr,
 		(unsigned long)__entry->value,
 		(unsigned long)__entry->required),
-	PVRGpuTraceEnableUfoCallback,
+	PVRGpuTraceEnableUfoCallbackWrapper,
 	PVRGpuTraceDisableUfoCallback
 );
 
@@ -308,7 +335,7 @@
 		(unsigned long)__entry->job_id,
 		(unsigned long)__entry->fwaddr,
 		(unsigned long)__entry->value),
-	PVRGpuTraceEnableUfoCallback,
+	PVRGpuTraceEnableUfoCallbackWrapper,
 	PVRGpuTraceDisableUfoCallback
 );
 
@@ -341,7 +368,7 @@
 		(unsigned long)__entry->job_id,
 		(unsigned long)__entry->fwaddr,
 		(unsigned long)__entry->value),
-	PVRGpuTraceEnableUfoCallback,
+	PVRGpuTraceEnableUfoCallbackWrapper,
 	PVRGpuTraceDisableUfoCallback
 );
 
@@ -369,6 +396,46 @@
 		__entry->curr_ordinal)
 );
 
+void PVRGpuTraceEnableFirmwareActivityCallback(void);
+void PVRGpuTraceDisableFirmwareActivityCallback(void);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+int PVRGpuTraceEnableFirmwareActivityCallbackWrapper(void);
+#else
+#define PVRGpuTraceEnableFirmwareActivityCallbackWrapper \
+		PVRGpuTraceEnableFirmwareActivityCallback
+#endif
+
+TRACE_EVENT_FN(rogue_firmware_activity,
+
+	TP_PROTO(u64 timestamp, const char *task, u32 fw_event),
+
+	TP_ARGS(timestamp, task, fw_event),
+
+	TP_STRUCT__entry(
+		__field(        u64,            timestamp       )
+		__string(       task,           task            )
+		__field(        u32,            fw_event        )
+	),
+
+	TP_fast_assign(
+		__entry->timestamp = timestamp;
+		__assign_str(task, task);
+		__entry->fw_event = fw_event;
+	),
+
+	TP_printk("ts=%llu.%06lu task=%s event=%s",
+		(unsigned long long)show_secs_from_ns(__entry->timestamp),
+		(unsigned long)show_usecs_from_ns(__entry->timestamp),
+		__get_str(task),
+		__print_symbolic(__entry->fw_event,
+			/* These values are from pvr_gputrace.h. */
+			{ 1, "begin" },
+			{ 2, "end" })),
+
+	PVRGpuTraceEnableFirmwareActivityCallbackWrapper,
+	PVRGpuTraceDisableFirmwareActivityCallback
+);
+
 #endif /* defined(SUPPORT_GPUTRACE_EVENTS) */
 
 #undef show_secs_from_ns
diff --git a/drivers/staging/imgtec/rogue/scp.c b/drivers/staging/imgtec/rogue/scp.c
index d8b2fb1..9e6bcc1 100644
--- a/drivers/staging/imgtec/rogue/scp.c
+++ b/drivers/staging/imgtec/rogue/scp.c
@@ -45,6 +45,7 @@
 #include "scp.h"
 #include "lists.h"
 #include "allocmem.h"
+#include "pvr_notifier.h"
 #include "pvrsrv.h"
 #include "pvr_debug.h"
 #include "osfunc.h"
@@ -65,6 +66,65 @@
 #include <../drivers/staging/android/sw_sync.h>
 #endif
 
+#include "kernel_compatibility.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0))
+static inline int sync_fence_get_status(struct sync_fence *psFence)
+{
+	return psFence->status;
+}
+
+static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
+{
+	return pt->parent;
+}
+
+static inline int sync_pt_get_status(struct sync_pt *pt)
+{
+	return pt->status;
+}
+
+static inline ktime_t sync_pt_get_timestamp(struct sync_pt *pt)
+{
+	return pt->timestamp;
+}
+
+#define for_each_sync_pt(s, f, c)							\
+	list_for_each_entry((s), &(f)->pt_list_head, pt_list)
+#else
+static inline int sync_fence_get_status(struct sync_fence *psFence)
+{
+	int iStatus = atomic_read(&psFence->status);
+
+	/*
+	 * When Android sync was rebased on top of fences the sync_fence status
+	 * values changed from 0 meaning 'active' to 'signalled' and, likewise,
+	 * values greater than 0 went from meaning 'signalled' to 'active'
+	 * (where the value corresponds to the number of active sync points).
+	 *
+	 * Convert to the old style status values.
+	 */
+	return iStatus > 0 ? 0 : iStatus ? iStatus : 1;
+}
+
+static inline int sync_pt_get_status(struct sync_pt *pt)
+{
+	/* No error state for raw dma-buf fences */
+	return fence_is_signaled(&pt->base) ? 1 : 0;
+}
+
+static inline ktime_t sync_pt_get_timestamp(struct sync_pt *pt)
+{
+	return pt->base.timestamp;
+}
+
+#define for_each_sync_pt(s, f, c)							   \
+	for ((c) = 0, (s) = (struct sync_pt *)(f)->cbs[0].sync_pt; \
+	     (c) < (f)->num_fences;								   \
+	     (c)++,   (s) = (struct sync_pt *)(f)->cbs[c].sync_pt)
+#endif
+
+
 static PVRSRV_ERROR AllocReleaseFence(struct sw_sync_timeline *psTimeline, const char *szName, IMG_UINT32 ui32FenceVal, int *piFenceFd)
 {
 	struct sync_fence *psFence = NULL;
@@ -148,8 +208,8 @@
 	struct sync_fence       *psAcquireFence;
 	struct sync_fence       *psReleaseFence;
 #endif /* defined(SUPPORT_NATIVE_FENCE_SYNC) */
-	SCPReady				pfnReady;           /*!< Pointer to the funtion to check if the command is ready */
-	SCPDo					pfnDo;           	/*!< Pointer to the funtion to call when the command is ready to go */
+	SCPReady				pfnReady;           /*!< Pointer to the function to check if the command is ready */
+	SCPDo					pfnDo;           	/*!< Pointer to the function to call when the command is ready to go */
 	void					*pvReadyData;        /*!< Data to pass into pfnReady */
 	void					*pvCompleteData;     /*!< Data to pass into pfnComplete */
 } SCP_COMMAND;
@@ -298,32 +358,40 @@
 					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 					void *pvDumpDebugFile)
 {
-	struct list_head *psEntry;
+	struct sync_pt *psPt;
 	char szTime[16]  = { '\0' };
 	char szVal1[64]  = { '\0' };
 	char szVal2[64]  = { '\0' };
 	char szVal3[132] = { '\0' };
+	int iStatus = sync_fence_get_status(psFence);
+	int i;
+
+	PVR_UNREFERENCED_PARAMETER(i);
 
 	PVR_DUMPDEBUG_LOG("\t  %s: [%p] %s: %s", psczName, psFence, psFence->name,
-			 (psFence->status >  0 ? "signaled" :
-			  psFence->status == 0 ? "active" : "error"));
-	list_for_each(psEntry, &psFence->pt_list_head)
+					   (iStatus > 0 ? "signalled" : iStatus ? "error" : "active"));
+
+	for_each_sync_pt(psPt, psFence, i)
 	{
-		struct sync_pt *psPt = container_of(psEntry, struct sync_pt, pt_list);
-		struct timeval tv = ktime_to_timeval(psPt->timestamp);
+		struct sync_timeline *psTimeline = sync_pt_parent(psPt);
+		ktime_t timestamp = sync_pt_get_timestamp(psPt);
+		struct timeval tv = ktime_to_timeval(timestamp);
+		int iPtStatus = sync_pt_get_status(psPt);
+
 		snprintf(szTime, sizeof(szTime), "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
-		if (psPt->parent->ops->pt_value_str &&
-			psPt->parent->ops->timeline_value_str)
+
+		if (psTimeline->ops->pt_value_str &&
+			psTimeline->ops->timeline_value_str)
 		{
-			psPt->parent->ops->pt_value_str(psPt, szVal1, sizeof(szVal1));
-			psPt->parent->ops->timeline_value_str(psPt->parent, szVal2, sizeof(szVal2));
+			psTimeline->ops->pt_value_str(psPt, szVal1, sizeof(szVal1));
+			psTimeline->ops->timeline_value_str(psTimeline, szVal2, sizeof(szVal2));
 			snprintf(szVal3, sizeof(szVal3), ": %s / %s", szVal1, szVal2);
 		}
-		PVR_DUMPDEBUG_LOG("\t    %s %s%s%s", psPt->parent->name,
-				 (psPt->status >  0 ? "signaled" :
-				  psPt->status == 0 ? "active" : "error"),
-				 (psPt->status >  0 ? szTime : ""),
-				 szVal3);
+
+		PVR_DUMPDEBUG_LOG("\t    %s %s%s%s", psTimeline->name,
+						   (iPtStatus > 0 ? "signalled" : iPtStatus ? "error" : "active"),
+						   (iPtStatus > 0 ? szTime : ""),
+						   szVal3);
 	}
 
 }
@@ -334,7 +402,7 @@
 @Function       _SCPCommandReady
 
 @Description    Check if a command is ready. Checks to see if the command
-                has had it's fences meet and is ready to go.
+                has had its fences met and is ready to go.
 
 @Input          psCommand               Command to check
 
@@ -460,9 +528,12 @@
 			*/
 			if (psSCPSyncData->ui32Flags & SCP_SYNC_DATA_FENCE)
 			{
+				IMG_UINT32 ui32SyncAddr;
+
 				PVR_ASSERT(psSCPSyncData->psSync != NULL);
+				(void)ServerSyncGetFWAddr(psSCPSyncData->psSync, &ui32SyncAddr);
 				PVR_DUMPDEBUG_LOG("\t\tFenced on 0x%08x = 0x%08x (?= 0x%08x)",
-						ServerSyncGetFWAddr(psSCPSyncData->psSync),
+						ui32SyncAddr,
 						psSCPSyncData->ui32Fence,
 						ServerSyncGetValue(psSCPSyncData->psSync));
 			}
@@ -498,14 +569,13 @@
 	PVRSRV_ERROR eError;
 
 	/* allocate an internal queue info structure */
-	psContext = OSAllocMem(sizeof(SCP_CONTEXT));
+	psContext = OSAllocZMem(sizeof(SCP_CONTEXT));
 	if (psContext == NULL)
 	{
 		PVR_DPF((PVR_DBG_ERROR,"SCPCreate: Failed to alloc queue struct"));
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto ErrorExit;
 	}
-	OSMemSet(psContext, 0, sizeof(SCP_CONTEXT));
 
 	/* allocate the command queue buffer - allow for overrun */
 	psContext->pvCCB = OSAllocMem(ui32Power2QueueSize);
@@ -516,10 +586,6 @@
 		goto ErrorExit;
 	}
 
-	/* Sanity check: Should be zeroed by OSMemSet */
-	PVR_ASSERT(psContext->ui32ReadOffset == 0);
-	PVR_ASSERT(psContext->ui32WriteOffset == 0);
-
 	psContext->ui32CCBSize = ui32Power2QueueSize;
 
 	eError = OSLockCreate(&psContext->hLock, LOCK_TYPE_NONE);
@@ -793,7 +859,8 @@
 	SCPCommandComplete
 */
 IMG_EXPORT
-void SCPCommandComplete(SCP_CONTEXT *psContext)
+void SCPCommandComplete(SCP_CONTEXT *psContext,
+                        IMG_BOOL bIgnoreFences)
 {
 	SCP_COMMAND *psCommand;
 	IMG_UINT32 i;
@@ -806,7 +873,7 @@
 
 	if (psContext->ui32ReadOffset == psContext->ui32DepOffset)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "SCPCommandComplete: Called with no work to do!"));
+		PVR_DPF((PVR_DBG_ERROR, "SCPCommandComplete: Called with nothing to do!"));
 		return;
 	}	
 
@@ -817,8 +884,50 @@
 
 		if (psCommand->ui32CmdType == SCP_COMMAND_CALLBACK)
 		{
-			IMG_UINT32 ui32UFOIdx = 0;
-			RGX_HWPERF_UFO_DATA_ELEMENT asSyncData[MAX_TRACED_UFOS];
+			RGX_HWPERF_UFO_DATA_ELEMENT asFenceSyncData[MAX_TRACED_UFOS];
+			RGX_HWPERF_UFO_DATA_ELEMENT asUpdateSyncData[MAX_TRACED_UFOS];
+			IMG_BOOL   bFenceFailed     = IMG_FALSE;
+			IMG_UINT32 ui32FenceUFOIdx  = 0;
+			IMG_UINT32 ui32UpdateUFOIdx = 0;
+
+			/* Do any fence checks */
+			if (bIgnoreFences == IMG_FALSE)
+			{
+				for (i=0;i<psCommand->ui32SyncCount;i++)
+				{
+					SCP_SYNC_DATA *psSCPSyncData = &psCommand->pasSCPSyncData[i];
+					IMG_BOOL bFence = (psSCPSyncData->ui32Flags & SCP_SYNC_DATA_FENCE);
+				
+					if (bFence)
+					{
+						IMG_UINT32 ui32CurrentValue = ServerSyncGetValue(psSCPSyncData->psSync);
+						IMG_UINT32 ui32SyncAddr;
+
+						(void)ServerSyncGetFWAddr(psSCPSyncData->psSync, &ui32SyncAddr);
+						PVR_ASSERT(ui32FenceUFOIdx < MAX_TRACED_UFOS);
+						asFenceSyncData[ui32FenceUFOIdx].sUpdate.ui32FWAddr = ui32SyncAddr;
+						asFenceSyncData[ui32FenceUFOIdx].sUpdate.ui32OldValue = ui32CurrentValue;
+						asFenceSyncData[ui32FenceUFOIdx].sUpdate.ui32NewValue = psSCPSyncData->ui32Update;
+						ui32FenceUFOIdx++;
+
+						if (ui32CurrentValue != psSCPSyncData->ui32Fence)
+						{
+							bFenceFailed = IMG_TRUE;
+						}
+					}
+				}
+
+				if (bFenceFailed)
+				{
+					RGX_HWPERF_HOST_UFO(RGX_HWPERF_UFO_EV_CHECK_FAIL, asFenceSyncData, ui32FenceUFOIdx);
+					return;
+				}
+				else
+				{
+					RGX_HWPERF_HOST_UFO(RGX_HWPERF_UFO_EV_CHECK_SUCCESS, asFenceSyncData, ui32FenceUFOIdx);
+				}
+			}
+			
 			/* Do any fence updates */
 			for (i=0;i<psCommand->ui32SyncCount;i++)
 			{
@@ -827,11 +936,14 @@
 
 				if (bUpdate)
 				{
-					PVR_ASSERT(ui32UFOIdx < MAX_TRACED_UFOS);
-					asSyncData[ui32UFOIdx].sUpdate.ui32FWAddr = ServerSyncGetFWAddr(psSCPSyncData->psSync);
-					asSyncData[ui32UFOIdx].sUpdate.ui32OldValue = ServerSyncGetValue(psSCPSyncData->psSync);
-					asSyncData[ui32UFOIdx].sUpdate.ui32NewValue = psSCPSyncData->ui32Update;
-					ui32UFOIdx++;
+					IMG_UINT32 ui32SyncAddr;
+
+					(void)ServerSyncGetFWAddr(psSCPSyncData->psSync, &ui32SyncAddr);
+					PVR_ASSERT(ui32UpdateUFOIdx < MAX_TRACED_UFOS);
+					asUpdateSyncData[ui32UpdateUFOIdx].sUpdate.ui32FWAddr = ui32SyncAddr;
+					asUpdateSyncData[ui32UpdateUFOIdx].sUpdate.ui32OldValue = ServerSyncGetValue(psSCPSyncData->psSync);
+					asUpdateSyncData[ui32UpdateUFOIdx].sUpdate.ui32NewValue = psSCPSyncData->ui32Update;
+					ui32UpdateUFOIdx++;
 				}
 
 				ServerSyncCompleteOp(psSCPSyncData->psSync, bUpdate, psSCPSyncData->ui32Update);
@@ -842,9 +954,9 @@
 					psSCPSyncData->psSync = NULL; /* Clear psSync as it is no longer referenced. */
 				}
 			}
-			if (ui32UFOIdx > 0)
+			if (ui32UpdateUFOIdx > 0)
 			{
-				RGX_HWPERF_HOST_UFO(RGX_HWPERF_UFO_EV_UPDATE, asSyncData, ui32UFOIdx);
+				RGX_HWPERF_HOST_UFO(RGX_HWPERF_UFO_EV_UPDATE, asUpdateSyncData, ui32UpdateUFOIdx);
 			}
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
diff --git a/drivers/staging/imgtec/rogue/scp.h b/drivers/staging/imgtec/rogue/scp.h
index effdb74..4584977 100644
--- a/drivers/staging/imgtec/rogue/scp.h
+++ b/drivers/staging/imgtec/rogue/scp.h
@@ -107,7 +107,7 @@
 @Output         ppvCompleteData         Pointer to memory allocated for command
                                         complete callback data
 
-@Return         PVRSRV_OK if the allocate was successfull
+@Return         PVRSRV_OK if the allocate was successful
 */
 /*****************************************************************************/
 IMG_IMPORT
@@ -164,11 +164,14 @@
 
 @Input          psSCPContext            Context to process
 
+@Input          bIgnoreFences           Do not respect any fence checks.
+
 @Return         PVRSRV_OK if the software command processor was run
 */
 /*****************************************************************************/
 IMG_IMPORT
-void SCPCommandComplete(SCP_CONTEXT *psContext);
+void SCPCommandComplete(SCP_CONTEXT *psContext,
+                        IMG_BOOL bIgnoreFences);
 
 /*************************************************************************/ /*!
 @Function       SCPFlush
diff --git a/drivers/staging/imgtec/rogue/services_km.h b/drivers/staging/imgtec/rogue/services_km.h
index 1015da3..9abc428 100644
--- a/drivers/staging/imgtec/rogue/services_km.h
+++ b/drivers/staging/imgtec/rogue/services_km.h
@@ -83,16 +83,58 @@
 	Flags for Services connection.
 	Allows to define per-client policy for Services
 */
-#define SRV_FLAGS_PERSIST		(1U << 0)  /*!< Persist client flag */
-#define SRV_FLAGS_INIT_PROCESS	(1U << 1)  /*!< Allows connect to succeed if SrvInit
+#define SRV_FLAGS_INIT_PROCESS          (1U << 1)  /*!< Allows connect to succeed if SrvInit
 											* has not yet run (used by SrvInit itself) */
-#define SRV_FLAGS_PDUMPCTRL     (1U << 31) /*!< PDump Ctrl client flag */
+
+#define SRV_WORKEST_ENABLED             (1U << 2)  /*!< If Workload Estimation is enabled */
+#define SRV_PDVFS_ENABLED               (1U << 3)  /*!< If PDVFS is enabled */
+
+#define SRV_NO_HWPERF_CLIENT_STREAM     (1U << 4)  /*!< Don't create HWPerf for this connection */
+
+/*
+ * Bits 20 - 27 are used to pass information needed for validation
+ * of the GPU Virtualisation Validation mechanism. In particular:
+ *
+ * Bits:
+ * [20 - 22]: OSid of the memory region that will be used for allocations
+ * [23 - 25]: OSid that will be emitted by the Firmware for all memory accesses
+ *            regarding that memory context.
+ *      [26]: If the AXI Protection register will be set to secure for that OSid
+ *      [27]: If the Emulator Wrapper Register checking for protection violation
+ *            will be set to secure for that OSid
+ */
+
+#define VIRTVAL_FLAG_OSID_SHIFT        (20)
+#define SRV_VIRTVAL_FLAG_OSID_MASK     (7U << VIRTVAL_FLAG_OSID_SHIFT)
+
+#define VIRTVAL_FLAG_OSIDREG_SHIFT     (23)
+#define SRV_VIRTVAL_FLAG_OSIDREG_MASK  (7U << VIRTVAL_FLAG_OSIDREG_SHIFT)
+
+#define VIRTVAL_FLAG_AXIPREG_SHIFT     (26)
+#define SRV_VIRTVAL_FLAG_AXIPREG_MASK  (1U << VIRTVAL_FLAG_AXIPREG_SHIFT)
+
+#define VIRTVAL_FLAG_AXIPTD_SHIFT      (27)
+#define SRV_VIRTVAL_FLAG_AXIPTD_MASK   (1U << VIRTVAL_FLAG_AXIPTD_SHIFT)
+
+#define SRV_FLAGS_PDUMPCTRL             (1U << 31) /*!< PDump Ctrl client flag */
 
 /*
     Pdump flags which are accessible to Services clients
 */
-#define PVRSRV_PDUMP_FLAGS_CONTINUOUS	0x40000000UL /*<! Output this entry always regardless of framed capture range,
+#define PDUMP_NONE		0x00000000UL /*<! No flags */
+
+#define PDUMP_CONT	0x40000000UL /*<! Output this entry always regardless of framed capture range,
                                                           used by client applications being dumped. */
+
+/* Status of the device. */
+typedef enum
+{
+	PVRSRV_DEVICE_STATUS_UNKNOWN,        /* status of the device is unknown */
+	PVRSRV_DEVICE_STATUS_OK,             /* the device is operational */
+	PVRSRV_DEVICE_STATUS_NOT_RESPONDING, /* the device is not responding */
+	PVRSRV_DEVICE_STATUS_DEVICE_ERROR    /* the device is not operational */
+} PVRSRV_DEVICE_STATUS;
+
 #endif /* SERVICES_KM_H */
 /**************************************************************************//**
 End of file (services_km.h)
diff --git a/drivers/staging/imgtec/rogue/servicesext.h b/drivers/staging/imgtec/rogue/servicesext.h
index 9ace660..a6537a0 100644
--- a/drivers/staging/imgtec/rogue/servicesext.h
+++ b/drivers/staging/imgtec/rogue/servicesext.h
@@ -152,32 +152,6 @@
 
 /*!
  *****************************************************************************
- * Enumeration of possible alpha types.
- *****************************************************************************/
-typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
-	PVRSRV_COLOURSPACE_FORMAT_UNKNOWN		=  0x00000000,  /*!< Colourspace Format: Unknown */
-	PVRSRV_COLOURSPACE_FORMAT_LINEAR		=  0x00010000,  /*!< Colourspace Format: Linear */
-	PVRSRV_COLOURSPACE_FORMAT_NONLINEAR		=  0x00020000,  /*!< Colourspace Format: Non-Linear */
-	PVRSRV_COLOURSPACE_FORMAT_MASK			=  0x000F0000,  /*!< Colourspace Format Mask */
-} PVRSRV_COLOURSPACE_FORMAT;
-
-
-/*!
- * Drawable orientation (in degrees clockwise).
- */
-typedef enum _IMG_ROTATION_ PVRSRV_ROTATION;
-
-#define PVRSRV_ROTATE_0 IMG_ROTATION_0DEG
-#define PVRSRV_ROTATE_90 IMG_ROTATION_90DEG
-#define PVRSRV_ROTATE_180 IMG_ROTATION_180DEG
-#define PVRSRV_ROTATE_270 IMG_ROTATION_270DEG
-#define PVRSRV_FLIP_Y IMG_ROTATION_FLIP_Y
-
-#define PVRSRV_ROTATE_BAD IMG_ROTATION_BAD
-
-
-/*!
- *****************************************************************************
  * This structure is used for OS independent registry (profile) access
  *****************************************************************************/
 
diff --git a/drivers/staging/imgtec/rogue/srvcore.c b/drivers/staging/imgtec/rogue/srvcore.c
index cefef89..f54d029 100644
--- a/drivers/staging/imgtec/rogue/srvcore.c
+++ b/drivers/staging/imgtec/rogue/srvcore.c
@@ -49,6 +49,7 @@
 #include "pvr_bridge.h"
 #include "connection_server.h"
 #include "device.h"
+#include "htbuffer.h"
 
 #include "pdump_km.h"
 
@@ -57,20 +58,28 @@
 #include "devicemem.h"
 
 #include "srvcore.h"
+#include "rgxinit.h"
 #include "pvrsrv.h"
 #include "power.h"
 #include "lists.h"
+#include "rgxdevice.h"
 
-#include "rgx_options_km.h"
+#include "rgx_options.h"
 #include "pvrversion.h"
 #include "lock.h"
 #include "osfunc.h"
+#include "device_connection.h"
+
+#include "rgxdevice.h"
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 #include "physmem_lma.h"
 #include "services_km.h"
 #endif
 
+#include "pvrsrv_tlstreams.h"
+#include "tlstream.h"
+
 /* For the purpose of maintainability, it is intended that this file should not
  * contain any OS specific #ifdefs. Please find a way to add e.g.
  * an osfunc.c abstraction or override the entire function in question within
@@ -84,8 +93,6 @@
 #define		PVR_DISPATCH_OFFSET_ARRAY_MAX 			2
 
 #define PVR_BUFFER_POOL_MAX 10
-#define PVR_BUFFER_POOL_IN_BUFFER_SIZE 0x200
-#define PVR_BUFFER_POOL_OUT_BUFFER_SIZE 0x100
 
 typedef struct
 {
@@ -103,6 +110,10 @@
 static IMG_UINT16 g_BridgeDispatchTableStartOffsets[BRIDGE_DISPATCH_TABLE_START_ENTRY_COUNT][PVR_DISPATCH_OFFSET_ARRAY_MAX];
 
 #if defined(DEBUG_BRIDGE_KM)
+/* a lock used for protecting bridge call timing calculations
+ * for calls which do not acquire a lock
+ */
+POS_LOCK g_hStatsLock;
 PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
 #endif
 
@@ -134,8 +145,8 @@
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_DMABUF][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_DMABUF_DISPATCH_LAST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_DC][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_DC_DISPATCH_FIRST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_DC][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_DC_DISPATCH_LAST;
-	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_CACHEGENERIC][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_FIRST;
-	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_CACHEGENERIC][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_CACHEGENERIC_DISPATCH_LAST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_CACHE][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_CACHE_DISPATCH_FIRST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_CACHE][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_CACHE_DISPATCH_LAST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_SMM][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_SMM_DISPATCH_FIRST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_SMM][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_SMM_DISPATCH_LAST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_PVRTL][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_PVRTL_DISPATCH_FIRST;
@@ -150,6 +161,12 @@
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_DEVICEMEMHISTORY][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_DEVICEMEMHISTORY_DISPATCH_LAST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_HTBUFFER][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_HTBUFFER_DISPATCH_FIRST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_HTBUFFER][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_HTBUFFER_DISPATCH_LAST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_DCPLAT][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_DCPLAT_DISPATCH_FIRST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_DCPLAT][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_DCPLAT_DISPATCH_LAST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_MMEXTMEM][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_FIRST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_MMEXTMEM][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_MMEXTMEM_DISPATCH_LAST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_SYNCTRACKING][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_FIRST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_SYNCTRACKING][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_SYNCTRACKING_DISPATCH_LAST;
 #if defined(SUPPORT_RGX)
 	/* Need a gap here to start next entry at element 128 */
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXTQ][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXTQ_DISPATCH_FIRST;
@@ -176,6 +193,10 @@
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_TIMERQUERY][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_TIMERQUERY_DISPATCH_LAST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXKICKSYNC][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_FIRST;
 	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXKICKSYNC][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXSIGNALS][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_FIRST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXSIGNALS][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_LAST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXTQ2][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST;
+	g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXTQ2][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST;
 #endif
 }
 
@@ -233,48 +254,137 @@
 				IMG_UINT32 ui32ClientDDKVersion,
 				IMG_UINT32 ui32ClientDDKBuild,
 				IMG_UINT8  *pui8KernelArch,
-				IMG_UINT32 *ui32Log2PageSize)
+				IMG_UINT32 *pui32CapabilityFlags,
+				IMG_UINT32 *ui32PVRBridges,
+				IMG_UINT32 *ui32RGXBridges)
 {
 	PVRSRV_ERROR		eError = PVRSRV_OK;
 	IMG_UINT32			ui32BuildOptions, ui32BuildOptionsMismatch;
 	IMG_UINT32			ui32DDKVersion, ui32DDKBuild;
 	PVRSRV_DATA			*psSRVData = NULL;
+	IMG_UINT64			ui64ProcessVASpaceSize = OSGetCurrentProcessVASpaceSize();
 	static IMG_BOOL		bIsFirstConnection=IMG_FALSE;
-	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVRSRV_RGXDEV_INFO *psDevInfo;
+
+	/* Clear the flags */
+	*pui32CapabilityFlags = 0;
+	psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
 	
 	psSRVData = PVRSRVGetPVRSRVData();
-	*ui32Log2PageSize = GET_LOG2_PAGESIZE();
 
 	psConnection->ui32ClientFlags = ui32Flags;
 
+	/* output the available bridges */
+	*ui32PVRBridges = gui32PVRBridges;
+	*ui32RGXBridges = gui32RGXBridges;
+
+	/*Set flags to pass back to the client showing which cache coherency is available.*/
+	/*Is the system CPU cache coherent?*/
+	if (PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig))
+	{
+		*pui32CapabilityFlags |= PVRSRV_CACHE_COHERENT_DEVICE_FLAG;
+	}
+	/*Is the system device cache coherent?*/
+	if (PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig))
+	{
+		*pui32CapabilityFlags |= PVRSRV_CACHE_COHERENT_CPU_FLAG;
+	}
+	/* Has the system device non-mappable local memory?*/
+	if (PVRSRVSystemHasNonMappableLocalMemory(psDeviceNode->psDevConfig))
+	{
+		*pui32CapabilityFlags |= PVRSRV_NONMAPPABLE_MEMORY_PRESENT_FLAG;
+	}
+
+	/* Set flags to indicate shared-virtual-memory (SVM) allocation availability */
+	if (! psDeviceNode->ui64GeneralSVMHeapTopVA || ! ui64ProcessVASpaceSize)
+	{
+		*pui32CapabilityFlags |= PVRSRV_DEVMEM_SVM_ALLOC_UNSUPPORTED;
+	}
+	else
+	{
+		if (ui64ProcessVASpaceSize <= psDeviceNode->ui64GeneralSVMHeapTopVA)
+		{
+			*pui32CapabilityFlags |= PVRSRV_DEVMEM_SVM_ALLOC_SUPPORTED;
+		}
+		else
+		{
+			/* This can happen when processor has more virtual address bits
+			   than device (i.e. alloc is not always guaranteed to succeed) */
+			*pui32CapabilityFlags |= PVRSRV_DEVMEM_SVM_ALLOC_CANFAIL;
+		}
+	}
+
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
 {
 	IMG_UINT32	ui32OSid = 0, ui32OSidReg = 0;
+    IMG_BOOL    bOSidAxiProtReg = IMG_FALSE;
 
 	IMG_PID pIDCurrent = OSGetCurrentClientProcessIDKM();
 
-	ui32OSid    = (ui32Flags & (OSID_BITS_FLAGS_MASK<<(OSID_BITS_FLAGS_OFFSET  ))) >> (OSID_BITS_FLAGS_OFFSET);
-	ui32OSidReg = (ui32Flags & (OSID_BITS_FLAGS_MASK<<(OSID_BITS_FLAGS_OFFSET+3))) >> (OSID_BITS_FLAGS_OFFSET+3);
+    ui32OSid    = (ui32Flags & SRV_VIRTVAL_FLAG_OSID_MASK)    >> (VIRTVAL_FLAG_OSID_SHIFT);
+    ui32OSidReg = (ui32Flags & SRV_VIRTVAL_FLAG_OSIDREG_MASK) >> (VIRTVAL_FLAG_OSIDREG_SHIFT);
 
-	InsertPidOSidsCoupling(pIDCurrent, ui32OSid, ui32OSidReg);
+#if defined(EMULATOR)
 
-	PVR_DPF((PVR_DBG_MESSAGE,"[GPU Virtualization Validation]: OSIDs: %d, %d\n",ui32OSid, ui32OSidReg));
+    if(psDevInfo->sDevFeatureCfg.ui64Features & RGX_FEATURE_AXI_ACELITE_BIT_MASK)
+    {
+    	IMG_UINT32 ui32OSidAxiProtReg = 0, ui32OSidAxiProtTD = 0;
+
+    	ui32OSidAxiProtReg = (ui32Flags & SRV_VIRTVAL_FLAG_AXIPREG_MASK) >> (VIRTVAL_FLAG_AXIPREG_SHIFT);
+    	ui32OSidAxiProtTD  = (ui32Flags & SRV_VIRTVAL_FLAG_AXIPTD_MASK)  >> (VIRTVAL_FLAG_AXIPTD_SHIFT);
+
+    	PVR_DPF((PVR_DBG_MESSAGE,
+    			"[AxiProt & Virt]: Setting bOSidAxiProt of Emulator's Trusted Device for Catbase %d to %s",
+				ui32OSidReg,
+				(ui32OSidAxiProtTD == 1)?"TRUE":"FALSE"));
+
+    	bOSidAxiProtReg = ui32OSidAxiProtReg == 1;
+    	PVR_DPF((PVR_DBG_MESSAGE,
+    			"[AxiProt & Virt]: Setting bOSidAxiProt of FW's Register for Catbase %d to %s",
+				ui32OSidReg,
+				bOSidAxiProtReg?"TRUE":"FALSE"));
+
+    	SetAxiProtOSid(ui32OSidReg, ui32OSidAxiProtTD);
+    }
+
+#endif
+
+    InsertPidOSidsCoupling(pIDCurrent, ui32OSid, ui32OSidReg, bOSidAxiProtReg);
+
+    PVR_DPF((PVR_DBG_MESSAGE,"[GPU Virtualization Validation]: OSIDs: %d, %d\n",ui32OSid, ui32OSidReg));
 }
 #endif
 
-#if defined(PDUMP)
-	/* Record this process ID in the persistent list to ensure
-	 * important PDump statements from this process are remembered
-	 * for PDump capture client connection that happen after the original
-	 * PDump statement was made e.g. for PDump connections after boot up.
-	 */
-	if (ui32Flags & SRV_FLAGS_PERSIST)
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+	/* Only enable if enabled in the UM */
+	if(ui32Flags & SRV_WORKEST_ENABLED)
 	{
-		eError = PDumpAddPersistantProcess();
+		psDevInfo->bWorkEstEnabled = IMG_TRUE;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVConnectKM: Workload Estimation disabled. Not enabled in UM."));
 	}
 #endif
 
-	if(ui32Flags & SRV_FLAGS_INIT_PROCESS)
+#if defined(SUPPORT_PDVFS)
+	/* Only enable if enabled in the UM */
+	if(ui32Flags & SRV_PDVFS_ENABLED)
+	{
+		psDevInfo->bPDVFSEnabled = IMG_TRUE;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVConnectKM: Proactive DVFS disabled. Not enabled in UM."));
+	}
+#endif
+
+	if (ui32Flags & SRV_FLAGS_INIT_PROCESS)
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	{
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+#else
 	{
 		PVR_DPF((PVR_DBG_MESSAGE, "%s: Connecting as init process", __func__));
 		if ((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
@@ -283,12 +393,27 @@
 			eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
 			goto chk_exit;
 		}
-#if defined (__linux__)
+#if defined (__linux__) || defined(INTEGRITY_OS)
 		PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
 #endif
 	}
 	else
 	{
+		/*
+		 * This check has to be done here (before the client against kernel check)
+		 * while the client options have not yet been modified
+		 */
+#if !defined(PVRSRV_GPUVIRT_GUESTDRV)
+		eError = RGXClientConnectCompatCheck_ClientAgainstFW(psDeviceNode, ui32ClientBuildOptions);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed. Mismatch between client and firmware build options.",
+					__FUNCTION__));
+			eError = PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+			goto chk_exit;
+		}
+#endif
+
 		if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
 		{
 			if (!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
@@ -317,6 +442,7 @@
 			}
 		}
 	}
+#endif /* defined(SUPPORT_KERNEL_SRVINIT) */
 
 	ui32DDKVersion = PVRVERSION_PACK(PVRVERSION_MAJ, PVRVERSION_MIN);
 	ui32DDKBuild = PVRVERSION_BUILD;
@@ -337,7 +463,10 @@
 		psSRVData->sDriverInfo.sUMBuildInfo.ui32BuildType = (ui32ClientBuildOptions & OPTIONS_DEBUG_MASK)? \
 																	BUILD_TYPE_DEBUG:BUILD_TYPE_RELEASE;
 	}
+
+	/* Masking out every option that is not kernel specific*/
 	ui32ClientBuildOptions &= RGX_BUILD_OPTIONS_MASK_KM;
+
 	/*
 	 * Validate the build options
 	 */
@@ -413,7 +542,30 @@
 				__FUNCTION__,
 				PVRVERSION_MAJ, PVRVERSION_MIN, PVRVERSION_MAJ, PVRVERSION_MIN));
 	}
-	
+
+	/* Create stream for every connection except for the special clients
+	 * that doesn't need it e.g.: recipients of HWPerf data. */
+	if (!(psConnection->ui32ClientFlags & SRV_NO_HWPERF_CLIENT_STREAM))
+	{
+		IMG_CHAR acStreamName[PRVSRVTL_MAX_STREAM_NAME_SIZE];
+		OSSNPrintf(acStreamName, PRVSRVTL_MAX_STREAM_NAME_SIZE,
+		           PVRSRV_TL_HWPERF_HOST_CLIENT_STREAM_FMTSPEC,
+		           psConnection->pid);
+		eError = TLStreamCreate(&psConnection->hClientTLStream, acStreamName,
+		                        131072, TL_FLAG_ALLOCATE_ON_FIRST_OPEN, NULL,
+		                        NULL, NULL, NULL);
+		if (eError != PVRSRV_OK && eError != PVRSRV_ERROR_ALREADY_EXISTS)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Could not create private TL stream (%s)",
+					PVRSRVGetErrorStringKM(eError)));
+			psConnection->hClientTLStream = NULL;
+		}
+		/* Reset error status. We don't want to propagate any errors from here. */
+		eError = PVRSRV_OK;
+
+		PVR_DPF((PVR_DBG_MESSAGE, "Created stream \"%s\".", acStreamName));
+	}
+
 	/*
 	 * Validate DDK build
 	 */
@@ -486,11 +638,47 @@
 	return PVRSRV_OK;
 }
 
+/**************************************************************************/ /*!
+@Function       PVRSRVAcquireGlobalEventObjectKM
+@Description    Acquire the global event object.
+@Output         phGlobalEventObject    On success, points to the global event
+                                       object handle
+@Return         PVRSRV_ERROR           PVRSRV_OK on success or an error
+                                       otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVAcquireGlobalEventObjectKM(IMG_HANDLE *phGlobalEventObject)
+{
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+	*phGlobalEventObject = psPVRSRVData->hGlobalEventObject;
+
+	return PVRSRV_OK;
+}
+
+/**************************************************************************/ /*!
+@Function       PVRSRVReleaseGlobalEventObjectKM
+@Description    Release the global event object.
+@Output         hGlobalEventObject    Global event object handle
+@Return         PVRSRV_ERROR          PVRSRV_OK on success or an error otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVReleaseGlobalEventObjectKM(IMG_HANDLE hGlobalEventObject)
+{
+	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+	PVR_ASSERT(psPVRSRVData->hGlobalEventObject == hGlobalEventObject);
+
+	return PVRSRV_OK;
+}
+
 /*
 	PVRSRVDumpDebugInfoKM
 */
 PVRSRV_ERROR
-PVRSRVDumpDebugInfoKM(IMG_UINT32 ui32VerbLevel)
+PVRSRVDumpDebugInfoKM(CONNECTION_DATA *psConnection,
+					  PVRSRV_DEVICE_NODE *psDeviceNode,
+					  IMG_UINT32 ui32VerbLevel)
 {
 	if (ui32VerbLevel > DEBUG_REQUEST_VERBOSITY_MAX)
 	{
@@ -498,8 +686,8 @@
 	}
 	PVR_LOG(("User requested PVR debug info"));
 
-	PVRSRVDebugRequest(ui32VerbLevel, NULL, NULL);
-									   
+	PVRSRVDebugRequest(psDeviceNode, ui32VerbLevel, NULL, NULL);
+	
 	return PVRSRV_OK;
 }
 
@@ -532,26 +720,25 @@
 	PVRSRVHWOpTimeoutKM
 */
 PVRSRV_ERROR
-PVRSRVHWOpTimeoutKM(void)
+PVRSRVHWOpTimeoutKM(CONNECTION_DATA *psConnection,
+					PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 #if defined(PVRSRV_RESET_ON_HWTIMEOUT)
 	PVR_LOG(("User requested OS reset"));
 	OSPanic();
 #endif
 	PVR_LOG(("HW operation timeout, dump server info"));
-	PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MEDIUM, NULL, NULL);
+	PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MEDIUM, NULL, NULL);
 	return PVRSRV_OK;
 }
 
+
 IMG_INT
 DummyBW(IMG_UINT32 ui32DispatchTableEntry,
 		void *psBridgeIn,
 		void *psBridgeOut,
 		CONNECTION_DATA *psConnection)
 {
-#if !defined(DEBUG)
-	PVR_UNREFERENCED_PARAMETER(ui32DispatchTableEntry);
-#endif
 	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
 	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
 	PVR_UNREFERENCED_PARAMETER(psConnection);
@@ -565,39 +752,75 @@
 			 "Dummy Wrapper (probably not what you want!)",
 			 __FUNCTION__, ui32DispatchTableEntry));
 #endif
-	return -ENOTTY;
+	return PVRSRV_ERROR_BRIDGE_ENOTTY;
 }
 
-
-/*
-	PVRSRVSoftResetKM
-*/
-PVRSRV_ERROR
-PVRSRVSoftResetKM(CONNECTION_DATA * psConnection,
-                  PVRSRV_DEVICE_NODE *psDeviceNode,
-                  IMG_UINT64 ui64ResetValue1,
-                  IMG_UINT64 ui64ResetValue2)
+#if defined(SUPPORT_KERNEL_SRVINIT)
+PVRSRV_ERROR PVRSRVAlignmentCheckKM(CONNECTION_DATA *psConnection,
+                                    PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    IMG_UINT32 ui32AlignChecksSize,
+                                    IMG_UINT32 aui32AlignChecks[])
 {
-	PVRSRV_ERROR eError = PVRSRV_OK;
-
 	PVR_UNREFERENCED_PARAMETER(psConnection);
 
-	if ((psDeviceNode == NULL) || (psDeviceNode->pfnSoftReset == NULL))
-	{
-		return PVRSRV_ERROR_INVALID_PARAMS;
-	}
+#if !defined(NO_HARDWARE) && defined(RGXFW_ALIGNCHECKS)
 
-	eError = psDeviceNode->pfnSoftReset(psDeviceNode, ui64ResetValue1, ui64ResetValue2);
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_WARNING, "PVRSRVSoftResetKM: "
-				"Failed to soft reset (error %d)",
-				eError));
-	}
+	PVR_ASSERT(psDeviceNode->pfnAlignmentCheck != NULL);
+	return psDeviceNode->pfnAlignmentCheck(psDeviceNode, ui32AlignChecksSize,
+	                                       aui32AlignChecks);
 
-	return eError;
+#else
+
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+	PVR_UNREFERENCED_PARAMETER(ui32AlignChecksSize);
+	PVR_UNREFERENCED_PARAMETER(aui32AlignChecks);
+
+	return PVRSRV_OK;
+
+#endif /* !defined(NO_HARDWARE) */
+
 }
+#endif /* defined(SUPPORT_KERNEL_SRVINIT) */
 
+PVRSRV_ERROR PVRSRVGetDeviceStatusKM(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_UINT32 *pui32DeviceStatus)
+{
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	/* First try to update the status. */
+	if (psDeviceNode->pfnUpdateHealthStatus != NULL)
+	{
+		PVRSRV_ERROR eError = psDeviceNode->pfnUpdateHealthStatus(psDeviceNode,
+		                                                          IMG_FALSE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetDeviceStatusKM: Failed to"
+					 "check for device status (%d)", eError));
+
+			/* Return unknown status and error because we don't know what
+			 * happened and if the status is valid. */
+			*pui32DeviceStatus = PVRSRV_DEVICE_STATUS_UNKNOWN;
+			return eError;
+		}
+	}
+
+	switch (OSAtomicRead(&psDeviceNode->eHealthStatus))
+	{
+		case PVRSRV_DEVICE_HEALTH_STATUS_OK:
+			*pui32DeviceStatus = PVRSRV_DEVICE_STATUS_OK;
+			return PVRSRV_OK;
+		case PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING:
+			*pui32DeviceStatus = PVRSRV_DEVICE_STATUS_NOT_RESPONDING;
+			return PVRSRV_OK;
+		case PVRSRV_DEVICE_HEALTH_STATUS_DEAD:
+			*pui32DeviceStatus = PVRSRV_DEVICE_STATUS_DEVICE_ERROR;
+			return PVRSRV_OK;
+		default:
+			*pui32DeviceStatus = PVRSRV_DEVICE_STATUS_UNKNOWN;
+			return PVRSRV_ERROR_INTERNAL_ERROR;
+	}
+}
 
 /*!
  * *****************************************************************************
@@ -622,9 +845,7 @@
 					   IMG_BOOL bUseLock)
 {
 	static IMG_UINT32 ui32PrevIndex = IMG_UINT32_MAX;		/* -1 */
-#if !defined(DEBUG)
-	PVR_UNREFERENCED_PARAMETER(pszIOCName);
-#endif
+
 #if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
 	PVR_UNREFERENCED_PARAMETER(pszFunctionName);
 	PVR_UNREFERENCED_PARAMETER(pszBridgeLockName);
@@ -646,7 +867,7 @@
 	 *
 	 * NOTE: This shouldn't be debug only since switching from debug->release
 	 * etc is likely to modify the available ioctls and thus be a point where
-	 * mistakes are exposed. This isn't run at at a performance critical time.
+	 * mistakes are exposed. This isn't run at a performance critical time.
 	 */
 	if((ui32PrevIndex != IMG_UINT32_MAX) &&
 	   ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
@@ -715,33 +936,42 @@
 	/* Panic if the previous entry has been overwritten as this is not allowed!
 	 * NOTE: This shouldn't be debug only since switching from debug->release
 	 * etc is likely to modify the available ioctls and thus be a point where
-	 * mistakes are exposed. This isn't run at at a performance critical time.
+	 * mistakes are exposed. This isn't run at a performance critical time.
 	 */
 	if(g_BridgeDispatchTable[ui32Index].pfFunction)
 	{
+		if(g_BridgeDispatchTable[ui32Index].pfFunction != pfFunction)
+		{
 #if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
-		PVR_DPF((PVR_DBG_ERROR,
-				 "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
-				 __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+			PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Adding dispatch table entry for %s clobbers an existing entry for %s (current pfn=<%p>, new pfn=<%p>)",
+				 __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName),
+				 (void*)g_BridgeDispatchTable[ui32Index].pfFunction, (void*)pfFunction));
 #else
-		PVR_DPF((PVR_DBG_ERROR,
-				 "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%u)",
-				 __FUNCTION__, pszIOCName, ui32Index));
-		PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+			PVR_DPF((PVR_DBG_ERROR,
+				 "%s: Adding dispatch table entry for %s clobbers an existing entry (index=%u). (current pfn=<%p>, new pfn=<%p>)",
+				 __FUNCTION__, pszIOCName, ui32Index,
+				 (void*)g_BridgeDispatchTable[ui32Index].pfFunction, (void*)pfFunction));
+			PVR_DPF((PVR_DBG_WARNING, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
 #endif
-		OSPanic();
+			OSPanic();
+		}
 	}
-
-	g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
-	g_BridgeDispatchTable[ui32Index].hBridgeLock = hBridgeLock;
-	g_BridgeDispatchTable[ui32Index].bUseLock = bUseLock;
+	else
+	{
+		g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+		g_BridgeDispatchTable[ui32Index].hBridgeLock = hBridgeLock;
+		g_BridgeDispatchTable[ui32Index].bUseLock = bUseLock;
 #if defined(DEBUG_BRIDGE_KM)
-	g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
-	g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
-	g_BridgeDispatchTable[ui32Index].pszBridgeLockName = pszBridgeLockName;
-	g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
-	g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+		g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+		g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+		g_BridgeDispatchTable[ui32Index].pszBridgeLockName = pszBridgeLockName;
+		g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+		g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+		g_BridgeDispatchTable[ui32Index].ui64TotalTimeNS = 0;
+		g_BridgeDispatchTable[ui32Index].ui64MaxTimeNS = 0;
 #endif
+	}
 
 	ui32PrevIndex = ui32Index;
 }
@@ -754,24 +984,33 @@
 {
 	PVRSRV_ERROR eError;
 
-#if !defined(SUPPORT_KERNEL_SRVINIT)
-	if(!(psConnection->ui32ClientFlags & SRV_FLAGS_INIT_PROCESS))
+#if defined(SUPPORT_KERNEL_SRVINIT)
+	if (psConnection)
+	{
+		/* Assume this is being called by a user space process */
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+#else
+	if (!(psConnection->ui32ClientFlags & SRV_FLAGS_INIT_PROCESS))
 	{
 		return PVRSRV_ERROR_SRV_DISCONNECT_FAILED;
 	}
-#endif
+
 	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
 	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+#endif
 
-	eError = PVRSRVFinaliseSystem(bInitSuccesful, ui32ClientBuildOptions);
+	eError = PVRSRVDeviceFinalise(psDeviceNode, bInitSuccesful);
 
+#if !defined(SUPPORT_KERNEL_SRVINIT)
 	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL,
 				(eError == PVRSRV_OK) && bInitSuccesful);
+#endif
 
 	return eError;
 }
 
-PVRSRV_ERROR BridgeBufferPoolCreate(void)
+static PVRSRV_ERROR _BridgeBufferPoolCreate(void)
 {
 	PVRSRV_ERROR eError;
 
@@ -790,14 +1029,14 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "BridgePoolCreate: Failed to create lock "
 				"for the bridge buffer pool."));
-		OSFREEMEMNOSTATS(g_psBridgePool);
+		OSFreeMemNoStats(g_psBridgePool);
 		return eError;
 	}
 
 	return PVRSRV_OK;
 }
 
-void BridgeBufferPoolDestroy(void)
+static void _BridgeBufferPoolDestroy(void)
 {
 	IMG_UINT i;
 
@@ -807,21 +1046,55 @@
 		OSFreeMem(g_psBridgePool->asPool[i].pvBuffer);
 
 	OSLockDestroy(g_psBridgePool->hLock);
-	OSFREEMEMNOSTATS(g_psBridgePool);
+	OSFreeMemNoStats(g_psBridgePool);
+}
+
+PVRSRV_ERROR BridgeInit(void)
+{
+	PVRSRV_ERROR eError;
+
+	eError = _BridgeBufferPoolCreate();
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Failed to create bridge buffer pool"));
+		return eError;
+	}
+
+#if defined(DEBUG_BRIDGE_KM)
+	eError = OSLockCreate(&g_hStatsLock, LOCK_TYPE_PASSIVE);
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Failed to create bridge stats lock"));
+		return eError;
+	}
+#endif
+
+	return PVRSRV_OK;
+}
+
+void BridgeDeinit(void)
+{
+#if defined(DEBUG_BRIDGE_KM)
+	if(g_hStatsLock)
+	{
+		OSLockDestroy(g_hStatsLock);
+		g_hStatsLock = NULL;
+	}
+#endif
+
+	_BridgeBufferPoolDestroy();
 }
 
 static PVR_POOL_BUFFER *_BridgePoolAcquireBuffer(void **ppvBridgeIn,
-                                                 IMG_UINT32 *ui32BridgeInBufferSize,
-                                                 void **ppvBridgeOut,
-                                                 IMG_UINT32 *ui32BridgeOutBufferSize)
+                                                 void **ppvBridgeOut)
 {
 	PVR_POOL_BUFFER *psPoolBuffer = NULL;
 	IMG_UINT i;
 
 	PVR_ASSERT(g_psBridgePool != NULL);
 	PVR_ASSERT(ppvBridgeIn != NULL && ppvBridgeOut != NULL);
-	PVR_ASSERT(ui32BridgeInBufferSize != NULL &&
-	           ui32BridgeOutBufferSize != NULL);
 
 	OSLockAcquire(g_psBridgePool->hLock);
 
@@ -839,10 +1112,8 @@
 
 			psBuffer->bTaken = IMG_TRUE;
 			*ppvBridgeIn = psBuffer->pvBuffer;
-			*ui32BridgeInBufferSize = PVR_BUFFER_POOL_IN_BUFFER_SIZE;
 			*ppvBridgeOut = ((IMG_BYTE *) psBuffer->pvBuffer) +
-			        PVR_BUFFER_POOL_IN_BUFFER_SIZE;
-			*ui32BridgeOutBufferSize = PVR_BUFFER_POOL_OUT_BUFFER_SIZE;
+			        PVRSRV_MAX_BRIDGE_IN_SIZE;
 
 			psPoolBuffer = psBuffer;
 			goto return_;
@@ -852,8 +1123,8 @@
 			PVR_DPF((PVR_DBG_VERBOSE, "_BridgePoolAcquireBuffer: "
 			        "Allocating new bridge buffer."));
 
-			psBuffer->pvBuffer = OSAllocZMemNoStats(PVR_BUFFER_POOL_IN_BUFFER_SIZE +
-			                                PVR_BUFFER_POOL_OUT_BUFFER_SIZE);
+			psBuffer->pvBuffer = OSAllocZMemNoStats(PVRSRV_MAX_BRIDGE_IN_SIZE +
+			                                PVRSRV_MAX_BRIDGE_OUT_SIZE);
 			if (psBuffer->pvBuffer == NULL)
 			{
 				PVR_DPF((PVR_DBG_ERROR, "_BridgePoolAcquireBuffer: "
@@ -862,10 +1133,8 @@
 			}
 
 			*ppvBridgeIn = psBuffer->pvBuffer;
-			*ui32BridgeInBufferSize = PVR_BUFFER_POOL_IN_BUFFER_SIZE;
 			*ppvBridgeOut = ((IMG_BYTE *) psBuffer->pvBuffer) +
-			        PVR_BUFFER_POOL_IN_BUFFER_SIZE;
-			*ui32BridgeOutBufferSize = PVR_BUFFER_POOL_OUT_BUFFER_SIZE;
+			        PVRSRV_MAX_BRIDGE_IN_SIZE;
 			g_psBridgePool->uiCount++;
 
 			psPoolBuffer = psBuffer;
@@ -902,7 +1171,7 @@
 	OSLockRelease(g_psBridgePool->hLock);
 }
 
-IMG_INT BridgedDispatchKM(CONNECTION_DATA * psConnection,
+PVRSRV_ERROR BridgedDispatchKM(CONNECTION_DATA * psConnection,
                           PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM)
 {
 
@@ -910,10 +1179,14 @@
 	void       * psBridgeOut=NULL;
 	BridgeWrapperFunction pfBridgeHandler;
 	IMG_UINT32   ui32DispatchTableEntry, ui32GroupBoundary;
-	IMG_INT      err          = -EFAULT;
-	IMG_UINT32	ui32BridgeInBufferSize;
-	IMG_UINT32	ui32BridgeOutBufferSize;
+	PVRSRV_ERROR err = PVRSRV_OK;
 	PVR_POOL_BUFFER *psPoolBuffer = NULL;
+	IMG_UINT32 ui32Timestamp = OSClockus();
+#if defined(DEBUG_BRIDGE_KM)
+	IMG_UINT64	ui64TimeStart;
+	IMG_UINT64	ui64TimeEnd;
+	IMG_UINT64	ui64TimeDiff;
+#endif
 
 #if defined(DEBUG_BRIDGE_KM_STOP_AT_DISPATCH)
 	PVR_DBG_BREAK;
@@ -923,16 +1196,19 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Out of range dispatch table group ID: %d",
 		        __FUNCTION__, psBridgePackageKM->ui32BridgeID));
+		err = PVRSRV_ERROR_BRIDGE_EINVAL;
 		goto return_error;
 	}
 	ui32DispatchTableEntry = g_BridgeDispatchTableStartOffsets[psBridgePackageKM->ui32BridgeID][PVR_DISPATCH_OFFSET_FIRST_FUNC];
 	ui32GroupBoundary = g_BridgeDispatchTableStartOffsets[psBridgePackageKM->ui32BridgeID][PVR_DISPATCH_OFFSET_LAST_FUNC];
 
+	/* bridge function is not implemented in this build */
 	if(0 == ui32DispatchTableEntry)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Dispatch table entry=%d, boundary = %d, (bridge module %d, function %d)",
 					__FUNCTION__,
 					ui32DispatchTableEntry,ui32GroupBoundary, psBridgePackageKM->ui32BridgeID, psBridgePackageKM->ui32FunctionID));
+		/* this points to DummyBW() which returns PVRSRV_ERROR_ENOTTY */
 		err = g_BridgeDispatchTable[ui32DispatchTableEntry].pfFunction(ui32DispatchTableEntry,
 				  psBridgeIn,
 				  psBridgeOut,
@@ -948,6 +1224,7 @@
 		PVR_DPF((PVR_DBG_ERROR, "%s: Dispatch table entry=%d, boundary = %d, (bridge module %d, function %d)",
 					__FUNCTION__,
 					ui32DispatchTableEntry,ui32GroupBoundary, psBridgePackageKM->ui32BridgeID, psBridgePackageKM->ui32FunctionID));
+		err = PVRSRV_ERROR_BRIDGE_EINVAL;
 		goto return_error;
 	}
 	if(BRIDGE_DISPATCH_TABLE_ENTRY_COUNT <= ui32DispatchTableEntry)
@@ -957,11 +1234,12 @@
 		        ui32DispatchTableEntry, BRIDGE_DISPATCH_TABLE_ENTRY_COUNT,
 		        psBridgePackageKM->ui32BridgeID,
 		        psBridgePackageKM->ui32FunctionID));
+		err = PVRSRV_ERROR_BRIDGE_EINVAL;
 		goto return_error;
 	}
 #if defined(DEBUG_BRIDGE_KM)
 	PVR_DPF((PVR_DBG_MESSAGE, "%s: Dispatch table entry=%d, (bridge module %d, function %d)",
-			__FUNCTION__, 
+			__FUNCTION__,
 			ui32DispatchTableEntry, psBridgePackageKM->ui32BridgeID, psBridgePackageKM->ui32FunctionID));
 	PVR_DPF((PVR_DBG_MESSAGE, "%s: %s",
 			 __FUNCTION__,
@@ -978,9 +1256,7 @@
 
 		/* Request for global bridge buffers */
 		OSGetGlobalBridgeBuffers(&psBridgeIn,
-		                         &ui32BridgeInBufferSize,
-		                         &psBridgeOut,
-		                         &ui32BridgeOutBufferSize);
+		                         &psBridgeOut);
 	}
 	else
 	{
@@ -991,31 +1267,34 @@
 		}
 
 		psPoolBuffer = _BridgePoolAcquireBuffer(&psBridgeIn,
-		                                        &ui32BridgeInBufferSize,
-		                                        &psBridgeOut,
-		                                        &ui32BridgeOutBufferSize);
+		                                        &psBridgeOut);
 		if (psPoolBuffer == NULL)
 		{
-			err = PVRSRV_ERROR_OUT_OF_MEMORY;
+			err = PVRSRV_ERROR_BRIDGE_ENOMEM;
 			goto unlock_and_return_error;
 		}
 	}
 
-	if (psBridgePackageKM->ui32InBufferSize > ui32BridgeInBufferSize)
+#if defined(DEBUG_BRIDGE_KM)
+	ui64TimeStart = OSClockns64();
+#endif
+
+	if (psBridgePackageKM->ui32InBufferSize > PVRSRV_MAX_BRIDGE_IN_SIZE)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Bridge input buffer too small "
 		        "(data size %u, buffer size %u)!", __FUNCTION__,
-		        psBridgePackageKM->ui32InBufferSize, ui32BridgeInBufferSize));
-		err = PVRSRV_ERROR_BUFFER_TOO_SMALL;
+		        psBridgePackageKM->ui32InBufferSize, PVRSRV_MAX_BRIDGE_IN_SIZE));
+		err = PVRSRV_ERROR_BRIDGE_ERANGE;
 		goto unlock_and_return_error;
 	}
-
-	if (psBridgePackageKM->ui32OutBufferSize > ui32BridgeOutBufferSize)
+	
+#if !defined(INTEGRITY_OS)
+	if (psBridgePackageKM->ui32OutBufferSize > PVRSRV_MAX_BRIDGE_OUT_SIZE)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: Bridge output buffer too small "
 		        "(data size %u, buffer size %u)!", __FUNCTION__,
-		        psBridgePackageKM->ui32OutBufferSize, ui32BridgeOutBufferSize));
-		err = PVRSRV_ERROR_BUFFER_TOO_SMALL;
+		        psBridgePackageKM->ui32OutBufferSize, PVRSRV_MAX_BRIDGE_OUT_SIZE));
+		err = PVRSRV_ERROR_BRIDGE_ERANGE;
 		goto unlock_and_return_error;
 	}
 
@@ -1035,8 +1314,13 @@
 		) /* end of if-condition */
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: CopyFromUserWrapper returned an error!", __FUNCTION__));
+		err = PVRSRV_ERROR_BRIDGE_EFAULT;
 		goto unlock_and_return_error;
 	}
+#else
+	psBridgeIn = psBridgePackageKM->pvParamIn;
+	psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
 
 	pfBridgeHandler =
 		(BridgeWrapperFunction)g_BridgeDispatchTable[ui32DispatchTableEntry].pfFunction;
@@ -1045,38 +1329,71 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: ui32DispatchTableEntry = %d is not a registered function!",
 				 __FUNCTION__, ui32DispatchTableEntry));
+		err = PVRSRV_ERROR_BRIDGE_EFAULT;
 		goto unlock_and_return_error;
 	}
 	
-	err = pfBridgeHandler(ui32DispatchTableEntry,
+	/* pfBridgeHandler functions do not fail and return an IMG_INT.
+	 * The value returned is either 0 or PVRSRV_OK (0).
+	 * In the event this changes an error may be +ve or -ve,
+	 * so try to return something consistent here.
+	 */
+	if (0 != pfBridgeHandler(ui32DispatchTableEntry,
 						  psBridgeIn,
 						  psBridgeOut,
-						  psConnection);
-	if(err < 0)
+						  psConnection)
+		)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: ...done (err=%d)", __FUNCTION__, err));
+		PVR_DPF((PVR_DBG_ERROR, "%s: pfBridgeHandler returned an error", __FUNCTION__));
+		err = PVRSRV_ERROR_BRIDGE_EPERM;
 		goto unlock_and_return_error;
 	}
 
-	/* 
+	/*
 	   This should always be true as a.t.m. all bridge calls have to
-   	   return an error message, but this could change so we do this
-   	   check to be safe.
-   	*/
+	   return an error message, but this could change so we do this
+	   check to be safe.
+	*/
 	if (psBridgePackageKM->ui32OutBufferSize > 0)
 	{
-		err = -EFAULT;
+#if !defined(INTEGRITY_OS)
 		if (CopyToUserWrapper (psConnection,
 						ui32DispatchTableEntry,
 						psBridgePackageKM->pvParamOut,
 						psBridgeOut,
 						psBridgePackageKM->ui32OutBufferSize) != PVRSRV_OK)
 		{
+			err = PVRSRV_ERROR_BRIDGE_EFAULT;
 			goto unlock_and_return_error;
 		}
+#endif
 	}
 
-	err = 0;
+#if defined(DEBUG_BRIDGE_KM)
+	ui64TimeEnd = OSClockns64();
+
+	ui64TimeDiff = ui64TimeEnd - ui64TimeStart;
+
+	/* if there is no lock held then acquire the stats lock to
+	 * ensure the calculations are done safely
+	 */
+	if(!g_BridgeDispatchTable[ui32DispatchTableEntry].bUseLock)
+	{
+		OSLockAcquire(g_hStatsLock);
+	}
+
+	g_BridgeDispatchTable[ui32DispatchTableEntry].ui64TotalTimeNS += ui64TimeDiff;
+
+	if(ui64TimeDiff > g_BridgeDispatchTable[ui32DispatchTableEntry].ui64MaxTimeNS)
+	{
+		g_BridgeDispatchTable[ui32DispatchTableEntry].ui64MaxTimeNS = ui64TimeDiff;
+	}
+
+	if(!g_BridgeDispatchTable[ui32DispatchTableEntry].bUseLock)
+	{
+		OSLockRelease(g_hStatsLock);
+	}
+#endif
 
 unlock_and_return_error:
 	if (g_BridgeDispatchTable[ui32DispatchTableEntry].hBridgeLock == NULL &&
@@ -1100,5 +1417,21 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: returning (err = %d)", __FUNCTION__, err));
 	}
+	/* ignore transport layer bridge to avoid HTB flooding */
+	if (psBridgePackageKM->ui32BridgeID != PVRSRV_BRIDGE_PVRTL)
+	{
+		if (err)
+		{
+			HTBLOGK(HTB_SF_BRG_BRIDGE_CALL_ERR, ui32Timestamp,
+			        psBridgePackageKM->ui32BridgeID,
+			        psBridgePackageKM->ui32FunctionID, err);
+		}
+		else
+		{
+			HTBLOGK(HTB_SF_BRG_BRIDGE_CALL, ui32Timestamp,
+			        psBridgePackageKM->ui32BridgeID,
+			        psBridgePackageKM->ui32FunctionID);
+		}
+	}
 	return err;
 }
diff --git a/drivers/staging/imgtec/rogue/srvcore.h b/drivers/staging/imgtec/rogue/srvcore.h
index 02f51c5..e915bf1 100644
--- a/drivers/staging/imgtec/rogue/srvcore.h
+++ b/drivers/staging/imgtec/rogue/srvcore.h
@@ -52,17 +52,6 @@
 #if defined(SUPPORT_RGX)
 #include "rgx_bridge.h"
 #endif
-#include "pvr_bridge_io.h"
-
-#ifndef ENOMEM
-#define ENOMEM	12
-#endif
-#ifndef EFAULT
-#define EFAULT	14
-#endif
-#ifndef ENOTTY
-#define ENOTTY	25
-#endif
 
 PVRSRV_ERROR
 CopyFromUserWrapper(CONNECTION_DATA *psConnection,
@@ -104,6 +93,8 @@
 											 userspace within this ioctl */
 	IMG_UINT32 ui32CopyToUserTotalBytes; /*!< The total number of bytes copied from
 										   userspace within this ioctl */
+	IMG_UINT64 ui64TotalTimeNS; /*!< The total amount of time spent in this bridge function */
+	IMG_UINT64 ui64MaxTimeNS; /*!< The maximum amount of time for a single call to this bridge function */
 #endif
 }PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
 
@@ -133,7 +124,7 @@
 /* PRQA S 0884,3410 2*/ /* macro relies on the lack of brackets */
 #define SetDispatchTableEntry(ui32BridgeGroup, ui32Index, pfFunction,\
 					hBridgeLock, bUseLock) \
-	_SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32BridgeGroup), ui32Index, #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction,\
+	_SetDispatchTableEntry(ui32BridgeGroup, ui32Index, #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction,\
 							(POS_LOCK)hBridgeLock, #hBridgeLock, bUseLock )
 
 #define DISPATCH_TABLE_GAP_THRESHOLD 5
@@ -153,10 +144,10 @@
 extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
 #endif
 
-PVRSRV_ERROR BridgeBufferPoolCreate(void);
-void BridgeBufferPoolDestroy(void);
+PVRSRV_ERROR BridgeInit(void);
+void BridgeDeinit(void);
 
-IMG_INT BridgedDispatchKM(CONNECTION_DATA * psConnection,
+PVRSRV_ERROR BridgedDispatchKM(CONNECTION_DATA * psConnection,
 					  PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM);
 
 
@@ -168,7 +159,9 @@
 				IMG_UINT32 ui32ClientDDKVersion,
 				IMG_UINT32 ui32ClientDDKBuild,
 				IMG_UINT8  *pui8KernelArch,
-				IMG_UINT32 *ui32Log2PageSize);
+				IMG_UINT32 *ui32CapabilityFlags,
+				IMG_UINT32 *ui32PVRBridges,
+				IMG_UINT32 *ui32RGXBridges);
 
 PVRSRV_ERROR
 PVRSRVDisconnectKM(void);
@@ -180,7 +173,15 @@
                           IMG_UINT32 ui32ClientBuildOptions);
 
 PVRSRV_ERROR
-PVRSRVDumpDebugInfoKM(IMG_UINT32 ui32VerbLevel);
+PVRSRVAcquireGlobalEventObjectKM(IMG_HANDLE *phGlobalEventObject);
+
+PVRSRV_ERROR
+PVRSRVReleaseGlobalEventObjectKM(IMG_HANDLE hGlobalEventObject);
+
+PVRSRV_ERROR
+PVRSRVDumpDebugInfoKM(CONNECTION_DATA *psConnection,
+					  PVRSRV_DEVICE_NODE *psDeviceNode,
+					  IMG_UINT32 ui32VerbLevel);
 
 PVRSRV_ERROR
 PVRSRVGetDevClockSpeedKM(CONNECTION_DATA * psConnection,
@@ -188,18 +189,20 @@
                          IMG_PUINT32  pui32RGXClockSpeed);
 
 PVRSRV_ERROR
-PVRSRVHWOpTimeoutKM(void);
+PVRSRVHWOpTimeoutKM(CONNECTION_DATA *psConnection,
+					PVRSRV_DEVICE_NODE *psDeviceNode);
 
-/* performs a SOFT_RESET on the given device node */
-PVRSRV_ERROR
-PVRSRVSoftResetKM(CONNECTION_DATA * psConnection,
-                  PVRSRV_DEVICE_NODE *psDeviceNode,
-                  IMG_UINT64 ui64ResetValue1,
-                  IMG_UINT64 ui64ResetValue2);
+PVRSRV_ERROR PVRSRVAlignmentCheckKM(CONNECTION_DATA *psConnection,
+                                    PVRSRV_DEVICE_NODE * psDeviceNode,
+                                    IMG_UINT32 ui32FWAlignChecksSize,
+                                    IMG_UINT32 aui32FWAlignChecks[]);
 
+PVRSRV_ERROR PVRSRVGetDeviceStatusKM(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_UINT32 *pui32DeviceStatus);
 
 #endif /* __BRIDGED_PVR_BRIDGE_H__ */
 
 /******************************************************************************
- End of file (bridged_pvr_bridge.h)
+ End of file (srvcore.h)
 ******************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/srvinit.h b/drivers/staging/imgtec/rogue/srvinit.h
index 3fff16a..a9d6db1 100644
--- a/drivers/staging/imgtec/rogue/srvinit.h
+++ b/drivers/staging/imgtec/rogue/srvinit.h
@@ -59,8 +59,6 @@
 IMG_INTERNAL PVRSRV_ERROR RGXInit(SHARED_DEV_CONNECTION hServices);
 #endif
 
-IMG_INTERNAL void _ParseHTBAppHints(SHARED_DEV_CONNECTION hServices);
-
 #if defined (__cplusplus)
 }
 #endif
diff --git a/drivers/staging/imgtec/rogue/srvinit_km.c b/drivers/staging/imgtec/rogue/srvinit_km.c
deleted file mode 100644
index 6a35d90..0000000
--- a/drivers/staging/imgtec/rogue/srvinit_km.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          In-kernel services initialisation routines
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Kernel equivalents of UM functions required to load the
-                firmware, but without any UM-only requirements.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include "img_defs.h"
-#include "pvrsrv_error.h"
-#include "power.h"
-#include "pvr_debug.h"
-#include "srvinit.h"
-#include "srvcore.h"
-#include "rgx_options.h"
-#include "pvrsrv.h"
-#include "lists.h"
-
-static void SrvInitDevice_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
-{
-	PVRSRV_ERROR *peError = va_arg(va, PVRSRV_ERROR *);
-	PVRSRV_ERROR eError = PVRSRV_OK;
-
-	switch(psDeviceNode->sDevId.eDeviceType)
-	{
-#if defined(SUPPORT_RGX)
-		case PVRSRV_DEVICE_TYPE_RGX:
-			eError = RGXInit(psDeviceNode);
-			if (eError != PVRSRV_OK)
-			{
-				PVR_DPF((PVR_DBG_ERROR,
-					 "%s: Initialisation of Rogue device failed (%d)", __func__, eError));
-			}
-			break;
-#endif
-		default:
-			break;
-	}
-
-	/* Only record the first error encountered */
-	if (*peError == PVRSRV_OK)
-	{
-		*peError = eError;
-	}
-}
-
-PVRSRV_ERROR SrvInit(void)
-{
-	PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-	static IMG_BOOL bInitSuccessful = IMG_FALSE;
-	PVRSRV_ERROR eError = PVRSRV_OK;
-	PVRSRV_ERROR eRet;
-
-	if (bInitSuccessful)
-	{
-		eRet = eError;
-		goto exit;
-	}
-
-	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
-
-	List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
-                                       &SrvInitDevice_ForEachVaCb,
-                                       &eError);
-	if (eError != PVRSRV_OK)
-	{
-		goto cleanup;
-	}
-
-	_ParseHTBAppHints(NULL);
-
-	bInitSuccessful = IMG_TRUE;
-cleanup:
-	eRet = eError;
-
-	eError = PVRSRVInitSrvDisconnectKM(NULL,
-						NULL,
-						bInitSuccessful,
-						(IMG_UINT32)(RGX_BUILD_OPTIONS));
-	if (eError != PVRSRV_OK)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: Services initialisation disconnect failed (%d).", __func__, eError));
-		eRet = eError;
-	}
-
-exit:
-	return eRet;
-}
diff --git a/drivers/staging/imgtec/rogue/srvinit_osfunc.h b/drivers/staging/imgtec/rogue/srvinit_osfunc.h
index 545635b..e529292 100644
--- a/drivers/staging/imgtec/rogue/srvinit_osfunc.h
+++ b/drivers/staging/imgtec/rogue/srvinit_osfunc.h
@@ -59,16 +59,16 @@
 #include <stdio.h>
 #endif
 
-#if defined(__linux__) && defined(__KERNEL__)
+#if (defined(__linux__) && defined(__KERNEL__)) || (defined(INTEGRITY_OS) && defined(SUPPORT_KERNEL_SRVINIT)) || defined(__QNXNTO__)
 #include "osfunc.h"
 static inline void SRVINITDeviceMemCopy(void *pvDst, const void *pvSrc, size_t uiSize)
 {
-	OSMemCopy(pvDst, pvSrc, uiSize);
+	OSDeviceMemCopy(pvDst, pvSrc, uiSize);
 }
 
 static inline void SRVINITDeviceMemSet(void *pvDest, IMG_UINT8 ui8Value, size_t uiSize)
 {
-	OSMemSet(pvDest, ui8Value, uiSize);
+	OSDeviceMemSet(pvDest, ui8Value, uiSize);
 }
 #else
 #include "services.h"
diff --git a/drivers/staging/imgtec/rogue/srvinit_param.h b/drivers/staging/imgtec/rogue/srvinit_param.h
deleted file mode 100644
index 78760c9..0000000
--- a/drivers/staging/imgtec/rogue/srvinit_param.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Initialisation server parameters header
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Defines the connections between the various parts of the
-		initialisation server.
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#ifndef __SRVINIT_PARAM_H__
-#define __SRVINIT_PARAM_H__
-
-#if defined(__linux__) && defined(__KERNEL__)
-#include "os_srvinit_param.h"
-#else
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-#include "img_defs.h"
-#include "img_types.h"
-
-typedef struct
-{
-	IMG_CHAR *pszValue;
-	IMG_UINT32 ui32Value;
-} SRV_INIT_PARAM_UINT32_LOOKUP;
-
-void *SrvInitParamOpen(void);
-void SrvInitParamClose(void *pvState);
-
-#define	SrvInitParamInitBOOL(name, defval) \
-	static const IMG_BOOL __SrvInitParam_ ## name = defval;
-
-void _SrvInitParamGetBOOL(void *pvState, const IMG_CHAR *pszName, const IMG_BOOL *pbDefault, IMG_BOOL *pbValue);
-
-#define	SrvInitParamGetBOOL(state, name, value) \
-		_SrvInitParamGetBOOL(state, # name, & __SrvInitParam_ ## name, &(value))
-
-#define	SrvInitParamInitUINT32(name, defval) \
-	static const IMG_UINT32 __SrvInitParam_ ## name = defval;
-
-void _SrvInitParamGetUINT32(void *pvState, const IMG_CHAR *pszName, const IMG_UINT32 *pui32Default, IMG_UINT32 *pui32Value);
-
-#define	SrvInitParamGetUINT32(state, name, value) \
-		_SrvInitParamGetUINT32(state, # name, & __SrvInitParam_ ## name, &(value))
-
-#define	SrvInitParamInitUINT32BitField(name, inival, lookup) \
-	static IMG_UINT32 __SrvInitParam_ ## name = inival; \
-	static SRV_INIT_PARAM_UINT32_LOOKUP * \
-		__SrvInitParamLookup_ ## name = &lookup[0]; \
-	static const IMG_UINT32 __SrvInitParamSize_ ## name = \
-					(sizeof(lookup) / sizeof(lookup[0]));
-
-IMG_BOOL _SrvInitParamGetUINT32BitField(void *pvState, const IMG_CHAR *pszBaseName, IMG_UINT32 uiDefault, const SRV_INIT_PARAM_UINT32_LOOKUP *psLookup, IMG_UINT32 uiSize, IMG_UINT32 *puiValue);
-
-#define	SrvInitParamGetUINT32BitField(state, name, value) \
-		_SrvInitParamGetUINT32BitField(state, # name, __SrvInitParam_ ## name, __SrvInitParamLookup_ ## name, __SrvInitParamSize_ ## name, &(value))
-
-#define	SrvInitParamInitUINT32List(name, defval, lookup) \
-	static IMG_UINT32 __SrvInitParam_ ## name = defval; \
-	static SRV_INIT_PARAM_UINT32_LOOKUP * \
-		__SrvInitParamLookup_ ## name = &lookup[0]; \
-	static const IMG_UINT32 __SrvInitParamSize_ ## name = \
-					(sizeof(lookup) / sizeof(lookup[0]));
-
-IMG_BOOL _SrvInitParamGetUINT32List(void *pvState, const IMG_CHAR *pszName, IMG_UINT32 uiDefault, const SRV_INIT_PARAM_UINT32_LOOKUP *psLookup, IMG_UINT32 uiSize, IMG_UINT32 *puiValue);
-
-#define	SrvInitParamGetUINT32List(state, name, value) \
-		_SrvInitParamGetUINT32List(state, # name, __SrvInitParam_ ## name, __SrvInitParamLookup_ ## name, __SrvInitParamSize_ ## name, &(value))
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif
-
-#endif /* __SRVINIT_PARAM_H__ */
diff --git a/drivers/staging/imgtec/rogue/srvinit_pdump.h b/drivers/staging/imgtec/rogue/srvinit_pdump.h
index 5501533..9f66eee 100644
--- a/drivers/staging/imgtec/rogue/srvinit_pdump.h
+++ b/drivers/staging/imgtec/rogue/srvinit_pdump.h
@@ -61,11 +61,8 @@
 
 #if defined(PDUMP)
 
-#if defined(__GNUC__)
-IMG_INTERNAL void SRVINITPDumpComment(SHARED_DEV_CONNECTION hServices, const IMG_CHAR *pszFormat, ...) __attribute__ ((format (printf, 2, 3)));
-#else
+__printf(2, 3)
 IMG_INTERNAL void SRVINITPDumpComment(SHARED_DEV_CONNECTION hServices, const IMG_CHAR *pszFormat, ...);
-#endif
 
 #else
 
diff --git a/drivers/staging/imgtec/rogue/srvkm.h b/drivers/staging/imgtec/rogue/srvkm.h
index 5cbdb7d..b300093 100644
--- a/drivers/staging/imgtec/rogue/srvkm.h
+++ b/drivers/staging/imgtec/rogue/srvkm.h
@@ -45,88 +45,57 @@
 
 #include "servicesext.h"
 
-
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
 #include <services_kernel_client.h>
 #endif
 
-/**	Use PVR_DPF() unless message is necessary in release build
- */
-#ifdef PVR_DISABLE_LOGGING
-#define PVR_LOG(X)
-#else
-/* PRQA S 3410 1 */ /* this macro requires no brackets in order to work */
-#define PVR_LOG(X)			PVRSRVReleasePrintf X;
+struct _PVRSRV_DEVICE_NODE_;
+
+/*************************************************************************/ /*!
+@Function     PVRSRVDriverInit
+@Description  Performs one time initialisation of Services.
+@Return       PVRSRV_ERROR   PVRSRV_OK on success and an error otherwise
+*/ /**************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDriverInit(void);
+
+/*************************************************************************/ /*!
+@Function     PVRSRVDriverInit
+@Description  Performs one time de-initialisation of Services.
+@Return       void 
+*/ /**************************************************************************/
+void IMG_CALLCONV PVRSRVDriverDeInit(void);
+
+/*************************************************************************/ /*!
+@Function     PVRSRVDeviceCreate
+@Description  Creates a PVR Services device node for an OS native device.
+@Input        pvOSDevice     OS native device
+@Output       ppsDeviceNode  Points to the new device node on success
+@Return       PVRSRV_ERROR   PVRSRV_OK on success and an error otherwise
+*/ /**************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV
+PVRSRVDeviceCreate(void *pvOSDevice,
+				   struct _PVRSRV_DEVICE_NODE_ **ppsDeviceNode);
+
+#if defined(SUPPORT_KERNEL_SRVINIT)
+/*************************************************************************/ /*!
+@Function     PVRSRVDeviceInitialise
+@Description  Initialises the given device, created by PVRSRVDeviceCreate, so
+              that's in a functional state ready to be used.
+@Input        psDeviceNode  Device node of the device to be initialised
+@Return       PVRSRV_ERROR  PVRSRV_OK on success and an error otherwise
+*/ /**************************************************************************/
+PVRSRV_ERROR PVRSRVDeviceInitialise(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 #endif
 
-IMG_IMPORT void IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVInit
-
- @Description	Initialise services
-
- @Input	   psSysData	: sysdata structure
-
- @Return   PVRSRV_ERROR	:
-
-******************************************************************************/
-PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(void *);
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVDeInit
-
- @Description	De-Initialise services
-
- @Input	   psSysData	: sysdata structure
-
- @Return   PVRSRV_ERROR	:
-
-******************************************************************************/
-void IMG_CALLCONV PVRSRVDeInit(void *);
-
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVScheduleDevicesKM
-
- @Description	Schedules all Services-Managed Devices to check their pending
- 				command queues. The intention is that ScheduleDevices be called by the
-				3rd party BC driver after it has finished writing new data to its output
-				texture.
-
- @Input		bInLISR
-
- @Return	void
-
-******************************************************************************/
-IMG_IMPORT void PVRSRVScheduleDevicesKM(IMG_BOOL bInLISR);
-
-void IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
-
-PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, size_t *puiBufSize, IMG_BOOL bSave);
-
-/*!
-******************************************************************************
-
- @Function	PVRSRVScheduleDeviceCallbacks
-
- @Description	Schedule all device callbacks
-
- @Input		ui32CallerID
-
- @Return	void
-
-******************************************************************************/
-void PVRSRVScheduleDeviceCallbacks(IMG_UINT32 ui32CallerID);
-
-
+/*************************************************************************/ /*!
+@Function     PVRSRVDeviceDestroy
+@Description  Destroys a PVR Services device node.
+@Input        psDeviceNode  Device node to destroy
+@Return       PVRSRV_ERROR  PVRSRV_OK on success and an error otherwise
+*/ /**************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV
+PVRSRVDeviceDestroy(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 
 /******************
 HIGHER LEVEL MACROS
@@ -169,22 +138,4 @@
 #define END_LOOP_UNTIL_TIMEOUT() \
 }
 
-/*!
- ******************************************************************************
-
- @Function		PVRSRVGetErrorStringKM
-
- @Description	Returns a text string relating to the PVRSRV_ERROR enum.
-
- ******************************************************************************/
-IMG_IMPORT
-const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
-
-typedef struct _SERVER_SYNC_PRIM_
-{
-	/* Placeholder until structure is properly implemented */
-	IMG_UINT32 ui32Placeholder;
-} SERVER_SYNC_PRIM;
-
-
 #endif /* SRVKM_H */
diff --git a/drivers/staging/imgtec/rogue/sync.c b/drivers/staging/imgtec/rogue/sync.c
index c53579b..71cfc44 100644
--- a/drivers/staging/imgtec/rogue/sync.c
+++ b/drivers/staging/imgtec/rogue/sync.c
@@ -44,6 +44,10 @@
 
 #include "img_types.h"
 #include "client_sync_bridge.h"
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+#include "client_synctracking_bridge.h"
+#endif
+#include "pvr_bridge.h"
 #include "allocmem.h"
 #include "osfunc.h"
 #include "devicemem.h"
@@ -54,13 +58,13 @@
 #include "sync_internal.h"
 #include "lock.h"
 #include "log2.h"
+/* FIXME */
 #if defined(__KERNEL__)
 #include "pvrsrv.h"
 #endif
 
 
 #define SYNC_BLOCK_LIST_CHUNCK_SIZE	10
-#define LOCAL_SYNC_PRIM_RESET_VALUE 0
 
 /*
 	This defines the maximum amount of synchronisation memory
@@ -108,7 +112,7 @@
 } SYNC_OP_COOKIE;
 
 /* forward declaration */
-static void
+static PVRSRV_ERROR
 _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value);
 
 /*
@@ -189,7 +193,8 @@
 	                           hSyncImportHandle,
 	                           PVRSRV_MEMALLOCFLAG_CPU_READABLE,
 	                           &psSyncBlk->hMemDesc,
-	                           &uiImportSize);
+	                           &uiImportSize,
+	                           "SyncPrimitiveBlock");
 
 	/*
 		Regardless of success or failure we "undo" the export
@@ -236,10 +241,11 @@
 	OSFreeMem(psSyncBlk);
 }
 
-static IMG_BOOL
+static PVRSRV_ERROR
 SyncPrimBlockImport(RA_PERARENA_HANDLE hArena,
 					RA_LENGTH_T uSize,
 					RA_FLAGS_T uFlags,
+					const IMG_CHAR *pszAnnotation,
 					RA_BASE_T *puiBase,
 					RA_LENGTH_T *puiActualSize,
 					RA_PERISPAN_HANDLE *phImport)
@@ -248,13 +254,13 @@
 	SYNC_PRIM_BLOCK *psSyncBlock = NULL;
 	RA_LENGTH_T uiSpanSize;
 	PVRSRV_ERROR eError;
-	IMG_BOOL bRet;
 	PVR_UNREFERENCED_PARAMETER(uFlags);
 
 	/* Check we've not be called with an unexpected size */
 	if (!hArena || sizeof(IMG_UINT32) != uSize)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		goto e0;
 	}
 
@@ -268,40 +274,42 @@
 	eError = AllocSyncPrimitiveBlock(psContext, &psSyncBlock);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Failed to allocation syncprim block (%d)", eError));
+		PVR_DPF((PVR_DBG_ERROR, "Failed to allocate syncprim block (%d)", eError));
 		goto fail_syncblockalloc;
 	}
 
 	/* Allocate a span for it */
-	bRet = RA_Alloc(psContext->psSpanRA,
+	eError = RA_Alloc(psContext->psSpanRA,
 					psSyncBlock->ui32SyncBlockSize,
 					RA_NO_IMPORT_MULTIPLIER,
 					0,
 					psSyncBlock->ui32SyncBlockSize,
+					pszAnnotation,
 					&psSyncBlock->uiSpanBase,
 					&uiSpanSize,
 					NULL);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_spanalloc;
+	}
 
 	/*
 		There is no reason the span RA should return an allocation larger
 		then we request
 	*/
-	if (bRet == IMG_FALSE || uiSpanSize != psSyncBlock->ui32SyncBlockSize)
-	{
-		goto fail_spanalloc;
-	}
+	PVR_ASSERT(uiSpanSize == psSyncBlock->ui32SyncBlockSize);
 
 	*puiBase = psSyncBlock->uiSpanBase;
 	*puiActualSize = psSyncBlock->ui32SyncBlockSize;
 	*phImport = psSyncBlock;
-	return IMG_TRUE;
+	return PVRSRV_OK;
 
 fail_spanalloc:
 	FreeSyncPrimitiveBlock(psSyncBlock);
 fail_syncblockalloc:
 	_SyncPrimContextUnref(psContext);
 e0:
-	return IMG_FALSE;
+	return eError;
 }
 
 static void
@@ -334,6 +342,10 @@
 	
 	PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL);
 
+	/* FIXME: Subtracting a 64-bit address from another and then implicit
+	 * cast to 32-bit number. Need to review all call sequences that use this
+	 * function, added explicit casting for now.
+	 */
 	ui64Temp =  psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase;
 	PVR_ASSERT(ui64Temp<IMG_UINT32_MAX);
 	return (IMG_UINT32)ui64Temp;
@@ -352,19 +364,39 @@
 	SYNC_PRIM_BLOCK *psSyncBlock;
 	SYNC_PRIM_CONTEXT *psContext;
 
-#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+	psContext = psSyncBlock->psContext;
+
 	{
 		PVRSRV_ERROR eError;
-		/* remove this sync record */
-		eError = BridgeSyncRecordRemoveByHandle(
-						psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection,
-						psSyncInt->u.sLocal.hRecord);
-		if (PVRSRV_OK != eError)
+		IMG_HANDLE hConn =
+				psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+		if(PVRSRVIsBridgeEnabled(hConn, PVRSRV_BRIDGE_SYNCTRACKING))
 		{
-			PVR_DPF((PVR_DBG_ERROR, "%s: failed to remove SyncRecord", __FUNCTION__));
+			/* remove this sync record */
+			eError = BridgeSyncRecordRemoveByHandle(hConn,
+			                                        psSyncInt->u.sLocal.hRecord);
+			if (PVRSRV_OK != eError)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: failed to remove SyncRecord", __FUNCTION__));
+			}
+		}
+		else
+#endif /* if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+		{
+			IMG_UINT32 ui32FWAddr = psSyncBlock->ui32FirmwareAddr +
+					SyncPrimGetOffset(psSyncInt);
+
+			eError = BridgeSyncFreeEvent(hConn, ui32FWAddr);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "BridgeSyncAllocEvent failed with error:"
+				        " %d", eError));
+			}
 		}
 	}
-#endif
 	/* reset the sync prim value as it is freed.
 	 * this guarantees the client sync allocated to the client will
 	 * have a value of zero and the client does not need to
@@ -372,10 +404,7 @@
 	 * the allocation of the backing memory for the sync prim block
 	 * is done with ZERO_ON_ALLOC so the memory is initially all zero.
 	 */
-	 _SyncPrimSetValue(psSyncInt, LOCAL_SYNC_PRIM_RESET_VALUE);
-
-	psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
-	psContext = psSyncBlock->psContext;
+	(void) _SyncPrimSetValue(psSyncInt, LOCAL_SYNC_PRIM_RESET_VALUE);
 
 	RA_Free(psContext->psSubAllocRA, psSyncInt->u.sLocal.uiSpanAddr);
 	OSFreeMem(psSyncInt);
@@ -706,13 +735,22 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s attempted with active references, may be the result of a race", __FUNCTION__));
 	}
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+#if defined(__KERNEL__)
+	if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Forcing context destruction due to bad driver state.", __FUNCTION__));
+		OSAtomicWrite(&psContext->hRefCount, 1);
+	}
+#endif
+#endif
 	_SyncPrimContextUnref(psContext);
 }
 
 static PVRSRV_ERROR _SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
-										PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
-										const IMG_CHAR *pszClassName,
-										IMG_BOOL bServerSync)
+                                   PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
+                                   const IMG_CHAR *pszClassName,
+                                   IMG_BOOL bServerSync)
 {
 	SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
 	SYNC_PRIM_BLOCK *psSyncBlock;
@@ -720,6 +758,12 @@
 	PVRSRV_ERROR eError;
 	RA_BASE_T uiSpanAddr;
 
+	if (!hSyncPrimContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: invalid context", __func__));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
 	psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
 	if (psNewSync == NULL)
 	{
@@ -727,16 +771,17 @@
 		goto fail_alloc;
 	}
 
-	if (!RA_Alloc(psContext->psSubAllocRA,
-				  sizeof(IMG_UINT32),
-				  RA_NO_IMPORT_MULTIPLIER,
-				  0,
-				  sizeof(IMG_UINT32),
-				  &uiSpanAddr,
-				  NULL,
-				  (RA_PERISPAN_HANDLE *) &psSyncBlock))
+	eError = RA_Alloc(psContext->psSubAllocRA,
+	                  sizeof(IMG_UINT32),
+	                  RA_NO_IMPORT_MULTIPLIER,
+	                  0,
+	                  sizeof(IMG_UINT32),
+	                  "Sync_Prim",
+	                  &uiSpanAddr,
+	                  NULL,
+	                  (RA_PERISPAN_HANDLE *) &psSyncBlock);
+	if (PVRSRV_OK != eError)
 	{
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto fail_raalloc;
 	}
 	psNewSync->eType = SYNC_PRIM_TYPE_LOCAL;
@@ -748,6 +793,7 @@
 	_SyncPrimContextRef(psContext);
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	if(PVRSRVIsBridgeEnabled(psSyncBlock->psContext->hDevConnection, PVRSRV_BRIDGE_SYNCTRACKING))
 	{
 		IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
 		if(pszClassName)
@@ -776,10 +822,20 @@
 			PVR_DPF((PVR_DBG_ERROR, "%s: failed to add SyncRecord", __FUNCTION__));
 		}
 	}
-#else
-	PVR_UNREFERENCED_PARAMETER(pszClassName);
-	PVR_UNREFERENCED_PARAMETER(bServerSync);
+	else
 #endif /* if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+	{
+		eError = BridgeSyncAllocEvent(hSyncPrimContext->hDevConnection,
+		                              bServerSync,
+		                              psSyncBlock->ui32FirmwareAddr + SyncPrimGetOffset(psNewSync),
+		                              OSStringNLength(pszClassName, SYNC_MAX_CLASS_NAME_LEN),
+		                              pszClassName);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "BridgeSyncAllocEvent failed with error: %d",
+			        eError));
+		}
+	}
 
 	return PVRSRV_OK;
 
@@ -806,12 +862,12 @@
 										const IMG_CHAR *pszClassName)
 {
 	return _SyncPrimAlloc(hSyncPrimContext,
-					  ppsSync,
-					  pszClassName,
-					  IMG_FALSE);
+	                      ppsSync,
+	                      pszClassName,
+	                      IMG_FALSE);
 }
 
-static void
+static PVRSRV_ERROR
 _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value)
 {
 	PVRSRV_ERROR eError;
@@ -836,20 +892,19 @@
 									ui32Value);
 	}
 	/* These functions don't actually fail */
-	if (PVRSRV_OK != eError)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
-	}
+	return eError;
 }
 
-IMG_INTERNAL void SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+IMG_INTERNAL PVRSRV_ERROR SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync)
 {
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	SYNC_PRIM *psSyncInt;
 
 	if (!psSync)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
-		return;
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto err_out;
 	}
 
 	psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
@@ -863,25 +918,31 @@
 	}
 	else
 	{
-		PVR_DPF((PVR_DBG_ERROR, "SyncPrimFree: Invalid sync type"));
 		/*
 			Either the client has given us a bad pointer or there is an
 			error in this module
 		*/
-		return;
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
+		goto err_out;
 	}
+
+err_out:
+	return eError;
 }
 
 #if defined(NO_HARDWARE)
-IMG_INTERNAL void
+IMG_INTERNAL PVRSRV_ERROR
 SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
 {
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	SYNC_PRIM *psSyncInt;
 
 	if (!psSync)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
-		return;
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto err_out;
 	}
 	psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
 
@@ -889,34 +950,41 @@
 	   substitutes the Firmware updating a sync and that sync could
 	   be a server one */
 
-	_SyncPrimSetValue(psSyncInt, ui32Value);
+	eError =  _SyncPrimSetValue(psSyncInt, ui32Value);
+
+err_out:
+	return eError;
 }
 #endif
 
-IMG_INTERNAL void
+IMG_INTERNAL PVRSRV_ERROR
 SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
 {
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	SYNC_PRIM *psSyncInt;
 
 	if (!psSync)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
-		return;
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto err_out;
 	}
 
 	psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
 	if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "SyncPrimSet: Invalid sync type"));
-		return;
+		eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
+		goto err_out;
 	}
 
-	_SyncPrimSetValue(psSyncInt, ui32Value);
+	eError = _SyncPrimSetValue(psSyncInt, ui32Value);
 
 #if defined(PDUMP)
 	SyncPrimPDump(psSync);
 #endif
-
+err_out:
+	return eError;
 }
 
 IMG_INTERNAL PVRSRV_ERROR SyncPrimLocalGetHandleAndOffset(PVRSRV_CLIENT_SYNC_PRIM *psSync,
@@ -952,35 +1020,41 @@
 	return eError;
 }
 
-IMG_INTERNAL IMG_UINT32 SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+IMG_INTERNAL PVRSRV_ERROR
+SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 *pui32FwAddr)
 {
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	SYNC_PRIM *psSyncInt;
+
+	*pui32FwAddr = 0;
 	if (!psSync)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		goto err_out;
 	}
 
 	psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
 	if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
 	{
-		return SyncPrimGetFirmwareAddrLocal(psSyncInt);
+		*pui32FwAddr = SyncPrimGetFirmwareAddrLocal(psSyncInt);
 	}
 	else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
 	{
-		return SyncPrimGetFirmwareAddrServer(psSyncInt);
+		*pui32FwAddr = SyncPrimGetFirmwareAddrServer(psSyncInt);
 	}
 	else
 	{
-		PVR_DPF((PVR_DBG_ERROR, "SyncPrimGetFirmwareAddr: Invalid sync type"));
-		/*
-			Either the client has given us a bad pointer or there is an
-			error in this module
-		*/
+		/* Either the client has given us a bad pointer or there is an
+		 * error in this module
+		 */
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
 		goto err_out;
 	}
+
 err_out:
-	return 0;
+	return eError;
 }
 
 #if !defined(__KERNEL__)
@@ -1024,7 +1098,7 @@
 			   Either the client has given us a bad pointer or there is an
 			   error in this module
 			   */
-			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
 			goto err_free;
 		}
 	}
@@ -1110,8 +1184,8 @@
 
 IMG_INTERNAL
 PVRSRV_ERROR SyncPrimOpCreate(IMG_UINT32 ui32SyncCount,
-							  PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim,
-							  PSYNC_OP_COOKIE *ppsCookie)
+			  PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim,
+			  PSYNC_OP_COOKIE *ppsCookie)
 {
 	SYNC_OP_COOKIE *psNewCookie;
 	SYNC_BLOCK_LIST *psSyncBlockList;
@@ -1128,9 +1202,10 @@
 	IMG_HANDLE *pahHandleList;
 	IMG_CHAR *pcPtr;
 	PVRSRV_ERROR eError;
+	IMG_BOOL bServerSync;
 
 	psSyncBlockList = _SyncPrimBlockListCreate();
-	
+
 	if (!psSyncBlockList)
 	{
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -1139,7 +1214,9 @@
 
 	for (i=0;i<ui32SyncCount;i++)
 	{
-		if (SyncPrimIsServerSync(papsSyncPrim[i]))
+		eError = SyncPrimIsServerSync(papsSyncPrim[i], &bServerSync);
+		if (PVRSRV_OK != eError) goto e1;
+		if (bServerSync)
 		{
 			ui32ServerSyncCount++;
 		}
@@ -1181,7 +1258,7 @@
 
 	pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
 	psNewCookie->paui32Index = (IMG_UINT32 *) pcPtr;
-	
+
 	pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
 	psNewCookie->paui32Flags = (IMG_UINT32 *) pcPtr;
 
@@ -1203,7 +1280,7 @@
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: cookie setup failed", __FUNCTION__));
 		eError = PVRSRV_ERROR_INTERNAL_ERROR;
-		goto e1;
+		goto e2;
 	}
 
 	psNewCookie->ui32SyncCount = ui32SyncCount;
@@ -1217,7 +1294,9 @@
 		Note: We assume the all syncs have been created with the same
 			  services connection.
 	*/
-	if (SyncPrimIsServerSync(papsSyncPrim[0]))
+	eError = SyncPrimIsServerSync(papsSyncPrim[0], &bServerSync);
+	if (PVRSRV_OK != eError) goto e2;
+	if (bServerSync)
 	{
 		SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
 
@@ -1227,7 +1306,7 @@
 	{
 		SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
 
-		hBridge = psSync->u.sLocal.psSyncBlock->psContext->hDevConnection;		
+		hBridge = psSync->u.sLocal.psSyncBlock->psContext->hDevConnection;
 	}
 
 	psNewCookie->hBridge = hBridge;
@@ -1246,7 +1325,9 @@
 	{
 		SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
 
-		if (SyncPrimIsServerSync(papsSyncPrim[i]))
+		eError = SyncPrimIsServerSync(papsSyncPrim[i], &bServerSync);
+		if (PVRSRV_OK != eError) goto e2;
+		if (bServerSync)
 		{
 			psNewCookie->pahServerSync[ui32ServerIndex] = psSync->u.sServer.hServerSync;
 
@@ -1332,10 +1413,11 @@
 							IMG_UINT32 ui32SyncCount,
 							PVRSRV_CLIENT_SYNC_PRIM_OP *pasSyncOp)
 {
-	PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	IMG_UINT32 ui32ServerIndex = 0;
 	IMG_UINT32 ui32ClientIndex = 0;
 	IMG_UINT32 i;
+	IMG_BOOL bServerSync;
 
 	/* Copy client sync operations */
 	for (i=0;i<ui32SyncCount;i++)
@@ -1346,10 +1428,13 @@
 		*/
 		if (psCookie->papsSyncPrim[i] != pasSyncOp[i].psSync)
 		{
-			return PVRSRV_ERROR_INVALID_PARAMS;
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto e0;
 		}
 
-		if (SyncPrimIsServerSync(pasSyncOp[i].psSync))
+		eError = SyncPrimIsServerSync(pasSyncOp[i].psSync, &bServerSync);
+		if (PVRSRV_OK != eError) goto e0;
+		if (bServerSync)
 		{
 			psCookie->paui32ServerFlags[ui32ServerIndex] =
 					pasSyncOp[i].ui32Flags;
@@ -1379,6 +1464,7 @@
 								  psCookie->ui32ServerSyncCount,
 								  psCookie->paui32ServerFlags);
 
+e0:
 	return eError;
 }
 
@@ -1454,11 +1540,20 @@
 }
 
 IMG_INTERNAL
-void SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie)
+PVRSRV_ERROR SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie)
 {
-	PVRSRV_ERROR eError;
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	IMG_UINT32 i;
 
+	eError = BridgeSyncPrimOpDestroy(psCookie->hBridge, psCookie->hServerCookie);
+	if (PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+			"%s: Failed to destroy SyncPrimOp (Error = %d)",
+			 __FUNCTION__, eError));
+		goto err_out;
+	}
+
 	/* Decrease the reference count on all referenced local sync prims
 	 * so that they can be freed now this Op is finished with
 	 */
@@ -1472,16 +1567,11 @@
 		}
 	}
 
-	eError = BridgeSyncPrimOpDestroy(psCookie->hBridge, psCookie->hServerCookie);
-	if (PVRSRV_OK != eError)
-	{
-		PVR_DPF((PVR_DBG_ERROR,
-			"%s: Failed to destroy SyncPrimOp (Error = %d)",
-			 __FUNCTION__, eError));
-	}
-
 	_SyncPrimBlockListDestroy(psCookie->psSyncBlockList);
 	OSFreeMem(psCookie);
+
+err_out:
+	return eError;
 }
 
 IMG_INTERNAL
@@ -1493,18 +1583,23 @@
 	IMG_UINT32 ui32ClientIndex = 0;
 	PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOps;
 	IMG_UINT32 i;
+	IMG_BOOL bServerSync;
+	PVRSRV_ERROR eError = PVRSRV_OK;
 
 	psSyncOps = OSAllocMem(sizeof(PVRSRV_CLIENT_SYNC_PRIM_OP) * 
 						   psCookie->ui32SyncCount);
 	if (!psSyncOps)
 	{
-		return PVRSRV_ERROR_OUT_OF_MEMORY;
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto e0;
 	}
-	
+
 	for (i=0; i<psCookie->ui32SyncCount; i++)
 	{
 		psSyncOps[i].psSync = psCookie->papsSyncPrim[i];
-		if (SyncPrimIsServerSync(psCookie->papsSyncPrim[i]))
+		eError = SyncPrimIsServerSync(psCookie->papsSyncPrim[i], &bServerSync);
+		if (PVRSRV_OK != eError) goto e1;
+		if (bServerSync)
 		{
 			psSyncOps[i].ui32FenceValue = 0;
 			psSyncOps[i].ui32UpdateValue = 0;
@@ -1523,7 +1618,10 @@
 	*ppsSyncOp = psSyncOps;
 	*pui32SyncCount = psCookie->ui32SyncCount;
 
-	return PVRSRV_OK;
+e1:
+	OSFreeMem(psSyncOps);
+e0:
+	return eError;
 }
 
 #if !defined(__KERNEL__)
@@ -1599,6 +1697,7 @@
 	IMG_UINT32 i;
 	SYNC_BRIDGE_HANDLE hBridge = NULL;
 	IMG_HANDLE *pahServerHandle;
+	IMG_BOOL bServerSync;
 
 	if (papsSync[0])
 	{
@@ -1626,7 +1725,9 @@
 	{
 		SYNC_PRIM *psIntSync = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
 
-		if (!SyncPrimIsServerSync(papsSync[i]))
+		eError = SyncPrimIsServerSync(papsSync[i], &bServerSync);
+		if (PVRSRV_OK != eError) goto e1;
+		if (!bServerSync)
 		{
 			eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
 			goto e1;
@@ -1665,24 +1766,39 @@
 
 #endif
 
-IMG_INTERNAL
-IMG_BOOL SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+IMG_INTERNAL PVRSRV_ERROR
+SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_BOOL *pbServerSync)
 {
+	PVRSRV_ERROR eError = PVRSRV_OK;
 	SYNC_PRIM *psSyncInt;
 
 	if (!psSync)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
 		goto e0;
 	}
 	psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
-	if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+	if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
 	{
-		return IMG_TRUE;
+		*pbServerSync = IMG_FALSE;
+	}
+	else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+	{
+		*pbServerSync = IMG_TRUE;
+	}
+	else
+	{
+		/* Either the client has given us a bad pointer or there is an
+		 * error in this module
+		 */
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
+		goto e0;
 	}
 
 e0:
-	return IMG_FALSE;
+	return eError;
 }
 
 IMG_INTERNAL
@@ -1911,6 +2027,12 @@
 	psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
 	psContext = psSyncBlock->psContext;
 
+	/* FIXME: uiWriteOffset, uiPacketSize, uiBufferSize were changed to
+	 * 64-bit quantities to resolve Windows compiler warnings.
+	 * However the bridge is only 32-bit hence compiler warnings
+	 * of implicit cast and loss of data.
+	 * Added explicit cast and assert to remove warning.
+	 */
 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
 	PVR_ASSERT(uiWriteOffset<IMG_UINT32_MAX);
 	PVR_ASSERT(uiPacketSize<IMG_UINT32_MAX);
diff --git a/drivers/staging/imgtec/rogue/sync.h b/drivers/staging/imgtec/rogue/sync.h
index f988683..ccf91f6 100644
--- a/drivers/staging/imgtec/rogue/sync.h
+++ b/drivers/staging/imgtec/rogue/sync.h
@@ -41,19 +41,19 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+#ifndef _SYNC_
+#define _SYNC_
+
 #include "img_types.h"
 #include "pvrsrv_error.h"
-#include "sync_external.h"
+#include <powervr/sync_external.h>
 #include "pdumpdefs.h"
 #include "dllist.h"
 #include "pvr_debug.h"
 
 #include "device_connection.h"
 
-#ifndef _SYNC_
-#define _SYNC_
-
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
 #include <services_kernel_client.h>
 #endif
@@ -145,10 +145,11 @@
 
 @Input          psSync                  The synchronisation primitive to free
 
-@Return         None
+@Return         PVRSRV_OK if the synchronisation primitive was
+                successfully freed
 */
 /*****************************************************************************/
-void
+PVRSRV_ERROR
 SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync);
 
 /*************************************************************************/ /*!
@@ -160,10 +161,10 @@
 
 @Input          ui32Value               Value to set it to
 
-@Return         None
+@Return         PVRSRV_OK on success
 */
 /*****************************************************************************/
-void
+PVRSRV_ERROR
 SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value);
 
 #if defined(NO_HARDWARE)
@@ -177,10 +178,10 @@
 
 @Input          ui32Value               Value to update it to
 
-@Return         None
+@Return         PVRSRV_OK on success
 */
 /*****************************************************************************/
-void
+PVRSRV_ERROR
 SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value);
 #endif
 
@@ -201,8 +202,8 @@
 PVRSRV_ERROR
 SyncPrimServerQueueOp(PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOp);
 
-IMG_BOOL
-SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+PVRSRV_ERROR
+SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_BOOL *pbServerSync);
 
 IMG_HANDLE
 SyncPrimGetServerHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync);
@@ -226,8 +227,8 @@
 PVRSRV_ERROR
 SyncPrimOpComplete(PSYNC_OP_COOKIE psCookie);
 
-void
-SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie);
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie);
 
 PVRSRV_ERROR
 SyncPrimOpResolve(PSYNC_OP_COOKIE psCookie,
diff --git a/drivers/staging/imgtec/rogue/sync_checkpoint.c b/drivers/staging/imgtec/rogue/sync_checkpoint.c
new file mode 100644
index 0000000..dc88f95
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/sync_checkpoint.c
@@ -0,0 +1,1197 @@
+/*************************************************************************/ /*!
+@File
+@Title          Services synchronisation checkpoint interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements server side code for services synchronisation
+                interface
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "img_types.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "pvr_debug.h"
+#include "pvr_notifier.h"
+#include "osfunc.h"
+#include "dllist.h"
+#include "sync.h"
+#include "sync_checkpoint_external.h"
+#include "sync_checkpoint.h"
+#include "sync_checkpoint_internal.h"
+#include "lock.h"
+#include "log2.h"
+#include "pvrsrv.h"
+#include "pdump_km.h"
+
+#include "pvrsrv_sync_km.h"
+
+#define SYNC_CHECKPOINT_BLOCK_LIST_CHUNK_SIZE  10
+#define LOCAL_SYNC_CHECKPOINT_RESET_VALUE      PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED
+
+/*
+	This defines the maximum amount of synchronisation memory
+	that can be allocated per sync checkpoint context.
+	In reality this number is meaningless as we would run out
+	of synchronisation memory before we reach this limit, but
+	we need to provide a size to the span RA.
+*/
+#define MAX_SYNC_CHECKPOINT_MEM  (4 * 1024 * 1024)
+
+/* definitions for functions to be implemented by OS-specific sync - the OS-specific sync code
+   will call x when initialised, in order to register functions we can then call */
+typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN)(PVRSRV_FENCE_KM fence, IMG_UINT32 *nr_checkpoints, PSYNC_CHECKPOINT *checkpoint_handles);
+typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN)(const IMG_CHAR *fence_name, PVRSRV_TIMELINE_KM timeline, PVRSRV_FENCE_KM *new_fence, PSYNC_CHECKPOINT *new_checkpoint_handle);
+
+
+typedef struct _SYNC_CHECKPOINT_BLOCK_LIST_
+{
+	IMG_UINT32            ui32BlockCount;            /*!< Number of contexts in the list */
+	IMG_UINT32            ui32BlockListSize;         /*!< Size of the array contexts */
+	SYNC_CHECKPOINT_BLOCK **papsSyncCheckpointBlock; /*!< Array of sync checkpoint blocks */
+} SYNC_CHECKPOINT_BLOCK_LIST;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+#define DECREMENT_WITH_WRAP(value, sz) ((value) ? ((value) - 1) : ((sz) - 1))
+
+struct SYNC_CHECKPOINT_RECORD
+{
+	SYNC_CHECKPOINT_BLOCK	*psSyncCheckpointBlock;	/*!< handle to SYNC_CHECKPOINT_BLOCK */
+	IMG_UINT32				ui32SyncOffset; 		/*!< offset to sync in block */
+	IMG_UINT32				ui32FwBlockAddr;
+	IMG_PID					uiPID;
+	IMG_UINT64				ui64OSTime;
+	DLLIST_NODE				sNode;
+	IMG_CHAR				szClassName[SYNC_MAX_CLASS_NAME_LEN];
+};
+#endif /* defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+
+static PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN g_pfnFenceResolve = NULL;
+static PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN g_pfnFenceCreate = NULL;
+
+PVRSRV_ERROR
+SyncCheckpointRecordAdd(PSYNC_CHECKPOINT_RECORD_HANDLE *phRecord,
+                        SYNC_CHECKPOINT_BLOCK *hSyncCheckpointBlock,
+                        IMG_UINT32 ui32FwBlockAddr,
+                        IMG_UINT32 ui32SyncOffset,
+                        IMG_UINT32 ui32ClassNameSize,
+                        const IMG_CHAR *pszClassName);
+PVRSRV_ERROR
+SyncCheckpointRecordRemove(PSYNC_CHECKPOINT_RECORD_HANDLE hRecord);
+static void _SyncCheckpointState(PDLLIST_NODE psNode,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile);
+static void _SyncCheckpointDebugRequest(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
+					IMG_UINT32 ui32VerbLevel,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile);
+static PVRSRV_ERROR _SyncCheckpointRecordListInit(_SYNC_CHECKPOINT_CONTEXT *psContext);
+static void _SyncCheckpointRecordListDeinit(_SYNC_CHECKPOINT_CONTEXT *psContext);
+
+PVRSRV_ERROR SyncCheckpointSignalPDump(_SYNC_CHECKPOINT *psSyncCheckpoint);
+PVRSRV_ERROR SyncCheckpointErrorPDump(_SYNC_CHECKPOINT *psSyncCheckpoint);
+
+PVRSRV_ERROR SyncCheckpointRegisterFunctions(PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN pfnFenceResolve,
+                                             PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN pfnFenceCreate);
+
+/* Unique incremental ID assigned to sync checkpoints when allocated */
+static IMG_UINT32 g_SyncCheckpointUID = 0;
+
+/*
+	Internal interfaces for management of _SYNC_CHECKPOINT_CONTEXT
+*/
+static void
+_SyncCheckpointContextUnref(_SYNC_CHECKPOINT_CONTEXT *psContext)
+{
+	if (!OSAtomicRead(&psContext->hRefCount))
+	{
+		PVR_LOG_ERROR(PVRSRV_ERROR_INVALID_CONTEXT, "_SyncCheckpointContextUnref context already freed");
+	}
+	else if (0 == OSAtomicDecrement(&psContext->hRefCount))
+	{
+		/* SyncCheckpointContextDestroy only when no longer referenced */
+		_SyncCheckpointRecordListDeinit(psContext);
+		PVRSRVUnregisterDbgRequestNotify(psContext->hCheckpointNotify);
+		OSLockDestroy(psContext->hCheckpointListLock);
+		RA_Delete(psContext->psSpanRA);
+		RA_Delete(psContext->psSubAllocRA);
+		OSFreeMem(psContext);
+	}
+}
+
+static void
+_SyncCheckpointContextRef(_SYNC_CHECKPOINT_CONTEXT *psContext)
+{
+	if (!OSAtomicRead(&psContext->hRefCount))
+	{
+		PVR_LOG_ERROR(PVRSRV_ERROR_INVALID_CONTEXT, "_SyncCheckpointContextRef context use after free");
+	}
+	else
+	{
+		OSAtomicIncrement(&psContext->hRefCount);
+	}
+}
+
+/*
+	Internal interfaces for management of synchronisation block memory
+*/
+static PVRSRV_ERROR
+_AllocSyncCheckpointBlock(_SYNC_CHECKPOINT_CONTEXT *psContext,
+						  SYNC_CHECKPOINT_BLOCK    **ppsSyncBlock)
+{
+	PVRSRV_DEVICE_NODE *psDevNode;
+	SYNC_CHECKPOINT_BLOCK *psSyncBlk;
+	PVRSRV_ERROR eError;
+
+	psSyncBlk = OSAllocMem(sizeof(SYNC_CHECKPOINT_BLOCK));
+	if (psSyncBlk == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		PVR_LOG_ERROR(eError, "OSAllocMem");
+		goto fail_alloc;
+	}
+	psSyncBlk->psContext = psContext;
+
+	/* Allocate sync checkpoint block */
+	psDevNode = psContext->psDevNode;
+	if (!psDevNode)
+	{
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		PVR_LOG_ERROR(eError, "context device node invalid");
+		goto fail_alloc_ufo_block;
+	}
+	psSyncBlk->psDevNode = psDevNode;
+
+	eError = psDevNode->pfnAllocUFOBlock(psDevNode,
+										 &psSyncBlk->hMemDesc,
+										 &psSyncBlk->ui32FirmwareAddr,
+										 &psSyncBlk->ui32SyncBlockSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_LOG_ERROR(eError, "failed to allocate ufo block");
+		goto fail_alloc_ufo_block;
+	}
+
+	eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc,
+									  (void **) &psSyncBlk->pui32LinAddr);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_LOG_ERROR(eError, "DevmemAcquireCpuVirtAddr");
+		goto fail_devmem_acquire;
+	}
+
+	OSAtomicWrite(&psSyncBlk->hRefCount, 1);
+
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+						  "Allocated Sync Checkpoint UFO block (FirmwareVAddr = 0x%08x)",
+						  psSyncBlk->ui32FirmwareAddr);
+
+	*ppsSyncBlock = psSyncBlk;
+	return PVRSRV_OK;
+
+fail_devmem_acquire:
+	psDevNode->pfnFreeUFOBlock(psDevNode, psSyncBlk->hMemDesc);
+fail_alloc_ufo_block:
+	OSFreeMem(psSyncBlk);
+fail_alloc:
+	return eError;
+}
+
+static void
+_FreeSyncCheckpointBlock(SYNC_CHECKPOINT_BLOCK *psSyncBlk)
+{
+	if (0 == OSAtomicDecrement(&psSyncBlk->hRefCount))
+	{
+		PVRSRV_DEVICE_NODE *psDevNode = psSyncBlk->psDevNode;
+
+		DevmemReleaseCpuVirtAddr(psSyncBlk->hMemDesc);
+		psDevNode->pfnFreeUFOBlock(psDevNode, psSyncBlk->hMemDesc);
+		OSFreeMem(psSyncBlk);
+	}
+}
+
+static PVRSRV_ERROR
+_SyncCheckpointBlockImport(RA_PERARENA_HANDLE hArena,
+                           RA_LENGTH_T uSize,
+                           RA_FLAGS_T uFlags,
+                           const IMG_CHAR *pszAnnotation,
+                           RA_BASE_T *puiBase,
+                           RA_LENGTH_T *puiActualSize,
+                           RA_PERISPAN_HANDLE *phImport)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = hArena;
+	SYNC_CHECKPOINT_BLOCK *psSyncBlock = NULL;
+	RA_LENGTH_T uiSpanSize;
+	PVRSRV_ERROR eError;
+	PVR_UNREFERENCED_PARAMETER(uFlags);
+
+	PVR_LOG_IF_FALSE((hArena != NULL), "hArena is NULL");
+
+	/* Check we've not be called with an unexpected size */
+	PVR_LOG_IF_FALSE((uSize == sizeof(_SYNC_CHECKPOINT_FW_OBJ)), "uiSize is not the size of _SYNC_CHECKPOINT_FW_OBJ");
+
+	/*
+		Ensure the sync checkpoint context doesn't go away while we have sync blocks
+		attached to it
+	*/
+	_SyncCheckpointContextRef(psContext);
+
+	/* Allocate the block of memory */
+	eError = _AllocSyncCheckpointBlock(psContext, &psSyncBlock);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_syncblockalloc;
+	}
+
+	/* Allocate a span for it */
+	eError = RA_Alloc(psContext->psSpanRA,
+					psSyncBlock->ui32SyncBlockSize,
+					RA_NO_IMPORT_MULTIPLIER,
+					0,
+					psSyncBlock->ui32SyncBlockSize,
+					pszAnnotation,
+					&psSyncBlock->uiSpanBase,
+					&uiSpanSize,
+					NULL);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_spanalloc;
+	}
+
+	/*
+		There is no reason the span RA should return an allocation larger
+		then we request
+	*/
+	PVR_LOG_IF_FALSE((uiSpanSize == psSyncBlock->ui32SyncBlockSize), "uiSpanSize invalid");
+
+	*puiBase = psSyncBlock->uiSpanBase;
+	*puiActualSize = psSyncBlock->ui32SyncBlockSize;
+	*phImport = psSyncBlock;
+	return PVRSRV_OK;
+
+fail_spanalloc:
+	_FreeSyncCheckpointBlock(psSyncBlock);
+fail_syncblockalloc:
+	_SyncCheckpointContextUnref(psContext);
+
+	return eError;
+}
+
+static void
+_SyncCheckpointBlockUnimport(RA_PERARENA_HANDLE hArena,
+                             RA_BASE_T uiBase,
+                             RA_PERISPAN_HANDLE hImport)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = hArena;
+	SYNC_CHECKPOINT_BLOCK   *psSyncBlock = hImport;
+
+	PVR_LOG_IF_FALSE((psContext != NULL), "hArena invalid");
+	PVR_LOG_IF_FALSE((psSyncBlock != NULL), "hImport invalid");
+	PVR_LOG_IF_FALSE((uiBase == psSyncBlock->uiSpanBase), "uiBase invalid");
+
+	/* Free the span this import is using */
+	RA_Free(psContext->psSpanRA, uiBase);
+
+	/* Free the sync checkpoint block */
+	_FreeSyncCheckpointBlock(psSyncBlock);
+
+	/*	Drop our reference to the sync checkpoint context */
+	_SyncCheckpointContextUnref(psContext);
+}
+
+static INLINE IMG_UINT32 _SyncCheckpointGetOffset(_SYNC_CHECKPOINT *psSyncInt)
+{
+	IMG_UINT64 ui64Temp;
+	
+	ui64Temp =  psSyncInt->uiSpanAddr - psSyncInt->psSyncCheckpointBlock->uiSpanBase;
+	PVR_ASSERT(ui64Temp<IMG_UINT32_MAX);
+	return (IMG_UINT32)ui64Temp;
+}
+
+/* Used by SyncCheckpointContextCreate() below */
+static INLINE IMG_UINT32 _Log2(IMG_UINT32 ui32Align)
+{
+	PVR_ASSERT(IsPower2(ui32Align));
+	return ExactLog2(ui32Align);
+}
+
+/*
+	External interfaces
+*/
+
+IMG_INTERNAL PVRSRV_ERROR
+SyncCheckpointRegisterFunctions(PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN pfnFenceResolve, PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN pfnFenceCreate)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	g_pfnFenceResolve = pfnFenceResolve;
+	g_pfnFenceCreate = pfnFenceCreate;
+
+	return eError;
+}
+IMG_INTERNAL PVRSRV_ERROR
+SyncCheckpointResolveFence(PVRSRV_FENCE_KM hFence, IMG_UINT32 *pui32NumSyncCheckpoints, PSYNC_CHECKPOINT *psSyncCheckpoints)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (!g_pfnFenceResolve)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: ERROR (eError=PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED)", __FUNCTION__));
+		PVR_LOG_ERROR(eError, "g_pfnFenceResolve is NULL");
+		eError = PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED;
+	}
+	else
+	{
+		eError = g_pfnFenceResolve(hFence, pui32NumSyncCheckpoints, psSyncCheckpoints);
+	}
+	return eError;
+}
+IMG_INTERNAL PVRSRV_ERROR
+SyncCheckpointCreateFence(const IMG_CHAR *pszFenceName, PVRSRV_TIMELINE_KM hTimeline, PVRSRV_FENCE_KM *phNewFence, PSYNC_CHECKPOINT *psNewSyncCheckpoint)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (!g_pfnFenceCreate)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: ERROR (eError=PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED)", __FUNCTION__));
+		PVR_LOG_ERROR(eError, "g_pfnFenceCreate is NULL");
+		eError = PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED;
+	}
+	else
+	{
+		eError = g_pfnFenceCreate(pszFenceName, hTimeline, phNewFence, psNewSyncCheckpoint);
+	}
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+SyncCheckpointContextCreate(PVRSRV_DEVICE_NODE *psDevNode,
+							PSYNC_CHECKPOINT_CONTEXT *ppsSyncCheckpointContext)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = NULL;
+	PVRSRV_ERROR eError;
+
+	PVR_LOGR_IF_FALSE((ppsSyncCheckpointContext != NULL), "ppsSyncCheckpointContext invalid", PVRSRV_ERROR_INVALID_PARAMS);
+
+	psContext = OSAllocZMem(sizeof(_SYNC_CHECKPOINT_CONTEXT));
+	if (psContext == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto fail_alloc;
+	}
+
+	psContext->psDevNode = psDevNode;
+
+	OSSNPrintf(psContext->azName, SYNC_CHECKPOINT_NAME_SIZE, "Sync Prim RA-%p", psContext);
+	OSSNPrintf(psContext->azSpanName, SYNC_CHECKPOINT_NAME_SIZE, "Sync Prim span RA-%p", psContext);
+
+	/*
+		Create the RA for sub-allocations of the sync checkpoints
+
+		Note:
+		The import size doesn't matter here as the server will pass
+		back the blocksize when it does the import which overrides
+		what we specify here.
+	*/
+	psContext->psSubAllocRA = RA_Create(psContext->azName,
+										/* Params for imports */
+										_Log2(sizeof(IMG_UINT32)),
+										RA_LOCKCLASS_2,
+										_SyncCheckpointBlockImport,
+										_SyncCheckpointBlockUnimport,
+										psContext,
+										IMG_FALSE);
+	if (psContext->psSubAllocRA == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto fail_suballoc;
+	}
+
+	/*
+		Create the span-management RA
+
+		The RA requires that we work with linear spans. For our use
+		here we don't require this behaviour as we're always working
+		within offsets of blocks (imports). However, we need to keep
+		the RA happy so we create the "span" management RA which
+		ensures that all are imports are added to the RA in a linear
+		fashion
+	*/
+	psContext->psSpanRA = RA_Create(psContext->azSpanName,
+									/* Params for imports */
+									0,
+									RA_LOCKCLASS_1,
+									NULL,
+									NULL,
+									NULL,
+									IMG_FALSE);
+	if (psContext->psSpanRA == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto fail_span;
+	}
+
+	if (!RA_Add(psContext->psSpanRA, 0, MAX_SYNC_CHECKPOINT_MEM, 0, NULL))
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto fail_span_add;
+	}
+
+	OSAtomicWrite(&psContext->hRefCount, 1);
+	OSAtomicWrite(&psContext->hCheckpointCount, 0);
+
+	eError = OSLockCreate(&psContext->hCheckpointListLock, LOCK_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_span;
+	}
+
+	dllist_init(&psContext->sCheckpointList);
+
+	eError = PVRSRVRegisterDbgRequestNotify(&psContext->hCheckpointNotify,
+											psDevNode,
+											_SyncCheckpointDebugRequest,
+											DEBUG_REQUEST_SYNCCHECKPOINT,
+											psContext);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_register_dbg_request;
+	}
+
+	eError = _SyncCheckpointRecordListInit(psContext);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_record_list_init;
+	}
+
+	*ppsSyncCheckpointContext = (PSYNC_CHECKPOINT_CONTEXT)psContext;
+	return PVRSRV_OK;
+
+fail_record_list_init:
+	PVRSRVUnregisterDbgRequestNotify(psContext->hCheckpointNotify);
+fail_register_dbg_request:
+	OSLockDestroy(psContext->hCheckpointListLock);
+fail_span_add:
+	RA_Delete(psContext->psSpanRA);
+fail_span:
+	RA_Delete(psContext->psSubAllocRA);
+fail_suballoc:
+	OSFreeMem(psContext);
+fail_alloc:
+	return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR SyncCheckpointContextDestroy(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	_SYNC_CHECKPOINT_CONTEXT *psContext = (_SYNC_CHECKPOINT_CONTEXT*)psSyncCheckpointContext;
+	IMG_INT iRf = 0;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpointContext != NULL), "psSyncCheckpointContext invalid");
+
+	iRf = OSAtomicRead(&psContext->hCheckpointCount);
+	if (iRf != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s <%p> attempted with active references (iRf=%d), may be the result of a race", __FUNCTION__, (void*)psContext, iRf));
+		eError = PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT;
+	}
+	else
+	{
+		IMG_INT iRf2 = 0;
+
+		iRf2 = OSAtomicRead(&psContext->hRefCount);
+		_SyncCheckpointContextUnref(psContext);
+	}
+	return eError;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR
+SyncCheckpointAlloc(PSYNC_CHECKPOINT_CONTEXT psSyncContext,
+                    const IMG_CHAR *pszCheckpointName,
+                    PSYNC_CHECKPOINT *ppsSyncCheckpoint)
+{
+	_SYNC_CHECKPOINT *psNewSyncCheckpoint = NULL;
+	_SYNC_CHECKPOINT_CONTEXT *psSyncContextInt = (_SYNC_CHECKPOINT_CONTEXT*)psSyncContext;
+	PVRSRV_ERROR eError;
+
+	PVR_LOGR_IF_FALSE((psSyncContext != NULL), "psSyncContext invalid", PVRSRV_ERROR_INVALID_PARAMS);
+	PVR_LOGR_IF_FALSE((ppsSyncCheckpoint != NULL), "ppsSyncCheckpoint invalid", PVRSRV_ERROR_INVALID_PARAMS);
+
+	psNewSyncCheckpoint = OSAllocMem(sizeof(*psNewSyncCheckpoint));
+
+	if (psNewSyncCheckpoint == NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		PVR_LOG_ERROR(eError, "OSAllocMem");
+		goto fail_alloc;
+	}
+
+	eError = RA_Alloc(psSyncContextInt->psSubAllocRA,
+	                  sizeof(_SYNC_CHECKPOINT_FW_OBJ),
+	                  RA_NO_IMPORT_MULTIPLIER,
+	                  0,
+	                  sizeof(IMG_UINT32),
+	                  (IMG_CHAR*)pszCheckpointName,
+	                  &psNewSyncCheckpoint->uiSpanAddr,
+	                  NULL,
+	                  (RA_PERISPAN_HANDLE *) &psNewSyncCheckpoint->psSyncCheckpointBlock);
+	if (PVRSRV_OK != eError)
+	{
+		PVR_LOG_ERROR(eError, "RA_Alloc");
+		goto fail_raalloc;
+	}
+	psNewSyncCheckpoint->psSyncCheckpointFwObj = (volatile _SYNC_CHECKPOINT_FW_OBJ*)(psNewSyncCheckpoint->psSyncCheckpointBlock->pui32LinAddr +
+	                                                                                 (_SyncCheckpointGetOffset(psNewSyncCheckpoint)/sizeof(IMG_UINT32)));
+
+	/* the allocation of the backing memory for the sync prim block
+	* is done with ZERO_ON_ALLOC so the memory is initially all zero.
+	* States are also reset to unsignalled on free, so no need to set here
+	*/
+	OSAtomicWrite(&psNewSyncCheckpoint->hRefCount, 1);
+	OSAtomicWrite(&psNewSyncCheckpoint->hEnqueuedCCBCount, 0);
+
+	if(pszCheckpointName)
+	{
+		/* Copy over the checkpoint name annotation */
+		OSStringNCopy(psNewSyncCheckpoint->azName, pszCheckpointName, SYNC_CHECKPOINT_NAME_SIZE);
+		psNewSyncCheckpoint->azName[SYNC_CHECKPOINT_NAME_SIZE-1] = 0;
+	}
+	else
+	{
+		/* No sync checkpoint name annotation */
+		psNewSyncCheckpoint->azName[0] = '\0';
+	}
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	{
+		IMG_CHAR szChkptName[SYNC_CHECKPOINT_MAX_CLASS_NAME_LEN];
+
+		if(pszCheckpointName)
+		{
+			/* Copy the checkpoint name annotation into a fixed-size array */
+			OSStringNCopy(szChkptName, pszCheckpointName, SYNC_CHECKPOINT_MAX_CLASS_NAME_LEN - 1);
+			szChkptName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
+		}
+		else
+		{
+			/* No checkpoint name annotation */
+			szChkptName[0] = 0;
+		}
+		/* record this sync */
+		eError = SyncCheckpointRecordAdd(&psNewSyncCheckpoint->hRecord,
+		                                 psNewSyncCheckpoint->psSyncCheckpointBlock,
+		                                 psNewSyncCheckpoint->psSyncCheckpointBlock->ui32FirmwareAddr,
+		                                 _SyncCheckpointGetOffset(psNewSyncCheckpoint),
+		                                 OSStringNLength(szChkptName, SYNC_CHECKPOINT_MAX_CLASS_NAME_LEN),
+		                                 szChkptName);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_LOG_ERROR(eError, "SyncCheckpointRecordAdd");
+		}
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(pszCheckpointName);
+#endif /* if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+
+	OSAtomicIncrement(&psNewSyncCheckpoint->psSyncCheckpointBlock->psContext->hCheckpointCount);
+
+	/* Assign unique ID to this sync checkpoint */
+	psNewSyncCheckpoint->ui32UID = g_SyncCheckpointUID++;
+
+	/* Add the sync checkpoint to the context list */
+	OSLockAcquire(psSyncContextInt->hCheckpointListLock);
+	dllist_add_to_head(&psSyncContextInt->sCheckpointList,
+	                   &psNewSyncCheckpoint->sListNode);
+	OSLockRelease(psSyncContextInt->hCheckpointListLock);
+
+	*ppsSyncCheckpoint = (PSYNC_CHECKPOINT)psNewSyncCheckpoint;
+
+	return PVRSRV_OK;
+
+fail_raalloc:
+	OSFreeMem(psNewSyncCheckpoint);
+fail_alloc:
+
+	return eError;
+}
+
+IMG_INTERNAL void SyncCheckpointFree(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+	_SYNC_CHECKPOINT_CONTEXT *psContext = psSyncCheckpointInt->psSyncCheckpointBlock->psContext;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
+
+	if (!OSAtomicRead(&psSyncCheckpointInt->hRefCount))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SyncCheckpointUnref sync checkpoint already freed"));
+	}
+	else if (0 == OSAtomicDecrement(&psSyncCheckpointInt->hRefCount))
+	{
+		/* If the firmware has serviced all enqueued references to the sync checkpoint, free it */
+		if (psSyncCheckpointInt->psSyncCheckpointFwObj->ui32FwRefCount == (IMG_UINT32)(OSAtomicRead(&psSyncCheckpointInt->hEnqueuedCCBCount)))
+		{
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+			{
+				PVRSRV_ERROR eError;
+				/* remove this sync record */
+				eError = SyncCheckpointRecordRemove(psSyncCheckpointInt->hRecord);
+				PVR_LOG_IF_ERROR(eError, "SyncCheckpointRecordRemove");
+			}
+#endif
+			/* Remove the sync checkpoint from the global list */
+			OSLockAcquire(psContext->hCheckpointListLock);
+			dllist_remove_node(&psSyncCheckpointInt->sListNode);
+			OSLockRelease(psContext->hCheckpointListLock);
+
+			OSAtomicDecrement(&psSyncCheckpointInt->psSyncCheckpointBlock->psContext->hCheckpointCount);
+			RA_Free(psSyncCheckpointInt->psSyncCheckpointBlock->psContext->psSubAllocRA, psSyncCheckpointInt->uiSpanAddr);
+		}
+	}
+}
+
+IMG_INTERNAL void
+SyncCheckpointSignal(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
+
+	if(psSyncCheckpointInt)
+	{
+		PVR_LOG_IF_FALSE((psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED), "psSyncCheckpoint already signalled");
+
+		if (psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED)
+		{
+			psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State = PVRSRV_SYNC_CHECKPOINT_SIGNALLED;
+#if defined(PDUMP)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+								  "Signalled Sync Checkpoint (FirmwareVAddr = 0x%08x)",
+			                      (psSyncCheckpointInt->psSyncCheckpointBlock->ui32FirmwareAddr + _SyncCheckpointGetOffset(psSyncCheckpointInt)));
+			SyncCheckpointSignalPDump(psSyncCheckpointInt);
+#endif
+		}
+	}
+}
+
+IMG_INTERNAL void
+SyncCheckpointError(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
+
+	if(psSyncCheckpointInt)
+	{
+		PVR_LOG_IF_FALSE((psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED), "psSyncCheckpoint already signalled");
+
+		if (psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED)
+		{
+			psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State = PVRSRV_SYNC_CHECKPOINT_ERRORED;
+#if defined(PDUMP)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+								  "Errored Sync Checkpoint (FirmwareVAddr = 0x%08x)",
+								  (psSyncCheckpointInt->psSyncCheckpointBlock->ui32FirmwareAddr + _SyncCheckpointGetOffset(psSyncCheckpointInt)));
+			SyncCheckpointErrorPDump(psSyncCheckpointInt);
+#endif
+		}
+	}
+}
+
+IMG_BOOL SyncCheckpointIsSignalled(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	IMG_BOOL bRet = IMG_FALSE;
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
+
+	if (psSyncCheckpointInt)
+	{
+		bRet = ((psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_SIGNALLED) ||
+		        (psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_ERRORED));
+	}
+	return bRet;
+}
+
+IMG_INTERNAL IMG_BOOL
+SyncCheckpointIsErrored(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	IMG_BOOL bRet = IMG_FALSE;
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
+
+	if (psSyncCheckpointInt)
+	{
+		bRet = (psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_ERRORED);
+	}
+	return bRet;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+SyncCheckpointTakeRef(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	PVRSRV_ERROR eRet = PVRSRV_OK;
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOGR_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", PVRSRV_ERROR_INVALID_PARAMS);
+
+	OSAtomicIncrement(&psSyncCheckpointInt->hRefCount);
+
+	return eRet;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+SyncCheckpointDropRef(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	PVRSRV_ERROR eRet = PVRSRV_OK;
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOGR_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", PVRSRV_ERROR_INVALID_PARAMS);
+
+	OSAtomicDecrement(&psSyncCheckpointInt->hRefCount);
+
+	return eRet;
+}
+
+IMG_INTERNAL void
+SyncCheckpointCCBEnqueued(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+
+	PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
+
+	if (psSyncCheckpointInt)
+	{
+		OSAtomicIncrement(&psSyncCheckpointInt->hEnqueuedCCBCount);
+	}
+}
+
+IMG_INTERNAL IMG_UINT32
+SyncCheckpointGetFirmwareAddr(PSYNC_CHECKPOINT psSyncCheckpoint)
+{
+	_SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+	SYNC_CHECKPOINT_BLOCK *psSyncBlock;
+
+	PVR_LOGG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", invalid_chkpt);
+
+	psSyncBlock = psSyncCheckpointInt->psSyncCheckpointBlock;
+	/* add 1 to addr to indicate this FW addr is a sync checkpoint (not a sync prim) */
+	return psSyncBlock->ui32FirmwareAddr + _SyncCheckpointGetOffset(psSyncCheckpointInt) + 1;
+
+invalid_chkpt:
+	return 0;
+}
+
+void SyncCheckpointErrorFromUFO(PSYNC_CHECKPOINT_CONTEXT psSyncContext,
+								IMG_UINT32 ui32FwAddr)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = (_SYNC_CHECKPOINT_CONTEXT *)psSyncContext;
+	_SYNC_CHECKPOINT *psSyncCheckpointInt;
+	IMG_BOOL bFound = IMG_FALSE;
+	PDLLIST_NODE psNode;
+
+	PVR_DPF((PVR_DBG_ERROR, "%s: Entry (ui32FWAddr=%d) >",__FUNCTION__, ui32FwAddr));
+
+	OSLockAcquire(psContext->hCheckpointListLock);
+	psNode = dllist_get_next_node(&psContext->sCheckpointList);
+	while ((psNode != NULL) && !bFound)
+	{
+		psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+		if (ui32FwAddr == SyncCheckpointGetFirmwareAddr((PSYNC_CHECKPOINT)psSyncCheckpointInt))
+		{
+			bFound = IMG_TRUE;
+			/* Mark as errored */
+			SyncCheckpointError((PSYNC_CHECKPOINT)psSyncCheckpointInt);
+		}
+		psNode = dllist_get_next_node(psNode);
+	}
+	OSLockRelease(psContext->hCheckpointListLock);
+
+	PVR_DPF((PVR_DBG_ERROR, "%s: Exit <",__FUNCTION__));
+}
+
+static void _SyncCheckpointState(PDLLIST_NODE psNode,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	_SYNC_CHECKPOINT *psSyncCheckpoint = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+
+	if (psSyncCheckpoint->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED)
+	{
+		PVR_DUMPDEBUG_LOG("\tPending sync checkpoint(ID = %d, FWAddr = 0x%08x): (%s)",
+		                   psSyncCheckpoint->ui32UID,
+		                   psSyncCheckpoint->psSyncCheckpointBlock->ui32FirmwareAddr + _SyncCheckpointGetOffset(psSyncCheckpoint),
+		                   psSyncCheckpoint->azName);
+	}
+}
+
+static void _SyncCheckpointDebugRequest(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
+					IMG_UINT32 ui32VerbLevel,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = (_SYNC_CHECKPOINT_CONTEXT *)hDebugRequestHandle;
+	DLLIST_NODE *psNode, *psNext;
+
+	if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
+	{
+		PVR_DUMPDEBUG_LOG("Dumping all pending sync checkpoints");
+		OSLockAcquire(psContext->hCheckpointListLock);
+		dllist_foreach_node(&psContext->sCheckpointList, psNode, psNext)
+		{
+			_SyncCheckpointState(psNode, pfnDumpDebugPrintf, pvDumpDebugFile);
+		}
+		OSLockRelease(psContext->hCheckpointListLock);
+	}
+}
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+PVRSRV_ERROR
+SyncCheckpointRecordAdd(
+			PSYNC_CHECKPOINT_RECORD_HANDLE * phRecord,
+			SYNC_CHECKPOINT_BLOCK * hSyncCheckpointBlock,
+			IMG_UINT32 ui32FwBlockAddr,
+			IMG_UINT32 ui32SyncOffset,
+			IMG_UINT32 ui32ClassNameSize,
+			const IMG_CHAR *pszClassName)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = hSyncCheckpointBlock->psContext;
+	struct SYNC_CHECKPOINT_RECORD * psSyncRec;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (!phRecord)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	*phRecord = NULL;
+
+	psSyncRec = OSAllocMem(sizeof(*psSyncRec));
+	if (!psSyncRec)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto fail_alloc;
+	}
+
+	psSyncRec->psSyncCheckpointBlock = hSyncCheckpointBlock;
+	psSyncRec->ui32SyncOffset = ui32SyncOffset;
+	psSyncRec->ui32FwBlockAddr = ui32FwBlockAddr;
+	psSyncRec->ui64OSTime = OSClockns64();
+	psSyncRec->uiPID = OSGetCurrentProcessID();
+
+	if(pszClassName)
+	{
+		if (ui32ClassNameSize >= SYNC_MAX_CLASS_NAME_LEN)
+			ui32ClassNameSize = SYNC_MAX_CLASS_NAME_LEN - 1;
+		/* Copy over the class name annotation */
+		OSStringNCopy(psSyncRec->szClassName, pszClassName, ui32ClassNameSize);
+		psSyncRec->szClassName[ui32ClassNameSize] = 0;
+	}
+	else
+	{
+		/* No class name annotation */
+		psSyncRec->szClassName[0] = 0;
+	}
+
+	OSLockAcquire(psContext->hCheckpointRecordLock);
+	dllist_add_to_head(&psContext->sCheckpointRecordList, &psSyncRec->sNode);
+	OSLockRelease(psContext->hCheckpointRecordLock);
+
+	*phRecord = (PSYNC_CHECKPOINT_RECORD_HANDLE)psSyncRec;
+
+fail_alloc:
+	return eError;
+}
+
+PVRSRV_ERROR
+SyncCheckpointRecordRemove(PSYNC_CHECKPOINT_RECORD_HANDLE hRecord)
+{
+	struct SYNC_CHECKPOINT_RECORD **ppFreedSync;
+	struct SYNC_CHECKPOINT_RECORD *pSync = (struct SYNC_CHECKPOINT_RECORD*)hRecord;
+	_SYNC_CHECKPOINT_CONTEXT *psContext;
+
+	if (!hRecord)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psContext = pSync->psSyncCheckpointBlock->psContext;
+
+	OSLockAcquire(psContext->hCheckpointRecordLock);
+
+	dllist_remove_node(&pSync->sNode);
+
+	if (psContext->uiCheckpointRecordFreeIdx >= PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: freed sync record index out of range", __FUNCTION__));
+		psContext->uiCheckpointRecordFreeIdx = 0;
+	}
+	ppFreedSync = &psContext->apsCheckpointRecordsFreed[psContext->uiCheckpointRecordFreeIdx];
+	psContext->uiCheckpointRecordFreeIdx =
+		(psContext->uiCheckpointRecordFreeIdx + 1) % PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN;
+
+	if (*ppFreedSync)
+	{
+		OSFreeMem(*ppFreedSync);
+	}
+	pSync->psSyncCheckpointBlock = NULL;
+	pSync->ui64OSTime = OSClockns64();
+	*ppFreedSync = pSync;
+
+	OSLockRelease(psContext->hCheckpointRecordLock);
+
+	return PVRSRV_OK;
+}
+
+#define NS_IN_S (1000000000UL)
+static void _SyncCheckpointRecordPrint(struct SYNC_CHECKPOINT_RECORD *psSyncCheckpointRec,
+					IMG_UINT64 ui64TimeNow,
+					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+					void *pvDumpDebugFile)
+{
+	SYNC_CHECKPOINT_BLOCK *psSyncCheckpointBlock = psSyncCheckpointRec->psSyncCheckpointBlock;
+	IMG_UINT64 ui64DeltaS;
+	IMG_UINT32 ui32DeltaF;
+	IMG_UINT64 ui64Delta = ui64TimeNow - psSyncCheckpointRec->ui64OSTime;
+	ui64DeltaS = OSDivide64(ui64Delta, NS_IN_S, &ui32DeltaF);
+
+	if (psSyncCheckpointBlock && psSyncCheckpointBlock->pui32LinAddr)
+	{
+		void *pSyncCheckpointAddr;
+		pSyncCheckpointAddr = (void*)(psSyncCheckpointBlock->pui32LinAddr + psSyncCheckpointRec->ui32SyncOffset);
+
+		PVR_DUMPDEBUG_LOG("\t%05u %05llu.%09u FWAddr=0x%08x State=%s (%s)",
+			psSyncCheckpointRec->uiPID,
+			ui64DeltaS, ui32DeltaF,
+			(psSyncCheckpointRec->ui32FwBlockAddr+psSyncCheckpointRec->ui32SyncOffset),
+			(*(IMG_UINT32*)pSyncCheckpointAddr == PVRSRV_SYNC_CHECKPOINT_SIGNALLED) ? "SIGNALLED" : ((*(IMG_UINT32*)pSyncCheckpointAddr == PVRSRV_SYNC_CHECKPOINT_ERRORED) ? "ERRORED" : "NOT_SIGNALLED"),
+			psSyncCheckpointRec->szClassName
+			);
+	}
+	else
+	{
+		PVR_DUMPDEBUG_LOG("\t%05u %05llu.%09u FWAddr=0x%08x State=<null_ptr> (%s)",
+			psSyncCheckpointRec->uiPID,
+			ui64DeltaS, ui32DeltaF,
+			(psSyncCheckpointRec->ui32FwBlockAddr+psSyncCheckpointRec->ui32SyncOffset),
+			psSyncCheckpointRec->szClassName
+			);
+	}
+}
+
+static void _SyncCheckpointRecordRequest(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
+						IMG_UINT32 ui32VerbLevel,
+						DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+						void *pvDumpDebugFile)
+{
+	_SYNC_CHECKPOINT_CONTEXT *psContext = (_SYNC_CHECKPOINT_CONTEXT *)hDebugRequestHandle;
+	IMG_UINT64 ui64TimeNowS;
+	IMG_UINT32 ui32TimeNowF;
+	IMG_UINT64 ui64TimeNow = OSClockns64();
+	DLLIST_NODE *psNode, *psNext;
+
+	ui64TimeNowS = OSDivide64(ui64TimeNow, NS_IN_S, &ui32TimeNowF);
+
+	if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
+	{
+		IMG_UINT32 i;
+
+		OSLockAcquire(psContext->hCheckpointRecordLock);
+
+		PVR_DUMPDEBUG_LOG("Dumping all allocated sync checkpoints @ %05llu.%09u", ui64TimeNowS, ui32TimeNowF);
+		PVR_DUMPDEBUG_LOG("\t%-5s %-15s %-17s %-14s (%s)",
+					"PID", "Time Delta (s)", "Address", "State", "Annotation");
+
+		dllist_foreach_node(&psContext->sCheckpointRecordList, psNode, psNext)
+		{
+			struct SYNC_CHECKPOINT_RECORD *psSyncCheckpointRec =
+				IMG_CONTAINER_OF(psNode, struct SYNC_CHECKPOINT_RECORD, sNode);
+			_SyncCheckpointRecordPrint(psSyncCheckpointRec, ui64TimeNow,
+							pfnDumpDebugPrintf, pvDumpDebugFile);
+		}
+
+		PVR_DUMPDEBUG_LOG("Dumping all recently freed sync checkpoints @ %05llu.%09u", ui64TimeNowS, ui32TimeNowF);
+		PVR_DUMPDEBUG_LOG("\t%-5s %-15s %-17s %-14s (%s)",
+					"PID", "Time Delta (s)", "Address", "State", "Annotation");
+		for (i = DECREMENT_WITH_WRAP(psContext->uiCheckpointRecordFreeIdx, PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN);
+			 i != psContext->uiCheckpointRecordFreeIdx;
+			 i = DECREMENT_WITH_WRAP(i, PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN))
+		{
+			if (psContext->apsCheckpointRecordsFreed[i])
+			{
+				_SyncCheckpointRecordPrint(psContext->apsCheckpointRecordsFreed[i],
+								ui64TimeNow, pfnDumpDebugPrintf, pvDumpDebugFile);
+			}
+			else
+			{
+				break;
+			}
+		}
+		OSLockRelease(psContext->hCheckpointRecordLock);
+	}
+}
+#undef NS_IN_S
+static PVRSRV_ERROR _SyncCheckpointRecordListInit(_SYNC_CHECKPOINT_CONTEXT *psContext)
+{
+	PVRSRV_ERROR eError;
+
+	eError = OSLockCreate(&psContext->hCheckpointRecordLock, LOCK_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_lock_create;
+	}
+	dllist_init(&psContext->sCheckpointRecordList);
+
+	eError = PVRSRVRegisterDbgRequestNotify(&psContext->hCheckpointRecordNotify,
+											psContext->psDevNode,
+											_SyncCheckpointRecordRequest,
+											DEBUG_REQUEST_SYNCCHECKPOINT,
+											psContext);
+
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_dbg_register;
+	}
+
+	return PVRSRV_OK;
+
+fail_dbg_register:
+	OSLockDestroy(psContext->hCheckpointRecordLock);
+fail_lock_create:
+	return eError;
+}
+
+static void _SyncCheckpointRecordListDeinit(_SYNC_CHECKPOINT_CONTEXT *psContext)
+{
+	int i;
+	DLLIST_NODE *psNode, *psNext;
+
+	OSLockAcquire(psContext->hCheckpointRecordLock);
+	dllist_foreach_node(&psContext->sCheckpointRecordList, psNode, psNext)
+	{
+		struct SYNC_CHECKPOINT_RECORD *pSyncCheckpointRec =
+			IMG_CONTAINER_OF(psNode, struct SYNC_CHECKPOINT_RECORD, sNode);
+
+		dllist_remove_node(psNode);
+		OSFreeMem(pSyncCheckpointRec);
+	}
+
+	for (i = 0; i < PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN; i++)
+	{
+		if (psContext->apsCheckpointRecordsFreed[i])
+		{
+			OSFreeMem(psContext->apsCheckpointRecordsFreed[i]);
+			psContext->apsCheckpointRecordsFreed[i] = NULL;
+		}
+	}
+	OSLockRelease(psContext->hCheckpointRecordLock);
+
+	PVRSRVUnregisterDbgRequestNotify(psContext->hCheckpointRecordNotify);
+	psContext->hCheckpointRecordNotify = NULL;
+
+	OSLockDestroy(psContext->hCheckpointRecordLock);
+	psContext->hCheckpointRecordLock = NULL;
+}
+#else /* defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+PVRSRV_ERROR
+SyncCheckpointRecordAdd(
+			PSYNC_CHECKPOINT_RECORD_HANDLE * phRecord,
+			SYNC_CHECKPOINT_BLOCK * hSyncCheckpointBlock,
+			IMG_UINT32 ui32FwBlockAddr,
+			IMG_UINT32 ui32SyncOffset,
+			IMG_UINT32 ui32ClassNameSize,
+			const IMG_CHAR *pszClassName)
+{
+	PVR_UNREFERENCED_PARAMETER(phRecord);
+	PVR_UNREFERENCED_PARAMETER(hSyncCheckpointBlock);
+	PVR_UNREFERENCED_PARAMETER(ui32FwBlockAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32SyncOffset);
+	PVR_UNREFERENCED_PARAMETER(ui32ClassNameSize);
+	PVR_UNREFERENCED_PARAMETER(pszClassName);
+	return PVRSRV_OK;
+}
+PVRSRV_ERROR
+SyncCheckpointRecordRemove(PSYNC_CHECKPOINT_RECORD_HANDLE hRecord)
+{
+	PVR_UNREFERENCED_PARAMETER(hRecord);
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _SyncCheckpointRecordListInit(_SYNC_CHECKPOINT_CONTEXT *psContext)
+{
+	PVR_UNREFERENCED_PARAMETER(psContext);
+	return PVRSRV_OK;
+}
+static void _SyncCheckpointRecordListDeinit(_SYNC_CHECKPOINT_CONTEXT *psContext)
+{
+	PVR_UNREFERENCED_PARAMETER(psContext);
+}
+#endif /* defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+#if defined(PDUMP)
+PVRSRV_ERROR
+SyncCheckpointSignalPDump(_SYNC_CHECKPOINT *psSyncCheckpoint)
+{
+	/*
+		We might be ask to PDump sync state outside of capture range
+		(e.g. texture uploads) so make this continuous.
+	*/
+	DevmemPDumpLoadMemValue32(psSyncCheckpoint->psSyncCheckpointBlock->hMemDesc,
+					   _SyncCheckpointGetOffset(psSyncCheckpoint),
+					   PVRSRV_SYNC_CHECKPOINT_SIGNALLED,
+					   PDUMP_FLAGS_CONTINUOUS);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+SyncCheckpointErrorPDump(_SYNC_CHECKPOINT *psSyncCheckpoint)
+{
+	/*
+		We might be ask to PDump sync state outside of capture range
+		(e.g. texture uploads) so make this continuous.
+	*/
+	DevmemPDumpLoadMemValue32(psSyncCheckpoint->psSyncCheckpointBlock->hMemDesc,
+					   _SyncCheckpointGetOffset(psSyncCheckpoint),
+					   PVRSRV_SYNC_CHECKPOINT_ERRORED,
+					   PDUMP_FLAGS_CONTINUOUS);
+
+	return PVRSRV_OK;
+}
+
+#endif
diff --git a/drivers/staging/imgtec/rogue/sync_checkpoint.h b/drivers/staging/imgtec/rogue/sync_checkpoint.h
new file mode 100644
index 0000000..1a84316
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/sync_checkpoint.h
@@ -0,0 +1,293 @@
+/*************************************************************************/ /*!
+@File
+@Title          Synchronisation checkpoint interface header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Defines the client side interface for synchronisation
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SYNC_CHECKPOINT_
+#define _SYNC_CHECKPOINT_
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_sync_km.h"
+#include "pdumpdefs.h"
+#include "dllist.h"
+#include "pvr_debug.h"
+
+#include "device_connection.h"
+
+typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
+
+typedef struct _SYNC_CHECKPOINT_CONTEXT *PSYNC_CHECKPOINT_CONTEXT;
+
+typedef struct _SYNC_CHECKPOINT *PSYNC_CHECKPOINT;
+
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointContextCreate
+
+@Description    Create a new synchronisation checkpoint context
+
+@Input          psDevNode                 Device node
+
+@Output         ppsSyncCheckpointContext  Handle to the created synchronisation
+                                          checkpoint context
+
+@Return         PVRSRV_OK if the synchronisation checkpoint context was
+                successfully created
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointContextCreate(PVRSRV_DEVICE_NODE *psDevNode,
+                            PSYNC_CHECKPOINT_CONTEXT *ppsSyncCheckpointContext);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointContextDestroy
+
+@Description    Destroy a synchronisation checkpoint context
+
+@Input          psSyncCheckpointContext  Handle to the synchronisation
+                                         checkpoint context to destroy
+
+@Return         PVRSRV_OK if the synchronisation checkpoint context was
+                successfully destroyed.
+                PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT if the context still
+                has sync checkpoints defined
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointContextDestroy(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointAlloc
+
+@Description    Allocate a new synchronisation checkpoint on the specified
+                synchronisation checkpoint context
+
+@Input          hSyncCheckpointContext  Handle to the synchronisation
+                                        checkpoint context
+
+@Input          pszClassName            Sync checkpoint source annotation
+                                        (will be truncated to at most
+                                         SYNC_CHECKPOINT_NAME_SIZE chars)
+
+@Output         ppsSyncCheckpoint       Created synchronisation checkpoint
+
+@Return         PVRSRV_OK if the synchronisation checkpoint was
+                successfully created
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointAlloc(PSYNC_CHECKPOINT_CONTEXT psSyncContext,
+                    const IMG_CHAR *pszCheckpointName,
+                    PSYNC_CHECKPOINT *ppsSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointFree
+
+@Description    Free a synchronization checkpoint
+                The reference count held for the synchronization checkpoint
+                is decremented - if it has becomes zero, it is also freed.
+
+@Input          psSyncCheckpoint        The synchronisation checkpoint to free
+
+@Return         None
+*/
+/*****************************************************************************/
+void
+SyncCheckpointFree(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointSignal
+
+@Description    Signal the synchronisation checkpoint
+
+@Input          psSyncCheckpoint        The synchronisation checkpoint to signal
+
+@Return         None
+*/
+/*****************************************************************************/
+void
+SyncCheckpointSignal(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointError
+
+@Description    Error the synchronisation checkpoint
+
+@Input          psSyncCheckpoint        The synchronisation checkpoint to error
+
+@Return         None
+*/
+/*****************************************************************************/
+void
+SyncCheckpointError(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointErrorFromUFO
+
+@Description    Error the synchronisation checkpoint which has the
+                given UFO firmware address
+
+@Input          hSyncCheckpointContext  Handle to the synchronisation checkpoint
+                                        context to which the checkpoint belongs
+
+@Input          ui32FwAddr              The firmware address of the sync
+                                        checkpoint to be errored
+
+@Return         None
+*/
+/*****************************************************************************/
+void
+SyncCheckpointErrorFromUFO(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
+						   IMG_UINT32 ui32FwAddr);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointIsSignalled
+
+@Description    Returns IMG_TRUE if the synchronisation checkpoint is
+                signalled or errored
+
+@Input          psSyncCheckpoint        The synchronisation checkpoint to test
+
+@Return         None
+*/
+/*****************************************************************************/
+IMG_BOOL
+SyncCheckpointIsSignalled(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointIsErrored
+
+@Description    Returns IMG_TRUE if the synchronisation checkpoint is
+                errored
+
+@Input          psSyncCheckpoint        The synchronisation checkpoint to test
+
+@Return         None
+*/
+/*****************************************************************************/
+IMG_BOOL
+SyncCheckpointIsErrored(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointTakeRef
+
+@Description    Take a reference on a synchronisation checkpoint
+
+@Input          psSyncCheckpoint        Synchronisation checkpoint to take a
+                                        reference on
+
+@Return         PVRSRV_OK if a reference was taken on the synchronisation
+                primitive
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointTakeRef(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointDropRef
+
+@Description    Drop a reference on a synchronisation checkpoint
+
+@Input          psSyncCheckpoint        Synchronisation checkpoint to drop a
+                                        reference on
+
+@Return         PVRSRV_OK if a reference was dropped on the synchronisation
+                primitive
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointDropRef(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointResolveFence
+
+@Description    Resolve a fence, returning a list of the sync checkpoints
+                that fence contains.
+                This function in turn calls a function provided by the
+                OS native sync implementation.
+
+@Input          hFence                  The fence to be resolved
+
+@Output         pui32NumSyncCheckpoints The number of sync checkpoints the
+                                        fence contains. Can return 0 if
+                                        passed a null (-1) fence.
+
+@Output         psSyncCheckpoints       List of sync checkpoints the fence
+                                        contains
+
+@Return         PVRSRV_OK if a valid fence was provided.
+                PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED if the OS native
+                sync has not registered a callback function.
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointResolveFence(PVRSRV_FENCE_KM hFence, IMG_UINT32 *pui32NumSyncCheckpoints, PSYNC_CHECKPOINT *psSyncCheckpoints);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointCreateFence
+
+@Description    Create a fence containing a single sync checkpoint.
+                Return the fence and a ptr to sync checkpoint it contains.
+                This function in turn calls a function provided by the
+                OS native sync implementation.
+
+@Input          pszFenceName            String to assign to the new fence
+                                        (for debugging purposes)
+
+@Input          hTimeline               Timeline on which the new fence is
+                                        to be created
+
+@Output         phNewFence              The newly created fence
+
+@Output         psNewSyncCheckpoint     The sync checkpoint contained in
+                                        the new fence
+
+@Return         PVRSRV_OK if a valid fence was provided.
+                PVRSRV_ERROR_SYNC_NATIVESYNC_NOT_REGISTERED if the OS native
+                sync has not registered a callback function.
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncCheckpointCreateFence(const IMG_CHAR *pszFenceName, PVRSRV_TIMELINE_KM hTimeline, PVRSRV_FENCE_KM *phNewFence, PSYNC_CHECKPOINT *psNewSyncCheckpoint);
+
+#endif	/* _SYNC_CHECKPOINT_ */
+
diff --git a/drivers/staging/imgtec/rogue/pvr_drm_shared.h b/drivers/staging/imgtec/rogue/sync_checkpoint_external.h
similarity index 63%
rename from drivers/staging/imgtec/rogue/pvr_drm_shared.h
rename to drivers/staging/imgtec/rogue/sync_checkpoint_external.h
index 89a06ea..02b3e49 100644
--- a/drivers/staging/imgtec/rogue/pvr_drm_shared.h
+++ b/drivers/staging/imgtec/rogue/sync_checkpoint_external.h
@@ -1,9 +1,9 @@
-/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File
-@Title          PVR DRM definitions shared between kernel and user space.
+@Title          Services external synchronisation checkpoint interface header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Defines synchronisation checkpoint structures that are visible
+				internally and externally
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -42,40 +42,32 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#if !defined(__PVR_DRM_SHARED_H__)
-#define __PVR_DRM_SHARED_H__
+#ifndef _SYNC_CHECKPOINT_EXTERNAL_
+#define _SYNC_CHECKPOINT_EXTERNAL_
 
-#include <linux/types.h>
+#define SYNC_CHECKPOINT_MAX_CLASS_NAME_LEN 32
 
-#if defined(__KERNEL__)
-#include <drm/drm.h>
-#elif defined(SUPPORT_ANDROID_PLATFORM) && \
-     !defined(PVR_ANDROID_OLD_LIBDRM_HEADER_PATH)
-#include <drm/drm.h>
-#else
-#include <libdrm/drm.h>
-#endif
+typedef struct _SYNC_CHECKPOINT_CONTEXT *PSYNC_CHECKPOINT_CONTEXT;
 
-/* Subcommands of DRM_PVR_UNPRIV_CMD */
-#define DRM_PVR_UNPRIV_CMD_INIT_SUCCESFUL	0 /* PVR Services init successful */
+typedef struct _SYNC_CHECKPOINT *PSYNC_CHECKPOINT;
 
-struct drm_pvr_unpriv_cmd {
-	/* Input parameter (preserved by the ioctl) */
-	__u32 cmd;
-
-	/* Output parameter */
-	__s32 result;
-};
-
-/*
- * DRM command numbers, relative to DRM_COMMAND_BASE.
- * These defines must be prefixed with "DRM_".
+/* PVRSRV_SYNC_CHECKPOINT states.
+ * The OS native sync implementation should call pfnIsSignalled() to determine if a
+ * PVRSRV_SYNC_CHECKPOINT has signalled (which will return an IMG_BOOL), but can set the
+ * state for a PVRSRV_SYNC_CHECKPOINT (which is currently in the NOT_SIGNALLED state)
+ * where that PVRSRV_SYNC_CHECKPOINT is representing a foreign sync.
  */
-#define DRM_PVR_SRVKM_CMD		0 /* Used for PVR Services ioctls */
-#define DRM_PVR_DBGDRV_CMD		1 /* Debug driver (PDUMP) ioctls */
-#define DRM_PVR_UNPRIV_CMD		2 /* PVR driver unprivileged ioctls */
+typedef enum
+{
+    PVRSRV_SYNC_CHECKPOINT_NOT_SIGNALLED = 0x0,  /*!< checkpoint has not signalled */
+    PVRSRV_SYNC_CHECKPOINT_SIGNALLED     = 0x1,  /*!< checkpoint has signalled */
+    PVRSRV_SYNC_CHECKPOINT_ERRORED       = 0x3   /*!< checkpoint has been errored */
+} PVRSRV_SYNC_CHECKPOINT_STATE;
 
-/* These defines must be prefixed with "DRM_IOCTL_". */
-#define DRM_IOCTL_PVR_UNPRIV_CMD	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_UNPRIV_CMD, struct drm_pvr_unpriv_cmd)
-
-#endif /* defined(__PVR_DRM_SHARED_H__) */
+#if defined(PVR_USE_SYNC_CHECKPOINTS)
+#if defined(__KERNEL__) && defined(LINUX) && !defined(__GENKSYMS__)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+#endif
+#endif /* _SYNC_CHECKPOINT_EXTERNAL_ */
diff --git a/drivers/staging/imgtec/rogue/sync_checkpoint_internal.h b/drivers/staging/imgtec/rogue/sync_checkpoint_internal.h
new file mode 100644
index 0000000..02b4d18
--- /dev/null
+++ b/drivers/staging/imgtec/rogue/sync_checkpoint_internal.h
@@ -0,0 +1,159 @@
+/*************************************************************************/ /*!
+@File
+@Title          Services internal synchronisation checkpoint interface header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Defines the internal server interface for services
+                synchronisation checkpoints.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SYNC_CHECKPOINT__
+#define __SYNC_CHECKPOINT__
+
+#include "img_types.h"
+#include "sync_checkpoint_internal_fw.h"
+#include "sync_checkpoint.h"
+#include "ra.h"
+#include "dllist.h"
+#include "lock.h"
+#include "devicemem.h"
+
+typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+struct SYNC_CHECKPOINT_RECORD;
+#endif
+
+/*
+	Private structures
+*/
+#define SYNC_CHECKPOINT_NAME_SIZE	SYNC_CHECKPOINT_MAX_CLASS_NAME_LEN
+
+typedef struct _SYNC_CHECKPOINT_CONTEXT_
+{
+	PVRSRV_DEVICE_NODE     *psDevNode;
+	IMG_CHAR               azName[SYNC_CHECKPOINT_NAME_SIZE];     /*!< Name of the RA */
+	RA_ARENA               *psSubAllocRA;                         /*!< RA context */
+	IMG_CHAR               azSpanName[SYNC_CHECKPOINT_NAME_SIZE]; /*!< Name of the span RA */
+	RA_ARENA               *psSpanRA;                             /*!< RA used for span management of SubAllocRA */
+	ATOMIC_T               hRefCount;                             /*!< Ref count for this context */
+	ATOMIC_T               hCheckpointCount;                      /*!< Checkpoint count for this context */
+	POS_LOCK               hCheckpointListLock;                   /*!< Checkpoint list lock */
+	DLLIST_NODE            sCheckpointList;                       /*!< List of checkpoints created on this context */
+	IMG_HANDLE             hCheckpointNotify;                     /*!< Handle for debug notifier callback */
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	POS_LOCK               hCheckpointRecordLock;
+	DLLIST_NODE            sCheckpointRecordList;
+	struct SYNC_CHECKPOINT_RECORD *apsCheckpointRecordsFreed[PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN];
+	IMG_UINT32             uiCheckpointRecordFreeIdx;
+	IMG_HANDLE             hCheckpointRecordNotify;
+#endif
+} _SYNC_CHECKPOINT_CONTEXT;
+
+typedef struct _SYNC_CHECKPOINT_BLOCK_
+{
+	ATOMIC_T                  hRefCount;                  /*!< Ref count for this sync block */
+	_SYNC_CHECKPOINT_CONTEXT  *psContext;                 /*!< Our copy of the services connection */
+	PVRSRV_DEVICE_NODE        *psDevNode;
+	IMG_UINT32                ui32SyncBlockSize;          /*!< Size of the sync checkpoint block */
+	IMG_UINT32                ui32FirmwareAddr;           /*!< Firmware address */
+	DEVMEM_MEMDESC            *hMemDesc;                  /*!< DevMem allocation for block */
+	volatile IMG_UINT32       *pui32LinAddr;              /*!< Server-code CPU mapping */
+	IMG_UINT64                uiSpanBase;                 /*!< Base of this import (FW DevMem) in the span RA */
+	DLLIST_NODE               sListNode;                  /*!< List node for the sync chkpt block list */
+} SYNC_CHECKPOINT_BLOCK;
+
+typedef struct SYNC_CHECKPOINT_RECORD* PSYNC_CHECKPOINT_RECORD_HANDLE;
+
+typedef struct _SYNC_CHECKPOINT_
+{
+	/* A sync checkpoint is assigned a unique ID, to avoid any confusion should
+	 * the same memory be re-used later for a different checkpoint
+	 */
+	IMG_UINT32                      ui32UID;                /*!< Unique ID assigned to sync checkpoint (to distinguish checkpoints if memory is re-used)*/
+	ATOMIC_T                        hRefCount;              /*!< Ref count for this sync */
+	ATOMIC_T                        hEnqueuedCCBCount;      /*!< Num times sync has been put in CCBs */
+	SYNC_CHECKPOINT_BLOCK           *psSyncCheckpointBlock; /*!< Synchronisation block this checkpoint is allocated on */
+	IMG_UINT64                      uiSpanAddr;             /*!< Span address of the sync */
+	volatile _SYNC_CHECKPOINT_FW_OBJ *psSyncCheckpointFwObj; /*!< CPU view of the data held in the sync block */
+	IMG_CHAR                        azName[SYNC_CHECKPOINT_NAME_SIZE]; /*!< Name of the checkpoint */
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+	PSYNC_CHECKPOINT_RECORD_HANDLE  hRecord;                /*!< Sync record handle */
+#endif
+	DLLIST_NODE                     sListNode;              /*!< List node for the sync chkpt list */
+} _SYNC_CHECKPOINT;
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointGetFirmwareAddr
+
+@Description    .
+
+@Input          psSyncCheckpoint        Synchronisation checkpoint to get
+                                        the firmware address of
+
+@Return         None
+
+*/
+/*****************************************************************************/
+IMG_UINT32
+SyncCheckpointGetFirmwareAddr(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+/*************************************************************************/ /*!
+@Function       SyncCheckpointCCBEnqueued
+
+@Description    Increment the CCB enqueued reference count for a
+                synchronisation checkpoint. This indicates how many FW
+                operations (checks/update) have been placed into CCBs for the
+                sync checkpoint.
+                When the FW services these operation, it increments its own
+                reference count. When these two values are equal, we know
+                there are not outstanding FW operating for the checkpoint
+                in any CCB.
+
+@Input          psSyncCheckpoint        Synchronisation checkpoint for which
+                                        to increment the enqueued reference
+                                        count
+
+@Return         None
+
+*/
+/*****************************************************************************/
+void
+SyncCheckpointCCBEnqueued(PSYNC_CHECKPOINT psSyncCheckpoint);
+
+#endif	/* __SYNC_CHECKPOINT__ */
diff --git a/drivers/staging/imgtec/rogue/fbc_types.h b/drivers/staging/imgtec/rogue/sync_checkpoint_internal_fw.h
similarity index 71%
rename from drivers/staging/imgtec/rogue/fbc_types.h
rename to drivers/staging/imgtec/rogue/sync_checkpoint_internal_fw.h
index 28be347..e8bda02 100644
--- a/drivers/staging/imgtec/rogue/fbc_types.h
+++ b/drivers/staging/imgtec/rogue/sync_checkpoint_internal_fw.h
@@ -1,7 +1,9 @@
 /*************************************************************************/ /*!
 @File
-@Title          Frame buffer compression definitions
+@Title          Services internal synchronisation checkpoint FW obj header
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Defines the internal FW object structure for services
+                synchronisation checkpoints.
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -40,25 +42,22 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _FBC_TYPES_H_
-#define	_FBC_TYPES_H_
+#ifndef _SYNC_CHECKPOINT_INTERNAL_FW_
+#define _SYNC_CHECKPOINT_INTERNAL_FW_
 
-/**
- * Types of framebuffer compression available.
+#include "img_types.h"
+
+/* Sync_checkpoint firmware object.
+ * This is the FW-addressable structure use to hold the sync checkpoint's
+ * state and other information which needs to be accessed by the firmware.
  */
-typedef enum _FB_COMPRESSION_
+typedef struct _SYNC_CHECKPOINT_FW_OBJ_
 {
-	FB_COMPRESSION_NONE,
-	FB_COMPRESSION_DIRECT_8x8,
-	FB_COMPRESSION_DIRECT_16x4,
-	FB_COMPRESSION_DIRECT_32x2,
-	FB_COMPRESSION_INDIRECT_8x8,
-	FB_COMPRESSION_INDIRECT_16x4,
-	FB_COMPRESSION_INDIRECT_4TILE_8x8,
-	FB_COMPRESSION_INDIRECT_4TILE_16x4
-} FB_COMPRESSION;
+	IMG_UINT32	ui32State;          /*!< Holds the current state of the sync checkpoint */
+	IMG_UINT32	ui32FwRefCount;     /*!< Holds the FW reference count (num of fences/updates processed) */
+} _SYNC_CHECKPOINT_FW_OBJ;
 
-#endif	/* _FBC_TYPES_H_ */
+/* Bit mask Firmware can use to test if a checkpoint has signalled or errored */
+#define SYNC_CHECKPOINT_SIGNALLED_MASK (0x1 << 0)
 
-/* EOF */
-
+#endif	/* _SYNC_CHECKPOINT_INTERNAL_FW_ */
diff --git a/drivers/staging/imgtec/rogue/sync_external.h b/drivers/staging/imgtec/rogue/sync_external.h
deleted file mode 100644
index dc8c158..0000000
--- a/drivers/staging/imgtec/rogue/sync_external.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Services external synchronisation interface header
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Defines synchronisation structures that are visible internally
-                and externally
-@License        Dual MIT/GPLv2
-
-The contents of this file are subject to the MIT license as set out below.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-Alternatively, the contents of this file may be used under the terms of
-the GNU General Public License Version 2 ("GPL") in which case the provisions
-of GPL are applicable instead of those above.
-
-If you wish to allow use of your version of this file only under the terms of
-GPL, and not to allow others to use your version of this file under the terms
-of the MIT license, indicate your decision by deleting the provisions above
-and replace them with the notice and other provisions required by GPL as set
-out in the file called "GPL-COPYING" included in this distribution. If you do
-not delete the provisions above, a recipient may use your version of this file
-under the terms of either the MIT license or GPL.
-
-This License is also included in this distribution in the file called
-"MIT-COPYING".
-
-EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
-PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
-
-#include "img_types.h"
-
-#ifndef _SYNC_EXTERNAL_
-#define _SYNC_EXTERNAL_
-
-#define SYNC_MAX_CLASS_NAME_LEN 32
-
-#define	PVRSRV_MAX_SYNC_PRIMS 32 /*!< number of sync primitives in operations */
-
-
-typedef IMG_HANDLE SYNC_BRIDGE_HANDLE;
-typedef struct SYNC_PRIM_CONTEXT *PSYNC_PRIM_CONTEXT;
-typedef struct _SYNC_OP_COOKIE_ *PSYNC_OP_COOKIE;
-
-typedef struct PVRSRV_CLIENT_SYNC_PRIM
-{
-	volatile IMG_UINT32	*pui32LinAddr;	/*!< User pointer to the primitive */
-} PVRSRV_CLIENT_SYNC_PRIM;
-
-typedef IMG_HANDLE PVRSRV_CLIENT_SYNC_PRIM_HANDLE;
-
-typedef struct PVRSRV_CLIENT_SYNC_PRIM_OP
-{
-	IMG_UINT32 					ui32Flags;				/*!< Operation flags */
-#define PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK	(1 << 0)
-#define PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE	(1 << 1)
-#define PVRSRV_CLIENT_SYNC_PRIM_OP_UNFENCED_UPDATE (PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE | (1<<2))
-	PVRSRV_CLIENT_SYNC_PRIM		*psSync;				/*!< Pointer to the client sync */
-	IMG_UINT32					ui32FenceValue;			/*!< The Fence value (only used if PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK is set) */
-	IMG_UINT32					ui32UpdateValue;		/*!< The Update value (only used if PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE is set) */
-} PVRSRV_CLIENT_SYNC_PRIM_OP;
-
-#if defined(__KERNEL__) && defined(ANDROID) && !defined(__GENKSYMS__)
-#define __pvrsrv_defined_struct_enum__
-#include <services_kernel_client.h>
-#endif
-
-#endif /* _SYNC_EXTERNAL_ */
diff --git a/drivers/staging/imgtec/rogue/sync_internal.h b/drivers/staging/imgtec/rogue/sync_internal.h
index 4f764ec..e9a2586 100644
--- a/drivers/staging/imgtec/rogue/sync_internal.h
+++ b/drivers/staging/imgtec/rogue/sync_internal.h
@@ -46,12 +46,15 @@
 #define _SYNC_INTERNAL_
 
 #include "img_types.h"
-#include "sync_external.h"
+#include <powervr/sync_external.h>
 #include "ra.h"
 #include "dllist.h"
 #include "lock.h"
 #include "devicemem.h"
 
+
+#define LOCAL_SYNC_PRIM_RESET_VALUE 0
+
 /*
 	Private structure's
 */
@@ -105,15 +108,17 @@
 typedef struct _SYNC_PRIM_
 {
 	PVRSRV_CLIENT_SYNC_PRIM	sCommon;		/*!< Client visible part of the sync prim */
-	SYNC_PRIM_TYPE			eType;			/*!< Sync primative type */
+	SYNC_PRIM_TYPE			eType;			/*!< Sync primitive type */
 	union {
-		SYNC_PRIM_LOCAL		sLocal;			/*!< Local sync primative data */
-		SYNC_PRIM_SERVER	sServer;		/*!< Server sync primative data */
+		SYNC_PRIM_LOCAL		sLocal;			/*!< Local sync primitive data */
+		SYNC_PRIM_SERVER	sServer;		/*!< Server sync primitive data */
 	} u;
 } SYNC_PRIM;
 
 
-IMG_INTERNAL IMG_UINT32 SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+/* FIXME this must return a correctly typed pointer */
+IMG_INTERNAL PVRSRV_ERROR
+SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 *pui32FwAddr);
 
 IMG_INTERNAL PVRSRV_ERROR SyncPrimLocalGetHandleAndOffset(PVRSRV_CLIENT_SYNC_PRIM *psSync,
 							IMG_HANDLE *phBlock,
diff --git a/drivers/staging/imgtec/rogue/sync_server.c b/drivers/staging/imgtec/rogue/sync_server.c
index 4718602..e480afd 100644
--- a/drivers/staging/imgtec/rogue/sync_server.c
+++ b/drivers/staging/imgtec/rogue/sync_server.c
@@ -44,16 +44,17 @@
 #include "sync_server.h"
 #include "sync_server_internal.h"
 #include "allocmem.h"
+#include "device.h"
 #include "devicemem.h"
 #include "devicemem_pdump.h"
 #include "osfunc.h"
 #include "pdump.h"
 #include "pvr_debug.h"
+#include "pvr_notifier.h"
 #include "pdump_km.h"
 #include "sync.h"
 #include "sync_internal.h"
 #include "pvrsrv.h"
-#include "debug_request_ids.h"
 #include "connection_server.h"
 #include "htbuffer.h"
 #include "rgxhwperf.h"
@@ -66,6 +67,9 @@
 #include "rgxdebug.h"
 #endif
 
+/* Max number of syncs allowed in a sync prim op */
+#define SYNC_PRIM_OP_MAX_SYNCS 1024
+
 struct _SYNC_PRIMITIVE_BLOCK_
 {
 	PVRSRV_DEVICE_NODE	*psDevNode;
@@ -81,6 +85,7 @@
 
 struct _SERVER_SYNC_PRIMITIVE_
 {
+	PVRSRV_DEVICE_NODE		*psDevNode;
 	PVRSRV_CLIENT_SYNC_PRIM *psSync;
 	IMG_UINT32				ui32NextOp;
 	IMG_UINT32				ui32RefCount;
@@ -152,6 +157,7 @@
 
 struct SYNC_RECORD
 {
+	PVRSRV_DEVICE_NODE		*psDevNode;
 	SYNC_PRIMITIVE_BLOCK	*psServerSyncPrimBlock;	/*!< handle to _SYNC_PRIMITIVE_BLOCK_ */
 	IMG_UINT32				ui32SyncOffset; 		/*!< offset to sync in block */
 	IMG_UINT32				ui32FwBlockAddr;
@@ -161,20 +167,10 @@
 	DLLIST_NODE				sNode;
 	IMG_CHAR				szClassName[SYNC_MAX_CLASS_NAME_LEN];
 };
-
-static POS_LOCK g_hSyncRecordListLock;
-static DLLIST_NODE g_sSyncRecordList;
-static unsigned g_uiFreedSyncRecordIdx = 0;
-static struct SYNC_RECORD * g_apsFreedSyncRecords[PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN] = {0};
-static IMG_HANDLE g_hSyncRecordNotify;
 #endif /* #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
 
 static IMG_UINT32 g_ServerSyncUID = 0;
 
-POS_LOCK g_hListLock;
-static DLLIST_NODE g_sAllServerSyncs;
-IMG_HANDLE g_hNotify;
-
 #define SYNC_REQUESTOR_UNKNOWN 0
 static IMG_UINT32 g_ui32NextSyncRequestorID = 1;
 
@@ -343,18 +339,26 @@
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
 PVRSRV_ERROR
-PVRSRVSyncRecordAddKM(
-			SYNC_RECORD_HANDLE * phRecord,
-			SYNC_PRIMITIVE_BLOCK * hServerSyncPrimBlock,
-			IMG_UINT32 ui32FwBlockAddr,
-			IMG_UINT32 ui32SyncOffset,
-			IMG_BOOL bServerSync,
-			IMG_UINT32 ui32ClassNameSize,
-			const IMG_CHAR *pszClassName)
+PVRSRVSyncRecordAddKM(CONNECTION_DATA *psConnection,
+					  PVRSRV_DEVICE_NODE *psDevNode,
+					  SYNC_RECORD_HANDLE *phRecord,
+					  SYNC_PRIMITIVE_BLOCK *hServerSyncPrimBlock,
+					  IMG_UINT32 ui32FwBlockAddr,
+					  IMG_UINT32 ui32SyncOffset,
+					  IMG_BOOL bServerSync,
+					  IMG_UINT32 ui32ClassNameSize,
+					  const IMG_CHAR *pszClassName)
 {
 	struct SYNC_RECORD * psSyncRec;
 	PVRSRV_ERROR eError = PVRSRV_OK;
 
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
+	RGX_HWPERF_HOST_ALLOC(SYNC,
+	                      ui32FwBlockAddr + ui32SyncOffset,
+	                      pszClassName,
+	                      ui32ClassNameSize);
+
 	if (!phRecord)
 	{
 		return PVRSRV_ERROR_INVALID_PARAMS;
@@ -368,6 +372,7 @@
 		goto fail_alloc;
 	}
 
+	psSyncRec->psDevNode = psDevNode;
 	psSyncRec->psServerSyncPrimBlock = hServerSyncPrimBlock;
 	psSyncRec->ui32SyncOffset = ui32SyncOffset;
 	psSyncRec->ui32FwBlockAddr = ui32FwBlockAddr;
@@ -389,9 +394,9 @@
 		psSyncRec->szClassName[0] = 0;
 	}
 
-	OSLockAcquire(g_hSyncRecordListLock);
-	dllist_add_to_head(&g_sSyncRecordList, &psSyncRec->sNode);
-	OSLockRelease(g_hSyncRecordListLock);
+	OSLockAcquire(psDevNode->hSyncServerRecordLock);
+	dllist_add_to_head(&psDevNode->sSyncServerRecordList, &psSyncRec->sNode);
+	OSLockRelease(psDevNode->hSyncServerRecordLock);
 
 	*phRecord = (SYNC_RECORD_HANDLE)psSyncRec;
 
@@ -405,23 +410,28 @@
 {
 	struct SYNC_RECORD **ppFreedSync;
 	struct SYNC_RECORD *pSync = (struct SYNC_RECORD*)hRecord;
+	PVRSRV_DEVICE_NODE *psDevNode = pSync->psDevNode;
 
 	if (!hRecord)
 	{
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
 
-	OSLockAcquire(g_hSyncRecordListLock);
+	OSLockAcquire(psDevNode->hSyncServerRecordLock);
+
+	RGX_HWPERF_HOST_FREE(SYNC, pSync->ui32FwBlockAddr + pSync->ui32SyncOffset);
 
 	dllist_remove_node(&pSync->sNode);
 
-	if (g_uiFreedSyncRecordIdx >= PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN)
+	if (psDevNode->uiSyncServerRecordFreeIdx >= PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "%s: g_uiFreedSyncRecordIdx out of range", __FUNCTION__));
-		g_uiFreedSyncRecordIdx = 0;
+		PVR_DPF((PVR_DBG_ERROR, "%s: freed sync record index out of range",
+				 __func__));
+		psDevNode->uiSyncServerRecordFreeIdx = 0;
 	}
-	ppFreedSync = &g_apsFreedSyncRecords[g_uiFreedSyncRecordIdx];
-	g_uiFreedSyncRecordIdx = (g_uiFreedSyncRecordIdx + 1) % PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN;
+	ppFreedSync = &psDevNode->apsSyncServerRecordsFreed[psDevNode->uiSyncServerRecordFreeIdx];
+	psDevNode->uiSyncServerRecordFreeIdx =
+		(psDevNode->uiSyncServerRecordFreeIdx + 1) % PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN;
 
 	if (*ppFreedSync)
 	{
@@ -431,22 +441,25 @@
 	pSync->ui64OSTime = OSClockns64();
 	*ppFreedSync = pSync;
 
-	OSLockRelease(g_hSyncRecordListLock);
+	OSLockRelease(psDevNode->hSyncServerRecordLock);
 
 	return PVRSRV_OK;
 }
 #else
 PVRSRV_ERROR
-PVRSRVSyncRecordAddKM(
-			SYNC_RECORD_HANDLE * phRecord,
-			SYNC_PRIMITIVE_BLOCK * hServerSyncPrimBlock,
-			IMG_UINT32 ui32FwBlockAddr,
-			IMG_UINT32 ui32SyncOffset,
-			IMG_BOOL bServerSync,
-			IMG_UINT32 ui32ClassNameSize,
-			const IMG_CHAR *pszClassName)
+PVRSRVSyncRecordAddKM(CONNECTION_DATA *psConnection,
+					  PVRSRV_DEVICE_NODE *psDevNode,
+					  SYNC_RECORD_HANDLE *phRecord,
+					  SYNC_PRIMITIVE_BLOCK *hServerSyncPrimBlock,
+					  IMG_UINT32 ui32FwBlockAddr,
+					  IMG_UINT32 ui32SyncOffset,
+					  IMG_BOOL bServerSync,
+					  IMG_UINT32 ui32ClassNameSize,
+					  const IMG_CHAR *pszClassName)
 {
 	*phRecord = NULL;
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+	PVR_UNREFERENCED_PARAMETER(psDevNode);
 	PVR_UNREFERENCED_PARAMETER(phRecord);
 	PVR_UNREFERENCED_PARAMETER(hServerSyncPrimBlock);
 	PVR_UNREFERENCED_PARAMETER(ui32FwBlockAddr);
@@ -465,6 +478,26 @@
 }
 #endif /* #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
 
+PVRSRV_ERROR
+PVRSRVSyncAllocEventKM(
+			IMG_BOOL bServerSync,
+			IMG_UINT32 ui32FWAddr,
+			IMG_UINT32 ui32ClassNameSize,
+			const IMG_CHAR *pszClassName)
+{
+	RGX_HWPERF_HOST_ALLOC(SYNC, ui32FWAddr, pszClassName, ui32ClassNameSize);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncFreeEventKM(IMG_UINT32 ui32FWAddr)
+{
+	RGX_HWPERF_HOST_FREE(SYNC, ui32FWAddr);
+
+	return PVRSRV_OK;
+}
+
 static
 void _SyncConnectionRef(SYNC_CONNECTION_DATA *psSyncConnectionData)
 {
@@ -671,11 +704,17 @@
 	return PVRSRV_OK;
 }
 
+static INLINE IMG_BOOL _CheckSyncIndex(SYNC_PRIMITIVE_BLOCK *psSyncBlk,
+							IMG_UINT32 ui32Index)
+{
+	return ((ui32Index * sizeof(IMG_UINT32)) < psSyncBlk->ui32BlockSize);
+}
+
 PVRSRV_ERROR
 PVRSRVSyncPrimSetKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Index,
 					IMG_UINT32 ui32Value)
 {
-	if((ui32Index * sizeof(IMG_UINT32)) < psSyncBlk->ui32BlockSize)
+	if(_CheckSyncIndex(psSyncBlk, ui32Index))
 	{
 		psSyncBlk->pui32LinAddr[ui32Index] = ui32Value;
 		return PVRSRV_OK;
@@ -699,8 +738,8 @@
 	return PVRSRV_OK;
 }
 
-void
-ServerSyncRef(SERVER_SYNC_PRIMITIVE *psSync)
+static void
+_ServerSyncRef(SERVER_SYNC_PRIMITIVE *psSync)
 {
 	IMG_UINT32 ui32RefCount;
 
@@ -712,9 +751,10 @@
 						__FUNCTION__, psSync, ui32RefCount);
 }
 
-void
-ServerSyncUnref(SERVER_SYNC_PRIMITIVE *psSync)
+static void
+_ServerSyncUnref(SERVER_SYNC_PRIMITIVE *psSync)
 {
+	PVRSRV_DEVICE_NODE *psDevNode = psSync->psDevNode;
 	IMG_UINT32 ui32RefCount;
 
 	OSLockAcquire(psSync->hLock);
@@ -723,17 +763,23 @@
 
 	if (ui32RefCount == 0)
 	{
+		IMG_UINT32 ui32SyncAddr;
+
+		(void)SyncPrimGetFirmwareAddr(psSync->psSync, &ui32SyncAddr);
 		SYNC_REFCOUNT_PRINT("%s: Server sync %p, refcount = %d",
-							__FUNCTION__, psSync, ui32RefCount);
-		HTBLOGK(HTB_SF_SYNC_SERVER_UNREF, SyncPrimGetFirmwareAddr(psSync->psSync));
+			__FUNCTION__, psSync, ui32RefCount);
+		HTBLOGK(HTB_SF_SYNC_SERVER_UNREF, ui32SyncAddr);
 
 		/* Remove the sync from the global list */
-		OSLockAcquire(g_hListLock);
+		OSLockAcquire(psDevNode->hSyncServerListLock);
 		dllist_remove_node(&psSync->sNode);
-		OSLockRelease(g_hListLock);
+		OSLockRelease(psDevNode->hSyncServerListLock);
 
 		OSLockDestroy(psSync->hLock);
-		SyncPrimFree(psSync->psSync);
+		/* safe to ignore return value as an error indicates
+		 * the sync is either already freed or not a sync
+		 */
+		(void)SyncPrimFree(psSync->psSync);
 		OSFreeMem(psSync);
 	}
 	else
@@ -745,11 +791,11 @@
 
 PVRSRV_ERROR
 PVRSRVServerSyncAllocKM(CONNECTION_DATA * psConnection,
-                        PVRSRV_DEVICE_NODE *psDevNode,
-						SERVER_SYNC_PRIMITIVE **ppsSync,
-						IMG_UINT32 *pui32SyncPrimVAddr,
-						IMG_UINT32 ui32ClassNameSize,
-						const IMG_CHAR *pszClassName)
+			PVRSRV_DEVICE_NODE *psDevNode,
+			SERVER_SYNC_PRIMITIVE **ppsSync,
+			IMG_UINT32 *pui32SyncPrimVAddr,
+			IMG_UINT32 ui32ClassNameSize,
+			const IMG_CHAR *pszClassName)
 {
 	SERVER_SYNC_PRIMITIVE *psNewSync;
 	PVRSRV_ERROR eError;
@@ -794,8 +840,13 @@
 		goto fail_lock_create;
 	}
 
-	SyncPrimSet(psNewSync->psSync, 0);
+	eError = SyncPrimSet(psNewSync->psSync, 0);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_sync_op;
+	}
 
+	psNewSync->psDevNode = psDevNode;
 	psNewSync->ui32NextOp = 0;
 	psNewSync->ui32RefCount = 1;
 	psNewSync->ui32UID = g_ServerSyncUID++;
@@ -804,17 +855,25 @@
 	psNewSync->ui32LastHWUpdate = 0x0bad592c;
 	psNewSync->bPDumped = IMG_FALSE;
 
-	/* Add the sync to the global list */
-	OSLockAcquire(g_hListLock);
-	dllist_add_to_head(&g_sAllServerSyncs, &psNewSync->sNode);
-	OSLockRelease(g_hListLock);
+	eError = SyncPrimGetFirmwareAddr(psNewSync->psSync, pui32SyncPrimVAddr);
+	if (PVRSRV_OK != eError)
+	{
+		goto fail_sync_op;
+	}
 
-	*pui32SyncPrimVAddr = SyncPrimGetFirmwareAddr(psNewSync->psSync);
+	/* Add the sync to the global list */
+	OSLockAcquire(psDevNode->hSyncServerListLock);
+	dllist_add_to_head(&psDevNode->sSyncServerSyncsList, &psNewSync->sNode);
+	OSLockRelease(psDevNode->hSyncServerListLock);
+
 	HTBLOGK(HTB_SF_SYNC_SERVER_ALLOC, *pui32SyncPrimVAddr);
 	SYNC_UPDATES_PRINT("%s: sync: %p, fwaddr: %8.8X", __FUNCTION__, psNewSync, *pui32SyncPrimVAddr);
 	*ppsSync = psNewSync;
 	return PVRSRV_OK;
 
+fail_sync_op:
+	OSLockDestroy(psNewSync->hLock);
+
 fail_lock_create:
 	SyncPrimFree(psNewSync->psSync);
 
@@ -826,30 +885,42 @@
 PVRSRV_ERROR
 PVRSRVServerSyncFreeKM(SERVER_SYNC_PRIMITIVE *psSync)
 {
-	ServerSyncUnref(psSync);
+	_ServerSyncUnref(psSync);
 	return PVRSRV_OK;
 }
 
 PVRSRV_ERROR
 PVRSRVServerSyncGetStatusKM(IMG_UINT32 ui32SyncCount,
-							SERVER_SYNC_PRIMITIVE **papsSyncs,
-							IMG_UINT32 *pui32UID,
-							IMG_UINT32 *pui32FWAddr,
-							IMG_UINT32 *pui32CurrentOp,
-							IMG_UINT32 *pui32NextOp)
+			SERVER_SYNC_PRIMITIVE **papsSyncs,
+			IMG_UINT32 *pui32UID,
+			IMG_UINT32 *pui32FWAddr,
+			IMG_UINT32 *pui32CurrentOp,
+			IMG_UINT32 *pui32NextOp)
 {
-	IMG_UINT32 i;
+	IMG_UINT32 i, ui32SyncAddr;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	PVRSRV_ERROR eReturn = PVRSRV_OK;
 
 	for (i=0;i<ui32SyncCount;i++)
 	{
 		PVRSRV_CLIENT_SYNC_PRIM *psClientSync = papsSyncs[i]->psSync;
 
-		pui32UID[i] = papsSyncs[i]->ui32UID;
-		pui32FWAddr[i] = SyncPrimGetFirmwareAddr(psClientSync);
-		pui32CurrentOp[i] = *psClientSync->pui32LinAddr;
+		eError = SyncPrimGetFirmwareAddr(psClientSync, &ui32SyncAddr);
+		if (PVRSRV_OK != eError)
+		{
+			pui32FWAddr[i] = 0;
+			pui32CurrentOp[i] = 0;
+			eReturn = eError;
+		}
+		else
+		{
+			pui32FWAddr[i] = ui32SyncAddr;
+			pui32CurrentOp[i] = *psClientSync->pui32LinAddr;
+		}
 		pui32NextOp[i] = papsSyncs[i]->ui32NextOp;
+		pui32UID[i] = papsSyncs[i]->ui32UID;
 	}
-	return PVRSRV_OK;
+	return eReturn;
 }
 
 #if defined(SUPPORT_INSECURE_EXPORT) || defined(SUPPORT_SECURE_EXPORT)
@@ -867,7 +938,7 @@
 		goto e0;
 	}
 
-	ServerSyncRef(psSync);
+	_ServerSyncRef(psSync);
 
 	psNewExport->psSync = psSync;
 	*ppsExport = psNewExport;
@@ -880,32 +951,44 @@
 static PVRSRV_ERROR
 _PVRSRVSyncPrimServerUnexportKM(SERVER_SYNC_EXPORT *psExport)
 {
-	ServerSyncUnref(psExport->psSync);
+	_ServerSyncUnref(psExport->psSync);
 
 	OSFreeMem(psExport);
 
 	return PVRSRV_OK;
 }
 
-static void
-_PVRSRVSyncPrimServerImportKM(SERVER_SYNC_EXPORT *psExport,
+static PVRSRV_ERROR
+_PVRSRVSyncPrimServerImportKM(PVRSRV_DEVICE_NODE *psDevNode,
+							  SERVER_SYNC_EXPORT *psExport,
 							  SERVER_SYNC_PRIMITIVE **ppsSync,
 							  IMG_UINT32 *pui32SyncPrimVAddr)
 {
-	ServerSyncRef(psExport->psSync);
+	SERVER_SYNC_PRIMITIVE *psSync = psExport->psSync;
+	PVRSRV_ERROR eError;
 
-	*ppsSync = psExport->psSync;
-	*pui32SyncPrimVAddr = SyncPrimGetFirmwareAddr(psExport->psSync->psSync);
+	if (psSync->psDevNode != psDevNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: server sync invalid for this device\n",
+				 __func__));
+		return PVRSRV_ERROR_PMR_NOT_PERMITTED;
+	}
+
+	_ServerSyncRef(psSync);
+
+	*ppsSync = psSync;
+	eError = SyncPrimGetFirmwareAddr(psSync->psSync,
+			pui32SyncPrimVAddr);
+	return eError;
 }
 #endif /* defined(SUPPORT_INSECURE_EXPORT) || defined(SUPPORT_SECURE_EXPORT) */
 
 #if defined(SUPPORT_INSECURE_EXPORT)
 PVRSRV_ERROR
 PVRSRVSyncPrimServerExportKM(SERVER_SYNC_PRIMITIVE *psSync,
-							SERVER_SYNC_EXPORT **ppsExport)
+				SERVER_SYNC_EXPORT **ppsExport)
 {
-	return _PVRSRVSyncPrimServerExportKM(psSync,
-										 ppsExport);
+	return _PVRSRVSyncPrimServerExportKM(psSync, ppsExport);
 }
 
 PVRSRV_ERROR
@@ -915,15 +998,16 @@
 }
 
 PVRSRV_ERROR
-PVRSRVSyncPrimServerImportKM(SERVER_SYNC_EXPORT *psExport,
-							SERVER_SYNC_PRIMITIVE **ppsSync,
-							IMG_UINT32 *pui32SyncPrimVAddr)
+PVRSRVSyncPrimServerImportKM(CONNECTION_DATA *psConnection,
+							 PVRSRV_DEVICE_NODE *psDevNode,
+							 SERVER_SYNC_EXPORT *psExport,
+							 SERVER_SYNC_PRIMITIVE **ppsSync,
+							 IMG_UINT32 *pui32SyncPrimVAddr)
 {
-	_PVRSRVSyncPrimServerImportKM(psExport,
-								  ppsSync,
-								  pui32SyncPrimVAddr);
+	PVR_UNREFERENCED_PARAMETER(psConnection);
 
-	return PVRSRV_OK;
+	return _PVRSRVSyncPrimServerImportKM(psDevNode, psExport, ppsSync,
+										 pui32SyncPrimVAddr);
 }
 #endif /* defined(SUPPORT_INSECURE_EXPORT) */
 
@@ -967,6 +1051,7 @@
 	return eError;
 }
 
+/* FIXME: This is the same as the non-secure version. */
 PVRSRV_ERROR
 PVRSRVSyncPrimServerSecureUnexportKM(SERVER_SYNC_EXPORT *psExport)
 {
@@ -975,13 +1060,17 @@
 }
 
 PVRSRV_ERROR
-PVRSRVSyncPrimServerSecureImportKM(IMG_SECURE_TYPE hSecure,
+PVRSRVSyncPrimServerSecureImportKM(CONNECTION_DATA *psConnection,
+								   PVRSRV_DEVICE_NODE *psDevNode,
+								   IMG_SECURE_TYPE hSecure,
 								   SERVER_SYNC_PRIMITIVE **ppsSync,
 								   IMG_UINT32 *pui32SyncPrimVAddr)
 {
 	PVRSRV_ERROR eError;
 	SERVER_SYNC_EXPORT *psImport;
 
+	PVR_UNREFERENCED_PARAMETER(psConnection);
+
 	/* Retrieve the data from the secure import */
 	eError = OSSecureImport(hSecure, (void **) &psImport);
 	if (eError != PVRSRV_OK)
@@ -989,13 +1078,9 @@
 		goto e0;
 	}
 
-	_PVRSRVSyncPrimServerImportKM(psImport,
-								  ppsSync,
-								  pui32SyncPrimVAddr);
-	return PVRSRV_OK;
-
+	eError = _PVRSRVSyncPrimServerImportKM(psDevNode, psImport, ppsSync,
+										   pui32SyncPrimVAddr);
 e0:
-	PVR_ASSERT(eError != PVRSRV_OK);
 	return eError;
 }
 #endif /* defined(SUPPORT_SECURE_EXPORT) */
@@ -1020,7 +1105,7 @@
 {
 	IMG_BOOL bInCaptureRange;
 
-	/* Only advance the pending if the an update is required */
+	/* Only advance the pending if an update is required */
 	if (bUpdate)
 	{
 		*pui32FenceValue = psSync->ui32NextOp++;
@@ -1040,10 +1125,15 @@
 	if (!psSync->bPDumped && bInCaptureRange)
 	{
 #if defined(PDUMP)
-		PDumpCommentWithFlags(0, "Dump initial sync state (0x%p, FW VAddr = 0x%08x) = 0x%08x\n",
-				   psSync,
-				   SyncPrimGetFirmwareAddr(psSync->psSync),
-				   *psSync->psSync->pui32LinAddr);
+		{
+			IMG_UINT32 ui32SyncAddr;
+			(void)SyncPrimGetFirmwareAddr(psSync->psSync, &ui32SyncAddr);
+			PDumpCommentWithFlags(0,
+				"Dump initial sync state (0x%p, FW VAddr = 0x%08x) = 0x%08x\n",
+				psSync,
+				ui32SyncAddr,
+				*psSync->psSync->pui32LinAddr);
+		}
 #endif
 
 		SyncPrimPDump(psSync->psSync);
@@ -1069,14 +1159,14 @@
 						  IMG_BOOL *pbFenceRequired)
 {
 
-	ServerSyncRef(psSync);
+	_ServerSyncRef(psSync);
 
 	/*
-		ServerSyncRef will acquire and release the lock but we need to
+		_ServerSyncRef will acquire and release the lock but we need to
 		reacquire here to ensure the state that we're modifying below
 		will be consistent with itself. But it doesn't matter if another
 		thread acquires the lock in between as we've ensured the sync
-		wont go away
+		won't go away
 	*/
 	OSLockAcquire(psSync->hLock);
 	_ServerSyncTakeOperation(psSync,
@@ -1086,8 +1176,8 @@
 
 	/*
 		The caller want to know if a fence command is required
-		i.e. was the last operation done on this sync done by the
-		the same sync requestor
+		i.e. was the last operation done on this sync done by
+		the same sync requester
 	*/
 	if (pbFenceRequired)
 	{
@@ -1162,11 +1252,16 @@
 
 	if (psSync->bSWOperation)
 	{
-#if defined(PDUMP)		
-		PDumpCommentWithFlags(0, "Wait for HW ops and dummy update for SW ops (0x%p, FW VAddr = 0x%08x, value = 0x%08x)\n",
-				   psSync,
-				   SyncPrimGetFirmwareAddr(psSync->psSync),
-				   *pui32FenceValue);
+#if defined(PDUMP)
+		{
+			IMG_UINT32 ui32SyncAddr;
+			(void)SyncPrimGetFirmwareAddr(psSync->psSync, &ui32SyncAddr);
+			PDumpCommentWithFlags(0,
+				"Wait for HW ops and dummy update for SW ops (0x%p, FW VAddr = 0x%08x, value = 0x%08x)\n",
+				psSync,
+				ui32SyncAddr,
+				*pui32FenceValue);
+		}
 #endif
 
 		if (psSync->bSWOpStartedInCaptRange)
@@ -1211,7 +1306,7 @@
 		*psSync->psSync->pui32LinAddr = ui32UpdateValue;
 	}
 
-	ServerSyncUnref(psSync);
+	_ServerSyncUnref(psSync);
 }
 
 IMG_UINT32 ServerSyncGetId(SERVER_SYNC_PRIMITIVE *psSync)
@@ -1219,9 +1314,10 @@
 	return psSync->ui32UID;
 }
 
-IMG_UINT32 ServerSyncGetFWAddr(SERVER_SYNC_PRIMITIVE *psSync)
+PVRSRV_ERROR
+ServerSyncGetFWAddr(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 *pui32SyncAddr)
 {
-	return SyncPrimGetFirmwareAddr(psSync->psSync);
+	return SyncPrimGetFirmwareAddr(psSync->psSync, pui32SyncAddr);
 }
 
 IMG_UINT32 ServerSyncGetValue(SERVER_SYNC_PRIMITIVE *psSync)
@@ -1242,19 +1338,22 @@
 
 	if (*psSync->psSync->pui32LinAddr != psSync->ui32NextOp)
 	{
+		IMG_UINT32 ui32SyncAddr;
+
+		(void)ServerSyncGetFWAddr(psSync, &ui32SyncAddr);
 #if !defined(SUPPORT_EXTRA_METASP_DEBUG)
 		PVR_DUMPDEBUG_LOG("\tPending server sync (ID = %d, FWAddr = 0x%08x): Current = 0x%08x, NextOp = 0x%08x (%s)",
-		                   psSync->ui32UID,
-		                   ServerSyncGetFWAddr(psSync),
-		                   ServerSyncGetValue(psSync),
-		                   psSync->ui32NextOp,
-		                   psSync->szClassName);
+				psSync->ui32UID,
+				ui32SyncAddr,
+		                ServerSyncGetValue(psSync),
+		                psSync->ui32NextOp,
+		                psSync->szClassName);
 #else
 		PVR_DUMPDEBUG_LOG("\tPending server sync (ID = %d, FWAddr = 0x%08x): Value (Host) = 0x%08x, Value (FW) = 0x%08x, NextOp = 0x%08x (%s)",
 		                   psSync->ui32UID,
-		                   ServerSyncGetFWAddr(psSync),
+				   ui32SyncAddr,
 		                   ServerSyncGetValue(psSync),
-		                   RGXReadWithSP(ServerSyncGetFWAddr(psSync)),
+		                   RGXReadWithSP(ui32SyncAddr),
 		                   psSync->ui32NextOp,
 		                   psSync->szClassName);
 #endif
@@ -1266,19 +1365,18 @@
 					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 					void *pvDumpDebugFile)
 {
+	PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)hDebugRequestHandle;
 	DLLIST_NODE *psNode, *psNext;
 
-	PVR_UNREFERENCED_PARAMETER(hDebugRequestHandle);
-	
 	if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
 	{
-		PVR_DUMPDEBUG_LOG("Dumping all pending server syncs");
-		OSLockAcquire(g_hListLock);
-		dllist_foreach_node(&g_sAllServerSyncs, psNode, psNext)
+		PVR_DUMPDEBUG_LOG("------[ Pending Server Syncs ]------");
+		OSLockAcquire(psDevNode->hSyncServerListLock);
+		dllist_foreach_node(&psDevNode->sSyncServerSyncsList, psNode, psNext)
 		{
 			_ServerSyncState(psNode, pfnDumpDebugPrintf, pvDumpDebugFile);
 		}
-		OSLockRelease(g_hListLock);
+		OSLockRelease(psDevNode->hSyncServerListLock);
 	}
 }
 
@@ -1301,6 +1399,12 @@
 	IMG_CHAR *pcPtr;
 	PVRSRV_ERROR eError;
 
+	if((ui32ClientSyncCount + ui32ServerSyncCount) > SYNC_PRIM_OP_MAX_SYNCS)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Too many syncs specified", __func__));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
 	/* Allocate space for all the sync block list */
 	ui32BlockAllocSize = ui32SyncBlockCount * (sizeof(SYNC_PRIMITIVE_BLOCK *));
 
@@ -1316,7 +1420,7 @@
 							 ui32ServerAllocSize +
 							 ui32ClientAllocSize;
 
-	psNewCookie = OSAllocMem(ui32TotalAllocSize);
+	psNewCookie = OSAllocZMem(ui32TotalAllocSize);
 	pcPtr = (IMG_CHAR *) psNewCookie;
 
 	if (!psNewCookie)
@@ -1324,7 +1428,6 @@
 		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 		goto e0;
 	}
-	OSMemSet(psNewCookie, 0, ui32TotalAllocSize);
 
 	/* Setup the pointers */
 	pcPtr += sizeof(SERVER_OP_COOKIE);
@@ -1367,18 +1470,54 @@
 			ui32ServerSyncCount, ui32ClientSyncCount);
 
 	/* Copy all the data into our server cookie */
-	OSMemCopy(psNewCookie->papsSyncPrimBlock,
+	OSCachedMemCopy(psNewCookie->papsSyncPrimBlock,
 			  papsSyncPrimBlock,
 			  sizeof(SYNC_PRIMITIVE_BLOCK *) * ui32SyncBlockCount);
 
-	OSMemCopy(psNewCookie->paui32SyncBlockIndex,
-			  paui32SyncBlockIndex,
-			  sizeof(IMG_UINT32) * ui32ClientSyncCount);
-	OSMemCopy(psNewCookie->paui32Index,
-			  paui32Index,
-			  sizeof(IMG_UINT32) * ui32ClientSyncCount);
+	/* Copy the sync block and sync indices.
+	 *
+	 * Each index must be verified:
+	 * Each Sync Block index must be within the range of the number of sync block
+	 * pointers received. All those pointers are valid, as verified by the bridge.
+	 * And each Sync index must be valid for the Sync Block it relates to.
+	 */
+	for(i = 0; i < ui32ClientSyncCount; i++)
+	{
+		SYNC_PRIMITIVE_BLOCK *psSyncBlock;
 
-	OSMemCopy(psNewCookie->papsServerSync,
+		/* first copy the sync block index and ensure it is in range */
+
+		if(paui32SyncBlockIndex[i] >= ui32SyncBlockCount)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Sync block index %u is out of range",
+										__func__,
+										paui32SyncBlockIndex[i]));
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto err_range;
+		}
+
+		psNewCookie->paui32SyncBlockIndex[i] = paui32SyncBlockIndex[i];
+
+		/* now copy the sync index and ensure it is a valid index within
+		 * the corresponding sync block (note the sync block index was
+		 * verified above
+		 */
+
+		psSyncBlock = psNewCookie->papsSyncPrimBlock[paui32SyncBlockIndex[i]];
+
+		if(_CheckSyncIndex(psSyncBlock, paui32Index[i]) == IMG_FALSE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Sync index %u is out of range",
+										__func__,
+										paui32Index[i]));
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto err_range;
+		}
+
+		psNewCookie->paui32Index[i] = paui32Index[i];
+	}
+
+	OSCachedMemCopy(psNewCookie->papsServerSync,
 			  papsServerSync,
 			  sizeof(SERVER_SYNC_PRIMITIVE *) *ui32ServerSyncCount);
 
@@ -1393,12 +1532,14 @@
 
 	for (i=0;i<ui32ServerSyncCount;i++)
 	{
-		ServerSyncRef(psNewCookie->papsServerSync[i]);
+		_ServerSyncRef(psNewCookie->papsServerSync[i]);
 	}
 
 	*ppsServerCookie = psNewCookie;
 	return PVRSRV_OK;
 
+err_range:
+	OSFreeMem(psNewCookie);
 e0:
 	return eError;
 }
@@ -1417,7 +1558,7 @@
 	if ((ui32ClientSyncCount != psServerCookie->ui32ClientSyncCount) ||
 		(ui32ServerSyncCount != psServerCookie->ui32ServerSyncCount))
 	{
-		/* The bridge layer should have stopped us getting here but check incase */
+		/* The bridge layer should have stopped us getting here but check in case */
 		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync counts", __FUNCTION__));
 		return PVRSRV_ERROR_INVALID_PARAMS;
 	}
@@ -1435,13 +1576,13 @@
 		For client syncs all we need to do is save the values
 		that we've been passed
 	*/
-	OSMemCopy(psServerCookie->paui32Flags,
+	OSCachedMemCopy(psServerCookie->paui32Flags,
 			  paui32Flags,
 			  sizeof(IMG_UINT32) * ui32ClientSyncCount);
-	OSMemCopy(psServerCookie->paui32FenceValue,
+	OSCachedMemCopy(psServerCookie->paui32FenceValue,
 			  paui32FenceValue,
 			  sizeof(IMG_UINT32) * ui32ClientSyncCount);
-	OSMemCopy(psServerCookie->paui32UpdateValue,
+	OSCachedMemCopy(psServerCookie->paui32UpdateValue,
 			  paui32UpdateValue,
 			  sizeof(IMG_UINT32) * ui32ClientSyncCount);
 
@@ -1452,7 +1593,7 @@
 	{
 		/*
 			Take op can only take one operation at a time so we can't
-			optimise away fences so just report the requestor as unknown
+			optimise away fences so just report the requester as unknown
 		*/
 		PVRSRVServerSyncQueueSWOpKM(psServerCookie->papsServerSync[i],
 								  &psServerCookie->paui32ServerFenceValue[i],
@@ -1547,7 +1688,10 @@
 
 		if (bUpdate)
 		{
-			asUFOData[ui32UFOIdx].sUpdate.ui32FWAddr = ServerSyncGetFWAddr(psServerCookie->papsServerSync[i]);
+			IMG_UINT32 ui32SyncAddr;
+
+			(void)ServerSyncGetFWAddr(psServerCookie->papsServerSync[i], &ui32SyncAddr);
+			asUFOData[ui32UFOIdx].sUpdate.ui32FWAddr = ui32SyncAddr;
 			asUFOData[ui32UFOIdx].sUpdate.ui32OldValue = ServerSyncGetValue(psServerCookie->papsServerSync[i]);
 			asUFOData[ui32UFOIdx].sUpdate.ui32NewValue = psServerCookie->paui32ServerUpdateValue[i];
 			ui32UFOIdx++;
@@ -1609,7 +1753,7 @@
 
 	for (i = 0; i < psServerCookie->ui32ServerSyncCount; i++)
 	{
-		ServerSyncUnref(psServerCookie->papsServerSync[i]);
+		_ServerSyncUnref(psServerCookie->papsServerSync[i]);
 	}
 
 	HTBLOGK(HTB_SF_SYNC_PRIM_OP_DESTROY, psServerCookie);
@@ -1788,11 +1932,8 @@
 }
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
-void SyncRecordLookup(
-	IMG_UINT32 ui32FwAddr,
-	IMG_CHAR * pszSyncInfo,
-	size_t len
-)
+void SyncRecordLookup(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT32 ui32FwAddr,
+					  IMG_CHAR * pszSyncInfo, size_t len)
 {
 	DLLIST_NODE *psNode, *psNext;
 	IMG_INT iEnd;
@@ -1802,10 +1943,10 @@
 		return;
 	}
 
-	OSLockAcquire(g_hSyncRecordListLock);
+	OSLockAcquire(psDevNode->hSyncServerRecordLock);
 	pszSyncInfo[0] = '\0';
 
-	dllist_foreach_node(&g_sSyncRecordList, psNode, psNext)
+	dllist_foreach_node(&psDevNode->sSyncServerRecordList, psNode, psNext)
 	{
 		struct SYNC_RECORD *psSyncRec =
 			IMG_CONTAINER_OF(psNode, struct SYNC_RECORD, sNode);
@@ -1832,7 +1973,7 @@
 		}
 	}
 
-	OSLockRelease(g_hSyncRecordListLock);
+	OSLockRelease(psDevNode->hSyncServerRecordLock);
 }
 
 #define NS_IN_S (1000000000UL)
@@ -1883,6 +2024,7 @@
 					DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 					void *pvDumpDebugFile)
 {
+	PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)hDebugRequestHandle;
 	IMG_UINT64 ui64TimeNowS;
 	IMG_UINT32 ui32TimeNowF;
 	IMG_UINT64 ui64TimeNow = OSClockns64();
@@ -1890,18 +2032,16 @@
 
 	ui64TimeNowS = OSDivide64(ui64TimeNow, NS_IN_S, &ui32TimeNowF);
 
-	PVR_UNREFERENCED_PARAMETER(hDebugRequestHandle);
-
 	if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
 	{
-		unsigned i;
-		OSLockAcquire(g_hSyncRecordListLock);
+		IMG_UINT32 i;
+		OSLockAcquire(psDevNode->hSyncServerRecordLock);
 
 		PVR_DUMPDEBUG_LOG("Dumping all allocated syncs @ %05llu.%09u", ui64TimeNowS, ui32TimeNowF);
 		PVR_DUMPDEBUG_LOG("\t%-6s %-5s %-15s %-17s %-14s (%s)",
 					"Type", "PID", "Time Delta (s)", "Address", "Value", "Annotation");
 
-		dllist_foreach_node(&g_sSyncRecordList, psNode, psNext)
+		dllist_foreach_node(&psDevNode->sSyncServerRecordList, psNode, psNext)
 		{
 			struct SYNC_RECORD *psSyncRec =
 				IMG_CONTAINER_OF(psNode, struct SYNC_RECORD, sNode);
@@ -1911,14 +2051,14 @@
 		PVR_DUMPDEBUG_LOG("Dumping all recently freed syncs @ %05llu.%09u", ui64TimeNowS, ui32TimeNowF);
 		PVR_DUMPDEBUG_LOG("\t%-6s %-5s %-15s %-17s %-14s (%s)",
 					"Type", "PID", "Time Delta (s)", "Address", "Value", "Annotation");
-		for(i = DECREMENT_WITH_WRAP(g_uiFreedSyncRecordIdx, PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN);
-				i != g_uiFreedSyncRecordIdx;
-				i = DECREMENT_WITH_WRAP(i, PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN))
+		for (i = DECREMENT_WITH_WRAP(psDevNode->uiSyncServerRecordFreeIdx, PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN);
+			 i != psDevNode->uiSyncServerRecordFreeIdx;
+			 i = DECREMENT_WITH_WRAP(i, PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN))
 		{
-			if (g_apsFreedSyncRecords[i])
+			if (psDevNode->apsSyncServerRecordsFreed[i])
 			{
-				_SyncRecordPrint(g_apsFreedSyncRecords[i],
-				                 ui64TimeNow, pfnDumpDebugPrintf, pvDumpDebugFile);
+				_SyncRecordPrint(psDevNode->apsSyncServerRecordsFreed[i],
+								 ui64TimeNow, pfnDumpDebugPrintf, pvDumpDebugFile);
 			}
 			else
 			{
@@ -1926,26 +2066,27 @@
 			}
 		}
 
-		OSLockRelease(g_hSyncRecordListLock);
+		OSLockRelease(psDevNode->hSyncServerRecordLock);
 	}
 }
 #undef NS_IN_S
 
-static PVRSRV_ERROR SyncRecordListInit(void)
+static PVRSRV_ERROR SyncRecordListInit(PVRSRV_DEVICE_NODE *psDevNode)
 {
 	PVRSRV_ERROR eError;
 
-	eError = OSLockCreate(&g_hSyncRecordListLock, LOCK_TYPE_NONE);
+	eError = OSLockCreate(&psDevNode->hSyncServerRecordLock, LOCK_TYPE_NONE);
 	if (eError != PVRSRV_OK)
 	{
 		goto fail_lock_create;
 	}
-	dllist_init(&g_sSyncRecordList);
+	dllist_init(&psDevNode->sSyncServerRecordList);
 
-	eError = PVRSRVRegisterDbgRequestNotify(&g_hSyncRecordNotify,
+	eError = PVRSRVRegisterDbgRequestNotify(&psDevNode->hSyncServerRecordNotify,
+											psDevNode,
 											_SyncRecordRequest,
 											DEBUG_REQUEST_SERVERSYNC,
-											NULL);
+											psDevNode);
 
 	if (eError != PVRSRV_OK)
 	{
@@ -1955,34 +2096,64 @@
 	return PVRSRV_OK;
 
 fail_dbg_register:
-	OSLockDestroy(g_hSyncRecordListLock);;
+	OSLockDestroy(psDevNode->hSyncServerRecordLock);
 fail_lock_create:
 	return eError;
 }
+
+static void SyncRecordListDeinit(PVRSRV_DEVICE_NODE *psDevNode)
+{
+	DLLIST_NODE *psNode, *psNext;
+	int i;
+
+	OSLockAcquire(psDevNode->hSyncServerRecordLock);
+	dllist_foreach_node(&psDevNode->sSyncServerRecordList, psNode, psNext)
+	{
+		struct SYNC_RECORD *pSyncRec =
+			IMG_CONTAINER_OF(psNode, struct SYNC_RECORD, sNode);
+
+		dllist_remove_node(psNode);
+		OSFreeMem(pSyncRec);
+	}
+
+	for (i = 0; i < PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN; i++)
+	{
+		if (psDevNode->apsSyncServerRecordsFreed[i])
+		{
+			OSFreeMem(psDevNode->apsSyncServerRecordsFreed[i]);
+			psDevNode->apsSyncServerRecordsFreed[i] = NULL;
+		}
+	}
+	OSLockRelease(psDevNode->hSyncServerRecordLock);
+
+	PVRSRVUnregisterDbgRequestNotify(psDevNode->hSyncServerRecordNotify);
+	OSLockDestroy(psDevNode->hSyncServerRecordLock);
+}
 #endif /* #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
 
-PVRSRV_ERROR ServerSyncInit(void)
+PVRSRV_ERROR ServerSyncInit(PVRSRV_DEVICE_NODE *psDevNode)
 {
 	PVRSRV_ERROR eError;
 
-	eError = OSLockCreate(&g_hListLock, LOCK_TYPE_NONE);
+	eError = OSLockCreate(&psDevNode->hSyncServerListLock, LOCK_TYPE_NONE);
 	if (eError != PVRSRV_OK)
 	{
 		goto fail_lock_create;
 	}
-	dllist_init(&g_sAllServerSyncs);
+	dllist_init(&psDevNode->sSyncServerSyncsList);
 
-	eError = PVRSRVRegisterDbgRequestNotify(&g_hNotify,
+	eError = PVRSRVRegisterDbgRequestNotify(&psDevNode->hSyncServerNotify,
+											psDevNode,
 											_ServerSyncDebugRequest,
 											DEBUG_REQUEST_SERVERSYNC,
-											NULL);
+											psDevNode);
 	if (eError != PVRSRV_OK)
 	{
 		goto fail_dbg_register;
 	}
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
-	eError = SyncRecordListInit();
+	eError = SyncRecordListInit(psDevNode);
 	if (eError != PVRSRV_OK)
 	{
 		goto fail_record_list;
@@ -1993,41 +2164,23 @@
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
 fail_record_list:
-	PVRSRVUnregisterDbgRequestNotify(g_hNotify);
+	PVRSRVUnregisterDbgRequestNotify(psDevNode->hSyncServerNotify);
 #endif
 fail_dbg_register:
-	OSLockDestroy(g_hListLock);;
+	OSLockDestroy(psDevNode->hSyncServerListLock);
 fail_lock_create:
 	return eError;
 }
 
-void ServerSyncDeinit(void)
+void ServerSyncDeinit(PVRSRV_DEVICE_NODE *psDevNode)
 {
-	PVRSRVUnregisterDbgRequestNotify(g_hNotify);
-	OSLockDestroy(g_hListLock);
+	PVRSRVUnregisterDbgRequestNotify(psDevNode->hSyncServerNotify);
+	psDevNode->hSyncServerNotify = NULL;
+
+	OSLockDestroy(psDevNode->hSyncServerListLock);
+	psDevNode->hSyncServerListLock = NULL;
+
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
-	{
-		int i;
-		DLLIST_NODE *psNode, *psNext;
-		OSLockAcquire(g_hSyncRecordListLock);
-		dllist_foreach_node(&g_sSyncRecordList, psNode, psNext)
-		{
-			struct SYNC_RECORD *pSyncRec =
-				IMG_CONTAINER_OF(psNode, struct SYNC_RECORD, sNode);
-			dllist_remove_node(psNode);
-			OSFreeMem(pSyncRec);
-		}
-		for (i=0; i < PVRSRV_FULL_SYNC_TRACKING_HISTORY_LEN; i++)
-		{
-			if (g_apsFreedSyncRecords[i])
-			{
-				OSFreeMem(g_apsFreedSyncRecords[i]);
-				g_apsFreedSyncRecords[i] = NULL;
-			}
-		}
-		OSLockRelease(g_hSyncRecordListLock);
-		PVRSRVUnregisterDbgRequestNotify(g_hSyncRecordNotify);
-		OSLockDestroy(g_hSyncRecordListLock);
-	}
+	SyncRecordListDeinit(psDevNode);
 #endif
 }
diff --git a/drivers/staging/imgtec/rogue/sync_server.h b/drivers/staging/imgtec/rogue/sync_server.h
index b2d4e9b..5ae0135 100644
--- a/drivers/staging/imgtec/rogue/sync_server.h
+++ b/drivers/staging/imgtec/rogue/sync_server.h
@@ -115,7 +115,9 @@
 PVRSRVSyncPrimServerUnexportKM(SERVER_SYNC_EXPORT *psExport);
 
 PVRSRV_ERROR
-PVRSRVSyncPrimServerImportKM(SERVER_SYNC_EXPORT *psExport,
+PVRSRVSyncPrimServerImportKM(CONNECTION_DATA *psConnection,
+							 PVRSRV_DEVICE_NODE *psDevNode,
+							 SERVER_SYNC_EXPORT *psExport,
 							 SERVER_SYNC_PRIMITIVE **ppsSync,
 							 IMG_UINT32 *pui32SyncPrimVAddr);
 #endif
@@ -133,7 +135,9 @@
 PVRSRVSyncPrimServerSecureUnexportKM(SERVER_SYNC_EXPORT *psExport);
 
 PVRSRV_ERROR
-PVRSRVSyncPrimServerSecureImportKM(IMG_SECURE_TYPE hSecure,
+PVRSRVSyncPrimServerSecureImportKM(CONNECTION_DATA *psConnection,
+								   PVRSRV_DEVICE_NODE *psDevNode,
+								   IMG_SECURE_TYPE hSecure,
 								   SERVER_SYNC_PRIMITIVE **ppsSync,
 								   IMG_UINT32 *pui32SyncPrimVAddr);
 #endif
@@ -142,14 +146,25 @@
 void PVRSRVServerSyncRequesterUnregisterKM(IMG_UINT32 ui32SyncRequesterID);
 
 PVRSRV_ERROR
-PVRSRVSyncRecordAddKM(
-			SYNC_RECORD_HANDLE * phRecord,
-			SYNC_PRIMITIVE_BLOCK * hServerSyncPrimBlock,
-			IMG_UINT32 ui32FwBlockAddr,
-			IMG_UINT32 ui32SyncOffset,
-			IMG_BOOL bServerSync,
-			IMG_UINT32 ui32ClassNameSize,
-			const IMG_CHAR *pszClassName);
+PVRSRVSyncAllocEventKM(IMG_BOOL bServerSync,
+                       IMG_UINT32 ui32FWAddr,
+                       IMG_UINT32 ui32ClassNameSize,
+                       const IMG_CHAR *pszClassName);
+
+PVRSRV_ERROR
+PVRSRVSyncFreeEventKM(IMG_UINT32 ui32FWAddr);
+
+PVRSRV_ERROR
+PVRSRVSyncRecordAddKM(CONNECTION_DATA *psConnection,
+					  PVRSRV_DEVICE_NODE *psDevNode,
+					  SYNC_RECORD_HANDLE *phRecord,
+					  SYNC_PRIMITIVE_BLOCK *hServerSyncPrimBlock,
+					  IMG_UINT32 ui32FwBlockAddr,
+					  IMG_UINT32 ui32SyncOffset,
+					  IMG_BOOL bServerSync,
+					  IMG_UINT32 ui32ClassNameSize,
+					  const IMG_CHAR *pszClassName);
+
 PVRSRV_ERROR
 PVRSRVSyncRecordRemoveByHandleKM(
 			SYNC_RECORD_HANDLE hRecord);
@@ -227,14 +242,16 @@
 
 IMG_UINT32 ServerSyncGetId(SERVER_SYNC_PRIMITIVE *psSync);
 
-IMG_UINT32 ServerSyncGetFWAddr(SERVER_SYNC_PRIMITIVE *psSync);
+PVRSRV_ERROR
+ServerSyncGetFWAddr(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 *pui32SyncAddr);
 
 IMG_UINT32 ServerSyncGetValue(SERVER_SYNC_PRIMITIVE *psSync);
 
 IMG_UINT32 ServerSyncGetNextValue(SERVER_SYNC_PRIMITIVE *psSync);
 
 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
-void SyncRecordLookup(IMG_UINT32 ui32FwAddr, IMG_CHAR * pszSyncInfo, size_t len);
+void SyncRecordLookup(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT32 ui32FwAddr,
+					  IMG_CHAR * pszSyncInfo, size_t len);
 #endif
 
 void ServerSyncDumpPending(void);
@@ -243,8 +260,8 @@
 void SyncUnregisterConnection(SYNC_CONNECTION_DATA *ppsSyncConnectionData);
 void SyncConnectionPDumpSyncBlocks(SYNC_CONNECTION_DATA *ppsSyncConnectionData);
 
-PVRSRV_ERROR ServerSyncInit(void);
-void ServerSyncDeinit(void);
+PVRSRV_ERROR ServerSyncInit(PVRSRV_DEVICE_NODE *psDevNode);
+void ServerSyncDeinit(PVRSRV_DEVICE_NODE *psDevNode);
 
 #if defined(PDUMP)
 PVRSRV_ERROR
diff --git a/drivers/staging/imgtec/rogue/sync_server_internal.h b/drivers/staging/imgtec/rogue/sync_server_internal.h
index dced4e8..2de4a71 100644
--- a/drivers/staging/imgtec/rogue/sync_server_internal.h
+++ b/drivers/staging/imgtec/rogue/sync_server_internal.h
@@ -48,10 +48,4 @@
 
 typedef struct _SERVER_SYNC_PRIMITIVE_ SERVER_SYNC_PRIMITIVE;
 
-void
-ServerSyncRef(SERVER_SYNC_PRIMITIVE *psSync);
-
-void
-ServerSyncUnref(SERVER_SYNC_PRIMITIVE *psSync);
-
 #endif	/*_SYNC_SERVER_INTERNAL_H_ */
diff --git a/drivers/staging/imgtec/rogue/syscommon.h b/drivers/staging/imgtec/rogue/syscommon.h
index f70097b..4280731 100644
--- a/drivers/staging/imgtec/rogue/syscommon.h
+++ b/drivers/staging/imgtec/rogue/syscommon.h
@@ -1,9 +1,9 @@
-/*************************************************************************/ /*!
+/**************************************************************************/ /*!
 @File
 @Title          Common System APIs and structures
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header provides common system-specific declarations and macros
-                that are supported by all systems
+@Description    This header provides common system-specific declarations and
+                macros that are supported by all systems
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -40,156 +40,85 @@
 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/ /**************************************************************************/
+*/ /***************************************************************************/
 
-#ifndef _SYSCOMMON_H
-#define _SYSCOMMON_H
+#if !defined(__SYSCOMMON_H__)
+#define __SYSCOMMON_H__
 
-#include "osfunc.h"
+#include "img_types.h"
+#include "pvr_notifier.h"
+#include "pvrsrv_device.h"
+#include "pvrsrv_error.h"
 
-#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
-#include <asm/io.h>
-#endif
+typedef IMG_BOOL (*PFN_LISR)(void *pvData);
 
-#if defined (__cplusplus)
-extern "C" {
-#endif
-#include "pvrsrv.h"
+/**************************************************************************/ /*!
+@Function       SysDevInit
+@Description    System specific device initialisation function.
+@Input          pvOSDevice          pointer to the OS device reference
+@Input          ppsDevConfig        returned device configuration info
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /***************************************************************************/
+PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig);
 
+/**************************************************************************/ /*!
+@Function       SysDevDeInit
+@Description    System specific device deinitialisation function.
+@Input          psDevConfig        device configuration info of the device to be
+                                   deinitialised
+@Return         None.
+*/ /***************************************************************************/
+void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig);
 
-#define PVRSRV_SYSTEM_CONFIG_APPLY_OFFSET (1 << 0)
+/**************************************************************************/ /*!
+@Function       SysDebugInfo
+@Description    Dump system specific device debug information.
+@Input          psDevConfig         pointer to device configuration info
+@Input          pfnDumpDebugPrintf  the 'printf' function to be called to
+                                    display the debug info
+@Input          pvDumpDebugFile     optional file identifier to be passed to
+                                    the 'printf' function if required
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /***************************************************************************/
+PVRSRV_ERROR SysDebugInfo(PVRSRV_DEVICE_CONFIG *psDevConfig,
+				DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+				void *pvDumpDebugFile);
 
-PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig, void *hDevice);
-void SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig);
-PVRSRV_ERROR SysAcquireSystemData(IMG_HANDLE hSysData);
-PVRSRV_ERROR SysReleaseSystemData(IMG_HANDLE hSysData);
-PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile);
+/**************************************************************************/ /*!
+@Function       SysInstallDeviceLISR
+@Description    Installs the system Low-level Interrupt Service Routine (LISR)
+                which handles low-level processing of interrupts from the device
+                (GPU).
+                The LISR will be invoked when the device raises an interrupt. An
+                LISR may not be descheduled, so code which needs to do so should
+                be placed in an MISR.
+                The installed LISR will schedule any MISRs once it has completed
+                its interrupt processing, by calling OSScheduleMISR().
+@Input          hSysData      pointer to the system data of the device
+@Input          ui32IRQ       the IRQ on which the LISR is to be installed
+@Input          pszName       name of the module installing the LISR
+@Input          pfnLISR       pointer to the function to be installed as the
+                              LISR
+@Input          pvData        private data provided to the LISR
+@Output         phLISRData    handle to the installed LISR (to be used for a
+                              subsequent uninstall)
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /***************************************************************************/
+PVRSRV_ERROR SysInstallDeviceLISR(IMG_HANDLE hSysData,
+								  IMG_UINT32 ui32IRQ,
+								  const IMG_CHAR *pszName,
+								  PFN_LISR pfnLISR,
+								  void *pvData,
+								  IMG_HANDLE *phLISRData);
 
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-#include "services_km.h"
-void SysSetOSidRegisters(IMG_UINT32 aui32OSidMin[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS], IMG_UINT32 aui32OSidMax[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS]);
-void SysPrintAndResetFaultStatusRegister(void);
-#endif
-
-#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
-PVRSRV_ERROR SysInstallDeviceLISR(IMG_UINT32 ui32IRQ,
-				  IMG_CHAR *pszName,
-				  PFN_LISR pfnLISR,
-				  void *pvData,
-				  IMG_HANDLE *phLISRData);
-
+/**************************************************************************/ /*!
+@Function       SysUninstallDeviceLISR
+@Description    Uninstalls the system Low-level Interrupt Service Routine (LISR)
+                which handles low-level processing of interrupts from the device
+                (GPU).
+@Input          hLISRData     handle of the LISR to be uninstalled
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /***************************************************************************/
 PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData);
-#endif /* defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) */
 
-
-/*
- * SysReadHWReg and SysWriteHWReg differ from OSReadHWReg and OSWriteHWReg
- * in that they are always intended for use with real hardware, even on
- * NO_HARDWARE systems.
- */
-#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
-#define	SysReadHWReg(p, o) OSReadHWReg(p, o)
-#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
-#else	/* !(defined(NO_HARDWARE) && defined(__linux__)) */
-/*!
-******************************************************************************
-
- @Function	SysReadHWReg
-
- @Description
-
- register read function
-
- @input pvLinRegBaseAddr :	lin addr of register block base
-
- @input ui32Offset :
-
- @Return   register value
-
-******************************************************************************/
-static inline IMG_UINT32 SysReadHWReg(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
-{
-	return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
-}
-
-/*!
-******************************************************************************
-
- @Function	SysWriteHWReg
-
- @Description
-
- register write function
-
- @input pvLinRegBaseAddr :	lin addr of register block base
-
- @input ui32Offset :
-
- @input ui32Value :
-
- @Return   none
-
-******************************************************************************/
-static inline void SysWriteHWReg(void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
-{
-	writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
-}
-#endif	/* !(defined(NO_HARDWARE) && defined(__linux__)) */
-
-/*!
-******************************************************************************
-
- @Function		SysCheckMemAllocSize
-
- @Description	Function to apply memory budgeting policies
-
- @input			psDevNode
-
- @input			uiChunkSize
-
- @input			ui32NumPhysChunks
-
- @Return		PVRSRV_ERROR
-
-******************************************************************************/
-FORCE_INLINE PVRSRV_ERROR SysCheckMemAllocSize(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-												IMG_UINT64 ui64MemSize)
-{
-	PVR_UNREFERENCED_PARAMETER(psDevNode);
-	PVR_UNREFERENCED_PARAMETER(ui64MemSize);
-
-	return PVRSRV_OK;
-}
-
-/* Address mask for the physical device addresses.
- * Some systems are limited to 32 bit like TC or Emulator because of the
- * PCI card they are using. */
-typedef enum 
-{
-    SYS_PHYS_ADDRESS_64_BIT = 0xFFFFFFFFFFFFFFFF,
-    SYS_PHYS_ADDRESS_32_BIT = 0xFFFFFFFF
-} SYS_PHYS_ADDRESS_MASK;
-
-/*!
-******************************************************************************
-
- @Function		SysDevicePhysAddressMask
-
- @Description	Function to retrieve a mask for the device physical address. 
-                Often PCI cards like the TC or EMU have restrictions on the 
-                maximum address size.
-
- @Return		The max address value.
-
-******************************************************************************/
-SYS_PHYS_ADDRESS_MASK SysDevicePhysAddressMask(void);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
-
-/*****************************************************************************
- End of file (syscommon.h)
-*****************************************************************************/
+#endif /* !defined(__SYSCOMMON_H__) */
diff --git a/drivers/staging/imgtec/rogue/cache_internal.h b/drivers/staging/imgtec/rogue/sysvalidation.h
similarity index 72%
copy from drivers/staging/imgtec/rogue/cache_internal.h
copy to drivers/staging/imgtec/rogue/sysvalidation.h
index 8326724..edcbead 100644
--- a/drivers/staging/imgtec/rogue/cache_internal.h
+++ b/drivers/staging/imgtec/rogue/sysvalidation.h
@@ -1,8 +1,9 @@
 /*************************************************************************/ /*!
 @File
-@Title          Services cache management header
+@Title          Validation System APIs and structures
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Defines for cache management which are visible internally only.
+@Description    This header provides system-specific declarations and macros
+                needed for hardware validation
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,18 +42,22 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef _CACHE_INTERNAL_H_
-#define _CACHE_INTERNAL_H_
+#if !defined(__SYSVALIDATION_H__)
+#define __SYSVALIDATION_H__
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
 #include "img_types.h"
-#include "pvrsrv_devmem.h"
-#include "cache_external.h"
+#include "rgxdefs_km.h"
+#include "virt_validation_defs.h"
 
-typedef struct _CACHE_BATCH_OP_ENTRY_
-{
-	IMG_UINT32			ui32PMREntryIndex;
-	PVRSRV_CACHE_OP  	eCacheOp;
-	IMG_DEVMEM_SIZE_T	uiSize;
-    IMG_DEVMEM_OFFSET_T uiOffset;
-} CACHE_BATCH_OP_ENTRY;
+void SysSetOSidRegisters(IMG_UINT32 aui32OSidMin[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS],
+						 IMG_UINT32 aui32OSidMax[GPUVIRT_VALIDATION_NUM_OS][GPUVIRT_VALIDATION_NUM_REGIONS]);
+void SysPrintAndResetFaultStatusRegister(void);
 
-#endif	/* _CACHE_INTERNAL_H_ */
+#if defined(SUPPORT_GPUVIRT_VALIDATION) && defined(EMULATOR)
+void SysSetAxiProtOSid(IMG_UINT32 ui32OSid, IMG_BOOL bState);
+void SysSetTrustedDeviceAceEnabled(void);
+#endif
+#endif /* defined(SUPPORT_GPUVIRT_VALIDATION) */
+
+#endif /* !defined(__SYSVALIDATION_H__) */
diff --git a/drivers/staging/imgtec/rogue/tlclient.c b/drivers/staging/imgtec/rogue/tlclient.c
index 805e5e0..d7edb90 100644
--- a/drivers/staging/imgtec/rogue/tlclient.c
+++ b/drivers/staging/imgtec/rogue/tlclient.c
@@ -67,12 +67,13 @@
 #include "devicemem.h"
 
 #include "tlclient.h"
+#include "pvr_tlcommon.h"
 #include "client_pvrtl_bridge.h"
+#include "pvrsrv_tlcommon.h"
 
 /* Defines/Constants
  */
 
-#define PVR_CONNECT_NO_FLAGS   0x00U
 #define NO_ACQUIRE             0xffffffffU
 
 /* User-side stream descriptor structure.
@@ -99,7 +100,7 @@
 
 IMG_INTERNAL
 PVRSRV_ERROR TLClientOpenStream(IMG_HANDLE hSrvHandle,
-		IMG_PCHAR    pszName,
+		const IMG_CHAR* pszName,
 		IMG_UINT32   ui32Mode,
 		IMG_HANDLE*  phSD)
 {
@@ -108,6 +109,7 @@
 	IMG_HANDLE hTLPMR;
 	IMG_HANDLE hTLImportHandle;
 	IMG_DEVMEM_SIZE_T uiImportSize;
+	IMG_UINT32 ui32MemFlags = PVRSRV_MEMALLOCFLAG_CPU_READABLE;
 
 	PVR_ASSERT(hSrvHandle);
 	PVR_ASSERT(pszName);
@@ -144,13 +146,17 @@
 										hTLPMR, &hTLImportHandle);
 	PVR_LOGG_IF_ERROR(eError, "DevmemMakeLocalImportHandle", e2);
 
+	ui32MemFlags |= ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WO ?
+	        PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE : 0;
 	/* Now convert client cookie into a client handle on the buffer's
 	 * physical memory region */
 	eError = DevmemLocalImport(hSrvHandle,
 	                           hTLImportHandle,
-	                           PVRSRV_MEMALLOCFLAG_CPU_READABLE,
+	                           PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+	                           PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
 	                           &psSD->psUMmemDesc,
-	                           &uiImportSize);
+	                           &uiImportSize,
+	                           "TLBuffer");
 	PVR_LOGG_IF_ERROR(eError, "DevmemImport", e3);
 
 	/* Now map the memory into the virtual address space of this process. */
@@ -196,7 +202,7 @@
 	PVR_ASSERT(hSD);
 
 	/* Check the caller provided connection is valid */
-	if(!psSD->hServerSD)
+	if (!psSD->hServerSD)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "TLClientCloseStream: descriptor already closed/not open"));
 		return PVRSRV_ERROR_HANDLE_NOT_FOUND;
@@ -222,7 +228,7 @@
 	if (eError != PVRSRV_OK)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "BridgeTLCloseStream: KM returned %d", eError));
-		/*/ Not much we can do with error, fall through to clean up
+		/* Not much we can do with error, fall through to clean up
 		 * return eError; */
 	}
 
@@ -232,6 +238,101 @@
 	return eError;
 }
 
+IMG_INTERNAL
+PVRSRV_ERROR TLClientDiscoverStreams(IMG_HANDLE hSrvHandle,
+		const IMG_CHAR *pszNamePattern,
+		IMG_UINT32 *pui32Streams,
+		IMG_UINT32 *pui32NumFound)
+{
+	PVR_ASSERT(hSrvHandle);
+	PVR_ASSERT(pszNamePattern);
+	PVR_ASSERT(pui32NumFound);
+
+	return BridgeTLDiscoverStreams(hSrvHandle,
+	                               pszNamePattern,
+	                               *pui32NumFound,
+	                               pui32Streams,
+	                               pui32NumFound);
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientReserveStream(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT8 **ppui8Data,
+		IMG_UINT32 ui32Size)
+{
+	PVRSRV_ERROR eError;
+	TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+	IMG_UINT32 ui32BufferOffset, ui32Dummy;
+
+	PVR_ASSERT(hSrvHandle);
+	PVR_ASSERT(hSD);
+	PVR_ASSERT(ppui8Data);
+	PVR_ASSERT(ui32Size);
+
+	eError = BridgeTLReserveStream(hSrvHandle, psSD->hServerSD,
+	                               &ui32BufferOffset, ui32Size, ui32Size,
+	                               &ui32Dummy);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	*ppui8Data = psSD->pBaseAddr + ui32BufferOffset;
+
+	return PVRSRV_OK;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientReserveStream2(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT8 **ppui8Data,
+		IMG_UINT32 ui32Size,
+		IMG_UINT32 ui32SizeMin,
+		IMG_UINT32 *pui32Available)
+{
+		PVRSRV_ERROR eError;
+	TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+	IMG_UINT32 ui32BufferOffset;
+
+	PVR_ASSERT(hSrvHandle);
+	PVR_ASSERT(hSD);
+	PVR_ASSERT(ppui8Data);
+	PVR_ASSERT(ui32Size);
+
+	eError = BridgeTLReserveStream(hSrvHandle, psSD->hServerSD,
+	                               &ui32BufferOffset, ui32Size, ui32SizeMin,
+	                               pui32Available);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	*ppui8Data = psSD->pBaseAddr + ui32BufferOffset;
+
+	return PVRSRV_OK;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientCommitStream(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT32 ui32Size)
+{
+	PVRSRV_ERROR eError;
+	TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+
+	PVR_ASSERT(hSrvHandle);
+	PVR_ASSERT(hSD);
+	PVR_ASSERT(ui32Size);
+
+	eError = BridgeTLCommitStream(hSrvHandle, psSD->hServerSD, ui32Size);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
 
 IMG_INTERNAL
 PVRSRV_ERROR TLClientAcquireData(IMG_HANDLE hSrvHandle,
@@ -278,7 +379,7 @@
 	}
 	else
 	{
-		/* On non blocking, zero length data could be returned from server
+		/* On non-blocking, zero length data could be returned from server
 		 * Which is basically a no-acquire operation */
 		*ppPacketBuf = 0;
 		*pui32BufLen = 0;
@@ -327,6 +428,42 @@
 	return eError;
 }
 
+IMG_INTERNAL
+PVRSRV_ERROR TLClientWriteData(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT32 ui32Size,
+		IMG_BYTE *pui8Data)
+{
+	PVRSRV_ERROR eError;
+	TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+
+	PVR_ASSERT(hSrvHandle);
+	PVR_ASSERT(hSD);
+	PVR_ASSERT(ui32Size);
+	PVR_ASSERT(pui8Data);
+
+	eError = BridgeTLWriteData(hSrvHandle, psSD->hServerSD, ui32Size, pui8Data);
+	if (eError != PVRSRV_OK)
+	{
+		if (eError == PVRSRV_ERROR_STREAM_RESERVE_TOO_BIG)
+		{
+			static IMG_BOOL bPrinted = IMG_FALSE;
+
+			if (!bPrinted) {
+				PVR_DPF((PVR_DBG_ERROR, "Not enough space. Failed to write"
+				        " data to the stream (%d).", eError));
+				bPrinted = IMG_TRUE;
+			}
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "TLClientWriteData: KM returned %d",
+			        eError));
+		}
+	}
+
+	return eError;
+}
 
 /******************************************************************************
  End of file (tlclient.c)
diff --git a/drivers/staging/imgtec/rogue/tlclient.h b/drivers/staging/imgtec/rogue/tlclient.h
index c5bcafb..b09594d 100644
--- a/drivers/staging/imgtec/rogue/tlclient.h
+++ b/drivers/staging/imgtec/rogue/tlclient.h
@@ -48,8 +48,6 @@
 #include "img_defs.h"
 #include "pvrsrv_error.h"
 
-#include "pvr_tlcommon.h"
-
 
 /* This value is used for the hSrvHandle argument in the client API when
  * called directly from the kernel which will lead to a direct bridge access.
@@ -73,7 +71,7 @@
 */ /***************************************************************************/
 IMG_INTERNAL
 PVRSRV_ERROR TLClientOpenStream(IMG_HANDLE hSrvHandle,
-		IMG_PCHAR    pszName,
+		const IMG_CHAR* pszName,
 		IMG_UINT32   ui32Mode,
 		IMG_HANDLE*  phSD);
 
@@ -93,6 +91,76 @@
 PVRSRV_ERROR TLClientCloseStream(IMG_HANDLE hSrvHandle,
 		IMG_HANDLE hSD);
 
+/**************************************************************************/ /*!
+ @Function      TLClientDiscoverStreams
+ @Description   Finds all streams that's name starts with pszNamePattern and
+                ends with a number.
+ @Input         hSrvHandle      Address of a pointer to a connection object
+ @Input         pszNamePattern  Name pattern. Must be beginning of a string.
+ @Output        pui32Streams    Array of numbers from end of the discovered
+                names.
+ @inOut         pui32Count      When input max number of number that can fit
+                                into pui32Streams. When output number of
+                                discovered streams.
+ @Return		PVRSRV_ERROR    for system codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientDiscoverStreams(IMG_HANDLE hSrvHandle,
+		const IMG_CHAR *pszNamePattern,
+		IMG_UINT32 *pui32Streams,
+		IMG_UINT32 *pui32NumFound);
+
+/**************************************************************************/ /*!
+ @Function      TLClientReserveStream
+ @Description   Reserves a region with given size in the stream. If the stream
+                is already reserved the function will return an error.
+ @Input         hSrvHandle      Address of a pointer to a connection object
+ @Input         hSD             Handle of the stream object to close
+ @Output        ppui8Data       pointer to the buffer
+ @Input         ui32Size        size of the data
+ @Return
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientReserveStream(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT8 **ppui8Data,
+		IMG_UINT32 ui32Size);
+
+/**************************************************************************/ /*!
+ @Function      TLClientStreamReserve2
+ @Description   Reserves a region with given size in the stream. If the stream
+                is already reserved the function will return an error.
+ @Input         hSrvHandle      Address of a pointer to a connection object
+ @Input         hSD             Handle of the stream object to close
+ @Output        ppui8Data       pointer to the buffer
+ @Input         ui32Size        size of the data
+ @Input         ui32SizeMin     minimum size of the data
+ @Input         ui32Available   available space in buffer
+ @Return
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientReserveStream2(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT8 **ppui8Data,
+		IMG_UINT32 ui32Size,
+		IMG_UINT32 ui32SizeMin,
+		IMG_UINT32 *pui32Available);
+
+/**************************************************************************/ /*!
+ @Function      TLClientStreamCommit
+ @Description   Commits previously reserved region in the stream and therefore
+                allows next reserves.
+                This function call has to be preceded by the call to
+                TLClientReserveStream or TLClientReserveStream2.
+ @Input         hSrvHandle      Address of a pointer to a connection object
+ @Input         hSD             Handle of the stream object to close
+ @Input         ui32Size        Size of the data
+ @Return
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientCommitStream(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT32 ui32Size);
 
 /**************************************************************************/ /*!
  @Function		TLClientAcquireData
@@ -142,6 +210,19 @@
 PVRSRV_ERROR TLClientReleaseData(IMG_HANDLE hSrvHandle,
 		IMG_HANDLE hSD);
 
+/**************************************************************************/ /*!
+ @Function      TLClientWriteData
+ @Description   Writes data to the stream.
+ @Input         hSrvHandle      Address of a pointer to a connection object
+ @Input         hSD             Handle of the stream object to read
+ @Input         ui32Size        Size of the data
+ @Input         pui8Data        Pointer to data
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientWriteData(IMG_HANDLE hSrvHandle,
+		IMG_HANDLE hSD,
+		IMG_UINT32 ui32Size,
+		IMG_BYTE *pui8Data);
 
 
 #endif /* TLCLIENT_H_ */
diff --git a/drivers/staging/imgtec/rogue/tlintern.c b/drivers/staging/imgtec/rogue/tlintern.c
index 5beb9a5..1a6e418 100644
--- a/drivers/staging/imgtec/rogue/tlintern.c
+++ b/drivers/staging/imgtec/rogue/tlintern.c
@@ -48,8 +48,9 @@
 #include "allocmem.h"
 #include "pvrsrv_error.h"
 #include "osfunc.h"
+#include "devicemem.h"
 
-#include "pvr_tlcommon.h"
+#include "pvrsrv_tlcommon.h"
 #include "tlintern.h"
 
 /*
@@ -65,7 +66,8 @@
 	}
 	ps->psNode = f1;
 	ps->ui32Flags = f2;
-	ps->hDataEvent = f3;
+	ps->hReadEvent = f3;
+	ps->uiRefCount = 1;
 	return ps;
 }
 
@@ -77,7 +79,7 @@
 	{
 		return NULL;
 	}
-	ps->hDataEventObj = f2;
+	ps->hReadEventObj = f2;
 	ps->psStream = f3;
 	ps->psRDesc = f4;
 	f3->psNode = ps;
@@ -105,7 +107,16 @@
 	PVR_DPF_ENTERED;
 
 	PVR_ASSERT(psDevNode);
-	PVR_ASSERT(sTLGlobalData.psRgxDevNode==0);
+
+	/*
+	 * The Transport Layer is designed to work in a single device system but
+	 * this function will be called multiple times in a multi-device system.
+	 * Return an error in this case.
+	 */
+	if (sTLGlobalData.psRgxDevNode)
+	{
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
 
 	/* Store the RGX device node for later use in devmem buffer allocations */
 	sTLGlobalData.psRgxDevNode = (void*)psDevNode;
@@ -155,11 +166,13 @@
 			/* Other calling code may have freed and zero'd the pointers */
 			if (psn->psRDesc)
 			{
-				OSFREEMEM(psn->psRDesc);
+				OSFreeMem(psn->psRDesc);
+				psn->psRDesc = NULL;
 			}
 			if (psn->psStream)
 			{
-				OSFREEMEM(psn->psStream);
+				OSFreeMem(psn->psStream);
+				psn->psStream = NULL;
 			}
 			*last = psn->psNext;
 			break;
@@ -168,25 +181,30 @@
 	}
 
 	// Release the event list object owned by the stream node
-	if (psRemove->hDataEventObj)
+	if (psRemove->hReadEventObj)
 	{
-		eError = OSEventObjectDestroy(psRemove->hDataEventObj);
+		eError = OSEventObjectDestroy(psRemove->hReadEventObj);
 		PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
 
-		psRemove->hDataEventObj = NULL;
+		psRemove->hReadEventObj = NULL;
 	}
 
 	// Release the memory of the stream node
-	OSFREEMEM(psRemove);
+	OSFreeMem(psRemove);
 
 	PVR_DPF_RETURN;
 }
 
 void
-TLDeInit(void)
+TLDeInit(PVRSRV_DEVICE_NODE *psDevNode)
 {
 	PVR_DPF_ENTERED;
 
+	if (sTLGlobalData.psRgxDevNode != psDevNode)
+	{
+		PVR_DPF_RETURN;
+	}
+
 	if (sTLGlobalData.uiClientCnt)
 	{
 		PVR_DPF((PVR_DBG_ERROR, "TLDeInit transport layer but %d client streams are still connected", sTLGlobalData.uiClientCnt));
@@ -246,7 +264,7 @@
 	PVR_DPF_RETURN;
 }
 
-PTL_SNODE TLFindStreamNodeByName(IMG_PCHAR pszName)
+PTL_SNODE TLFindStreamNodeByName(const IMG_CHAR *pszName)
 {
 	TL_GLOBAL_DATA*  psGD = TLGGD();
 	PTL_SNODE 		 psn;
@@ -266,18 +284,18 @@
 	PVR_DPF_RETURN_VAL(NULL);
 }
 
-PTL_SNODE TLFindStreamNodeByDesc(PTL_STREAM_DESC psRDesc)
+PTL_SNODE TLFindStreamNodeByDesc(PTL_STREAM_DESC psDesc)
 {
 	TL_GLOBAL_DATA*  psGD = TLGGD();
 	PTL_SNODE 		 psn;
 
 	PVR_DPF_ENTERED;
 
-	PVR_ASSERT(psRDesc);
+	PVR_ASSERT(psDesc);
 
 	for (psn = psGD->psHead; psn; psn=psn->psNext)
 	{
-		if (psn->psRDesc == psRDesc)
+		if (psn->psRDesc == psDesc || psn->psWDesc == psDesc)
 		{
 			PVR_DPF_RETURN_VAL(psn);
 		}
@@ -285,6 +303,120 @@
 	PVR_DPF_RETURN_VAL(NULL);
 }
 
+static inline IMG_BOOL IsDigit(IMG_CHAR c)
+{
+	return c >= '0' && c <= '9';
+}
+
+static inline IMG_BOOL ReadNumber(const IMG_CHAR *pszBuffer,
+                                  IMG_UINT32 *pui32Number)
+{
+	IMG_CHAR acTmp[11] = {0}; // max 10 digits
+	IMG_UINT32 ui32Result;
+	IMG_UINT i;
+
+	for (i = 0; i < sizeof(acTmp) - 1; i++)
+	{
+		if (!IsDigit(*pszBuffer))
+			break;
+		acTmp[i] = *pszBuffer++;
+	}
+
+	/* if there are no digits or there is something after the number */
+	if (i == 0 || *pszBuffer != '\0')
+		return IMG_FALSE;
+
+	if (OSStringToUINT32(acTmp, 10, &ui32Result) != PVRSRV_OK)
+		return IMG_FALSE;
+
+	*pui32Number = ui32Result;
+
+	return IMG_TRUE;
+}
+
+/**
+ * Matches pszPattern against pszName and stores results in pui32Numbers.
+ *
+ * @Input pszPattern this is a beginning part of the name string that should
+ *                   be followed by a number.
+ * @Input pszName name of the stream
+ * @Output pui32Number will contain numbers from stream's name end e.g.
+ *                     1234 for name abc_1234
+ * @Return IMG_TRUE when a stream was found or IMG_FALSE if not
+ */
+static IMG_BOOL MatchNamePattern(const IMG_CHAR *pszNamePattern,
+                                 const IMG_CHAR *pszName,
+                                 IMG_UINT32 *pui32Number)
+{
+	IMG_UINT uiPatternLen;
+
+	uiPatternLen = OSStringLength(pszNamePattern);
+
+	if (OSStringNCompare(pszNamePattern, pszName, uiPatternLen) != 0)
+		return IMG_FALSE;
+
+	return ReadNumber(pszName + uiPatternLen, pui32Number);
+}
+
+IMG_UINT32 TLDiscoverStreamNodes(const IMG_CHAR *pszNamePattern,
+                                 IMG_UINT32 *pui32Streams,
+                                 IMG_UINT32 ui32Max)
+{
+	TL_GLOBAL_DATA *psGD = TLGGD();
+	PTL_SNODE psn;
+	IMG_UINT32 ui32Count = 0;
+
+	PVR_ASSERT(pszNamePattern);
+
+	for (psn = psGD->psHead; psn; psn = psn->psNext)
+	{
+		IMG_UINT32 ui32Number = 0;
+
+		if (!MatchNamePattern(pszNamePattern, psn->psStream->szName,
+		                      &ui32Number))
+			continue;
+
+		if (pui32Streams != NULL)
+		{
+			if (ui32Count > ui32Max)
+				break;
+
+			pui32Streams[ui32Count] = ui32Number;
+		}
+
+		ui32Count++;
+	}
+
+	return ui32Count;
+}
+
+PTL_SNODE TLFindAndGetStreamNodeByDesc(PTL_STREAM_DESC psDesc)
+{
+	PTL_SNODE psn;
+
+	PVR_DPF_ENTERED;
+
+	psn = TLFindStreamNodeByDesc(psDesc);
+	if (psn == NULL)
+		PVR_DPF_RETURN_VAL(NULL);
+
+	PVR_ASSERT(psDesc == psn->psWDesc);
+
+	psn->uiWRefCount++;
+	psDesc->uiRefCount++;
+
+	PVR_DPF_RETURN_VAL(psn);
+}
+
+void TLReturnStreamNode(PTL_SNODE psNode)
+{
+	psNode->uiWRefCount--;
+	psNode->psWDesc->uiRefCount--;
+
+	PVR_ASSERT(psNode->uiWRefCount > 0);
+	PVR_ASSERT(psNode->psWDesc->uiRefCount > 0);
+}
+
 IMG_BOOL TLTryRemoveStreamAndFreeStreamNode(PTL_SNODE psRemove)
 {
 	PVR_DPF_ENTERED;
@@ -292,7 +424,7 @@
 	PVR_ASSERT(psRemove);
 
 	/* If there is a client connected to this stream, defer stream's deletion */
-	if (psRemove->psRDesc != NULL)
+	if (psRemove->psRDesc != NULL || psRemove->psWDesc != NULL)
 	{
 		PVR_DPF_RETURN_VAL (IMG_FALSE);
 	}
@@ -304,26 +436,52 @@
 	PVR_DPF_RETURN_VAL (IMG_TRUE);
 }
 
-IMG_BOOL TLRemoveDescAndTryFreeStreamNode(PTL_SNODE psRemove)
+IMG_BOOL TLUnrefDescAndTryFreeStreamNode(PTL_SNODE psNodeToRemove,
+                                          PTL_STREAM_DESC psSD)
 {
 	PVR_DPF_ENTERED;
 
-	PVR_ASSERT(psRemove);
+	PVR_ASSERT(psNodeToRemove);
+	PVR_ASSERT(psSD);
 
-	/* Remove stream descriptor (i.e. stream reader context) */
-	psRemove->psRDesc = NULL;
+	/* Decrement reference count. For descriptor obtained by reader it must
+	 * reach 0 (only single reader allowed) and for descriptors obtained by
+	 * writers it must reach value greater or equal to 0 (multiple writers
+	 * model). */
+	psSD->uiRefCount--;
 
-	/* Do not Free Stream Node if there is a write reference (a producer context) to the stream */
-	if (0 != psRemove->uiWRefCount)
+	if (psSD == psNodeToRemove->psRDesc)
+	{
+		PVR_ASSERT(0 == psSD->uiRefCount);
+		/* Remove stream descriptor (i.e. stream reader context) */
+		psNodeToRemove->psRDesc = NULL;
+	}
+	else if (psSD == psNodeToRemove->psWDesc)
+	{
+		PVR_ASSERT(0 <= psSD->uiRefCount);
+
+		psNodeToRemove->uiWRefCount--;
+
+		/* Remove stream descriptor if reference == 0 */
+		if (0 == psSD->uiRefCount)
+		{
+			psNodeToRemove->psWDesc = NULL;
+		}
+	}
+
+	/* Do not Free Stream Node if there is a write reference (a producer
+	 * context) to the stream */
+	if (NULL != psNodeToRemove->psRDesc || NULL != psNodeToRemove->psWDesc ||
+	    0 != psNodeToRemove->uiWRefCount)
 	{
 		PVR_DPF_RETURN_VAL (IMG_FALSE);
 	}
 
-	/* Make stream pointer NULL to prevent it from being destroyed in RemoveAndFreeStreamNode
-	 * Cleanup of stream should be done by the calling context */
-	psRemove->psStream = NULL;
-	RemoveAndFreeStreamNode(psRemove);
+	/* Make stream pointer NULL to prevent it from being destroyed in
+	 * RemoveAndFreeStreamNode Cleanup of stream should be done by the calling
+	 * context */
+	psNodeToRemove->psStream = NULL;
+	RemoveAndFreeStreamNode(psNodeToRemove);
 	
 	PVR_DPF_RETURN_VAL (IMG_TRUE);
 }
-
diff --git a/drivers/staging/imgtec/rogue/tlintern.h b/drivers/staging/imgtec/rogue/tlintern.h
index c27f96a..fbcc28b 100644
--- a/drivers/staging/imgtec/rogue/tlintern.h
+++ b/drivers/staging/imgtec/rogue/tlintern.h
@@ -45,7 +45,7 @@
 
 
 #include "devicemem_typedefs.h"
-#include "pvr_tlcommon.h"
+#include "pvrsrv_tlcommon.h"
 #include "device.h"
 #include "lock.h"
 
@@ -108,7 +108,7 @@
 	IMG_HANDLE			hProducerEvent;			/*!< Handle to wait on if there is not enough space */
 	IMG_HANDLE			hProducerEventObj;		/*!< Handle to signal blocked reserve calls */
 
-	POS_LOCK 			hStreamLock;			/*!< Lock for ui32Pending & ui32Write*/
+	POS_LOCK 			hStreamLock;			/*!< Writers Lock for ui32Pending & ui32Write*/
 } TL_STREAM, *PTL_STREAM;
 
 /* there need to be enough space reserved in the buffer for 2 minimal packets
@@ -136,7 +136,8 @@
 {
 	PTL_SNODE	psNode;			/*!< Ptr to parent stream node */
 	IMG_UINT32	ui32Flags;
-	IMG_HANDLE	hDataEvent; 	/*!< For wait call */
+	IMG_HANDLE	hReadEvent; 	/*!< For wait call (only used/set in reader descriptors) */
+	IMG_INT		uiRefCount;     /*!< Reference count to the SD */
 } TL_STREAM_DESC, *PTL_STREAM_DESC;
 
 PTL_STREAM_DESC TLMakeStreamDesc(PTL_SNODE f1, IMG_UINT32 f2, IMG_HANDLE f3);
@@ -153,10 +154,11 @@
 typedef struct _TL_SNODE_
 {
 	struct _TL_SNODE_*  psNext;				/*!< Linked list next element */
-	IMG_HANDLE			hDataEventObj;		/*!< Readers 'wait for data' event */
+	IMG_HANDLE			hReadEventObj;		/*!< Readers 'wait for data' event */
 	PTL_STREAM 			psStream;			/*!< TL Stream object */
 	IMG_INT				uiWRefCount;		/*!< Stream writer reference count */
 	PTL_STREAM_DESC 	psRDesc;			/*!< Stream reader 0 or ptr only */
+	PTL_STREAM_DESC		psWDesc;			/*!< Stream writer 0 or ptr only */
 } TL_SNODE;
 
 PTL_SNODE TLMakeSNode(IMG_HANDLE f2, TL_STREAM *f3, TL_STREAM_DESC *f4);
@@ -191,13 +193,18 @@
 TL_GLOBAL_DATA* TLGGD(void);		/* TLGetGlobalData() */
 
 PVRSRV_ERROR TLInit(PVRSRV_DEVICE_NODE *psDevNode);
-void TLDeInit(void);
+void TLDeInit(PVRSRV_DEVICE_NODE *psDevNode);
 
 PVRSRV_DEVICE_NODE* TLGetGlobalRgxDevice(void);
 
 void  TLAddStreamNode(PTL_SNODE psAdd);
-PTL_SNODE TLFindStreamNodeByName(IMG_PCHAR pszName);
+PTL_SNODE TLFindStreamNodeByName(const IMG_CHAR *pszName);
 PTL_SNODE TLFindStreamNodeByDesc(PTL_STREAM_DESC psDesc);
+IMG_UINT32 TLDiscoverStreamNodes(const IMG_CHAR *pszNamePattern,
+                                 IMG_UINT32 *pui32Streams,
+                                 IMG_UINT32 ui32Max);
+PTL_SNODE TLFindAndGetStreamNodeByDesc(PTL_STREAM_DESC psDesc);
+void TLReturnStreamNode(PTL_SNODE psNode);
 
 /****************************************************************************************
  Function Name	: TLTryRemoveStreamAndFreeStreamNode
@@ -222,10 +229,11 @@
 IMG_BOOL  TLTryRemoveStreamAndFreeStreamNode(PTL_SNODE psRemove);
 
 /*****************************************************************************************
- Function Name	: TLRemoveDescAndTryFreeStreamNode
+ Function Name	: TLUnrefDescAndTryFreeStreamNode
  
  Inputs		: PTL_SNODE	Pointer to the TL_SNODE whose descriptor is
- 			requested to be removed 
+ 			requested to be removed
+ 			: PTL_STREAM_DESC	Pointer to the STREAM_DESC
  
  Return Value	: IMG_TRUE	-	If this	TL_SNODE was removed from the
 					TL_GLOBAL_DATA's list
@@ -239,13 +247,15 @@
 			TL_GLOBAL_DATA's list. The caller is responsible for the
 			cleanup of the TL_STREAM whose TL_SNODE may be removed
 ******************************************************************************************/
-IMG_BOOL  TLRemoveDescAndTryFreeStreamNode(PTL_SNODE psRemove);
+IMG_BOOL  TLUnrefDescAndTryFreeStreamNode(PTL_SNODE psRemove, PTL_STREAM_DESC psSD);
 
 /*
  * Transport Layer stream interface to server part declared here to avoid
  * circular dependency.
  */
-IMG_UINT32 TLStreamAcquireReadPos(PTL_STREAM psStream, IMG_UINT32* puiReadOffset);
+IMG_UINT32 TLStreamAcquireReadPos(PTL_STREAM psStream,
+                                  IMG_BOOL bDisableCallback,
+                                  IMG_UINT32* puiReadOffset);
 void TLStreamAdvanceReadPos(PTL_STREAM psStream, IMG_UINT32 uiReadLen);
 
 DEVMEM_MEMDESC* TLStreamGetBufferPointer(PTL_STREAM psStream);
@@ -264,8 +274,8 @@
 /*
  * Test related functions
  */
-PVRSRV_ERROR TUtilsInit (void);
-PVRSRV_ERROR TUtilsDeinit (void);
+PVRSRV_ERROR TUtilsInit (PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR TUtilsDeinit (PVRSRV_DEVICE_NODE *psDeviceNode);
 
 
 #endif /* __TLINTERN_H__ */
diff --git a/drivers/staging/imgtec/rogue/tlserver.c b/drivers/staging/imgtec/rogue/tlserver.c
index abb8027..d300403 100644
--- a/drivers/staging/imgtec/rogue/tlserver.c
+++ b/drivers/staging/imgtec/rogue/tlserver.c
@@ -50,19 +50,23 @@
 
 #include "connection_server.h"
 #include "allocmem.h"
+#include "devicemem.h"
 
 #include "tlintern.h"
+#include "tlstream.h"
 #include "tlserver.h"
 
-#define NO_STREAM_WAIT_PERIOD 2000
-#define NO_DATA_WAIT_PERIOD   1000
+#define NO_STREAM_WAIT_PERIOD 2000000ULL
+#define NO_DATA_WAIT_PERIOD   1000000ULL
 #define NO_ACQUIRE            0xffffffffU
 
+#include "rgxhwperf.h"
+
 /*
  * Transport Layer Client API Kernel-Mode bridge implementation
  */
 PVRSRV_ERROR
-TLServerOpenStreamKM(IMG_PCHAR  	 	   pszName,
+TLServerOpenStreamKM(const IMG_CHAR*  	 	   pszName,
 			   	     IMG_UINT32 		   ui32Mode,
 			   	     PTL_STREAM_DESC* 	   ppsSD,
 			   	     PMR** 				   ppsTLPMR)
@@ -72,6 +76,8 @@
 	PTL_SNODE		psNode = 0;
 	TL_STREAM_DESC* psNewSD = 0;
 	IMG_HANDLE 		hEvent;
+	IMG_BOOL		bIsWriteOnly = ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WO ?
+	                               IMG_TRUE : IMG_FALSE;
 	PTL_GLOBAL_DATA psGD = TLGGD();
 
 #if defined(PVR_DPF_FUNCTION_TRACE_ON)
@@ -81,8 +87,8 @@
 	PVR_ASSERT(pszName);
 
 	/* Acquire TL_GLOBAL_DATA lock here, as if the following TLFindStreamNodeByName
-	 * returns NON NULL PTL_SNODE, we try updating the global data client count and 
-	 * PTL_SNODE's psRDesc and we want to make sure the TL_SNODE is valid (eg. has 
+	 * returns NON NULL PTL_SNODE, we try updating the global data client count and
+	 * PTL_SNODE's psRDesc and we want to make sure the TL_SNODE is valid (eg. has
 	 * not been deleted) while we are updating it
 	 */
 	OSLockAcquire (psGD->hTLGDLock);
@@ -126,36 +132,83 @@
 		else
 		{
 			eError = PVRSRV_ERROR_NOT_FOUND;
-			PVR_DPF((PVR_DBG_ERROR, "Stream does not exist"));
+			PVR_DPF((PVR_DBG_ERROR, "Stream \"%s\" does not exist", pszName));
 		}
 		goto e0;
 	}
 
-	// Only one client/descriptor per stream supported
-	if (psNode->psRDesc != NULL)
-	{
-		PVR_DPF((PVR_DBG_ERROR, "Can not open \"%s\" stream, stream already"
-		        " opened", pszName));
-		eError = PVRSRV_ERROR_ALREADY_OPEN;
-		goto e0;
-	}
-
-	// Create an event handle for this client to wait on when no data in stream
-	// buffer.
-	eError = OSEventObjectOpen(psNode->hDataEventObj, &hEvent);
+	/* Allocate memory for the stream. The memory will be allocated with the
+	 * first call. */
+	eError = TLAllocSharedMemIfNull(psNode->psStream);
 	if (eError != PVRSRV_OK)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Not possible to open node's event object"));
-		eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
-		goto e0;
+		PVR_DPF((PVR_DBG_ERROR, "Failed to allocate memory for stream"
+				" \"%s\"", pszName));
+		return eError;
 	}
 
-	psNewSD = TLMakeStreamDesc(psNode, ui32Mode, hEvent);
-	if (!psNewSD)
+	if (bIsWriteOnly)
 	{
-		PVR_DPF((PVR_DBG_ERROR, "Not possible to make a new stream descriptor"));
-		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto e1;
+
+		/* If psWDesc == NULL it means that this is the first attempt
+		 * to open stream for write. If yes create the descriptor or increment
+		 * reference count otherwise. */
+		if (psNode->psWDesc == NULL)
+		{
+			psNewSD = TLMakeStreamDesc(psNode, ui32Mode, NULL);
+			psNode->psWDesc = psNewSD;
+		}
+		else
+		{
+			psNewSD = psNode->psWDesc;
+			psNode->psWDesc->uiRefCount++;
+		}
+
+		if (!psNewSD)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Not possible to make a new stream"
+			        " writer descriptor"));
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e1;
+		}
+
+		psNode->uiWRefCount++;
+	}
+	else
+	{
+		// Only one reader per stream supported
+		if (psNode->psRDesc != NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Cannot open \"%s\" stream, stream already"
+			        " opened", pszName));
+			eError = PVRSRV_ERROR_ALREADY_OPEN;
+			goto e0;
+		}
+
+		// Create an event handle for this client to wait on when no data in
+		// stream buffer.
+		eError = OSEventObjectOpen(psNode->hReadEventObj, &hEvent);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Not possible to open node's event object"));
+			eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
+			goto e0;
+		}
+
+		psNewSD = TLMakeStreamDesc(psNode, ui32Mode, hEvent);
+		psNode->psRDesc = psNewSD;
+
+		if (!psNewSD)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Not possible to make a new stream descriptor"));
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto e1;
+		}
+
+		PVR_DPF((PVR_DBG_VERBOSE,
+		        "TLServerOpenStreamKM evList=%p, evObj=%p",
+		        psNode->hReadEventObj,
+		        psNode->psRDesc->hReadEvent));
 	}
 
 	// Copy the import handle back to the user mode API to enable access to
@@ -164,28 +217,37 @@
 	PVR_LOGG_IF_ERROR(eError, "DevmemLocalGetImportHandle", e2);
 
 	psGD->uiClientCnt++;
-	psNode->psRDesc = psNewSD;
 
 	/* Global data updated. Now release global lock */
 	OSLockRelease (psGD->hTLGDLock);
 
 	*ppsSD = psNewSD;
 
-	PVR_DPF((PVR_DBG_VERBOSE, 
-			 "TLServerOpenStreamKM evList=%p, evObj=%p", 
-			 psNode->hDataEventObj, 
-			 psNode->psRDesc->hDataEvent));
-
-	if (psNode->psStream->pfOnReaderOpenCallback != NULL)
+	/* This callback is executed only on reader open. There are some actions
+	 * executed on reader open that don't make much sense for writers e.g.
+	 * injection on time synchronisation packet into the stream. */
+	if (!bIsWriteOnly && psNode->psStream->pfOnReaderOpenCallback != NULL)
 	{
 		psNode->psStream->pfOnReaderOpenCallback(
 		        psNode->psStream->pvOnReaderOpenUserData);
 	}
 
+	if (bIsWriteOnly)
+	{
+		/* Sending HWPerf event from TL is a temporary solution and this
+		 * will change once TL is expanded by event allowing to signal
+		 * stream opening. */
+		RGX_HWPERF_HOST_CTRL(CLIENT_STREAM_OPEN,
+		                     OSGetCurrentClientProcessIDKM());
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE, "%s: Stream %s opened for %s", __func__, pszName,
+	        ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WO ? "write" : "read"));
+
 	PVR_DPF_RETURN_OK;
 
 e2:
-	OSFREEMEM(psNewSD);
+	OSFreeMem(psNewSD);
 e1:
 	OSEventObjectClose(hEvent);
 e0:
@@ -201,6 +263,8 @@
 	PTL_SNODE		psNode = 0;
 	PTL_STREAM	psStream;
 	IMG_BOOL	bDestroyStream;
+	IMG_BOOL	bIsWriteOnly = psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO ?
+	                           IMG_TRUE : IMG_FALSE;
 
 	PVR_DPF_ENTERED;
 
@@ -230,40 +294,202 @@
 	 * call will update the TL_SNODE's descriptor value */
 	OSLockAcquire (psGD->hTLGDLock);
 
+	/* Close event handle because event object list might be destroyed in
+	 * TLUnrefDescAndTryFreeStreamNode(). */
+	if (!bIsWriteOnly)
+	{
+		// Close and free the event handle resource used by this descriptor
+		eError = OSEventObjectClose(psSD->hReadEvent);
+		if (eError != PVRSRV_OK)
+		{
+			// Log error but continue as it seems best
+			PVR_DPF((PVR_DBG_ERROR, "OSEventObjectClose() failed error %d",
+			        eError));
+			eError = PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+		}
+	}
+	else
+	{
+		/* Sending HWPerf event from TL is a temporary solution and this
+		 * will change once TL is expanded by event allowing to signal
+		 * stream closing. */
+		RGX_HWPERF_HOST_CTRL(CLIENT_STREAM_CLOSE,
+		                     OSGetCurrentClientProcessIDKM());
+	}
+
 	// Remove descriptor from stream object/list
-	bDestroyStream = TLRemoveDescAndTryFreeStreamNode (psNode);
+	bDestroyStream = TLUnrefDescAndTryFreeStreamNode (psNode, psSD);
 
 	// Assert the counter is sane after input data validated.
 	PVR_ASSERT(psGD->uiClientCnt > 0);
 	psGD->uiClientCnt--;
 
-	OSLockRelease (psGD->hTLGDLock);	
-	
+	OSLockRelease (psGD->hTLGDLock);
+
 	/* Destroy the stream if its TL_SNODE was removed from TL_GLOBAL_DATA */
 	if (bDestroyStream)
 	{
 		TLStreamDestroy (psStream);
 		psStream = NULL;
 	}
-	
-	/* Clean up the descriptor structure */
 
-	// Close and free the event handle resource used by this descriptor
-	eError = OSEventObjectClose(psSD->hDataEvent);
-	if (eError != PVRSRV_OK)
+	PVR_DPF((PVR_DBG_VERBOSE, "%s: Stream closed", __func__));
+
+	/* Free the descriptor if ref count reaches 0. */
+	if (psSD->uiRefCount == 0)
 	{
-		// Log error but continue as it seems best
-		PVR_DPF((PVR_DBG_ERROR, "OSEventObjectClose() failed error %d", eError));
-		eError = PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+		// Free the stream descriptor object
+		OSFreeMem(psSD);
 	}
 
-	// Free the stream descriptor object
-	OSFREEMEM(psSD);
+	PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR
+TLServerReserveStreamKM(PTL_STREAM_DESC psSD,
+                        IMG_UINT32* ui32BufferOffset,
+                        IMG_UINT32 ui32Size,
+                        IMG_UINT32 ui32SizeMin,
+                        IMG_UINT32* pui32Available)
+{
+	TL_GLOBAL_DATA* psGD = TLGGD();
+	PTL_SNODE psNode = 0;
+	IMG_UINT8* pui8Buffer = NULL;
+	PVRSRV_ERROR eError;
+
+	PVR_DPF_ENTERED;
+
+	PVR_ASSERT(psSD);
+
+	if (!(psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO))
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	// Sanity check, quick exit if there are no streams
+	if (psGD->psHead == NULL)
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
+	}
+
+	/* Acquire the global lock. We have to be sure that no one modifies
+	 * the list while we are looking for our stream. */
+	OSLockAcquire(psGD->hTLGDLock);
+	// Check stream still valid
+	psNode = TLFindAndGetStreamNodeByDesc(psSD);
+	OSLockRelease(psGD->hTLGDLock);
+
+	if ((psNode == NULL) || (psNode != psSD->psNode))
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+	}
+
+
+	/* Since we have a valid stream descriptor, the stream should not have been
+	 * made NULL by any producer context. */
+	PVR_ASSERT (psNode->psStream);
+
+	eError = TLStreamReserve2(psNode->psStream, &pui8Buffer, ui32Size,
+	                          ui32SizeMin, pui32Available);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "Failed to reserve the stream (%d).", eError));
+	}
+	else if (pui8Buffer == NULL)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "Not enough space in the stream."));
+		eError = PVRSRV_ERROR_STREAM_RESERVE_TOO_BIG;
+	}
+	else
+	{
+		*ui32BufferOffset = pui8Buffer - psNode->psStream->pbyBuffer;
+		PVR_ASSERT(*ui32BufferOffset < psNode->psStream->ui32Size);
+	}
+
+	OSLockAcquire(psGD->hTLGDLock);
+	TLReturnStreamNode(psNode);
+	OSLockRelease(psGD->hTLGDLock);
 
 	PVR_DPF_RETURN_RC(eError);
 }
 
 PVRSRV_ERROR
+TLServerCommitStreamKM(PTL_STREAM_DESC psSD,
+                       IMG_UINT32 ui32Size)
+{
+	TL_GLOBAL_DATA*	psGD = TLGGD();
+	PTL_SNODE psNode = 0;
+	PVRSRV_ERROR eError;
+
+	PVR_DPF_ENTERED;
+
+	PVR_ASSERT(psSD);
+
+	if (!(psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO))
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	// Sanity check, quick exit if there are no streams
+	if (psGD->psHead == NULL)
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
+	}
+
+	/* Acquire the global lock. We have to be sure that no one modifies
+	 * the list while we are looking for our stream. */
+	OSLockAcquire(psGD->hTLGDLock);
+	// Check stream still valid
+	psNode = TLFindAndGetStreamNodeByDesc(psSD);
+	OSLockRelease(psGD->hTLGDLock);
+
+	if ((psNode == NULL) || (psNode != psSD->psNode))
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+	}
+
+	/* Since we have a valid stream descriptor, the stream should not have been
+	 * made NULL by any producer context. */
+	PVR_ASSERT (psNode->psStream);
+
+	eError = TLStreamCommit(psNode->psStream, ui32Size);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Failed to commit data into stream."));
+	}
+
+	OSLockAcquire(psGD->hTLGDLock);
+	TLReturnStreamNode(psNode);
+	OSLockRelease(psGD->hTLGDLock);
+
+	PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR
+TLServerDiscoverStreamsKM(const IMG_CHAR *pszNamePattern,
+                          IMG_UINT32 ui32Max,
+                          IMG_UINT32 *pui32Streams,
+                          IMG_UINT32 *pui32NumFound)
+{
+	if (*pszNamePattern == '\0')
+		return PVRSRV_ERROR_INVALID_PARAMS;
+
+	// Sanity check, quick exit if there are no streams
+	if (TLGGD()->psHead == NULL)
+	{
+		*pui32NumFound = 0;
+		return PVRSRV_OK;
+	}
+
+	OSLockAcquire(TLGGD()->hTLGDLock);
+	*pui32NumFound = TLDiscoverStreamNodes(pszNamePattern, pui32Streams,
+	                                       ui32Max);
+	OSLockRelease(TLGGD()->hTLGDLock);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
 TLServerAcquireDataKM(PTL_STREAM_DESC psSD,
 		   	   		  IMG_UINT32*	  puiReadOffset,
 		   	   		  IMG_UINT32* 	  puiReadLen)
@@ -291,17 +517,19 @@
 		PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
 	}
 
-	/* If we are here, the stream will never be made NULL until this context itself 
+	/* If we are here, the stream will never be made NULL until this context itself
 	 * calls TLRemoveDescAndTryFreeStreamNode(). This is because the producer will
 	 * fail to make the stream NULL (by calling TLTryRemoveStreamAndFreeStreamNode)
 	 * when a valid stream descriptor is present (i.e. a client is connected).
 	 * Hence, no checks for stream being NON NULL are required after this. */
 	PVR_ASSERT (psNode->psStream);
 	
-	//PVR_DPF((PVR_DBG_VERBOSE, "TLServerAcquireDataKM evList=%p, evObj=%p", psSD->psNode->hDataEventObj, psSD->hDataEvent));
+	//PVR_DPF((PVR_DBG_VERBOSE, "TLServerAcquireDataKM evList=%p, evObj=%p", psSD->psNode->hReadEventObj, psSD->hReadEvent));
 
 	/* Check for data in the associated stream buffer, sleep/wait if none */
-	while (((uiTmpLen = TLStreamAcquireReadPos(psNode->psStream, &uiTmpOffset)) == 0) &&
+	while (((uiTmpLen = TLStreamAcquireReadPos(psNode->psStream,
+			 psSD->ui32Flags & PVRSRV_STREAM_FLAG_DISABLE_PRODUCER_CALLBACK,
+			 &uiTmpOffset)) == 0) &&
 	       (!(psSD->ui32Flags&PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING)) )
 	{
 		PVR_DPF((PVR_DBG_VERBOSE, "TLAcquireDataKM sleeping..."));
@@ -310,7 +538,7 @@
 		// exit loop if not time out but data is ready for client
 		while (TLStreamEOS(psNode->psStream))
 		{
-			eError = OSEventObjectWaitTimeout(psSD->hDataEvent, NO_DATA_WAIT_PERIOD);
+			eError = OSEventObjectWaitTimeout(psSD->hReadEvent, NO_DATA_WAIT_PERIOD);
 			if (eError != PVRSRV_OK)
 			{
 				/* Return timeout or other error condition to the caller who
@@ -318,8 +546,13 @@
 				 * Indefinitely as we want the user mode application to have a
 				 * chance to break out and end if it needs to, so we return the
 				 * time out error code. */
+				PVR_DPF((PVR_DBG_VERBOSE, "TL Server timed out"));
 				PVR_DPF_RETURN_RC(eError);
 			}
+			else
+			{
+				PVR_DPF((PVR_DBG_VERBOSE, "TL Server signalled"));
+			}
 		}
 	}
 
@@ -373,6 +606,59 @@
 	PVR_DPF_RETURN_OK;
 }
 
+PVRSRV_ERROR
+TLServerWriteDataKM(PTL_STREAM_DESC psSD,
+                    IMG_UINT32 ui32Size,
+                    IMG_BYTE* pui8Data)
+{
+	TL_GLOBAL_DATA* psGD = TLGGD();
+	PTL_SNODE psNode = 0;
+	PVRSRV_ERROR eError;
+
+	PVR_DPF_ENTERED;
+
+	PVR_ASSERT(psSD);
+
+	if (!(psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO))
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	// Sanity check, quick exit if there are no streams
+	if (psGD->psHead == NULL)
+	{
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
+	}
+
+	OSLockAcquire(psGD->hTLGDLock);
+	// Check stream still valid
+	psNode = TLFindAndGetStreamNodeByDesc(psSD);
+	OSLockRelease(psGD->hTLGDLock);
+
+	if ((psNode == NULL) || (psNode != psSD->psNode))
+	{
+		OSLockRelease(psGD->hTLGDLock);
+		PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+	}
+
+	/* Since we have a valid stream descriptor, the stream should not have been
+	 * made NULL by any producer context. */
+	PVR_ASSERT (psNode->psStream);
+
+	eError = TLStreamWrite(psNode->psStream, pui8Data, ui32Size);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Failed to write data to the stream (%d).",
+		        eError));
+	}
+
+	OSLockAcquire(psGD->hTLGDLock);
+	TLReturnStreamNode(psNode);
+	OSLockRelease(psGD->hTLGDLock);
+
+	PVR_DPF_RETURN_RC(eError);
+}
+
 /*****************************************************************************
  End of file (tlserver.c)
 *****************************************************************************/
diff --git a/drivers/staging/imgtec/rogue/tlserver.h b/drivers/staging/imgtec/rogue/tlserver.h
index d9ed604..cadbbcc 100644
--- a/drivers/staging/imgtec/rogue/tlserver.h
+++ b/drivers/staging/imgtec/rogue/tlserver.h
@@ -59,13 +59,27 @@
 PVRSRV_ERROR TLServerConnectKM(CONNECTION_DATA *psConnection);
 PVRSRV_ERROR TLServerDisconnectKM(CONNECTION_DATA *psConnection);
 
-PVRSRV_ERROR TLServerOpenStreamKM(IMG_PCHAR pszName,
+PVRSRV_ERROR TLServerOpenStreamKM(const IMG_CHAR* pszName,
 			   IMG_UINT32 ui32Mode,
 			   PTL_STREAM_DESC* ppsSD,
 			   PMR** ppsTLPMR);
 
 PVRSRV_ERROR TLServerCloseStreamKM(PTL_STREAM_DESC psSD);
 
+PVRSRV_ERROR TLServerDiscoverStreamsKM(const IMG_CHAR *pszNamePattern,
+                                       IMG_UINT32 ui32Max,
+                                       IMG_UINT32 *pui32Streams,
+                                       IMG_UINT32 *pui32NumFound);
+
+PVRSRV_ERROR TLServerReserveStreamKM(PTL_STREAM_DESC psSD,
+                                     IMG_UINT32* ui32BufferOffset,
+                                     IMG_UINT32 ui32Size,
+                                     IMG_UINT32 ui32SizeMin,
+                                     IMG_UINT32* pui32Available);
+
+PVRSRV_ERROR TLServerCommitStreamKM(PTL_STREAM_DESC psSD,
+                                    IMG_UINT32 ui32Size);
+
 PVRSRV_ERROR TLServerAcquireDataKM(PTL_STREAM_DESC psSD,
 			   IMG_UINT32* puiReadOffset,
 			   IMG_UINT32* puiReadLen);
@@ -74,6 +88,9 @@
 				 IMG_UINT32 uiReadOffset,
 				 IMG_UINT32 uiReadLen);
 
+PVRSRV_ERROR TLServerWriteDataKM(PTL_STREAM_DESC psSD,
+                                 IMG_UINT32 ui32Size,
+                                 IMG_BYTE *pui8Data);
 
 #endif /* __TLSERVER_H_ */
 
diff --git a/drivers/staging/imgtec/rogue/tlstream.c b/drivers/staging/imgtec/rogue/tlstream.c
index cf3658b..2ae6ee4 100644
--- a/drivers/staging/imgtec/rogue/tlstream.c
+++ b/drivers/staging/imgtec/rogue/tlstream.c
@@ -47,10 +47,12 @@
 #include "pvr_debug.h"
 
 #include "allocmem.h"
+#include "devicemem.h"
 #include "pvrsrv_error.h"
 #include "osfunc.h"
+#include "log2.h"
 
-#include "pvr_tlcommon.h"
+#include "pvrsrv_tlcommon.h"
 #include "tlintern.h"
 #include "tlstream.h"
 
@@ -60,7 +62,7 @@
  * stream buffer utilisation. */
 //#define TL_BUFFER_UTILIZATION 1
 
-#define EVENT_OBJECT_TIMEOUT_MS 1000
+#define EVENT_OBJECT_TIMEOUT_US 1000000ULL
 
 /* Given the state of the buffer it returns a number of bytes that the client
  * can use for a successful allocation. */
@@ -92,7 +94,7 @@
 		}
 	}
     /* The max size of a TL packet currently is UINT16. adjust accordingly */
-	return MIN(ui32AvSpace, IMG_UINT16_MAX);
+	return MIN(ui32AvSpace, PVRSRVTL_MAX_PACKET_SIZE);
 }
 
 /* Returns bytes left in the buffer. Negative if there is not any.
@@ -116,6 +118,62 @@
 	}
 }   
 
+PVRSRV_ERROR TLAllocSharedMemIfNull(IMG_HANDLE hStream)
+{
+	PTL_STREAM psStream = (PTL_STREAM) hStream;
+	PVRSRV_ERROR eError;
+
+	IMG_CHAR pszBufferLabel[PRVSRVTL_MAX_STREAM_NAME_SIZE + 20];
+	DEVMEM_FLAGS_T uiMemFlags = PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+	                            PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+	                            PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+	                            PVRSRV_MEMALLOCFLAG_CPU_UNCACHED |
+	                            PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
+
+	/* Exit if memory has already been allocated. */
+	if (psStream->pbyBuffer != NULL)
+		return PVRSRV_OK;
+
+	OSSNPrintf(pszBufferLabel, sizeof(pszBufferLabel), "TLStreamBuf-%s",
+	           psStream->szName);
+
+	eError = DevmemAllocateExportable((IMG_HANDLE) TLGetGlobalRgxDevice(),
+	                                  (IMG_DEVMEM_SIZE_T) psStream->ui32Size,
+	                                  (IMG_DEVMEM_ALIGN_T) OSGetPageSize(),
+	                                  ExactLog2(OSGetPageSize()),
+	                                  uiMemFlags,
+	                                  pszBufferLabel,
+	                                  &psStream->psStreamMemDesc);
+	PVR_LOGG_IF_ERROR(eError, "DevmemAllocateExportable", e0);
+
+	eError = DevmemAcquireCpuVirtAddr(psStream->psStreamMemDesc,
+	                                  (void**) &psStream->pbyBuffer);
+	PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e1);
+
+	return PVRSRV_OK;
+
+e1:
+	DevmemFree(psStream->psStreamMemDesc);
+e0:
+	return eError;
+}
+
+void TLFreeSharedMem(IMG_HANDLE hStream)
+{
+	PTL_STREAM psStream = (PTL_STREAM) hStream;
+
+	if (psStream->pbyBuffer != NULL)
+	{
+		DevmemReleaseCpuVirtAddr(psStream->psStreamMemDesc);
+		psStream->pbyBuffer = NULL;
+	}
+	if (psStream->psStreamMemDesc != NULL)
+	{
+		DevmemFree(psStream->psStreamMemDesc);
+		psStream->psStreamMemDesc = NULL;
+	}
+}
+
 /******************************************************************************* 
  * TL Server public API implementation.
  ******************************************************************************/
@@ -133,23 +191,16 @@
 	PVRSRV_ERROR   eError;
 	IMG_HANDLE     hEventList;
 	PTL_SNODE      psn = 0;
-	IMG_CHAR       pszBufferLabel[PRVSRVTL_MAX_STREAM_NAME_SIZE+20];
-
-	DEVMEM_FLAGS_T uiMemFlags =  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-								 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | 
-								 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
-								 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-								 PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT | /* CPU only */
-								 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
 	PVR_DPF_ENTERED;
 	/* Sanity checks:  */
 	/* non NULL handler required */
-	if ( NULL == phStream ) 
-	{ 
+	if ( NULL == phStream )
+	{
 		PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
 	}
-	if (OSStringLength(szStreamName) >= PRVSRVTL_MAX_STREAM_NAME_SIZE) 
+	if (szStreamName == NULL || *szStreamName == '\0' ||
+	    OSStringLength(szStreamName) >= PRVSRVTL_MAX_STREAM_NAME_SIZE)
 	{
 		PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
 	}
@@ -157,7 +208,7 @@
 	/* Acquire TL_GLOBAL_DATA lock here because, if the following TLFindStreamNodeByName()
 	 * returns NULL, a new TL_SNODE will be added to TL_GLOBAL_DATA's TL_SNODE list */
 	OSLockAcquire (TLGGD()->hTLGDLock);
-	
+
 	/* Check if there already exists a stream with this name. */
 	psn = TLFindStreamNodeByName( szStreamName );
 	if ( NULL != psn )
@@ -165,7 +216,7 @@
 		eError = PVRSRV_ERROR_ALREADY_EXISTS;
 		goto e0;
 	}
-	
+
 	/* Allocate stream structure container (stream struct) for the new stream */
 	psTmp = OSAllocZMem(sizeof(TL_STREAM)) ;
 	if ( NULL == psTmp ) 
@@ -196,7 +247,7 @@
     {	/* Additional synchronization object required for this kind of stream */
         psTmp->bBlock = IMG_TRUE;
     }
-	
+
 	eError = OSEventObjectCreate(NULL, &psTmp->hProducerEventObj);
 	if (eError != PVRSRV_OK)
 	{
@@ -221,31 +272,25 @@
 	psTmp->ui32Write = 0;
 	psTmp->ui32Pending = NOTHING_PENDING;
 
-	OSSNPrintf(pszBufferLabel, sizeof(pszBufferLabel), "TLStreamBuf-%s", szStreamName);
+	/* Memory will be allocated on first connect to the stream */
+	if (!(ui32StreamFlags & TL_FLAG_ALLOCATE_ON_FIRST_OPEN))
+	{
+		/* Allocate memory for the circular buffer and export it to user space. */
+		eError = TLAllocSharedMemIfNull(psTmp);
+		PVR_LOGG_IF_ERROR(eError, "TLAllocSharedMem", e3);
+	}
 
-	/* Allocate memory for the circular buffer and export it to user space. */
-	eError = DevmemAllocateExportable((IMG_HANDLE) TLGetGlobalRgxDevice(),
-	                                  (IMG_DEVMEM_SIZE_T)psTmp->ui32Size,
-	                                  (IMG_DEVMEM_ALIGN_T) OSGetPageSize(),
-	                                  uiMemFlags | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
-	                                  pszBufferLabel,
-	                                  &psTmp->psStreamMemDesc);
-	PVR_LOGG_IF_ERROR(eError, "DevmemAllocateExportable", e3);
-
-	eError = DevmemAcquireCpuVirtAddr( psTmp->psStreamMemDesc, (void**) &psTmp->pbyBuffer );
-	PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e4);
-
-	/* Synchronization object to synchronize with user side data transfers. */
+	/* Synchronisation object to synchronise with user side data transfers. */
 	eError = OSEventObjectCreate(psTmp->szName, &hEventList);
 	if (eError != PVRSRV_OK)
 	{
-		goto e5;
+		goto e4;
 	}
 
 	eError = OSLockCreate (&psTmp->hStreamLock, LOCK_TYPE_PASSIVE);
 	if (eError != PVRSRV_OK)
 	{
-		goto e6;
+		goto e5;
 	}
 
 	/* Now remember the stream in the global TL structures */
@@ -253,7 +298,7 @@
 	if (psn == NULL)
 	{
 		eError=PVRSRV_ERROR_OUT_OF_MEMORY;
-		goto e7;
+		goto e6;
 	}
 
 	/* Stream node created, now reset the write reference count to 1
@@ -274,20 +319,18 @@
 	*phStream = (IMG_HANDLE)psTmp;
 	PVR_DPF_RETURN_OK;
 
-e7:
-	OSLockDestroy(psTmp->hStreamLock);
 e6:
-	OSEventObjectDestroy(hEventList);
+	OSLockDestroy(psTmp->hStreamLock);
 e5:
-	DevmemReleaseCpuVirtAddr( psTmp->psStreamMemDesc );
+	OSEventObjectDestroy(hEventList);
 e4:
-	DevmemFree(psTmp->psStreamMemDesc);
+	TLFreeSharedMem(psTmp);
 e3:
 	OSEventObjectClose(psTmp->hProducerEvent);
 e2:
 	OSEventObjectDestroy(psTmp->hProducerEventObj);
 e1:
-	OSFREEMEM(psTmp);
+	OSFreeMem(psTmp);
 e0:
 	OSLockRelease (TLGGD()->hTLGDLock);
 
@@ -432,7 +475,7 @@
 				/* Release lock before sleeping */
 				OSLockRelease (TLGGD()->hTLGDLock);
 				
-				OSEventObjectWaitTimeout(psTmp->hProducerEvent, EVENT_OBJECT_TIMEOUT_MS);
+				OSEventObjectWaitTimeout(psTmp->hProducerEvent, EVENT_OBJECT_TIMEOUT_US);
 				
 				OSLockAcquire (TLGGD()->hTLGDLock);
 
@@ -505,7 +548,7 @@
 		PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY);
 	}
 
-	if ( IMG_UINT16_MAX < lReqSizeAligned )
+	if ( PVRSRVTL_MAX_PACKET_SIZE < lReqSizeAligned )
 	{
 		psTmp->ui32Pending = NOTHING_PENDING;
 		if (pui32AvSpace)
@@ -697,16 +740,16 @@
 	ui32OldWrite = ui32LWrite;
 
 	// Space in buffer is aligned
-	ui32ReqSize = PVRSRVTL_ALIGN(ui32ReqSize);
+	ui32ReqSize = PVRSRVTL_ALIGN(ui32ReqSize) + sizeof(PVRSRVTL_PACKETHDR);
 
-	/* Sanity check. ReqSize + packet header size. */
-	if ( ui32LPending != ui32ReqSize + sizeof(PVRSRVTL_PACKETHDR) )
+	/* Check pending reserver and ReqSize + packet header size. */
+	if ((ui32LPending == NOTHING_PENDING) || (ui32ReqSize > ui32LPending))
 	{
 		PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE);
 	}
 
 	/* Update pointer to written data. */
-	ui32LWrite = (ui32LWrite + ui32LPending) % psTmp->ui32Size;
+	ui32LWrite = (ui32LWrite + ui32ReqSize) % psTmp->ui32Size;
 
 	/* and reset LPending to 0 since data are now submitted  */
 	ui32LPending = NOTHING_PENDING;
@@ -747,7 +790,7 @@
 	if (ui32OldWrite == ui32LRead && !psTmp->bNoSignalOnCommit)
 	{
 		/* Signal consumers that may be waiting */
-		eError = OSEventObjectSignal(psTmp->psNode->hDataEventObj);
+		eError = OSEventObjectSignal(psTmp->psNode->hReadEventObj);
 		if ( eError != PVRSRV_OK)
 		{
 			PVR_DPF_RETURN_RC(eError);
@@ -777,7 +820,7 @@
 	}
 	else if ( pbyDest )
 	{
-		OSMemCopy((void*)pbyDest, (void*)pui8Src, ui32Size);
+		OSDeviceMemCopy((void*)pbyDest, (void*)pui8Src, ui32Size);
 		eError = TLStreamCommit(hStream, ui32Size);
 		if ( PVRSRV_OK != eError ) 
 		{	
@@ -798,7 +841,7 @@
 	IMG_DEVMEM_ALIGN_T align = 4; /* Low dummy value so the real value can be obtained */
 
  	actual_req_size = 2; 
-	DevmemExportalignAdjustSizeAndAlign(NULL, &actual_req_size, &align);
+	DevmemExportalignAdjustSizeAndAlign(OSGetPageShift(), &actual_req_size, &align);
 
 	psInfo->headerSize = sizeof(PVRSRVTL_PACKETHDR);
 	psInfo->minReservationSize = sizeof(IMG_UINT32);
@@ -842,10 +885,13 @@
 	}
 	psTmp = (PTL_STREAM)psStream;
 	
-	/* Signal clients only when data is available to read */
-	if (psTmp->ui32Read != psTmp->ui32Write)
+	/* If read client exists and has opened stream in blocking mode,
+	 * signal when data is available to read. */
+	if (psTmp->psNode->psRDesc &&
+		 (!(psTmp->psNode->psRDesc->ui32Flags & PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING)) &&
+			psTmp->ui32Read != psTmp->ui32Write)
 	{
-		eError = OSEventObjectSignal(psTmp->psNode->hDataEventObj);
+		eError = OSEventObjectSignal(psTmp->psNode->hReadEventObj);
 	}
 
 	PVR_DPF_RETURN_RC(eError);
@@ -857,7 +903,9 @@
  * these functions are internal.
  */
 IMG_UINT32
-TLStreamAcquireReadPos(PTL_STREAM psStream, IMG_UINT32* puiReadOffset)
+TLStreamAcquireReadPos(PTL_STREAM psStream,
+                       IMG_BOOL bDisableCallback,
+                       IMG_UINT32* puiReadOffset)
 {
 	IMG_UINT32 uiReadLen = 0;
 	IMG_UINT32 ui32LRead, ui32LWrite;
@@ -872,7 +920,7 @@
 	ui32LWrite = psStream->ui32Write;
 
 	/* No data available and CB defined - try and get data */
-	if ((ui32LRead == ui32LWrite) && psStream->pfProducerCallback)
+	if ((ui32LRead == ui32LWrite) && psStream->pfProducerCallback && !bDisableCallback)
 	{
 		PVRSRV_ERROR eRc;
 		IMG_UINT32   ui32Resp = 0;
@@ -959,9 +1007,8 @@
 	OSEventObjectClose(psStream->hProducerEvent);
 	OSEventObjectDestroy(psStream->hProducerEventObj);
 
-	DevmemReleaseCpuVirtAddr(psStream->psStreamMemDesc);
-	DevmemFree(psStream->psStreamMemDesc);
-	OSFREEMEM(psStream);
+	TLFreeSharedMem(psStream);
+	OSFreeMem(psStream);
 }
 
 DEVMEM_MEMDESC*
diff --git a/drivers/staging/imgtec/rogue/tlstream.h b/drivers/staging/imgtec/rogue/tlstream.h
index 6a794db..5b7aecf 100644
--- a/drivers/staging/imgtec/rogue/tlstream.h
+++ b/drivers/staging/imgtec/rogue/tlstream.h
@@ -103,6 +103,9 @@
  * it chooses. */
 #define TL_FLAG_NO_SIGNAL_ON_COMMIT    (1U<<9)
 
+/*! Defer allocation of stream's shared memory until first open. */
+#define TL_FLAG_ALLOCATE_ON_FIRST_OPEN (1U<<10)
+
 /*! Structure used to pass internal TL stream sizes information to users.*/
 typedef struct _TL_STREAM_INFO_
 {
@@ -129,6 +132,25 @@
 typedef void (*TL_STREAM_ONREADEROPENCB)(void *pvArg);
 
 /*************************************************************************/ /*!
+ @Function      TLAllocSharedMem
+ @Description   Allocates shared memory for the stream.
+ @Input         phStream    Stream handle.
+ @Return        eError      Internal services call returned eError error
+                            number.
+ @Return        PVRSRV_OK
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLAllocSharedMemIfNull(IMG_HANDLE hStream);
+
+/*************************************************************************/ /*!
+ @Function      TLFreeSharedMem
+ @Description   Frees stream's shared memory.
+ @Input         phStream    Stream handle.
+*/ /**************************************************************************/
+void
+TLFreeSharedMem(IMG_HANDLE hStream);
+
+/*************************************************************************/ /*!
  @Function      TLStreamCreate
  @Description   Request the creation of a new stream and open a handle.
  				If creating a stream which should continue to exist after the
diff --git a/drivers/staging/imgtec/rogue/trace_events.c b/drivers/staging/imgtec/rogue/trace_events.c
index a75f005..34dd335 100644
--- a/drivers/staging/imgtec/rogue/trace_events.c
+++ b/drivers/staging/imgtec/rogue/trace_events.c
@@ -39,6 +39,7 @@
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
+#include <linux/version.h>
 #include <linux/sched.h>
 
 #include "img_types.h"
@@ -48,6 +49,60 @@
 #endif
 #include "rogue_trace_events.h"
 
+static bool fence_update_event_enabled, fence_check_event_enabled;
+
+bool trace_rogue_are_fence_updates_traced(void)
+{
+	return fence_update_event_enabled;
+}
+
+bool trace_rogue_are_fence_checks_traced(void)
+{
+	return fence_check_event_enabled;
+}
+
+/*
+ * Call backs referenced from rogue_trace_events.h. Note that these are not
+ * thread-safe, however, since running trace code when tracing is not enabled is
+ * simply a no-op, there is no harm in it.
+ */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+int trace_fence_update_enabled_callback(void)
+#else
+void trace_fence_update_enabled_callback(void)
+#endif
+{
+	fence_update_event_enabled = true;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+	return 0;
+#endif
+}
+
+void trace_fence_update_disabled_callback(void)
+{
+	fence_update_event_enabled = false;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+int trace_fence_check_enabled_callback(void)
+#else
+void trace_fence_check_enabled_callback(void)
+#endif
+{
+	fence_check_event_enabled = true;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+	return 0;
+#endif
+}
+
+void trace_fence_check_disabled_callback(void)
+{
+	fence_check_event_enabled = false;
+}
+
 /* This is a helper that calls trace_rogue_fence_update for each fence in an
  * array.
  */
@@ -156,4 +211,20 @@
 	}
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+
+int PVRGpuTraceEnableUfoCallbackWrapper(void)
+{
+	PVRGpuTraceEnableUfoCallback();
+
+	return 0;
+}
+
+int PVRGpuTraceEnableFirmwareActivityCallbackWrapper(void)
+{
+	PVRGpuTraceEnableFirmwareActivityCallback();
+
+	return 0;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) */
 #endif /* defined(SUPPORT_GPUTRACE_EVENTS) */
diff --git a/drivers/staging/imgtec/rogue/trace_events.h b/drivers/staging/imgtec/rogue/trace_events.h
index 8204c43..d822e52 100644
--- a/drivers/staging/imgtec/rogue/trace_events.h
+++ b/drivers/staging/imgtec/rogue/trace_events.h
@@ -50,6 +50,10 @@
  * defines for us.
  */
 #ifdef CONFIG_EVENT_TRACING
+bool trace_rogue_are_fence_checks_traced(void);
+
+bool trace_rogue_are_fence_updates_traced(void);
+
 void trace_rogue_fence_updates(const char *cmd, const char *dm,
 							   IMG_UINT32 ui32FWContext,
 							   IMG_UINT32 ui32Offset,
@@ -86,6 +90,18 @@
 
 #else  /* CONFIG_TRACE_EVENTS */
 static inline
+bool trace_rogue_are_fence_checks_traced(void)
+{
+	return false;
+}
+
+static inline
+bool trace_rogue_are_fence_updates_traced(void)
+{
+	return false;
+}
+
+static inline
 void trace_rogue_fence_updates(const char *cmd, const char *dm,
 							   IMG_UINT32 ui32FWContext,
 							   IMG_UINT32 ui32Offset,
diff --git a/drivers/staging/imgtec/services_kernel_client.h b/drivers/staging/imgtec/services_kernel_client.h
index 7a1ab69..b3d6230 100644
--- a/drivers/staging/imgtec/services_kernel_client.h
+++ b/drivers/staging/imgtec/services_kernel_client.h
@@ -1,3 +1,5 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
 /*************************************************************************/ /*!
 @File           services_kernel_client.h
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@@ -38,7 +40,6 @@
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
-/* vi: set ts=8: */
 
 /* This file contains a partial redefinition of the PowerVR Services 5
  * interface for use by components which are checkpatch clean. This
@@ -49,17 +50,16 @@
 #ifndef __SERVICES_KERNEL_CLIENT__
 #define __SERVICES_KERNEL_CLIENT__
 
-#include "debug_request_ids.h"
 #include "pvrsrv_error.h"
 
 #include <linux/types.h>
 
 #ifndef __pvrsrv_defined_struct_enum__
 
-/* pvrsrv_device_types.h */
+/* rgx_fwif_shared.h */
 
-enum PVRSRV_DEVICE_TYPE {
-	PVRSRV_DEVICE_TYPE_RGX = 10,
+struct _RGXFWIF_DEV_VIRTADDR_ {
+	__u32 ui32Addr;
 };
 
 /* sync_external.h */
@@ -77,54 +77,78 @@
 
 #else /* __pvrsrv_defined_struct_enum__ */
 
-enum PVRSRV_DEVICE_TYPE;
+struct _RGXFWIF_DEV_VIRTADDR_;
+
 struct PVRSRV_CLIENT_SYNC_PRIM;
 struct PVRSRV_CLIENT_SYNC_PRIM_OP;
 
 #endif /* __pvrsrv_defined_struct_enum__ */
 
+struct _PMR_;
 struct _PVRSRV_DEVICE_NODE_;
+struct dma_buf;
 struct SYNC_PRIM_CONTEXT;
 
-/* pvrsrv.h */
-
-#define DEBUG_REQUEST_VERBOSITY_LOW    0
-#define DEBUG_REQUEST_VERBOSITY_MEDIUM 1
-#define DEBUG_REQUEST_VERBOSITY_HIGH   2
-#define DEBUG_REQUEST_VERBOSITY_MAX    (DEBUG_REQUEST_VERBOSITY_HIGH)
-
-typedef void (DUMPDEBUG_PRINTF_FUNC)(void *pvDumpDebugFile, const char *fmt, ...) __printf(2, 3);
+/* pvr_notifier.h */
 
 typedef void (*PFN_CMDCOMP_NOTIFY)(void *hCmdCompHandle);
 enum PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(void **phNotify,
 	PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, void *hPrivData);
 enum PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(void *hNotify);
+void PVRSRVCheckStatus(void *hCmdCompCallerHandle);
+
+#define DEBUG_REQUEST_DC               0
+#define DEBUG_REQUEST_SERVERSYNC       1
+#define DEBUG_REQUEST_SYS              2
+#define DEBUG_REQUEST_ANDROIDSYNC      3
+#define DEBUG_REQUEST_LINUXFENCE       4
+#define DEBUG_REQUEST_SYNCCHECKPOINT   5
+#define DEBUG_REQUEST_HTB              6
+#define DEBUG_REQUEST_APPHINT          7
+
+#define DEBUG_REQUEST_VERBOSITY_LOW    0
+#define DEBUG_REQUEST_VERBOSITY_MEDIUM 1
+#define DEBUG_REQUEST_VERBOSITY_HIGH   2
+#define DEBUG_REQUEST_VERBOSITY_MAX    DEBUG_REQUEST_VERBOSITY_HIGH
+
+typedef void (DUMPDEBUG_PRINTF_FUNC)(void *pvDumpDebugFile,
+	const char *fmt, ...) __printf(2, 3);
 
 typedef void (*PFN_DBGREQ_NOTIFY) (void *hDebugRequestHandle,
 	__u32 ui32VerbLevel,
-	DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile);
+	DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+	void *pvDumpDebugFile);
 enum PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(void **phNotify,
+	struct _PVRSRV_DEVICE_NODE_ *psDevNode,
 	PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
-	__u32 ui32RequesterID, void *hDbgReqeustHandle);
+	__u32 ui32RequesterID,
+	void *hDbgRequestHandle);
 enum PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(void *hNotify);
 
-enum PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(__u32 ui32DevIndex,
-	enum PVRSRV_DEVICE_TYPE eDeviceType, void **phDevCookie);
-enum PVRSRV_ERROR PVRSRVReleaseDeviceDataKM(void *hDevCookie);
-void PVRSRVCheckStatus(void *hCmdCompCallerHandle);
-enum PVRSRV_ERROR AcquireGlobalEventObjectServer(void **phGlobalEventObject);
-enum PVRSRV_ERROR ReleaseGlobalEventObjectServer(void *hGlobalEventObject);
+/* physmem_dmabuf.h */
+
+struct dma_buf *PhysmemGetDmaBuf(struct _PMR_ *psPMR);
+
+/* pvrsrv.h */
+
+enum PVRSRV_ERROR PVRSRVAcquireGlobalEventObjectKM(void **phGlobalEventObject);
+enum PVRSRV_ERROR PVRSRVReleaseGlobalEventObjectKM(void *hGlobalEventObject);
 
 /* sync.h */
 
-enum PVRSRV_ERROR SyncPrimContextCreate(struct _PVRSRV_DEVICE_NODE_ *psDevConnection,
+enum PVRSRV_ERROR SyncPrimContextCreate(
+	struct _PVRSRV_DEVICE_NODE_ *psDevConnection,
 	struct SYNC_PRIM_CONTEXT **phSyncPrimContext);
 void SyncPrimContextDestroy(struct SYNC_PRIM_CONTEXT *hSyncPrimContext);
 
 enum PVRSRV_ERROR SyncPrimAlloc(struct SYNC_PRIM_CONTEXT *hSyncPrimContext,
-	struct PVRSRV_CLIENT_SYNC_PRIM **ppsSync, const char * pszClassName);
-void SyncPrimFree(struct PVRSRV_CLIENT_SYNC_PRIM *psSync);
-__u32 SyncPrimGetFirmwareAddr(struct PVRSRV_CLIENT_SYNC_PRIM *psSync);
+	struct PVRSRV_CLIENT_SYNC_PRIM **ppsSync, const char *pszClassName);
+enum PVRSRV_ERROR SyncPrimFree(struct PVRSRV_CLIENT_SYNC_PRIM *psSync);
+enum PVRSRV_ERROR SyncPrimGetFirmwareAddr(
+	struct PVRSRV_CLIENT_SYNC_PRIM *psSync,
+	__u32 *sync_addr);
+enum PVRSRV_ERROR SyncPrimSet(struct PVRSRV_CLIENT_SYNC_PRIM *psSync,
+	__u32 ui32Value);
 
 /* pdump_km.h */
 
@@ -141,14 +165,16 @@
 
 void OSAcquireBridgeLock(void);
 void OSReleaseBridgeLock(void);
-void PMRLock(void);
-void PMRUnlock(void);
 enum PVRSRV_ERROR OSEventObjectWait(void *hOSEventKM);
 enum PVRSRV_ERROR OSEventObjectOpen(void *hEventObject, void **phOSEventKM);
 enum PVRSRV_ERROR OSEventObjectClose(void *hOSEventKM);
 
 /* srvkm.h */
 
+enum PVRSRV_ERROR PVRSRVDeviceCreate(void *pvOSDevice,
+	struct _PVRSRV_DEVICE_NODE_ **ppsDeviceNode);
+enum PVRSRV_ERROR PVRSRVDeviceDestroy(
+	struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 const char *PVRSRVGetErrorStringKM(enum PVRSRV_ERROR eError);
 
 #endif /* __SERVICES_KERNEL_CLIENT__ */
diff --git a/fs/attr.c b/fs/attr.c
index 6a54f13..920e5bc 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -167,7 +167,7 @@
 }
 EXPORT_SYMBOL(setattr_copy);
 
-int notify_change(struct dentry * dentry, struct iattr * attr)
+int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr)
 {
 	struct inode *inode = dentry->d_inode;
 	umode_t mode = inode->i_mode;
@@ -244,7 +244,9 @@
 	if (error)
 		return error;
 
-	if (inode->i_op->setattr)
+	if (mnt && inode->i_op->setattr2)
+		error = inode->i_op->setattr2(mnt, dentry, attr);
+	else if (inode->i_op->setattr)
 		error = inode->i_op->setattr(dentry, attr);
 	else
 		error = simple_setattr(dentry, attr);
@@ -257,4 +259,10 @@
 
 	return error;
 }
+EXPORT_SYMBOL(notify_change2);
+
+int notify_change(struct dentry * dentry, struct iattr * attr)
+{
+	return notify_change2(NULL, dentry, attr);
+}
 EXPORT_SYMBOL(notify_change);
diff --git a/fs/coredump.c b/fs/coredump.c
index dafafba..6c5ce07 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -644,7 +644,7 @@
 			goto close_fail;
 		if (!cprm.file->f_op || !cprm.file->f_op->write)
 			goto close_fail;
-		if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file))
+		if (do_truncate2(cprm.file->f_path.mnt, cprm.file->f_path.dentry, 0, 0, cprm.file))
 			goto close_fail;
 	}
 
diff --git a/fs/exec.c b/fs/exec.c
index b23604c..fc5a628 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1100,7 +1100,7 @@
 
 void would_dump(struct linux_binprm *bprm, struct file *file)
 {
-	if (inode_permission(file_inode(file), MAY_READ) < 0)
+	if (inode_permission2(file->f_path.mnt, file_inode(file), MAY_READ) < 0)
 		bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
 }
 EXPORT_SYMBOL(would_dump);
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index d8ac61d..5a1bb82 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -127,6 +127,7 @@
 	}
 	return fs;
 }
+EXPORT_SYMBOL_GPL(copy_fs_struct);
 
 int unshare_fs_struct(void)
 {
diff --git a/fs/inode.c b/fs/inode.c
index 1eab5de..e7a0547 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1634,12 +1634,12 @@
 }
 EXPORT_SYMBOL(should_remove_suid);
 
-static int __remove_suid(struct dentry *dentry, int kill)
+static int __remove_suid(struct vfsmount *mnt, struct dentry *dentry, int kill)
 {
 	struct iattr newattrs;
 
 	newattrs.ia_valid = ATTR_FORCE | kill;
-	return notify_change(dentry, &newattrs);
+	return notify_change2(mnt, dentry, &newattrs);
 }
 
 int file_remove_suid(struct file *file)
@@ -1662,7 +1662,7 @@
 	if (killpriv)
 		error = security_inode_killpriv(dentry);
 	if (!error && killsuid)
-		error = __remove_suid(dentry, killsuid);
+		error = __remove_suid(file->f_path.mnt, dentry, killsuid);
 	if (!error && (inode->i_sb->s_flags & MS_NOSEC))
 		inode->i_flags |= S_NOSEC;
 
diff --git a/fs/internal.h b/fs/internal.h
index 6812158..8c89460 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -83,9 +83,11 @@
  * super.c
  */
 extern int do_remount_sb(struct super_block *, int, void *, int);
+extern int do_remount_sb2(struct vfsmount *, struct super_block *, int,
+								void *, int);
 extern bool grab_super_passive(struct super_block *sb);
 extern struct dentry *mount_fs(struct file_system_type *,
-			       int, const char *, void *);
+			       int, const char *, struct vfsmount *, void *);
 extern struct super_block *user_get_super(dev_t);
 
 /*
diff --git a/fs/namei.c b/fs/namei.c
index 9777ec1..6cfcfa8 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -355,9 +355,11 @@
  * flag in inode->i_opflags, that says "this has not special
  * permission function, use the fast case".
  */
-static inline int do_inode_permission(struct inode *inode, int mask)
+static inline int do_inode_permission(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) {
+		if (likely(mnt && inode->i_op->permission2))
+			return inode->i_op->permission2(mnt, inode, mask);
 		if (likely(inode->i_op->permission))
 			return inode->i_op->permission(inode, mask);
 
@@ -381,7 +383,7 @@
  * This does not check for a read-only file system.  You probably want
  * inode_permission().
  */
-int __inode_permission(struct inode *inode, int mask)
+int __inode_permission2(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	int retval;
 
@@ -393,7 +395,7 @@
 			return -EACCES;
 	}
 
-	retval = do_inode_permission(inode, mask);
+	retval = do_inode_permission(mnt, inode, mask);
 	if (retval)
 		return retval;
 
@@ -403,6 +405,13 @@
 
 	return security_inode_permission(inode, mask);
 }
+EXPORT_SYMBOL(__inode_permission2);
+
+int __inode_permission(struct inode *inode, int mask)
+{
+	return __inode_permission2(NULL, inode, mask);
+}
+EXPORT_SYMBOL(__inode_permission);
 
 /**
  * sb_permission - Check superblock-level permissions
@@ -436,15 +445,22 @@
  *
  * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
  */
-int inode_permission(struct inode *inode, int mask)
+int inode_permission2(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	int retval;
 
 	retval = sb_permission(inode->i_sb, inode, mask);
 	if (retval)
 		return retval;
-	return __inode_permission(inode, mask);
+	return __inode_permission2(mnt, inode, mask);
 }
+EXPORT_SYMBOL(inode_permission2);
+
+int inode_permission(struct inode *inode, int mask)
+{
+	return inode_permission2(NULL, inode, mask);
+}
+EXPORT_SYMBOL(inode_permission);
 
 /**
  * path_get - get a reference to a path
@@ -1459,13 +1475,13 @@
 static inline int may_lookup(struct nameidata *nd)
 {
 	if (nd->flags & LOOKUP_RCU) {
-		int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
+		int err = inode_permission2(nd->path.mnt, nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
 		if (err != -ECHILD)
 			return err;
 		if (unlazy_walk(nd, NULL))
 			return -ECHILD;
 	}
-	return inode_permission(nd->inode, MAY_EXEC);
+	return inode_permission2(nd->path.mnt, nd->inode, MAY_EXEC);
 }
 
 static inline int handle_dots(struct nameidata *nd, int type)
@@ -1840,10 +1856,11 @@
 	nd->depth = 0;
 	if (flags & LOOKUP_ROOT) {
 		struct inode *inode = nd->root.dentry->d_inode;
+		struct vfsmount *mnt = nd->root.mnt;
 		if (*name) {
 			if (!can_lookup(inode))
 				return -ENOTDIR;
-			retval = inode_permission(inode, MAY_EXEC);
+			retval = inode_permission2(mnt, inode, MAY_EXEC);
 			if (retval)
 				return retval;
 		}
@@ -2085,6 +2102,7 @@
 /**
  * lookup_one_len - filesystem helper to lookup single pathname component
  * @name:	pathname component to lookup
+ * @mnt:	mount we are looking up on
  * @base:	base directory to lookup from
  * @len:	maximum length @len should be interpreted to
  *
@@ -2093,7 +2111,7 @@
  * nameidata argument is passed to the filesystem methods and a filesystem
  * using this helper needs to be prepared for that.
  */
-struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
+struct dentry *lookup_one_len2(const char *name, struct vfsmount *mnt, struct dentry *base, int len)
 {
 	struct qstr this;
 	unsigned int c;
@@ -2127,12 +2145,19 @@
 			return ERR_PTR(err);
 	}
 
-	err = inode_permission(base->d_inode, MAY_EXEC);
+	err = inode_permission2(mnt, base->d_inode, MAY_EXEC);
 	if (err)
 		return ERR_PTR(err);
 
 	return __lookup_hash(&this, base, 0);
 }
+EXPORT_SYMBOL(lookup_one_len2);
+
+struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
+{
+	return lookup_one_len2(name, NULL, base, len);
+}
+EXPORT_SYMBOL(lookup_one_len);
 
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
 		 struct path *path, int *empty)
@@ -2222,7 +2247,7 @@
  * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
  *     nfs_async_unlink().
  */
-static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
+static int may_delete(struct vfsmount *mnt, struct inode *dir,struct dentry *victim,int isdir)
 {
 	int error;
 
@@ -2232,7 +2257,7 @@
 	BUG_ON(victim->d_parent->d_inode != dir);
 	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
-	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	error = inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
 	if (IS_APPEND(dir))
@@ -2262,13 +2287,13 @@
  *  3. We should have write and exec permissions on dir
  *  4. We can't do it if dir is immutable (done in permission())
  */
-static inline int may_create(struct inode *dir, struct dentry *child)
+static inline int may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child)
 {
 	if (child->d_inode)
 		return -EEXIST;
 	if (IS_DEADDIR(dir))
 		return -ENOENT;
-	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	return inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC);
 }
 
 /*
@@ -2313,10 +2338,10 @@
 	}
 }
 
-int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-		bool want_excl)
+int vfs_create2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry,
+		umode_t mode, bool want_excl)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 	if (error)
 		return error;
 
@@ -2332,10 +2357,19 @@
 		fsnotify_create(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_create2);
+
+int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+		bool want_excl)
+{
+	return vfs_create2(NULL, dir, dentry, mode, want_excl);
+}
+EXPORT_SYMBOL(vfs_create);
 
 static int may_open(struct path *path, int acc_mode, int flag)
 {
 	struct dentry *dentry = path->dentry;
+	struct vfsmount *mnt = path->mnt;
 	struct inode *inode = dentry->d_inode;
 	int error;
 
@@ -2364,7 +2398,7 @@
 		break;
 	}
 
-	error = inode_permission(inode, acc_mode);
+	error = inode_permission2(mnt, inode, acc_mode);
 	if (error)
 		return error;
 
@@ -2399,7 +2433,7 @@
 	if (!error)
 		error = security_path_truncate(path);
 	if (!error) {
-		error = do_truncate(path->dentry, 0,
+		error = do_truncate2(path->mnt, path->dentry, 0,
 				    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
 				    filp);
 	}
@@ -2420,7 +2454,7 @@
 	if (error)
 		return error;
 
-	error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
+	error = inode_permission2(dir->mnt, dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
 
@@ -2608,6 +2642,7 @@
 			bool got_write, int *opened)
 {
 	struct dentry *dir = nd->path.dentry;
+	struct vfsmount *mnt = nd->path.mnt;
 	struct inode *dir_inode = dir->d_inode;
 	struct dentry *dentry;
 	int error;
@@ -2655,7 +2690,7 @@
 		error = security_path_mknod(&nd->path, dentry, mode, 0);
 		if (error)
 			goto out_dput;
-		error = vfs_create(dir->d_inode, dentry, mode,
+		error = vfs_create2(mnt, dir->d_inode, dentry, mode,
 				   nd->flags & LOOKUP_EXCL);
 		if (error)
 			goto out_dput;
@@ -3116,9 +3151,9 @@
 }
 EXPORT_SYMBOL(user_path_create);
 
-int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
+int vfs_mknod2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 
 	if (error)
 		return error;
@@ -3142,6 +3177,13 @@
 		fsnotify_create(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_mknod2);
+
+int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
+{
+	return vfs_mknod2(NULL, dir, dentry, mode, dev);
+}
+EXPORT_SYMBOL(vfs_mknod);
 
 static int may_mknod(umode_t mode)
 {
@@ -3183,10 +3225,10 @@
 		goto out;
 	switch (mode & S_IFMT) {
 		case 0: case S_IFREG:
-			error = vfs_create(path.dentry->d_inode,dentry,mode,true);
+			error = vfs_create2(path.mnt, path.dentry->d_inode,dentry,mode,true);
 			break;
 		case S_IFCHR: case S_IFBLK:
-			error = vfs_mknod(path.dentry->d_inode,dentry,mode,
+			error = vfs_mknod2(path.mnt, path.dentry->d_inode,dentry,mode,
 					new_decode_dev(dev));
 			break;
 		case S_IFIFO: case S_IFSOCK:
@@ -3207,9 +3249,9 @@
 	return sys_mknodat(AT_FDCWD, filename, mode, dev);
 }
 
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+int vfs_mkdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 	unsigned max_links = dir->i_sb->s_max_links;
 
 	if (error)
@@ -3231,6 +3273,13 @@
 		fsnotify_mkdir(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_mkdir2);
+
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	return vfs_mkdir2(NULL, dir, dentry, mode);
+}
+EXPORT_SYMBOL(vfs_mkdir);
 
 SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
 {
@@ -3248,7 +3297,7 @@
 		mode &= ~current_umask();
 	error = security_path_mkdir(&path, dentry, mode);
 	if (!error)
-		error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+		error = vfs_mkdir2(path.mnt, path.dentry->d_inode, dentry, mode);
 	done_path_create(&path, dentry);
 	if (retry_estale(error, lookup_flags)) {
 		lookup_flags |= LOOKUP_REVAL;
@@ -3286,9 +3335,9 @@
 	spin_unlock(&dentry->d_lock);
 }
 
-int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+int vfs_rmdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry)
 {
-	int error = may_delete(dir, dentry, 1);
+	int error = may_delete(mnt, dir, dentry, 1);
 
 	if (error)
 		return error;
@@ -3322,6 +3371,13 @@
 		d_delete(dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_rmdir2);
+
+int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	return vfs_rmdir2(NULL, dir, dentry);
+}
+EXPORT_SYMBOL(vfs_rmdir);
 
 static long do_rmdir(int dfd, const char __user *pathname)
 {
@@ -3364,7 +3420,7 @@
 	error = security_path_rmdir(&nd.path, dentry);
 	if (error)
 		goto exit3;
-	error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
+	error = vfs_rmdir2(nd.path.mnt, nd.path.dentry->d_inode, dentry);
 exit3:
 	dput(dentry);
 exit2:
@@ -3385,9 +3441,9 @@
 	return do_rmdir(AT_FDCWD, pathname);
 }
 
-int vfs_unlink(struct inode *dir, struct dentry *dentry)
+int vfs_unlink2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry)
 {
-	int error = may_delete(dir, dentry, 0);
+	int error = may_delete(mnt, dir, dentry, 0);
 
 	if (error)
 		return error;
@@ -3416,6 +3472,13 @@
 
 	return error;
 }
+EXPORT_SYMBOL(vfs_unlink2);
+
+int vfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	return vfs_unlink2(NULL, dir, dentry);
+}
+EXPORT_SYMBOL(vfs_unlink);
 
 /*
  * Make sure that the actual truncation of the file will occur outside its
@@ -3459,7 +3522,7 @@
 		error = security_path_unlink(&nd.path, dentry);
 		if (error)
 			goto exit2;
-		error = vfs_unlink(nd.path.dentry->d_inode, dentry);
+		error = vfs_unlink2(nd.path.mnt, nd.path.dentry->d_inode, dentry);
 exit2:
 		dput(dentry);
 	}
@@ -3499,9 +3562,9 @@
 	return do_unlinkat(AT_FDCWD, pathname);
 }
 
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
+int vfs_symlink2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, const char *oldname)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 
 	if (error)
 		return error;
@@ -3518,6 +3581,13 @@
 		fsnotify_create(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_symlink2);
+
+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
+{
+	return vfs_symlink2(NULL, dir, dentry, oldname);
+}
+EXPORT_SYMBOL(vfs_symlink);
 
 SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
 		int, newdfd, const char __user *, newname)
@@ -3539,7 +3609,7 @@
 
 	error = security_path_symlink(&path, dentry, from->name);
 	if (!error)
-		error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
+		error = vfs_symlink2(path.mnt, path.dentry->d_inode, dentry, from->name);
 	done_path_create(&path, dentry);
 	if (retry_estale(error, lookup_flags)) {
 		lookup_flags |= LOOKUP_REVAL;
@@ -3555,7 +3625,7 @@
 	return sys_symlinkat(oldname, AT_FDCWD, newname);
 }
 
-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+int vfs_link2(struct vfsmount *mnt, struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
 	unsigned max_links = dir->i_sb->s_max_links;
@@ -3564,7 +3634,7 @@
 	if (!inode)
 		return -ENOENT;
 
-	error = may_create(dir, new_dentry);
+	error = may_create(mnt, dir, new_dentry);
 	if (error)
 		return error;
 
@@ -3598,6 +3668,13 @@
 		fsnotify_link(dir, inode, new_dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_link2);
+
+int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+{
+	return vfs_link2(NULL, old_dentry, dir, new_dentry);
+}
+EXPORT_SYMBOL(vfs_link);
 
 /*
  * Hardlinks are often used in delicate situations.  We avoid
@@ -3651,7 +3728,7 @@
 	error = security_path_link(old_path.dentry, &new_path, new_dentry);
 	if (error)
 		goto out_dput;
-	error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry);
+	error = vfs_link2(old_path.mnt, old_path.dentry, new_path.dentry->d_inode, new_dentry);
 out_dput:
 	done_path_create(&new_path, new_dentry);
 	if (retry_estale(error, how)) {
@@ -3696,8 +3773,9 @@
  *	   ->i_mutex on parents, which works but leads to some truly excessive
  *	   locking].
  */
-static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-			  struct inode *new_dir, struct dentry *new_dentry)
+static int vfs_rename_dir(struct vfsmount *mnt,
+	       struct inode *old_dir, struct dentry *old_dentry,
+	       struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error = 0;
 	struct inode *target = new_dentry->d_inode;
@@ -3708,7 +3786,7 @@
 	 * we'll need to flip '..'.
 	 */
 	if (new_dir != old_dir) {
-		error = inode_permission(old_dentry->d_inode, MAY_WRITE);
+		error = inode_permission2(mnt, old_dentry->d_inode, MAY_WRITE);
 		if (error)
 			return error;
 	}
@@ -3783,7 +3861,8 @@
 	return error;
 }
 
-int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+int vfs_rename2(struct vfsmount *mnt,
+	       struct inode *old_dir, struct dentry *old_dentry,
 	       struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error;
@@ -3793,14 +3872,14 @@
 	if (old_dentry->d_inode == new_dentry->d_inode)
  		return 0;
  
-	error = may_delete(old_dir, old_dentry, is_dir);
+	error = may_delete(mnt, old_dir, old_dentry, is_dir);
 	if (error)
 		return error;
 
 	if (!new_dentry->d_inode)
-		error = may_create(new_dir, new_dentry);
+		error = may_create(mnt, new_dir, new_dentry);
 	else
-		error = may_delete(new_dir, new_dentry, is_dir);
+		error = may_delete(mnt, new_dir, new_dentry, is_dir);
 	if (error)
 		return error;
 
@@ -3810,7 +3889,7 @@
 	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
 
 	if (is_dir)
-		error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
+		error = vfs_rename_dir(mnt, old_dir,old_dentry,new_dir,new_dentry);
 	else
 		error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
 	if (!error)
@@ -3820,6 +3899,14 @@
 
 	return error;
 }
+EXPORT_SYMBOL(vfs_rename2);
+
+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+	       struct inode *new_dir, struct dentry *new_dentry)
+{
+	return vfs_rename2(NULL, old_dir, old_dentry, new_dir, new_dentry);
+}
+EXPORT_SYMBOL(vfs_rename);
 
 SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
 		int, newdfd, const char __user *, newname)
@@ -3902,7 +3989,7 @@
 				     &newnd.path, new_dentry);
 	if (error)
 		goto exit5;
-	error = vfs_rename(old_dir->d_inode, old_dentry,
+	error = vfs_rename2(oldnd.path.mnt, old_dir->d_inode, old_dentry,
 				   new_dir->d_inode, new_dentry);
 exit5:
 	dput(new_dentry);
@@ -4076,7 +4163,6 @@
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* nfsd */
 EXPORT_SYMBOL(lock_rename);
-EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);
 EXPORT_SYMBOL(page_readlink);
@@ -4085,18 +4171,9 @@
 EXPORT_SYMBOL(page_symlink_inode_operations);
 EXPORT_SYMBOL(kern_path);
 EXPORT_SYMBOL(vfs_path_lookup);
-EXPORT_SYMBOL(inode_permission);
 EXPORT_SYMBOL(unlock_rename);
-EXPORT_SYMBOL(vfs_create);
 EXPORT_SYMBOL(vfs_follow_link);
-EXPORT_SYMBOL(vfs_link);
-EXPORT_SYMBOL(vfs_mkdir);
-EXPORT_SYMBOL(vfs_mknod);
 EXPORT_SYMBOL(generic_permission);
 EXPORT_SYMBOL(vfs_readlink);
-EXPORT_SYMBOL(vfs_rename);
-EXPORT_SYMBOL(vfs_rmdir);
-EXPORT_SYMBOL(vfs_symlink);
-EXPORT_SYMBOL(vfs_unlink);
 EXPORT_SYMBOL(dentry_unhash);
 EXPORT_SYMBOL(generic_readlink);
diff --git a/fs/namespace.c b/fs/namespace.c
index a45ba4f..850699b 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -541,6 +541,7 @@
 
 static void free_vfsmnt(struct mount *mnt)
 {
+	kfree(mnt->mnt.data);
 	kfree(mnt->mnt_devname);
 	mnt_free_id(mnt);
 #ifdef CONFIG_SMP
@@ -784,11 +785,21 @@
 	if (!mnt)
 		return ERR_PTR(-ENOMEM);
 
+	mnt->mnt.data = NULL;
+	if (type->alloc_mnt_data) {
+		mnt->mnt.data = type->alloc_mnt_data();
+		if (!mnt->mnt.data) {
+			mnt_free_id(mnt);
+			free_vfsmnt(mnt);
+			return ERR_PTR(-ENOMEM);
+		}
+	}
 	if (flags & MS_KERNMOUNT)
 		mnt->mnt.mnt_flags = MNT_INTERNAL;
 
-	root = mount_fs(type, flags, name, data);
+	root = mount_fs(type, flags, name, &mnt->mnt, data);
 	if (IS_ERR(root)) {
+		kfree(mnt->mnt.data);
 		free_vfsmnt(mnt);
 		return ERR_CAST(root);
 	}
@@ -815,6 +826,14 @@
 	if (!mnt)
 		return ERR_PTR(-ENOMEM);
 
+	if (sb->s_op->clone_mnt_data) {
+		mnt->mnt.data = sb->s_op->clone_mnt_data(old->mnt.data);
+		if (!mnt->mnt.data) {
+			err = -ENOMEM;
+			goto out_free;
+		}
+	}
+
 	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
 		mnt->mnt_group_id = 0; /* not a peer of original */
 	else
@@ -826,7 +845,7 @@
 			goto out_free;
 	}
 
-	mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
+	mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED);
 	/* Don't allow unprivileged users to change mount flags */
 	if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
 		mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
@@ -865,6 +884,7 @@
 	return mnt;
 
  out_free:
+	kfree(mnt->mnt.data);
 	free_vfsmnt(mnt);
 	return ERR_PTR(err);
 }
@@ -1560,16 +1580,14 @@
 		err = invent_group_ids(source_mnt, true);
 		if (err)
 			goto out;
-	}
-	err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
-	if (err)
-		goto out_cleanup_ids;
-
-	br_write_lock(&vfsmount_lock);
-
-	if (IS_MNT_SHARED(dest_mnt)) {
+		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
+		br_write_lock(&vfsmount_lock);
+		if (err)
+			goto out_cleanup_ids;
 		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
 			set_mnt_shared(p);
+	} else {
+		br_write_lock(&vfsmount_lock);
 	}
 	if (parent_path) {
 		detach_mnt(source_mnt, parent_path);
@@ -1589,8 +1607,12 @@
 	return 0;
 
  out_cleanup_ids:
-	if (IS_MNT_SHARED(dest_mnt))
-		cleanup_group_ids(source_mnt, NULL);
+	while (!list_empty(&tree_list)) {
+		child = list_first_entry(&tree_list, struct mount, mnt_hash);
+		umount_tree(child, 0);
+	}
+	br_write_unlock(&vfsmount_lock);
+	cleanup_group_ids(source_mnt, NULL);
  out:
 	return err;
 }
@@ -1801,8 +1823,14 @@
 		err = change_mount_flags(path->mnt, flags);
 	else if (!capable(CAP_SYS_ADMIN))
 		err = -EPERM;
-	else
-		err = do_remount_sb(sb, flags, data, 0);
+	else {
+		err = do_remount_sb2(path->mnt, sb, flags, data, 0);
+		namespace_lock();
+		br_write_lock(&vfsmount_lock);
+		propagate_remount(mnt);
+		br_write_unlock(&vfsmount_lock);
+		namespace_unlock();
+	}
 	if (!err) {
 		br_write_lock(&vfsmount_lock);
 		mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
@@ -1927,7 +1955,7 @@
 	struct mount *parent;
 	int err;
 
-	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
+	mnt_flags &= ~MNT_INTERNAL_FLAGS;
 
 	mp = lock_mount(path);
 	if (IS_ERR(mp))
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 77cc85d..f8ec754 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -490,7 +490,7 @@
 	}
 
 	/* you can only watch an inode if you have read permissions on it */
-	ret = inode_permission(path->dentry->d_inode, MAY_READ);
+	ret = inode_permission2(path->mnt, path->dentry->d_inode, MAY_READ);
 	if (ret)
 		path_put(path);
 out:
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index fce2b85..941e59d 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -349,7 +349,7 @@
 	if (error)
 		return error;
 	/* you can only watch an inode if you have read permissions on it */
-	error = inode_permission(path->dentry->d_inode, MAY_READ);
+	error = inode_permission2(path->mnt, path->dentry->d_inode, MAY_READ);
 	if (error)
 		path_put(path);
 	return error;
diff --git a/fs/open.c b/fs/open.c
index 8c74100..a02d9a9 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -34,8 +34,8 @@
 
 #include "internal.h"
 
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
-	struct file *filp)
+int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
+		unsigned int time_attrs, struct file *filp)
 {
 	int ret;
 	struct iattr newattrs;
@@ -57,17 +57,24 @@
 		newattrs.ia_valid |= ret | ATTR_FORCE;
 
 	mutex_lock(&dentry->d_inode->i_mutex);
-	ret = notify_change(dentry, &newattrs);
+	ret = notify_change2(mnt, dentry, &newattrs);
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	return ret;
 }
+int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+	struct file *filp)
+{
+	return do_truncate2(NULL, dentry, length, time_attrs, filp);
+}
 
 long vfs_truncate(struct path *path, loff_t length)
 {
 	struct inode *inode;
+	struct vfsmount *mnt;
 	long error;
 
 	inode = path->dentry->d_inode;
+	mnt = path->mnt;
 
 	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
 	if (S_ISDIR(inode->i_mode))
@@ -79,7 +86,7 @@
 	if (error)
 		goto out;
 
-	error = inode_permission(inode, MAY_WRITE);
+	error = inode_permission2(mnt, inode, MAY_WRITE);
 	if (error)
 		goto mnt_drop_write_and_out;
 
@@ -103,7 +110,7 @@
 	if (!error)
 		error = security_path_truncate(path);
 	if (!error)
-		error = do_truncate(path->dentry, length, 0, NULL);
+		error = do_truncate2(mnt, path->dentry, length, 0, NULL);
 
 put_write_and_out:
 	put_write_access(inode);
@@ -152,6 +159,7 @@
 {
 	struct inode *inode;
 	struct dentry *dentry;
+	struct vfsmount *mnt;
 	struct fd f;
 	int error;
 
@@ -168,6 +176,7 @@
 		small = 0;
 
 	dentry = f.file->f_path.dentry;
+	mnt = f.file->f_path.mnt;
 	inode = dentry->d_inode;
 	error = -EINVAL;
 	if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
@@ -187,7 +196,7 @@
 	if (!error)
 		error = security_path_truncate(&f.file->f_path);
 	if (!error)
-		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
+		error = do_truncate2(mnt, dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
 	sb_end_write(inode->i_sb);
 out_putf:
 	fdput(f);
@@ -302,6 +311,7 @@
 	struct cred *override_cred;
 	struct path path;
 	struct inode *inode;
+	struct vfsmount *mnt;
 	int res;
 	unsigned int lookup_flags = LOOKUP_FOLLOW;
 
@@ -332,6 +342,7 @@
 		goto out;
 
 	inode = path.dentry->d_inode;
+	mnt = path.mnt;
 
 	if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
 		/*
@@ -343,7 +354,7 @@
 			goto out_path_release;
 	}
 
-	res = inode_permission(inode, mode | MAY_ACCESS);
+	res = inode_permission2(mnt, inode, mode | MAY_ACCESS);
 	/* SuS v2 requires we report a read only fs too */
 	if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
 		goto out_path_release;
@@ -387,7 +398,7 @@
 	if (error)
 		goto out;
 
-	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
+	error = inode_permission2(path.mnt, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
 	if (error)
 		goto dput_and_out;
 
@@ -407,6 +418,7 @@
 {
 	struct fd f = fdget_raw(fd);
 	struct inode *inode;
+	struct vfsmount *mnt;
 	int error = -EBADF;
 
 	error = -EBADF;
@@ -414,12 +426,13 @@
 		goto out;
 
 	inode = file_inode(f.file);
+	mnt = f.file->f_path.mnt;
 
 	error = -ENOTDIR;
 	if (!S_ISDIR(inode->i_mode))
 		goto out_putf;
 
-	error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
+	error = inode_permission2(mnt, inode, MAY_EXEC | MAY_CHDIR);
 	if (!error)
 		set_fs_pwd(current->fs, &f.file->f_path);
 out_putf:
@@ -438,7 +451,7 @@
 	if (error)
 		goto out;
 
-	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
+	error = inode_permission2(path.mnt, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
 	if (error)
 		goto dput_and_out;
 
@@ -476,7 +489,7 @@
 		goto out_unlock;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	error = notify_change(path->dentry, &newattrs);
+	error = notify_change2(path->mnt, path->dentry, &newattrs);
 out_unlock:
 	mutex_unlock(&inode->i_mutex);
 	mnt_drop_write(path->mnt);
@@ -550,7 +563,7 @@
 	mutex_lock(&inode->i_mutex);
 	error = security_path_chown(path, uid, gid);
 	if (!error)
-		error = notify_change(path->dentry, &newattrs);
+		error = notify_change2(path->mnt, path->dentry, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 
 	return error;
diff --git a/fs/pnode.c b/fs/pnode.c
index 9af0df1..e8d7d68 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -164,46 +164,94 @@
 	}
 }
 
-/*
- * return the source mount to be used for cloning
- *
- * @dest 	the current destination mount
- * @last_dest  	the last seen destination mount
- * @last_src  	the last seen source mount
- * @type	return CL_SLAVE if the new mount has to be
- * 		cloned as a slave.
- */
-static struct mount *get_source(struct mount *dest,
-				struct mount *last_dest,
-				struct mount *last_src,
-				int *type)
+static struct mount *next_group(struct mount *m, struct mount *origin)
 {
-	struct mount *p_last_src = NULL;
-	struct mount *p_last_dest = NULL;
-
-	while (last_dest != dest->mnt_master) {
-		p_last_dest = last_dest;
-		p_last_src = last_src;
-		last_dest = last_dest->mnt_master;
-		last_src = last_src->mnt_master;
-	}
-
-	if (p_last_dest) {
-		do {
-			p_last_dest = next_peer(p_last_dest);
-		} while (IS_MNT_NEW(p_last_dest));
-		/* is that a peer of the earlier? */
-		if (dest == p_last_dest) {
-			*type = CL_MAKE_SHARED;
-			return p_last_src;
+	while (1) {
+		while (1) {
+			struct mount *next;
+			if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
+				return first_slave(m);
+			next = next_peer(m);
+			if (m->mnt_group_id == origin->mnt_group_id) {
+				if (next == origin)
+					return NULL;
+			} else if (m->mnt_slave.next != &next->mnt_slave)
+				break;
+			m = next;
 		}
+		/* m is the last peer */
+		while (1) {
+			struct mount *master = m->mnt_master;
+			if (m->mnt_slave.next != &master->mnt_slave_list)
+				return next_slave(m);
+			m = next_peer(master);
+			if (master->mnt_group_id == origin->mnt_group_id)
+				break;
+			if (master->mnt_slave.next == &m->mnt_slave)
+				break;
+			m = master;
+		}
+		if (m == origin)
+			return NULL;
 	}
-	/* slave of the earlier, then */
-	*type = CL_SLAVE;
-	/* beginning of peer group among the slaves? */
-	if (IS_MNT_SHARED(dest))
-		*type |= CL_MAKE_SHARED;
-	return last_src;
+}
+
+/* all accesses are serialized by namespace_sem */
+static struct user_namespace *user_ns;
+static struct mount *last_dest, *last_source, *dest_master;
+static struct mountpoint *mp;
+static struct list_head *list;
+
+static int propagate_one(struct mount *m)
+{
+	struct mount *child;
+	int type;
+	/* skip ones added by this propagate_mnt() */
+	if (IS_MNT_NEW(m))
+		return 0;
+	/* skip if mountpoint isn't covered by it */
+	if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
+		return 0;
+	if (m->mnt_group_id == last_dest->mnt_group_id) {
+		type = CL_MAKE_SHARED;
+	} else {
+		struct mount *n, *p;
+		for (n = m; ; n = p) {
+			p = n->mnt_master;
+			if (p == dest_master || IS_MNT_MARKED(p)) {
+				while (last_dest->mnt_master != p) {
+					last_source = last_source->mnt_master;
+					last_dest = last_source->mnt_parent;
+				}
+				if (n->mnt_group_id != last_dest->mnt_group_id) {
+					last_source = last_source->mnt_master;
+					last_dest = last_source->mnt_parent;
+				}
+				break;
+			}
+		}
+		type = CL_SLAVE;
+		/* beginning of peer group among the slaves? */
+		if (IS_MNT_SHARED(m))
+			type |= CL_MAKE_SHARED;
+	}
+		
+	/* Notice when we are propagating across user namespaces */
+	if (m->mnt_ns->user_ns != user_ns)
+		type |= CL_UNPRIVILEGED;
+	child = copy_tree(last_source, last_source->mnt.mnt_root, type);
+	if (IS_ERR(child))
+		return PTR_ERR(child);
+	mnt_set_mountpoint(m, mp, child);
+	last_dest = m;
+	last_source = child;
+	if (m->mnt_master != dest_master) {
+		br_write_lock(&vfsmount_lock);
+		SET_MNT_MARK(m->mnt_master);
+		br_write_unlock(&vfsmount_lock);
+	}
+	list_add_tail(&child->mnt_hash, list);
+	return 0;
 }
 
 /*
@@ -222,52 +270,46 @@
 int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
 		    struct mount *source_mnt, struct list_head *tree_list)
 {
-	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
-	struct mount *m, *child;
+	struct mount *m, *n;
 	int ret = 0;
-	struct mount *prev_dest_mnt = dest_mnt;
-	struct mount *prev_src_mnt  = source_mnt;
-	LIST_HEAD(tmp_list);
 
-	for (m = propagation_next(dest_mnt, dest_mnt); m;
-			m = propagation_next(m, dest_mnt)) {
-		int type;
-		struct mount *source;
+	/*
+	 * we don't want to bother passing tons of arguments to
+	 * propagate_one(); everything is serialized by namespace_sem,
+	 * so globals will do just fine.
+	 */
+	user_ns = current->nsproxy->mnt_ns->user_ns;
+	last_dest = dest_mnt;
+	last_source = source_mnt;
+	mp = dest_mp;
+	list = tree_list;
+	dest_master = dest_mnt->mnt_master;
 
-		if (IS_MNT_NEW(m))
-			continue;
-
-		source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
-
-		/* Notice when we are propagating across user namespaces */
-		if (m->mnt_ns->user_ns != user_ns)
-			type |= CL_UNPRIVILEGED;
-
-		child = copy_tree(source, source->mnt.mnt_root, type);
-		if (IS_ERR(child)) {
-			ret = PTR_ERR(child);
-			list_splice(tree_list, tmp_list.prev);
+	/* all peers of dest_mnt, except dest_mnt itself */
+	for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
+		ret = propagate_one(n);
+		if (ret)
 			goto out;
-		}
+	}
 
-		if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
-			mnt_set_mountpoint(m, dest_mp, child);
-			list_add_tail(&child->mnt_hash, tree_list);
-		} else {
-			/*
-			 * This can happen if the parent mount was bind mounted
-			 * on some subdirectory of a shared/slave mount.
-			 */
-			list_add_tail(&child->mnt_hash, &tmp_list);
-		}
-		prev_dest_mnt = m;
-		prev_src_mnt  = child;
+	/* all slave groups */
+	for (m = next_group(dest_mnt, dest_mnt); m;
+			m = next_group(m, dest_mnt)) {
+		/* everything in that slave group */
+		n = m;
+		do {
+			ret = propagate_one(n);
+			if (ret)
+				goto out;
+			n = next_peer(n);
+		} while (n != m);
 	}
 out:
 	br_write_lock(&vfsmount_lock);
-	while (!list_empty(&tmp_list)) {
-		child = list_first_entry(&tmp_list, struct mount, mnt_hash);
-		umount_tree(child, 0);
+	list_for_each_entry(n, tree_list, mnt_hash) {
+		m = n->mnt_parent;
+		if (m->mnt_master != dest_mnt->mnt_master)
+			CLEAR_MNT_MARK(m->mnt_master);
 	}
 	br_write_unlock(&vfsmount_lock);
 	return ret;
@@ -359,3 +401,37 @@
 		__propagate_umount(mnt);
 	return 0;
 }
+
+/*
+ *  Iterates over all slaves, and slaves of slaves.
+ */
+static struct mount *next_descendent(struct mount *root, struct mount *cur)
+{
+	if (!IS_MNT_NEW(cur) && !list_empty(&cur->mnt_slave_list))
+		return first_slave(cur);
+	do {
+		struct mount *master = cur->mnt_master;
+
+		if (!master || cur->mnt_slave.next != &master->mnt_slave_list) {
+			struct mount *next = next_slave(cur);
+
+			return (next == root) ? NULL : next;
+		}
+		cur = master;
+	} while (cur != root);
+	return NULL;
+}
+
+void propagate_remount(struct mount *mnt)
+{
+	struct mount *m = mnt;
+	struct super_block *sb = mnt->mnt.mnt_sb;
+
+	if (sb->s_op->copy_mnt_data) {
+		m = next_descendent(mnt, m);
+		while (m) {
+			sb->s_op->copy_mnt_data(m->mnt.data, mnt->mnt.data);
+			m = next_descendent(mnt, m);
+		}
+	}
+}
diff --git a/fs/pnode.h b/fs/pnode.h
index b091445..e16e597 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -16,6 +16,9 @@
 #define IS_MNT_NEW(m)  (!(m)->mnt_ns)
 #define CLEAR_MNT_SHARED(m) ((m)->mnt.mnt_flags &= ~MNT_SHARED)
 #define IS_MNT_UNBINDABLE(m) ((m)->mnt.mnt_flags & MNT_UNBINDABLE)
+#define IS_MNT_MARKED(m) ((m)->mnt.mnt_flags & MNT_MARKED)
+#define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED)
+#define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED)
 
 #define CL_EXPIRE    		0x01
 #define CL_SLAVE     		0x02
@@ -36,6 +39,7 @@
 		struct list_head *);
 int propagate_umount(struct list_head *);
 int propagate_mount_busy(struct mount *, int);
+void propagate_remount(struct mount *);
 void mnt_release_group_id(struct mount *);
 int get_dominating_id(struct mount *mnt, const struct path *root);
 unsigned int mnt_get_count(struct mount *mnt);
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 05dff1c..f5fa4e7 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -316,7 +316,8 @@
 static inline void task_cap(struct seq_file *m, struct task_struct *p)
 {
 	const struct cred *cred;
-	kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
+	kernel_cap_t cap_inheritable, cap_permitted, cap_effective,
+			cap_bset, cap_ambient;
 
 	rcu_read_lock();
 	cred = __task_cred(p);
@@ -324,6 +325,7 @@
 	cap_permitted	= cred->cap_permitted;
 	cap_effective	= cred->cap_effective;
 	cap_bset	= cred->cap_bset;
+	cap_ambient	= cred->cap_ambient;
 	rcu_read_unlock();
 
 	NORM_CAPS(cap_inheritable);
@@ -335,6 +337,7 @@
 	render_cap_t(m, "CapPrm:\t", &cap_permitted);
 	render_cap_t(m, "CapEff:\t", &cap_effective);
 	render_cap_t(m, "CapBnd:\t", &cap_bset);
+	render_cap_t(m, "CapAmb:\t", &cap_ambient);
 }
 
 static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index de8ab82..6949753 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -3010,6 +3010,44 @@
 }
 
 /*
+ * proc_tid_comm_permission is a special permission function exclusively
+ * used for the node /proc/<pid>/task/<tid>/comm.
+ * It bypasses generic permission checks in the case where a task of the same
+ * task group attempts to access the node.
+ * The rational behind this is that glibc and bionic access this node for
+ * cross thread naming (pthread_set/getname_np(!self)). However, if
+ * PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
+ * which locks out the cross thread naming implementation.
+ * This function makes sure that the node is always accessible for members of
+ * same thread group.
+ */
+static int proc_tid_comm_permission(struct inode *inode, int mask)
+{
+	bool is_same_tgroup;
+	struct task_struct *task;
+
+	task = get_proc_task(inode);
+	if (!task)
+		return -ESRCH;
+	is_same_tgroup = same_thread_group(current, task);
+	put_task_struct(task);
+
+	if (likely(is_same_tgroup && !(mask & MAY_EXEC))) {
+		/* This file (/proc/<pid>/task/<tid>/comm) can always be
+		 * read or written by the members of the corresponding
+		 * thread group.
+		 */
+		return 0;
+	}
+
+	return generic_permission(inode, mask);
+}
+
+static const struct inode_operations proc_tid_comm_inode_operations = {
+		.permission = proc_tid_comm_permission,
+};
+
+/*
  * Tasks
  */
 static const struct pid_entry tid_base_stuff[] = {
@@ -3024,7 +3062,9 @@
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
-	REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
+	NOD("comm",      S_IFREG|S_IRUGO|S_IWUSR,
+			 &proc_tid_comm_inode_operations,
+			 &proc_pid_set_comm_operations, {}),
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 	INF("syscall",   S_IRUGO, proc_pid_syscall),
 #endif
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index 5fe34c3..9243966 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -112,7 +112,9 @@
 	if (err)
 		goto out;
 	show_mnt_opts(m, mnt);
-	if (sb->s_op->show_options)
+	if (sb->s_op->show_options2)
+			err = sb->s_op->show_options2(mnt, m, mnt_path.dentry);
+	else if (sb->s_op->show_options)
 		err = sb->s_op->show_options(m, mnt_path.dentry);
 	seq_puts(m, " 0 0\n");
 out:
@@ -173,7 +175,9 @@
 	err = show_sb_opts(m, sb);
 	if (err)
 		goto out;
-	if (sb->s_op->show_options)
+	if (sb->s_op->show_options2) {
+		err = sb->s_op->show_options2(mnt, m, mnt->mnt_root);
+	} else if (sb->s_op->show_options)
 		err = sb->s_op->show_options(m, mnt->mnt_root);
 	seq_putc(m, '\n');
 out:
diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c
index b2fa36f..c8f3bcb 100755
--- a/fs/sdcardfs/dentry.c
+++ b/fs/sdcardfs/dentry.c
@@ -34,6 +34,8 @@
 	struct dentry *parent_lower_dentry = NULL;
 	struct dentry *lower_cur_parent_dentry = NULL;
 	struct dentry *lower_dentry = NULL;
+	struct inode *inode;
+	struct sdcardfs_inode_data *data;
 
 	if (flags & LOOKUP_RCU)
 		return -ECHILD;
@@ -46,7 +48,8 @@
 	spin_unlock(&dentry->d_lock);
 
 	/* check uninitialized obb_dentry and
-	 * whether the base obbpath has been changed or not */
+	 * whether the base obbpath has been changed or not
+	 */
 	if (is_obbpath_invalid(dentry)) {
 		d_drop(dentry);
 		return 0;
@@ -59,6 +62,14 @@
 	lower_dentry = lower_path.dentry;
 	lower_cur_parent_dentry = dget_parent(lower_dentry);
 
+	if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) {
+		err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
+		if (err == 0) {
+			d_drop(dentry);
+			goto out;
+		}
+	}
+
 	spin_lock(&lower_dentry->d_lock);
 	if (d_unhashed(lower_dentry)) {
 		spin_unlock(&lower_dentry->d_lock);
@@ -76,17 +87,13 @@
 
 	if (dentry < lower_dentry) {
 		spin_lock(&dentry->d_lock);
-		spin_lock(&lower_dentry->d_lock);
+		spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED);
 	} else {
 		spin_lock(&lower_dentry->d_lock);
-		spin_lock(&dentry->d_lock);
+		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 	}
 
-	if (dentry->d_name.len != lower_dentry->d_name.len) {
-		__d_drop(dentry);
-		err = 0;
-	} else if (strncasecmp(dentry->d_name.name, lower_dentry->d_name.name,
-				dentry->d_name.len) != 0) {
+	if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
 		__d_drop(dentry);
 		err = 0;
 	}
@@ -98,6 +105,21 @@
 		spin_unlock(&dentry->d_lock);
 		spin_unlock(&lower_dentry->d_lock);
 	}
+	if (!err)
+		goto out;
+
+	/* If our top's inode is gone, we may be out of date */
+	inode = igrab(dentry->d_inode);
+	if (inode) {
+		data = top_data_get(SDCARDFS_I(inode));
+		if (!data || data->abandoned) {
+			d_drop(dentry);
+			err = 0;
+		}
+		if (data)
+			data_put(data);
+		iput(inode);
+	}
 
 out:
 	dput(parent_dentry);
@@ -110,12 +132,10 @@
 static void sdcardfs_d_release(struct dentry *dentry)
 {
 	/* release and reset the lower paths */
-	if(has_graft_path(dentry)) {
+	if (has_graft_path(dentry))
 		sdcardfs_put_reset_orig_path(dentry);
-	}
 	sdcardfs_put_reset_lower_path(dentry);
 	free_dentry_private_data(dentry);
-	return;
 }
 
 static int sdcardfs_hash_ci(const struct dentry *dentry,
@@ -132,12 +152,10 @@
 	unsigned long hash;
 
 	name = qstr->name;
-	//len = vfat_striptail_len(qstr);
 	len = qstr->len;
 
 	hash = init_name_hash();
 	while (len--)
-		//hash = partial_name_hash(nls_tolower(t, *name++), hash);
 		hash = partial_name_hash(tolower(*name++), hash);
 	qstr->hash = end_name_hash(hash);
 
@@ -152,35 +170,25 @@
 		const struct dentry *dentry, const struct inode *inode,
 		unsigned int len, const char *str, const struct qstr *name)
 {
-	/* This function is copy of vfat_cmpi */
-	// FIXME Should we support national language?
-	//struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
-	//unsigned int alen, blen;
+	/* FIXME Should we support national language? */
 
-	/* A filename cannot end in '.' or we treat it like it has none */
-	/*
-	alen = vfat_striptail_len(name);
-	blen = __vfat_striptail_len(len, str);
-	if (alen == blen) {
-		if (nls_strnicmp(t, name->name, str, alen) == 0)
-			return 0;
-	}
-	*/
 	if (name->len == len) {
-		if (strncasecmp(name->name, str, len) == 0)
+		if (str_n_case_eq(name->name, str, len))
 			return 0;
 	}
 	return 1;
 }
 
-static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) {
+static void sdcardfs_canonical_path(const struct path *path,
+				struct path *actual_path)
+{
 	sdcardfs_get_real_lower(path->dentry, actual_path);
 }
 
 const struct dentry_operations sdcardfs_ci_dops = {
 	.d_revalidate	= sdcardfs_d_revalidate,
 	.d_release	= sdcardfs_d_release,
-	.d_hash 	= sdcardfs_hash_ci,
+	.d_hash	= sdcardfs_hash_ci,
 	.d_compare	= sdcardfs_cmp_ci,
 	.d_canonical_path = sdcardfs_canonical_path,
 };
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 9de45bc..8a42e01 100755
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -26,100 +26,295 @@
 	struct sdcardfs_inode_info *pi = SDCARDFS_I(parent);
 	struct sdcardfs_inode_info *ci = SDCARDFS_I(child);
 
-	ci->perm = PERM_INHERIT;
-	ci->userid = pi->userid;
-	ci->d_uid = pi->d_uid;
-	ci->under_android = pi->under_android;
+	ci->data->perm = PERM_INHERIT;
+	ci->data->userid = pi->data->userid;
+	ci->data->d_uid = pi->data->d_uid;
+	ci->data->under_android = pi->data->under_android;
+	ci->data->under_cache = pi->data->under_cache;
+	ci->data->under_obb = pi->data->under_obb;
+	set_top(ci, pi->top_data);
 }
 
 /* helper function for derived state */
-void setup_derived_state(struct inode *inode, perm_t perm,
-                        userid_t userid, uid_t uid, bool under_android)
+void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid,
+					uid_t uid, bool under_android,
+					struct sdcardfs_inode_data *top)
 {
 	struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
 
-	info->perm = perm;
-	info->userid = userid;
-	info->d_uid = uid;
-	info->under_android = under_android;
+	info->data->perm = perm;
+	info->data->userid = userid;
+	info->data->d_uid = uid;
+	info->data->under_android = under_android;
+	info->data->under_cache = false;
+	info->data->under_obb = false;
+	set_top(info, top);
 }
 
-/* While renaming, there is a point where we want the path from dentry, but the name from newdentry */
-void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry)
+/* While renaming, there is a point where we want the path from dentry,
+ * but the name from newdentry
+ */
+void get_derived_permission_new(struct dentry *parent, struct dentry *dentry,
+				const struct qstr *name)
 {
-	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 	struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
-	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
+	struct sdcardfs_inode_data *parent_data =
+			SDCARDFS_I(parent->d_inode)->data;
 	appid_t appid;
+	unsigned long user_num;
+	int err;
+	struct qstr q_Android = QSTR_LITERAL("Android");
+	struct qstr q_data = QSTR_LITERAL("data");
+	struct qstr q_obb = QSTR_LITERAL("obb");
+	struct qstr q_media = QSTR_LITERAL("media");
+	struct qstr q_cache = QSTR_LITERAL("cache");
 
 	/* By default, each inode inherits from its parent.
 	 * the properties are maintained on its private fields
 	 * because the inode attributes will be modified with that of
 	 * its lower inode.
-	 * The derived state will be updated on the last
-	 * stage of each system call by fix_derived_permission(inode).
+	 * These values are used by our custom permission call instead
+	 * of using the inode permissions.
 	 */
 
 	inherit_derived_state(parent->d_inode, dentry->d_inode);
 
+	/* Files don't get special labels */
+	if (!S_ISDIR(dentry->d_inode->i_mode))
+		return;
 	/* Derive custom permissions based on parent and current node */
-	switch (parent_info->perm) {
-		case PERM_INHERIT:
-			/* Already inherited above */
-			break;
-		case PERM_PRE_ROOT:
-			/* Legacy internal layout places users at top level */
-			info->perm = PERM_ROOT;
-			info->userid = simple_strtoul(newdentry->d_name.name, NULL, 10);
-			break;
-		case PERM_ROOT:
-			/* Assume masked off by default. */
-			if (!strcasecmp(newdentry->d_name.name, "Android")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID;
-				info->under_android = true;
-			}
-			break;
-		case PERM_ANDROID:
-			if (!strcasecmp(newdentry->d_name.name, "data")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID_DATA;
-			} else if (!strcasecmp(newdentry->d_name.name, "obb")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID_OBB;
-				/* Single OBB directory is always shared */
-			} else if (!strcasecmp(newdentry->d_name.name, "media")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID_MEDIA;
-			}
-			break;
-		case PERM_ANDROID_DATA:
-		case PERM_ANDROID_OBB:
-		case PERM_ANDROID_MEDIA:
-			appid = get_appid(sbi->pkgl_id, newdentry->d_name.name);
-			if (appid != 0) {
-				info->d_uid = multiuser_get_uid(parent_info->userid, appid);
-			}
-			break;
+	switch (parent_data->perm) {
+	case PERM_INHERIT:
+	case PERM_ANDROID_PACKAGE_CACHE:
+		/* Already inherited above */
+		break;
+	case PERM_PRE_ROOT:
+		/* Legacy internal layout places users at top level */
+		info->data->perm = PERM_ROOT;
+		err = kstrtoul(name->name, 10, &user_num);
+		if (err)
+			info->data->userid = 0;
+		else
+			info->data->userid = user_num;
+		set_top(info, info->data);
+		break;
+	case PERM_ROOT:
+		/* Assume masked off by default. */
+		if (qstr_case_eq(name, &q_Android)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID;
+			info->data->under_android = true;
+			set_top(info, info->data);
+		}
+		break;
+	case PERM_ANDROID:
+		if (qstr_case_eq(name, &q_data)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID_DATA;
+			set_top(info, info->data);
+		} else if (qstr_case_eq(name, &q_obb)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID_OBB;
+			info->data->under_obb = true;
+			set_top(info, info->data);
+			/* Single OBB directory is always shared */
+		} else if (qstr_case_eq(name, &q_media)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID_MEDIA;
+			set_top(info, info->data);
+		}
+		break;
+	case PERM_ANDROID_OBB:
+	case PERM_ANDROID_DATA:
+	case PERM_ANDROID_MEDIA:
+		info->data->perm = PERM_ANDROID_PACKAGE;
+		appid = get_appid(name->name);
+		if (appid != 0 && !is_excluded(name->name, parent_data->userid))
+			info->data->d_uid =
+				multiuser_get_uid(parent_data->userid, appid);
+		set_top(info, info->data);
+		break;
+	case PERM_ANDROID_PACKAGE:
+		if (qstr_case_eq(name, &q_cache)) {
+			info->data->perm = PERM_ANDROID_PACKAGE_CACHE;
+			info->data->under_cache = true;
+		}
+		break;
 	}
 }
 
 void get_derived_permission(struct dentry *parent, struct dentry *dentry)
 {
-	get_derived_permission_new(parent, dentry, dentry);
+	get_derived_permission_new(parent, dentry, &dentry->d_name);
 }
 
-void get_derive_permissions_recursive(struct dentry *parent) {
-	struct dentry *dentry;
-	list_for_each_entry(dentry, &parent->d_subdirs, d_u.d_child) {
-		if (dentry && dentry->d_inode) {
-			mutex_lock(&dentry->d_inode->i_mutex);
-			get_derived_permission(parent, dentry);
-			fix_derived_permission(dentry->d_inode);
-			get_derive_permissions_recursive(dentry);
-			mutex_unlock(&dentry->d_inode->i_mutex);
+static appid_t get_type(const char *name)
+{
+	const char *ext = strrchr(name, '.');
+	appid_t id;
+
+	if (ext && ext[0]) {
+		ext = &ext[1];
+		id = get_ext_gid(ext);
+		return id?:AID_MEDIA_RW;
+	}
+	return AID_MEDIA_RW;
+}
+
+void fixup_lower_ownership(struct dentry *dentry, const char *name)
+{
+	struct path path;
+	struct inode *inode;
+	int error;
+	struct sdcardfs_inode_info *info;
+	struct sdcardfs_inode_data *info_d;
+	struct sdcardfs_inode_data *info_top;
+	perm_t perm;
+	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+	uid_t uid = sbi->options.fs_low_uid;
+	gid_t gid = sbi->options.fs_low_gid;
+	struct iattr newattrs;
+
+	info = SDCARDFS_I(dentry->d_inode);
+	info_d = info->data;
+	perm = info_d->perm;
+	if (info_d->under_obb) {
+		perm = PERM_ANDROID_OBB;
+	} else if (info_d->under_cache) {
+		perm = PERM_ANDROID_PACKAGE_CACHE;
+	} else if (perm == PERM_INHERIT) {
+		info_top = top_data_get(info);
+		perm = info_top->perm;
+		data_put(info_top);
+	}
+
+	switch (perm) {
+	case PERM_ROOT:
+	case PERM_ANDROID:
+	case PERM_ANDROID_DATA:
+	case PERM_ANDROID_MEDIA:
+	case PERM_ANDROID_PACKAGE:
+	case PERM_ANDROID_PACKAGE_CACHE:
+		uid = multiuser_get_uid(info_d->userid, uid);
+		break;
+	case PERM_ANDROID_OBB:
+		uid = AID_MEDIA_OBB;
+		break;
+	case PERM_PRE_ROOT:
+	default:
+		break;
+	}
+	switch (perm) {
+	case PERM_ROOT:
+	case PERM_ANDROID:
+	case PERM_ANDROID_DATA:
+	case PERM_ANDROID_MEDIA:
+		if (S_ISDIR(dentry->d_inode->i_mode))
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
+		else
+			gid = multiuser_get_uid(info_d->userid, get_type(name));
+		break;
+	case PERM_ANDROID_OBB:
+		gid = AID_MEDIA_OBB;
+		break;
+	case PERM_ANDROID_PACKAGE:
+		if (uid_is_app(info_d->d_uid))
+			gid = multiuser_get_ext_gid(info_d->d_uid);
+		else
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
+		break;
+	case PERM_ANDROID_PACKAGE_CACHE:
+		if (uid_is_app(info_d->d_uid))
+			gid = multiuser_get_ext_cache_gid(info_d->d_uid);
+		else
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
+		break;
+	case PERM_PRE_ROOT:
+	default:
+		break;
+	}
+
+	sdcardfs_get_lower_path(dentry, &path);
+	inode = path.dentry->d_inode;
+	if (path.dentry->d_inode->i_gid != gid || path.dentry->d_inode->i_uid != uid) {
+		newattrs.ia_valid = ATTR_GID | ATTR_UID | ATTR_FORCE;
+		newattrs.ia_uid = make_kuid(current_user_ns(), uid);
+		newattrs.ia_gid = make_kgid(current_user_ns(), gid);
+		if (!S_ISDIR(inode->i_mode))
+			newattrs.ia_valid |=
+				ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+		mutex_lock(&inode->i_mutex);
+		error = security_path_chown(&path, newattrs.ia_uid, newattrs.ia_gid);
+		if (!error)
+			error = notify_change2(path.mnt, path.dentry, &newattrs);
+		mutex_unlock(&inode->i_mutex);
+		if (error)
+			pr_debug("sdcardfs: Failed to touch up lower fs gid/uid for %s\n", name);
+	}
+	sdcardfs_put_lower_path(dentry, &path);
+}
+
+static int descendant_may_need_fixup(struct sdcardfs_inode_data *data,
+		struct limit_search *limit)
+{
+	if (data->perm == PERM_ROOT)
+		return (limit->flags & BY_USERID) ?
+				data->userid == limit->userid : 1;
+	if (data->perm == PERM_PRE_ROOT || data->perm == PERM_ANDROID)
+		return 1;
+	return 0;
+}
+
+static int needs_fixup(perm_t perm)
+{
+	if (perm == PERM_ANDROID_DATA || perm == PERM_ANDROID_OBB
+			|| perm == PERM_ANDROID_MEDIA)
+		return 1;
+	return 0;
+}
+
+static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit, int depth)
+{
+	struct dentry *child;
+	struct sdcardfs_inode_info *info;
+
+	/*
+	 * All paths will terminate their recursion on hitting PERM_ANDROID_OBB,
+	 * PERM_ANDROID_MEDIA, or PERM_ANDROID_DATA. This happens at a depth of
+	 * at most 3.
+	 */
+	WARN(depth > 3, "%s: Max expected depth exceeded!\n", __func__);
+	spin_lock_nested(&dentry->d_lock, depth);
+	if (!dentry->d_inode) {
+		spin_unlock(&dentry->d_lock);
+		return;
+	}
+	info = SDCARDFS_I(dentry->d_inode);
+
+	if (needs_fixup(info->data->perm)) {
+		list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+			spin_lock_nested(&child->d_lock, depth + 1);
+			if (!(limit->flags & BY_NAME) || qstr_case_eq(&child->d_name, &limit->name)) {
+				if (child->d_inode) {
+					get_derived_permission(dentry, child);
+					fixup_tmp_permissions(child->d_inode);
+					spin_unlock(&child->d_lock);
+					break;
+				}
+			}
+			spin_unlock(&child->d_lock);
+		}
+	} else if (descendant_may_need_fixup(info->data, limit)) {
+		list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+			__fixup_perms_recursive(child, limit, depth + 1);
 		}
 	}
+	spin_unlock(&dentry->d_lock);
+}
+
+void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit)
+{
+	__fixup_perms_recursive(dentry, limit, 0);
 }
 
 /* main function for updating derived permission */
@@ -127,41 +322,38 @@
 {
 	struct dentry *parent;
 
-	if(!dentry || !dentry->d_inode) {
-		printk(KERN_ERR "sdcardfs: %s: invalid dentry\n", __func__);
+	if (!dentry || !dentry->d_inode) {
+		pr_err("sdcardfs: %s: invalid dentry\n", __func__);
 		return;
 	}
 	/* FIXME:
 	 * 1. need to check whether the dentry is updated or not
 	 * 2. remove the root dentry update
 	 */
-	mutex_lock(&dentry->d_inode->i_mutex);
-	if(IS_ROOT(dentry)) {
-		//setup_default_pre_root_state(dentry->d_inode);
-	} else {
+	if (!IS_ROOT(dentry)) {
 		parent = dget_parent(dentry);
-		if(parent) {
+		if (parent) {
 			get_derived_permission(parent, dentry);
 			dput(parent);
 		}
 	}
-	fix_derived_permission(dentry->d_inode);
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	fixup_tmp_permissions(dentry->d_inode);
 }
 
 int need_graft_path(struct dentry *dentry)
 {
 	int ret = 0;
 	struct dentry *parent = dget_parent(dentry);
-	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
+	struct sdcardfs_inode_info *parent_info = SDCARDFS_I(parent->d_inode);
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+	struct qstr obb = QSTR_LITERAL("obb");
 
-	if(parent_info->perm == PERM_ANDROID &&
-			!strcasecmp(dentry->d_name.name, "obb")) {
+	if (parent_info->data->perm == PERM_ANDROID &&
+			qstr_case_eq(&dentry->d_name, &obb)) {
 
 		/* /Android/obb is the base obbpath of DERIVED_UNIFIED */
-		if(!(sbi->options.multiuser == false
-				&& parent_info->userid == 0)) {
+		if (!(sbi->options.multiuser == false
+				&& parent_info->data->userid == 0)) {
 			ret = 1;
 		}
 	}
@@ -175,36 +367,40 @@
 	struct sdcardfs_dentry_info *di = SDCARDFS_D(dent);
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dent->d_sb);
 	char *path_buf, *obbpath_s;
+	int need_put = 0;
+	struct path lower_path;
 
 	/* check the base obbpath has been changed.
 	 * this routine can check an uninitialized obb dentry as well.
-	 * regarding the uninitialized obb, refer to the sdcardfs_mkdir() */
+	 * regarding the uninitialized obb, refer to the sdcardfs_mkdir()
+	 */
 	spin_lock(&di->lock);
-	if(di->orig_path.dentry) {
- 		if(!di->lower_path.dentry) {
+	if (di->orig_path.dentry) {
+		if (!di->lower_path.dentry) {
 			ret = 1;
 		} else {
 			path_get(&di->lower_path);
-			//lower_parent = lock_parent(lower_path->dentry);
 
 			path_buf = kmalloc(PATH_MAX, GFP_ATOMIC);
-			if(!path_buf) {
+			if (!path_buf) {
 				ret = 1;
-				printk(KERN_ERR "sdcardfs: fail to allocate path_buf in %s.\n", __func__);
+				pr_err("sdcardfs: fail to allocate path_buf in %s.\n", __func__);
 			} else {
 				obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX);
 				if (d_unhashed(di->lower_path.dentry) ||
-					strcasecmp(sbi->obbpath_s, obbpath_s)) {
+					!str_case_eq(sbi->obbpath_s, obbpath_s)) {
 					ret = 1;
 				}
 				kfree(path_buf);
 			}
 
-			//unlock_dir(lower_parent);
-			path_put(&di->lower_path);
+			pathcpy(&lower_path, &di->lower_path);
+			need_put = 1;
 		}
 	}
 	spin_unlock(&di->lock);
+	if (need_put)
+		path_put(&lower_path);
 	return ret;
 }
 
@@ -212,17 +408,18 @@
 {
 	int ret = 0;
 	struct dentry *parent = dget_parent(dentry);
-	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
+	struct sdcardfs_inode_info *parent_info = SDCARDFS_I(parent->d_inode);
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+	struct qstr q_obb = QSTR_LITERAL("obb");
 
 	spin_lock(&SDCARDFS_D(dentry)->lock);
 	if (sbi->options.multiuser) {
-		if(parent_info->perm == PERM_PRE_ROOT &&
-				!strcasecmp(dentry->d_name.name, "obb")) {
+		if (parent_info->data->perm == PERM_PRE_ROOT &&
+				qstr_case_eq(&dentry->d_name, &q_obb)) {
 			ret = 1;
 		}
-	} else  if (parent_info->perm == PERM_ANDROID &&
-			!strcasecmp(dentry->d_name.name, "obb")) {
+	} else  if (parent_info->data->perm == PERM_ANDROID &&
+			qstr_case_eq(&dentry->d_name, &q_obb)) {
 		ret = 1;
 	}
 	spin_unlock(&SDCARDFS_D(dentry)->lock);
@@ -232,7 +429,8 @@
 /* The lower_path will be stored to the dentry's orig_path
  * and the base obbpath will be copyed to the lower_path variable.
  * if an error returned, there's no change in the lower_path
- * returns: -ERRNO if error (0: no error) */
+ * returns: -ERRNO if error (0: no error)
+ */
 int setup_obb_dentry(struct dentry *dentry, struct path *lower_path)
 {
 	int err = 0;
@@ -241,23 +439,24 @@
 
 	/* A local obb dentry must have its own orig_path to support rmdir
 	 * and mkdir of itself. Usually, we expect that the sbi->obbpath
-	 * is avaiable on this stage. */
+	 * is avaiable on this stage.
+	 */
 	sdcardfs_set_orig_path(dentry, lower_path);
 
 	err = kern_path(sbi->obbpath_s,
 			LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath);
 
-	if(!err) {
+	if (!err) {
 		/* the obbpath base has been found */
-		printk(KERN_INFO "sdcardfs: the sbi->obbpath is found\n");
 		pathcpy(lower_path, &obbpath);
 	} else {
 		/* if the sbi->obbpath is not available, we can optionally
 		 * setup the lower_path with its orig_path.
 		 * but, the current implementation just returns an error
 		 * because the sdcard daemon also regards this case as
-		 * a lookup fail. */
-		printk(KERN_INFO "sdcardfs: the sbi->obbpath is not available\n");
+		 * a lookup fail.
+		 */
+		pr_info("sdcardfs: the sbi->obbpath is not available\n");
 	}
 	return err;
 }
diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c
index 369051e..8943bef 100755
--- a/fs/sdcardfs/file.c
+++ b/fs/sdcardfs/file.c
@@ -65,7 +65,7 @@
 
 	/* check disk space */
 	if (!check_min_free_space(dentry, count, 0)) {
-		printk(KERN_INFO "No minimum free space.\n");
+		pr_err("No minimum free space.\n");
 		return -ENOSPC;
 	}
 
@@ -113,6 +113,10 @@
 	if (lower_file->f_op->unlocked_ioctl)
 		err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
 
+	/* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */
+	if (!err)
+		sdcardfs_copy_and_fix_attrs(file_inode(file),
+				      file_inode(lower_file));
 out:
 	return err;
 }
@@ -160,8 +164,7 @@
 	lower_file = sdcardfs_lower_file(file);
 	if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
 		err = -EINVAL;
-		printk(KERN_ERR "sdcardfs: lower file system does not "
-		       "support writeable mmap\n");
+		pr_err("sdcardfs: lower file system does not support writeable mmap\n");
 		goto out;
 	}
 
@@ -173,16 +176,10 @@
 	if (!SDCARDFS_F(file)->lower_vm_ops) {
 		err = lower_file->f_op->mmap(lower_file, vma);
 		if (err) {
-			printk(KERN_ERR "sdcardfs: lower mmap failed %d\n", err);
+			pr_err("sdcardfs: lower mmap failed %d\n", err);
 			goto out;
 		}
 		saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */
-		err = do_munmap(current->mm, vma->vm_start,
-				vma->vm_end - vma->vm_start);
-		if (err) {
-			printk(KERN_ERR "sdcardfs: do_munmap failed %d\n", err);
-			goto out;
-		}
 	}
 
 	/*
@@ -195,6 +192,9 @@
 	file->f_mapping->a_ops = &sdcardfs_aops; /* set our aops */
 	if (!SDCARDFS_F(file)->lower_vm_ops) /* save for our ->fault */
 		SDCARDFS_F(file)->lower_vm_ops = saved_vm_ops;
+	vma->vm_private_data = file;
+	get_file(lower_file);
+	vma->vm_file = lower_file;
 
 out:
 	return err;
@@ -216,16 +216,13 @@
 		goto out_err;
 	}
 
-	if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-                         "	dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(parent->d_inode, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_err;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(sbi, saved_cred);
+	OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(inode));
 
 	file->private_data =
 		kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL);
@@ -251,9 +248,8 @@
 
 	if (err)
 		kfree(SDCARDFS_F(file));
-	else {
+	else
 		sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode));
-	}
 
 out_revert_cred:
 	REVERT_CRED(saved_cred);
@@ -321,6 +317,29 @@
 	return err;
 }
 
+/*
+ * Sdcardfs cannot use generic_file_llseek as ->llseek, because it would
+ * only set the offset of the upper file.  So we have to implement our
+ * own method to set both the upper and lower file offsets
+ * consistently.
+ */
+static loff_t sdcardfs_file_llseek(struct file *file, loff_t offset, int whence)
+{
+	int err;
+	struct file *lower_file;
+
+	err = generic_file_llseek(file, offset, whence);
+	if (err < 0)
+		goto out;
+
+	lower_file = sdcardfs_lower_file(file);
+	err = generic_file_llseek(lower_file, offset, whence);
+
+out:
+	return err;
+}
+
+
 const struct file_operations sdcardfs_main_fops = {
 	.llseek		= generic_file_llseek,
 	.read		= sdcardfs_read,
@@ -339,7 +358,7 @@
 
 /* trimmed directory options */
 const struct file_operations sdcardfs_dir_fops = {
-	.llseek		= generic_file_llseek,
+	.llseek		= sdcardfs_file_llseek,
 	.read		= generic_read_dir,
 	.iterate	= sdcardfs_readdir,
 	.unlocked_ioctl	= sdcardfs_unlocked_ioctl,
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 0f4aa17..030210a 100755
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -19,18 +19,26 @@
  */
 
 #include "sdcardfs.h"
+#include <linux/fs_struct.h>
+#include <linux/ratelimit.h>
 
 /* Do not directly use this function. Use OVERRIDE_CRED() instead. */
-const struct cred * override_fsids(struct sdcardfs_sb_info* sbi)
+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
+		struct sdcardfs_inode_data *data)
 {
-	struct cred * cred;
-	const struct cred * old_cred;
+	struct cred *cred;
+	const struct cred *old_cred;
+	uid_t uid;
 
 	cred = prepare_creds();
 	if (!cred)
 		return NULL;
 
-	cred->fsuid = sbi->options.fs_low_uid;
+	if (data->under_obb)
+		uid = AID_MEDIA_OBB;
+	else
+		uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
+	cred->fsuid = uid;
 	cred->fsgid = sbi->options.fs_low_gid;
 
 	old_cred = override_creds(cred);
@@ -39,9 +47,9 @@
 }
 
 /* Do not directly use this function, use REVERT_CRED() instead. */
-void revert_fsids(const struct cred * old_cred)
+void revert_fsids(const struct cred *old_cred)
 {
-	const struct cred * cur_cred;
+	const struct cred *cur_cred;
 
 	cur_cred = current->cred;
 	revert_creds(old_cred);
@@ -53,38 +61,54 @@
 {
 	int err = 0;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_dentry_mnt;
 	struct dentry *lower_parent_dentry = NULL;
 	struct path lower_path;
 	const struct cred *saved_cred = NULL;
+	struct fs_struct *saved_fs;
+	struct fs_struct *copied_fs;
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_dentry_mnt = lower_path.mnt;
 	lower_parent_dentry = lock_parent(lower_dentry);
 
 	/* set last 16bytes of mode field to 0664 */
 	mode = (mode & S_IFMT) | 00664;
-	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, want_excl);
+
+	/* temporarily change umask for lower fs write */
+	saved_fs = current->fs;
+	copied_fs = copy_fs_struct(current->fs);
+	if (!copied_fs) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+	current->fs = copied_fs;
+	current->fs->umask = 0;
+	err = vfs_create2(lower_dentry_mnt, lower_parent_dentry->d_inode, lower_dentry, mode, want_excl);
 	if (err)
 		goto out;
 
-	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, SDCARDFS_I(dir)->userid);
+	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path,
+			SDCARDFS_I(dir)->data->userid);
 	if (err)
 		goto out;
 	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
 	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
+	fixup_lower_ownership(dentry, dentry->d_name.name);
 
 out:
+	current->fs = saved_fs;
+	free_fs_struct(copied_fs);
+out_unlock:
 	unlock_dir(lower_parent_dentry);
 	sdcardfs_put_lower_path(dentry, &lower_path);
 	REVERT_CRED(saved_cred);
@@ -138,28 +162,27 @@
 {
 	int err;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct inode *lower_dir_inode = sdcardfs_lower_inode(dir);
 	struct dentry *lower_dir_dentry;
 	struct path lower_path;
 	const struct cred *saved_cred = NULL;
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	dget(lower_dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
 
-	err = vfs_unlink(lower_dir_inode, lower_dentry);
+	err = vfs_unlink2(lower_mnt, lower_dir_inode, lower_dentry);
 
 	/*
 	 * Note: unlinking on top of NFS can cause silly-renamed files.
@@ -219,14 +242,15 @@
 }
 #endif
 
-static int touch(char *abs_path, mode_t mode) {
+static int touch(char *abs_path, mode_t mode)
+{
 	struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode);
+
 	if (IS_ERR(filp)) {
 		if (PTR_ERR(filp) == -EEXIST) {
 			return 0;
-		}
-		else {
-			printk(KERN_ERR "sdcardfs: failed to open(%s): %ld\n",
+		} else {
+			pr_err("sdcardfs: failed to open(%s): %ld\n",
 						abs_path, PTR_ERR(filp));
 			return PTR_ERR(filp);
 		}
@@ -240,31 +264,29 @@
 	int err = 0;
 	int make_nomedia_in_obb = 0;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *lower_parent_dentry = NULL;
 	struct path lower_path;
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 	const struct cred *saved_cred = NULL;
-	struct sdcardfs_inode_info *pi = SDCARDFS_I(dir);
-	char *page_buf;
-	char *nomedia_dir_name;
-	char *nomedia_fullpath;
-	int fullpath_namelen;
+	struct sdcardfs_inode_data *pd = SDCARDFS_I(dir)->data;
 	int touch_err = 0;
+	struct fs_struct *saved_fs;
+	struct fs_struct *copied_fs;
+	struct qstr q_obb = QSTR_LITERAL("obb");
+	struct qstr q_data = QSTR_LITERAL("data");
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	/* check disk space */
 	if (!check_min_free_space(dentry, 0, 1)) {
-		printk(KERN_INFO "sdcardfs: No minimum free space.\n");
+		pr_err("sdcardfs: No minimum free space.\n");
 		err = -ENOSPC;
 		goto out_revert;
 	}
@@ -272,87 +294,84 @@
 	/* the lower_dentry is negative here */
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	lower_parent_dentry = lock_parent(lower_dentry);
 
 	/* set last 16bytes of mode field to 0775 */
 	mode = (mode & S_IFMT) | 00775;
-	err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode);
 
-	if (err)
+	/* temporarily change umask for lower fs write */
+	saved_fs = current->fs;
+	copied_fs = copy_fs_struct(current->fs);
+	if (!copied_fs) {
+		err = -ENOMEM;
+		unlock_dir(lower_parent_dentry);
+		goto out_unlock;
+	}
+	current->fs = copied_fs;
+	current->fs->umask = 0;
+	err = vfs_mkdir2(lower_mnt, lower_parent_dentry->d_inode, lower_dentry, mode);
+
+	if (err) {
+		unlock_dir(lower_parent_dentry);
 		goto out;
+	}
 
 	/* if it is a local obb dentry, setup it with the base obbpath */
-	if(need_graft_path(dentry)) {
+	if (need_graft_path(dentry)) {
 
 		err = setup_obb_dentry(dentry, &lower_path);
-		if(err) {
+		if (err) {
 			/* if the sbi->obbpath is not available, the lower_path won't be
 			 * changed by setup_obb_dentry() but the lower path is saved to
 			 * its orig_path. this dentry will be revalidated later.
-			 * but now, the lower_path should be NULL */
+			 * but now, the lower_path should be NULL
+			 */
 			sdcardfs_put_reset_lower_path(dentry);
 
 			/* the newly created lower path which saved to its orig_path or
 			 * the lower_path is the base obbpath.
-			 * therefore, an additional path_get is required */
+			 * therefore, an additional path_get is required
+			 */
 			path_get(&lower_path);
 		} else
 			make_nomedia_in_obb = 1;
 	}
 
-	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pi->userid);
-	if (err)
+	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pd->userid);
+	if (err) {
+		unlock_dir(lower_parent_dentry);
 		goto out;
+	}
 
 	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
 	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
 	/* update number of links on parent directory */
 	set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink);
-
-	if ((!sbi->options.multiuser) && (!strcasecmp(dentry->d_name.name, "obb"))
-		&& (pi->perm == PERM_ANDROID) && (pi->userid == 0))
+	fixup_lower_ownership(dentry, dentry->d_name.name);
+	unlock_dir(lower_parent_dentry);
+	if ((!sbi->options.multiuser) && (qstr_case_eq(&dentry->d_name, &q_obb))
+		&& (pd->perm == PERM_ANDROID) && (pd->userid == 0))
 		make_nomedia_in_obb = 1;
 
 	/* When creating /Android/data and /Android/obb, mark them as .nomedia */
 	if (make_nomedia_in_obb ||
-		((pi->perm == PERM_ANDROID) && (!strcasecmp(dentry->d_name.name, "data")))) {
-
-		page_buf = (char *)__get_free_page(GFP_KERNEL);
-		if (!page_buf) {
-			printk(KERN_ERR "sdcardfs: failed to allocate page buf\n");
-			goto out;
-		}
-
-		nomedia_dir_name = d_absolute_path(&lower_path, page_buf, PAGE_SIZE);
-		if (IS_ERR(nomedia_dir_name)) {
-			free_page((unsigned long)page_buf);
-			printk(KERN_ERR "sdcardfs: failed to get .nomedia dir name\n");
-			goto out;
-		}
-
-		fullpath_namelen = page_buf + PAGE_SIZE - nomedia_dir_name - 1;
-		fullpath_namelen += strlen("/.nomedia");
-		nomedia_fullpath = kzalloc(fullpath_namelen + 1, GFP_KERNEL);
-		if (!nomedia_fullpath) {
-			free_page((unsigned long)page_buf);
-			printk(KERN_ERR "sdcardfs: failed to allocate .nomedia fullpath buf\n");
-			goto out;
-		}
-
-		strcpy(nomedia_fullpath, nomedia_dir_name);
-		free_page((unsigned long)page_buf);
-		strcat(nomedia_fullpath, "/.nomedia");
-		touch_err = touch(nomedia_fullpath, 0664);
+		((pd->perm == PERM_ANDROID)
+				&& (qstr_case_eq(&dentry->d_name, &q_data)))) {
+		REVERT_CRED(saved_cred);
+		OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dentry->d_inode));
+		set_fs_pwd(current->fs, &lower_path);
+		touch_err = touch(".nomedia", 0664);
 		if (touch_err) {
-			printk(KERN_ERR "sdcardfs: failed to touch(%s): %d\n",
-							nomedia_fullpath, touch_err);
-			kfree(nomedia_fullpath);
+			pr_err("sdcardfs: failed to create .nomedia in %s: %d\n",
+							lower_path.dentry->d_name.name, touch_err);
 			goto out;
 		}
-		kfree(nomedia_fullpath);
 	}
 out:
-	unlock_dir(lower_parent_dentry);
+	current->fs = saved_fs;
+	free_fs_struct(copied_fs);
+out_unlock:
 	sdcardfs_put_lower_path(dentry, &lower_path);
 out_revert:
 	REVERT_CRED(saved_cred);
@@ -364,29 +383,29 @@
 {
 	struct dentry *lower_dentry;
 	struct dentry *lower_dir_dentry;
+	struct vfsmount *lower_mnt;
 	int err;
 	struct path lower_path;
 	const struct cred *saved_cred = NULL;
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	/* sdcardfs_get_real_lower(): in case of remove an user's obb dentry
-	 * the dentry on the original path should be deleted. */
+	 * the dentry on the original path should be deleted.
+	 */
 	sdcardfs_get_real_lower(dentry, &lower_path);
 
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	lower_dir_dentry = lock_parent(lower_dentry);
 
-	err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+	err = vfs_rmdir2(lower_mnt, lower_dir_dentry->d_inode, lower_dentry);
 	if (err)
 		goto out;
 
@@ -450,27 +469,25 @@
 	struct dentry *lower_new_dentry = NULL;
 	struct dentry *lower_old_dir_dentry = NULL;
 	struct dentry *lower_new_dir_dentry = NULL;
+	struct vfsmount *lower_mnt = NULL;
 	struct dentry *trap = NULL;
-	struct dentry *new_parent = NULL;
 	struct path lower_old_path, lower_new_path;
 	const struct cred *saved_cred = NULL;
 
-	if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name) ||
-		!check_caller_access_to_name(new_dir, new_dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  new_dentry: %s, task:%s\n",
-						 __func__, new_dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(old_dir, &old_dentry->d_name) ||
+		!check_caller_access_to_name(new_dir, &new_dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred, SDCARDFS_I(new_dir));
 
 	sdcardfs_get_real_lower(old_dentry, &lower_old_path);
 	sdcardfs_get_lower_path(new_dentry, &lower_new_path);
 	lower_old_dentry = lower_old_path.dentry;
 	lower_new_dentry = lower_new_path.dentry;
+	lower_mnt = lower_old_path.mnt;
 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
 
@@ -486,7 +503,8 @@
 		goto out;
 	}
 
-	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
+	err = vfs_rename2(lower_mnt,
+			 lower_old_dir_dentry->d_inode, lower_old_dentry,
 			 lower_new_dir_dentry->d_inode, lower_new_dentry);
 	if (err)
 		goto out;
@@ -498,25 +516,11 @@
 	if (new_dir != old_dir) {
 		sdcardfs_copy_and_fix_attrs(old_dir, lower_old_dir_dentry->d_inode);
 		fsstack_copy_inode_size(old_dir, lower_old_dir_dentry->d_inode);
-
-		/* update the derived permission of the old_dentry
-		 * with its new parent
-		 */
-		new_parent = dget_parent(new_dentry);
-		if(new_parent) {
-			if(old_dentry->d_inode) {
-				update_derived_permission_lock(old_dentry);
-			}
-			dput(new_parent);
-		}
 	}
-	/* At this point, not all dentry information has been moved, so
-	 * we pass along new_dentry for the name.*/
-	mutex_lock(&old_dentry->d_inode->i_mutex);
-	get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry);
-	fix_derived_permission(old_dentry->d_inode);
-	get_derive_permissions_recursive(old_dentry);
-	mutex_unlock(&old_dentry->d_inode->i_mutex);
+	get_derived_permission_new(new_dentry->d_parent, old_dentry, &new_dentry->d_name);
+	fixup_tmp_permissions(old_dentry->d_inode);
+	fixup_lower_ownership(old_dentry, new_dentry->d_name.name);
+	d_invalidate(old_dentry); /* Can't fixup ownership recursively :( */
 out:
 	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
 	dput(lower_old_dir_dentry);
@@ -598,16 +602,61 @@
 }
 #endif
 
-static int sdcardfs_permission(struct inode *inode, int mask)
+static int sdcardfs_permission_wrn(struct inode *inode, int mask)
+{
+	WARN_RATELIMIT(1, "sdcardfs does not support permission. Use permission2.\n");
+	return -EINVAL;
+}
+
+void copy_attrs(struct inode *dest, const struct inode *src)
+{
+	dest->i_mode = src->i_mode;
+	dest->i_uid = src->i_uid;
+	dest->i_gid = src->i_gid;
+	dest->i_rdev = src->i_rdev;
+	dest->i_atime = src->i_atime;
+	dest->i_mtime = src->i_mtime;
+	dest->i_ctime = src->i_ctime;
+	dest->i_blkbits = src->i_blkbits;
+	dest->i_flags = src->i_flags;
+#ifdef CONFIG_FS_POSIX_ACL
+	dest->i_acl = src->i_acl;
+#endif
+#ifdef CONFIG_SECURITY
+	dest->i_security = src->i_security;
+#endif
+}
+
+static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	int err;
+	struct inode tmp;
+	struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode));
+
+	if (!top)
+		return -EINVAL;
 
 	/*
 	 * Permission check on sdcardfs inode.
 	 * Calling process should have AID_SDCARD_RW permission
+	 * Since generic_permission only needs i_mode, i_uid,
+	 * i_gid, and i_sb, we can create a fake inode to pass
+	 * this information down in.
+	 *
+	 * The underlying code may attempt to take locks in some
+	 * cases for features we're not using, but if that changes,
+	 * locks must be dealt with to avoid undefined behavior.
 	 */
-	err = generic_permission(inode, mask);
-
+	copy_attrs(&tmp, inode);
+	tmp.i_uid = make_kuid(&init_user_ns, top->d_uid);
+	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	tmp.i_mode = (inode->i_mode & S_IFMT)
+			| get_mode(mnt, SDCARDFS_I(inode), top);
+	data_put(top);
+	tmp.i_sb = inode->i_sb;
+	if (IS_POSIXACL(inode))
+		pr_warn("%s: This may be undefined behavior...\n", __func__);
+	err = generic_permission(&tmp, mask);
 	/* XXX
 	 * Original sdcardfs code calls inode_permission(lower_inode,.. )
 	 * for checking inode permission. But doing such things here seems
@@ -624,6 +673,7 @@
 		 * we check it with AID_MEDIA_RW permission
 		 */
 		struct inode *lower_inode;
+
 		OVERRIDE_CRED(SDCARDFS_SB(inode->sb));
 
 		lower_inode = sdcardfs_lower_inode(inode);
@@ -636,82 +686,85 @@
 
 }
 
-static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-		 struct kstat *stat)
+static int sdcardfs_setattr_wrn(struct dentry *dentry, struct iattr *ia)
 {
-	struct dentry *lower_dentry;
-	struct inode *inode;
-	struct inode *lower_inode;
-	struct path lower_path;
-	struct dentry *parent;
-
-	parent = dget_parent(dentry);
-	if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
-		dput(parent);
-		return -EACCES;
-	}
-	dput(parent);
-
-	inode = dentry->d_inode;
-
-	sdcardfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_inode = sdcardfs_lower_inode(inode);
-
-
-	sdcardfs_copy_and_fix_attrs(inode, lower_inode);
-	fsstack_copy_inode_size(inode, lower_inode);
-
-
-	generic_fillattr(inode, stat);
-	sdcardfs_put_lower_path(dentry, &lower_path);
-	return 0;
+	WARN_RATELIMIT(1, "sdcardfs does not support setattr. User setattr2.\n");
+	return -EINVAL;
 }
 
-static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
+static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct iattr *ia)
 {
 	int err = 0;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct inode *inode;
 	struct inode *lower_inode;
 	struct path lower_path;
 	struct iattr lower_ia;
 	struct dentry *parent;
+	struct inode tmp;
+	struct sdcardfs_inode_data *top;
+	const struct cred *saved_cred = NULL;
 
 	inode = dentry->d_inode;
+	top = top_data_get(SDCARDFS_I(inode));
+
+	if (!top)
+		return -EINVAL;
+
+	/*
+	 * Permission check on sdcardfs inode.
+	 * Calling process should have AID_SDCARD_RW permission
+	 * Since generic_permission only needs i_mode, i_uid,
+	 * i_gid, and i_sb, we can create a fake inode to pass
+	 * this information down in.
+	 *
+	 * The underlying code may attempt to take locks in some
+	 * cases for features we're not using, but if that changes,
+	 * locks must be dealt with to avoid undefined behavior.
+	 *
+	 */
+	copy_attrs(&tmp, inode);
+	tmp.i_uid = make_kuid(&init_user_ns, top->d_uid);
+	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	tmp.i_mode = (inode->i_mode & S_IFMT)
+			| get_mode(mnt, SDCARDFS_I(inode), top);
+	tmp.i_size = i_size_read(inode);
+	data_put(top);
+	tmp.i_sb = inode->i_sb;
 
 	/*
 	 * Check if user has permission to change inode.  We don't check if
 	 * this user can change the lower inode: that should happen when
 	 * calling notify_change on the lower inode.
 	 */
-	err = inode_change_ok(inode, ia);
+	/* prepare our own lower struct iattr (with the lower file) */
+	memcpy(&lower_ia, ia, sizeof(lower_ia));
+	/* Allow touch updating timestamps. A previous permission check ensures
+	 * we have write access. Changes to mode, owner, and group are ignored
+	 */
+	ia->ia_valid |= ATTR_FORCE;
+	err = inode_change_ok(&tmp, ia);
 
-	/* no vfs_XXX operations required, cred overriding will be skipped. wj*/
 	if (!err) {
 		/* check the Android group ID */
 		parent = dget_parent(dentry);
-		if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
-			printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-							 "  dentry: %s, task:%s\n",
-							 __func__, dentry->d_name.name, current->comm);
+		if (!check_caller_access_to_name(parent->d_inode, &dentry->d_name))
 			err = -EACCES;
-		}
 		dput(parent);
 	}
 
 	if (err)
 		goto out_err;
 
+	/* save current_cred and override it */
+	OVERRIDE_CRED(SDCARDFS_SB(dentry->d_sb), saved_cred, SDCARDFS_I(inode));
+
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	lower_inode = sdcardfs_lower_inode(inode);
 
-	/* prepare our own lower struct iattr (with the lower file) */
-	memcpy(&lower_ia, ia, sizeof(lower_ia));
 	if (ia->ia_valid & ATTR_FILE)
 		lower_ia.ia_file = sdcardfs_lower_file(ia->ia_file);
 
@@ -725,13 +778,9 @@
 	 * afterwards in the other cases: we fsstack_copy_inode_size from
 	 * the lower level.
 	 */
-	if (current->mm)
-		down_write(&current->mm->mmap_sem);
 	if (ia->ia_valid & ATTR_SIZE) {
-		err = inode_newsize_ok(inode, ia->ia_size);
+		err = inode_newsize_ok(&tmp, ia->ia_size);
 		if (err) {
-			if (current->mm)
-				up_write(&current->mm->mmap_sem);
 			goto out;
 		}
 		truncate_setsize(inode, ia->ia_size);
@@ -751,10 +800,9 @@
 	 * tries to open(), unlink(), then ftruncate() a file.
 	 */
 	mutex_lock(&lower_dentry->d_inode->i_mutex);
-	err = notify_change(lower_dentry, &lower_ia); /* note: lower_ia */
+	err = notify_change2(lower_mnt, lower_dentry, &lower_ia); /* note: lower_ia */
+
 	mutex_unlock(&lower_dentry->d_inode->i_mutex);
-	if (current->mm)
-		up_write(&current->mm->mmap_sem);
 	if (err)
 		goto out;
 
@@ -769,13 +817,68 @@
 
 out:
 	sdcardfs_put_lower_path(dentry, &lower_path);
+	REVERT_CRED(saved_cred);
 out_err:
 	return err;
 }
 
+static int sdcardfs_fillattr(struct vfsmount *mnt,
+				struct inode *inode, struct kstat *stat)
+{
+	struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
+	struct sdcardfs_inode_data *top = top_data_get(info);
+
+	if (!top)
+		return -EINVAL;
+
+	stat->dev = inode->i_sb->s_dev;
+	stat->ino = inode->i_ino;
+	stat->mode = (inode->i_mode  & S_IFMT) | get_mode(mnt, info, top);
+	stat->nlink = inode->i_nlink;
+	stat->uid = make_kuid(&init_user_ns, top->d_uid);
+	stat->gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	stat->rdev = inode->i_rdev;
+	stat->size = i_size_read(inode);
+	stat->atime = inode->i_atime;
+	stat->mtime = inode->i_mtime;
+	stat->ctime = inode->i_ctime;
+	stat->blksize = (1 << inode->i_blkbits);
+	stat->blocks = inode->i_blocks;
+	data_put(top);
+	return 0;
+}
+
+static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		 struct kstat *stat)
+{
+	struct kstat lower_stat;
+	struct path lower_path;
+	struct dentry *parent;
+	int err;
+
+	parent = dget_parent(dentry);
+	if (!check_caller_access_to_name(parent->d_inode, &dentry->d_name)) {
+		dput(parent);
+		return -EACCES;
+	}
+	dput(parent);
+
+	sdcardfs_get_lower_path(dentry, &lower_path);
+	err = vfs_getattr(&lower_path, &lower_stat);
+	if (err)
+		goto out;
+	sdcardfs_copy_and_fix_attrs(dentry->d_inode,
+			      lower_path.dentry->d_inode);
+	err = sdcardfs_fillattr(mnt, dentry->d_inode, stat);
+	stat->blocks = lower_stat.blocks;
+out:
+	sdcardfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
 const struct inode_operations sdcardfs_symlink_iops = {
-	.permission	= sdcardfs_permission,
-	.setattr	= sdcardfs_setattr,
+	.permission2	= sdcardfs_permission,
+	.setattr2	= sdcardfs_setattr,
 	/* XXX Following operations are implemented,
 	 *     but FUSE(sdcard) or FAT does not support them
 	 *     These methods are *NOT* perfectly tested.
@@ -788,14 +891,14 @@
 const struct inode_operations sdcardfs_dir_iops = {
 	.create		= sdcardfs_create,
 	.lookup		= sdcardfs_lookup,
-#if 0
-	.permission	= sdcardfs_permission,
-#endif
+	.permission	= sdcardfs_permission_wrn,
+	.permission2	= sdcardfs_permission,
 	.unlink		= sdcardfs_unlink,
 	.mkdir		= sdcardfs_mkdir,
 	.rmdir		= sdcardfs_rmdir,
 	.rename		= sdcardfs_rename,
-	.setattr	= sdcardfs_setattr,
+	.setattr	= sdcardfs_setattr_wrn,
+	.setattr2	= sdcardfs_setattr,
 	.getattr	= sdcardfs_getattr,
 	/* XXX Following operations are implemented,
 	 *     but FUSE(sdcard) or FAT does not support them
@@ -807,7 +910,9 @@
 };
 
 const struct inode_operations sdcardfs_main_iops = {
-	.permission	= sdcardfs_permission,
-	.setattr	= sdcardfs_setattr,
+	.permission	= sdcardfs_permission_wrn,
+	.permission2	= sdcardfs_permission,
+	.setattr	= sdcardfs_setattr_wrn,
+	.setattr2	= sdcardfs_setattr,
 	.getattr	= sdcardfs_getattr,
 };
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index a01b06a..369b94e 100755
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -36,8 +36,7 @@
 
 void sdcardfs_destroy_dentry_cache(void)
 {
-	if (sdcardfs_dentry_cachep)
-		kmem_cache_destroy(sdcardfs_dentry_cachep);
+	kmem_cache_destroy(sdcardfs_dentry_cachep);
 }
 
 void free_dentry_private_data(struct dentry *dentry)
@@ -72,7 +71,8 @@
 static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
 {
 	struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
-	userid_t current_userid = SDCARDFS_I(inode)->userid;
+	userid_t current_userid = SDCARDFS_I(inode)->data->userid;
+
 	if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
 			current_userid == ((struct inode_data *)candidate_data)->id)
 		return 1; /* found a match */
@@ -91,7 +91,9 @@
 	struct sdcardfs_inode_info *info;
 	struct inode_data data;
 	struct inode *inode; /* the new inode to return */
-	int err;
+
+	if (!igrab(lower_inode))
+		return ERR_PTR(-ESTALE);
 
 	data.id = id;
 	data.lower_inode = lower_inode;
@@ -102,26 +104,23 @@
 			      * instead.
 			      */
 			     lower_inode->i_ino, /* hashval */
-			     sdcardfs_inode_test,	/* inode comparison function */
+			     sdcardfs_inode_test, /* inode comparison function */
 			     sdcardfs_inode_set, /* inode init function */
 			     &data); /* data passed to test+set fxns */
 	if (!inode) {
-		err = -EACCES;
 		iput(lower_inode);
-		return ERR_PTR(err);
+		return ERR_PTR(-ENOMEM);
 	}
-	/* if found a cached inode, then just return it */
-	if (!(inode->i_state & I_NEW))
+	/* if found a cached inode, then just return it (after iput) */
+	if (!(inode->i_state & I_NEW)) {
+		iput(lower_inode);
 		return inode;
+	}
 
 	/* initialize new inode */
 	info = SDCARDFS_I(inode);
 
 	inode->i_ino = lower_inode->i_ino;
-	if (!igrab(lower_inode)) {
-		err = -ESTALE;
-		return ERR_PTR(err);
-	}
 	sdcardfs_set_lower_inode(inode, lower_inode);
 
 	inode->i_version++;
@@ -164,27 +163,25 @@
 }
 
 /*
- * Connect a sdcardfs inode dentry/inode with several lower ones.  This is
- * the classic stackable file system "vnode interposition" action.
- *
- * @dentry: sdcardfs's dentry which interposes on lower one
- * @sb: sdcardfs's super_block
- * @lower_path: the lower path (caller does path_get/put)
+ * Helper interpose routine, called directly by ->lookup to handle
+ * spliced dentries.
  */
-int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
-		     struct path *lower_path, userid_t id)
+static struct dentry *__sdcardfs_interpose(struct dentry *dentry,
+					 struct super_block *sb,
+					 struct path *lower_path,
+					 userid_t id)
 {
-	int err = 0;
 	struct inode *inode;
 	struct inode *lower_inode;
 	struct super_block *lower_sb;
+	struct dentry *ret_dentry;
 
 	lower_inode = lower_path->dentry->d_inode;
 	lower_sb = sdcardfs_lower_super(sb);
 
 	/* check that the lower file system didn't cross a mount point */
 	if (lower_inode->i_sb != lower_sb) {
-		err = -EXDEV;
+		ret_dentry = ERR_PTR(-EXDEV);
 		goto out;
 	}
 
@@ -196,14 +193,54 @@
 	/* inherit lower inode number for sdcardfs's inode */
 	inode = sdcardfs_iget(sb, lower_inode, id);
 	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
+		ret_dentry = ERR_CAST(inode);
 		goto out;
 	}
 
-	d_add(dentry, inode);
+	ret_dentry = d_splice_alias(inode, dentry);
+	dentry = ret_dentry ?: dentry;
 	update_derived_permission_lock(dentry);
 out:
-	return err;
+	return ret_dentry;
+}
+
+/*
+ * Connect an sdcardfs inode dentry/inode with several lower ones.  This is
+ * the classic stackable file system "vnode interposition" action.
+ *
+ * @dentry: sdcardfs's dentry which interposes on lower one
+ * @sb: sdcardfs's super_block
+ * @lower_path: the lower path (caller does path_get/put)
+ */
+int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
+		     struct path *lower_path, userid_t id)
+{
+	struct dentry *ret_dentry;
+
+	ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id);
+	return PTR_ERR(ret_dentry);
+}
+
+struct sdcardfs_name_data {
+	struct dir_context ctx;
+	const struct qstr *to_find;
+	char *name;
+	bool found;
+};
+
+static int sdcardfs_name_match(void *__buf, const char *name, int namelen,
+		loff_t offset, u64 ino, unsigned int d_type)
+{
+	struct sdcardfs_name_data *buf = (struct sdcardfs_name_data *) __buf;
+	struct qstr candidate = QSTR_INIT(name, namelen);
+
+	if (qstr_case_eq(buf->to_find, &candidate)) {
+		memcpy(buf->name, name, namelen);
+		buf->name[namelen] = 0;
+		buf->found = true;
+		return 1;
+	}
+	return 0;
 }
 
 /*
@@ -219,9 +256,10 @@
 	struct vfsmount *lower_dir_mnt;
 	struct dentry *lower_dir_dentry = NULL;
 	struct dentry *lower_dentry;
-	const char *name;
+	const struct qstr *name;
 	struct path lower_path;
-	struct qstr this;
+	struct qstr dname;
+	struct dentry *ret_dentry = NULL;
 	struct sdcardfs_sb_info *sbi;
 
 	sbi = SDCARDFS_SB(dentry->d_sb);
@@ -231,47 +269,90 @@
 	if (IS_ROOT(dentry))
 		goto out;
 
-	name = dentry->d_name.name;
+	name = &dentry->d_name;
 
 	/* now start the actual lookup procedure */
 	lower_dir_dentry = lower_parent_path->dentry;
 	lower_dir_mnt = lower_parent_path->mnt;
 
 	/* Use vfs_path_lookup to check if the dentry exists or not */
-	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0,
+	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
 				&lower_path);
+	/* check for other cases */
+	if (err == -ENOENT) {
+		struct file *file;
+		const struct cred *cred = current_cred();
+
+		struct sdcardfs_name_data buffer = {
+			.ctx.actor = sdcardfs_name_match,
+			.to_find = name,
+			.name = __getname(),
+			.found = false,
+		};
+
+		if (!buffer.name) {
+			err = -ENOMEM;
+			goto out;
+		}
+		file = dentry_open(lower_parent_path, O_RDONLY, cred);
+		if (IS_ERR(file)) {
+			err = PTR_ERR(file);
+			goto put_name;
+		}
+		err = iterate_dir(file, &buffer.ctx);
+		fput(file);
+		if (err)
+			goto put_name;
+
+		if (buffer.found)
+			err = vfs_path_lookup(lower_dir_dentry,
+						lower_dir_mnt,
+						buffer.name, 0,
+						&lower_path);
+		else
+			err = -ENOENT;
+put_name:
+		__putname(buffer.name);
+	}
 
 	/* no error: handle positive dentries */
 	if (!err) {
 		/* check if the dentry is an obb dentry
 		 * if true, the lower_inode must be replaced with
-		 * the inode of the graft path */
+		 * the inode of the graft path
+		 */
 
-		if(need_graft_path(dentry)) {
+		if (need_graft_path(dentry)) {
 
 			/* setup_obb_dentry()
- 			 * The lower_path will be stored to the dentry's orig_path
+			 * The lower_path will be stored to the dentry's orig_path
 			 * and the base obbpath will be copyed to the lower_path variable.
 			 * if an error returned, there's no change in the lower_path
-			 * 		returns: -ERRNO if error (0: no error) */
+			 * returns: -ERRNO if error (0: no error)
+			 */
 			err = setup_obb_dentry(dentry, &lower_path);
 
-			if(err) {
+			if (err) {
 				/* if the sbi->obbpath is not available, we can optionally
 				 * setup the lower_path with its orig_path.
 				 * but, the current implementation just returns an error
 				 * because the sdcard daemon also regards this case as
-				 * a lookup fail. */
-				printk(KERN_INFO "sdcardfs: base obbpath is not available\n");
+				 * a lookup fail.
+				 */
+				pr_info("sdcardfs: base obbpath is not available\n");
 				sdcardfs_put_reset_orig_path(dentry);
 				goto out;
 			}
 		}
 
 		sdcardfs_set_lower_path(dentry, &lower_path);
-		err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
-		if (err) /* path_put underlying path on error */
+		ret_dentry =
+			__sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
+		if (IS_ERR(ret_dentry)) {
+			err = PTR_ERR(ret_dentry);
+			 /* path_put underlying path on error */
 			sdcardfs_put_reset_lower_path(dentry);
+		}
 		goto out;
 	}
 
@@ -283,21 +364,24 @@
 		goto out;
 
 	/* instatiate a new negative dentry */
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = full_name_hash(this.name, this.len);
-	lower_dentry = d_lookup(lower_dir_dentry, &this);
-	if (lower_dentry)
-		goto setup_lower;
+	dname.name = name->name;
+	dname.len = name->len;
 
-	lower_dentry = d_alloc(lower_dir_dentry, &this);
+	/* See if the low-level filesystem might want
+	 * to use its own hash
+	 */
+	lower_dentry = d_hash_and_lookup(lower_dir_dentry, &dname);
+	if (IS_ERR(lower_dentry))
+		return lower_dentry;
 	if (!lower_dentry) {
-		err = -ENOMEM;
+		/* We called vfs_path_lookup earlier, and did not get a negative
+		 * dentry then. Don't confuse the lower filesystem by forcing
+		 * one on it now...
+		 */
+		err = -ENOENT;
 		goto out;
 	}
-	d_add(lower_dentry, NULL); /* instantiate and hash */
 
-setup_lower:
 	lower_path.dentry = lower_dentry;
 	lower_path.mnt = mntget(lower_dir_mnt);
 	sdcardfs_set_lower_path(dentry, &lower_path);
@@ -311,14 +395,16 @@
 		err = 0;
 
 out:
-	return ERR_PTR(err);
+	if (err)
+		return ERR_PTR(err);
+	return ret_dentry;
 }
 
 /*
  * On success:
- * 	fills dentry object appropriate values and returns NULL.
+ * fills dentry object appropriate values and returns NULL.
  * On fail (== error)
- * 	returns error ptr
+ * returns error ptr
  *
  * @dir : Parent inode. It is locked (dir->i_mutex)
  * @dentry : Target dentry to lookup. we should set each of fields.
@@ -335,16 +421,13 @@
 
 	parent = dget_parent(dentry);
 
-	if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
+	if (!check_caller_access_to_name(parent->d_inode, &dentry->d_name)) {
 		ret = ERR_PTR(-EACCES);
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-                         "	dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
 		goto out_err;
-        }
+	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	sdcardfs_get_lower_path(parent, &lower_parent_path);
 
@@ -355,21 +438,19 @@
 		goto out;
 	}
 
-	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
+	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path,
+				SDCARDFS_I(dir)->data->userid);
 	if (IS_ERR(ret))
-	{
 		goto out;
-	}
 	if (ret)
 		dentry = ret;
 	if (dentry->d_inode) {
 		fsstack_copy_attr_times(dentry->d_inode,
 					sdcardfs_lower_inode(dentry->d_inode));
-		/* get drived permission */
-		mutex_lock(&dentry->d_inode->i_mutex);
+		/* get derived permission */
 		get_derived_permission(parent, dentry);
-		fix_derived_permission(dentry->d_inode);
-		mutex_unlock(&dentry->d_inode->i_mutex);
+		fixup_tmp_permissions(dentry->d_inode);
+		fixup_lower_ownership(dentry, dentry->d_name.name);
 	}
 	/* update parent directory's atime */
 	fsstack_copy_attr_atime(parent->d_inode,
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 8b51a12..129d98e 100755
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -28,9 +28,8 @@
 	Opt_fsgid,
 	Opt_gid,
 	Opt_debug,
-	Opt_lower_fs,
 	Opt_mask,
-	Opt_multiuser, // May need?
+	Opt_multiuser,
 	Opt_userid,
 	Opt_reserved_mb,
 	Opt_err,
@@ -49,7 +48,8 @@
 };
 
 static int parse_options(struct super_block *sb, char *options, int silent,
-				int *debug, struct sdcardfs_mount_options *opts)
+				int *debug, struct sdcardfs_vfsmount_options *vfsopts,
+				struct sdcardfs_mount_options *opts)
 {
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
@@ -58,10 +58,10 @@
 	/* by default, we use AID_MEDIA_RW as uid, gid */
 	opts->fs_low_uid = AID_MEDIA_RW;
 	opts->fs_low_gid = AID_MEDIA_RW;
-	opts->mask = 0;
+	vfsopts->mask = 0;
 	opts->multiuser = false;
 	opts->fs_user_id = 0;
-	opts->gid = 0;
+	vfsopts->gid = 0;
 	/* by default, 0MB is reserved */
 	opts->reserved_mb = 0;
 
@@ -72,6 +72,7 @@
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
+
 		if (!*p)
 			continue;
 
@@ -94,7 +95,7 @@
 		case Opt_gid:
 			if (match_int(&args[0], &option))
 				return 0;
-			opts->gid = option;
+			vfsopts->gid = option;
 			break;
 		case Opt_userid:
 			if (match_int(&args[0], &option))
@@ -104,7 +105,7 @@
 		case Opt_mask:
 			if (match_int(&args[0], &option))
 				return 0;
-			opts->mask = option;
+			vfsopts->mask = option;
 			break;
 		case Opt_multiuser:
 			opts->multiuser = true;
@@ -116,25 +117,81 @@
 			break;
 		/* unknown option */
 		default:
-			if (!silent) {
-				printk( KERN_ERR "Unrecognized mount option \"%s\" "
-						"or missing value", p);
-			}
+			if (!silent)
+				pr_err("Unrecognized mount option \"%s\" or missing value", p);
 			return -EINVAL;
 		}
 	}
 
 	if (*debug) {
-		printk( KERN_INFO "sdcardfs : options - debug:%d\n", *debug);
-		printk( KERN_INFO "sdcardfs : options - uid:%d\n",
+		pr_info("sdcardfs : options - debug:%d\n", *debug);
+		pr_info("sdcardfs : options - uid:%d\n",
 							opts->fs_low_uid);
-		printk( KERN_INFO "sdcardfs : options - gid:%d\n",
+		pr_info("sdcardfs : options - gid:%d\n",
 							opts->fs_low_gid);
 	}
 
 	return 0;
 }
 
+int parse_options_remount(struct super_block *sb, char *options, int silent,
+				struct sdcardfs_vfsmount_options *vfsopts)
+{
+	char *p;
+	substring_t args[MAX_OPT_ARGS];
+	int option;
+	int debug;
+
+	if (!options)
+		return 0;
+
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+
+		if (!*p)
+			continue;
+
+		token = match_token(p, sdcardfs_tokens, args);
+
+		switch (token) {
+		case Opt_debug:
+			debug = 1;
+			break;
+		case Opt_gid:
+			if (match_int(&args[0], &option))
+				return 0;
+			vfsopts->gid = option;
+
+			break;
+		case Opt_mask:
+			if (match_int(&args[0], &option))
+				return 0;
+			vfsopts->mask = option;
+			break;
+		case Opt_multiuser:
+		case Opt_userid:
+		case Opt_fsuid:
+		case Opt_fsgid:
+		case Opt_reserved_mb:
+			pr_warn("Option \"%s\" can't be changed during remount\n", p);
+			break;
+		/* unknown option */
+		default:
+			if (!silent)
+				pr_err("Unrecognized mount option \"%s\" or missing value", p);
+			return -EINVAL;
+		}
+	}
+
+	if (debug) {
+		pr_info("sdcardfs : options - debug:%d\n", debug);
+		pr_info("sdcardfs : options - gid:%d\n", vfsopts->gid);
+		pr_info("sdcardfs : options - mask:%d\n", vfsopts->mask);
+	}
+
+	return 0;
+}
+
 #if 0
 /*
  * our custom d_alloc_root work-alike
@@ -164,57 +221,58 @@
 #endif
 
 DEFINE_MUTEX(sdcardfs_super_list_lock);
-LIST_HEAD(sdcardfs_super_list);
 EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock);
+LIST_HEAD(sdcardfs_super_list);
 EXPORT_SYMBOL_GPL(sdcardfs_super_list);
 
 /*
  * There is no need to lock the sdcardfs_super_info's rwsem as there is no
  * way anyone can have a reference to the superblock at this point in time.
  */
-static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
-						void *raw_data, int silent)
+static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb,
+		const char *dev_name, void *raw_data, int silent)
 {
 	int err = 0;
 	int debug;
 	struct super_block *lower_sb;
 	struct path lower_path;
 	struct sdcardfs_sb_info *sb_info;
+	struct sdcardfs_vfsmount_options *mnt_opt = mnt->data;
 	struct inode *inode;
 
-	printk(KERN_INFO "sdcardfs version 2.0\n");
+	pr_info("sdcardfs version 2.0\n");
 
 	if (!dev_name) {
-		printk(KERN_ERR
-		       "sdcardfs: read_super: missing dev_name argument\n");
+		pr_err("sdcardfs: read_super: missing dev_name argument\n");
 		err = -EINVAL;
 		goto out;
 	}
 
-	printk(KERN_INFO "sdcardfs: dev_name -> %s\n", dev_name);
-	printk(KERN_INFO "sdcardfs: options -> %s\n", (char *)raw_data);
+	pr_info("sdcardfs: dev_name -> %s\n", dev_name);
+	pr_info("sdcardfs: options -> %s\n", (char *)raw_data);
+	pr_info("sdcardfs: mnt -> %p\n", mnt);
 
 	/* parse lower path */
 	err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
 			&lower_path);
 	if (err) {
-		printk(KERN_ERR	"sdcardfs: error accessing lower directory '%s'\n", dev_name);
+		pr_err("sdcardfs: error accessing lower directory '%s'\n", dev_name);
 		goto out;
 	}
 
 	/* allocate superblock private data */
 	sb->s_fs_info = kzalloc(sizeof(struct sdcardfs_sb_info), GFP_KERNEL);
 	if (!SDCARDFS_SB(sb)) {
-		printk(KERN_CRIT "sdcardfs: read_super: out of memory\n");
+		pr_crit("sdcardfs: read_super: out of memory\n");
 		err = -ENOMEM;
 		goto out_free;
 	}
 
 	sb_info = sb->s_fs_info;
 	/* parse options */
-	err = parse_options(sb, raw_data, silent, &debug, &sb_info->options);
+	err = parse_options(sb, raw_data, silent, &debug, mnt_opt, &sb_info->options);
 	if (err) {
-		printk(KERN_ERR	"sdcardfs: invalid options\n");
+		pr_err("sdcardfs: invalid options\n");
 		goto out_freesbi;
 	}
 
@@ -274,23 +332,24 @@
 	/* setup permission policy */
 	sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
 	mutex_lock(&sdcardfs_super_list_lock);
-	if(sb_info->options.multiuser) {
-		setup_derived_state(sb->s_root->d_inode, PERM_PRE_ROOT, sb_info->options.fs_user_id, AID_ROOT, false);
+	if (sb_info->options.multiuser) {
+		setup_derived_state(sb->s_root->d_inode, PERM_PRE_ROOT,
+				sb_info->options.fs_user_id, AID_ROOT,
+				false, SDCARDFS_I(sb->s_root->d_inode)->data);
 		snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name);
-		/*err =  prepare_dir(sb_info->obbpath_s,
-					sb_info->options.fs_low_uid,
-					sb_info->options.fs_low_gid, 00755);*/
 	} else {
-		setup_derived_state(sb->s_root->d_inode, PERM_ROOT, sb_info->options.fs_low_uid, AID_ROOT, false);
+		setup_derived_state(sb->s_root->d_inode, PERM_ROOT,
+				sb_info->options.fs_user_id, AID_ROOT,
+				false, SDCARDFS_I(sb->s_root->d_inode)->data);
 		snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
 	}
-	fix_derived_permission(sb->s_root->d_inode);
+	fixup_tmp_permissions(sb->s_root->d_inode);
 	sb_info->sb = sb;
 	list_add(&sb_info->list, &sdcardfs_super_list);
 	mutex_unlock(&sdcardfs_super_list_lock);
 
 	if (!silent)
-		printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n",
+		pr_info("sdcardfs: mounted on top of %s type %s\n",
 				dev_name, lower_sb->s_type->name);
 	goto out; /* all is well */
 
@@ -313,9 +372,11 @@
 }
 
 /* A feature which supports mount_nodev() with options */
-static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type,
-        int flags, const char *dev_name, void *data,
-        int (*fill_super)(struct super_block *, const char *, void *, int))
+static struct dentry *mount_nodev_with_options(struct vfsmount *mnt,
+			struct file_system_type *fs_type, int flags,
+			const char *dev_name, void *data,
+			int (*fill_super)(struct vfsmount *, struct super_block *,
+						const char *, void *, int))
 
 {
 	int error;
@@ -326,7 +387,7 @@
 
 	s->s_flags = flags;
 
-	error = fill_super(s, dev_name, data, flags & MS_SILENT ? 1 : 0);
+	error = fill_super(mnt, s, dev_name, data, flags & MS_SILENT ? 1 : 0);
 	if (error) {
 		deactivate_locked_super(s);
 		return ERR_PTR(error);
@@ -335,19 +396,34 @@
 	return dget(s->s_root);
 }
 
-struct dentry *sdcardfs_mount(struct file_system_type *fs_type, int flags,
+static struct dentry *sdcardfs_mount(struct vfsmount *mnt,
+		struct file_system_type *fs_type, int flags,
 			    const char *dev_name, void *raw_data)
 {
 	/*
 	 * dev_name is a lower_path_name,
 	 * raw_data is a option string.
 	 */
-	return mount_nodev_with_options(fs_type, flags, dev_name,
-					raw_data, sdcardfs_read_super);
+	return mount_nodev_with_options(mnt, fs_type, flags, dev_name,
+						raw_data, sdcardfs_read_super);
 }
 
-void sdcardfs_kill_sb(struct super_block *sb) {
+static struct dentry *sdcardfs_mount_wrn(struct file_system_type *fs_type,
+		    int flags, const char *dev_name, void *raw_data)
+{
+	WARN(1, "sdcardfs does not support mount. Use mount2.\n");
+	return ERR_PTR(-EINVAL);
+}
+
+void *sdcardfs_alloc_mnt_data(void)
+{
+	return kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
+}
+
+void sdcardfs_kill_sb(struct super_block *sb)
+{
 	struct sdcardfs_sb_info *sbi;
+
 	if (sb->s_magic == SDCARDFS_SUPER_MAGIC) {
 		sbi = SDCARDFS_SB(sb);
 		mutex_lock(&sdcardfs_super_list_lock);
@@ -360,10 +436,13 @@
 static struct file_system_type sdcardfs_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= SDCARDFS_NAME,
-	.mount		= sdcardfs_mount,
+	.mount		= sdcardfs_mount_wrn,
+	.mount2		= sdcardfs_mount,
+	.alloc_mnt_data = sdcardfs_alloc_mnt_data,
 	.kill_sb	= sdcardfs_kill_sb,
 	.fs_flags	= 0,
 };
+MODULE_ALIAS_FS(SDCARDFS_NAME);
 
 static int __init init_sdcardfs_fs(void)
 {
@@ -399,10 +478,15 @@
 	pr_info("Completed sdcardfs module unload\n");
 }
 
-MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
-	      " (http://www.fsl.cs.sunysb.edu/)");
-MODULE_DESCRIPTION("Wrapfs " SDCARDFS_VERSION
-		   " (http://wrapfs.filesystems.org/)");
+/* Original wrapfs authors */
+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University (http://www.fsl.cs.sunysb.edu/)");
+
+/* Original sdcardfs authors */
+MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil System Memory Lab., Samsung Electronics");
+
+/* Current maintainer */
+MODULE_AUTHOR("Daniel Rosenberg, Google");
+MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION);
 MODULE_LICENSE("GPL");
 
 module_init(init_sdcardfs_fs);
diff --git a/fs/sdcardfs/mmap.c b/fs/sdcardfs/mmap.c
index c807d7f..96759ca 100755
--- a/fs/sdcardfs/mmap.c
+++ b/fs/sdcardfs/mmap.c
@@ -23,28 +23,46 @@
 static int sdcardfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	int err;
-	struct file *file, *lower_file;
+	struct file *file;
 	const struct vm_operations_struct *lower_vm_ops;
-	struct vm_area_struct lower_vma;
 
-	memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
-	file = lower_vma.vm_file;
+	file = (struct file *)vma->vm_private_data;
 	lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops;
 	BUG_ON(!lower_vm_ops);
 
-	lower_file = sdcardfs_lower_file(file);
-	/*
-	 * XXX: vm_ops->fault may be called in parallel.  Because we have to
-	 * resort to temporarily changing the vma->vm_file to point to the
-	 * lower file, a concurrent invocation of sdcardfs_fault could see a
-	 * different value.  In this workaround, we keep a different copy of
-	 * the vma structure in our stack, so we never expose a different
-	 * value of the vma->vm_file called to us, even temporarily.  A
-	 * better fix would be to change the calling semantics of ->fault to
-	 * take an explicit file pointer.
-	 */
-	lower_vma.vm_file = lower_file;
-	err = lower_vm_ops->fault(&lower_vma, vmf);
+	err = lower_vm_ops->fault(vma, vmf);
+	return err;
+}
+
+static void sdcardfs_vm_open(struct vm_area_struct *vma)
+{
+	struct file *file = (struct file *)vma->vm_private_data;
+
+	get_file(file);
+}
+
+static void sdcardfs_vm_close(struct vm_area_struct *vma)
+{
+	struct file *file = (struct file *)vma->vm_private_data;
+
+	fput(file);
+}
+
+static int sdcardfs_page_mkwrite(struct vm_area_struct *vma,
+			       struct vm_fault *vmf)
+{
+	int err = 0;
+	struct file *file;
+	const struct vm_operations_struct *lower_vm_ops;
+
+	file = (struct file *)vma->vm_private_data;
+	lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops;
+	BUG_ON(!lower_vm_ops);
+	if (!lower_vm_ops->page_mkwrite)
+		goto out;
+
+	err = lower_vm_ops->page_mkwrite(vma, vmf);
+out:
 	return err;
 }
 
@@ -53,30 +71,20 @@
 			      unsigned long nr_segs)
 {
 	/*
-     * This function returns zero on purpose in order to support direct IO.
-	 * __dentry_open checks a_ops->direct_IO and returns EINVAL if it is null.
-     *
-	 * However, this function won't be called by certain file operations
-     * including generic fs functions.  * reads and writes are delivered to
-     * the lower file systems and the direct IOs will be handled by them.
-	 *
-     * NOTE: exceptionally, on the recent kernels (since Linux 3.8.x),
-     * swap_writepage invokes this function directly.
+	 * This function should never be called directly.  We need it
+	 * to exist, to get past a check in open_check_o_direct(),
+	 * which is called from do_last().
 	 */
-	printk(KERN_INFO "%s, operation is not supported\n", __func__);
-	return 0;
+	return -EINVAL;
 }
 
-/*
- * XXX: the default address_space_ops for sdcardfs is empty.  We cannot set
- * our inode->i_mapping->a_ops to NULL because too many code paths expect
- * the a_ops vector to be non-NULL.
- */
 const struct address_space_operations sdcardfs_aops = {
-	/* empty on purpose */
 	.direct_IO	= sdcardfs_direct_IO,
 };
 
 const struct vm_operations_struct sdcardfs_vm_ops = {
 	.fault		= sdcardfs_fault,
+	.page_mkwrite	= sdcardfs_page_mkwrite,
+	.open		= sdcardfs_vm_open,
+	.close		= sdcardfs_vm_close,
 };
diff --git a/fs/sdcardfs/multiuser.h b/fs/sdcardfs/multiuser.h
index 923ba10..85341e7 100755
--- a/fs/sdcardfs/multiuser.h
+++ b/fs/sdcardfs/multiuser.h
@@ -18,20 +18,36 @@
  * General Public License.
  */
 
-#define MULTIUSER_APP_PER_USER_RANGE 100000
+#define AID_USER_OFFSET     100000 /* offset for uid ranges for each user */
+#define AID_APP_START        10000 /* first app user */
+#define AID_APP_END          19999 /* last app user */
+#define AID_CACHE_GID_START  20000 /* start of gids for apps to mark cached data */
+#define AID_EXT_GID_START    30000 /* start of gids for apps to mark external data */
+#define AID_EXT_CACHE_GID_START 40000 /* start of gids for apps to mark external cached data */
+#define AID_EXT_CACHE_GID_END 49999   /* end of gids for apps to mark external cached data */
+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
 
 typedef uid_t userid_t;
 typedef uid_t appid_t;
 
-static inline userid_t multiuser_get_user_id(uid_t uid) {
-    return uid / MULTIUSER_APP_PER_USER_RANGE;
+static inline uid_t multiuser_get_uid(userid_t user_id, appid_t app_id)
+{
+	return (user_id * AID_USER_OFFSET) + (app_id % AID_USER_OFFSET);
 }
 
-static inline appid_t multiuser_get_app_id(uid_t uid) {
-    return uid % MULTIUSER_APP_PER_USER_RANGE;
+static inline bool uid_is_app(uid_t uid)
+{
+	appid_t appid = uid % AID_USER_OFFSET;
+
+	return appid >= AID_APP_START && appid <= AID_APP_END;
 }
 
-static inline uid_t multiuser_get_uid(userid_t userId, appid_t appId) {
-    return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE);
+static inline gid_t multiuser_get_ext_cache_gid(uid_t uid)
+{
+	return uid - AID_APP_START + AID_EXT_CACHE_GID_START;
 }
 
+static inline gid_t multiuser_get_ext_gid(uid_t uid)
+{
+	return uid - AID_APP_START + AID_EXT_GID_START;
+}
diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c
index 0cf9c34..f120bcc 100755
--- a/fs/sdcardfs/packagelist.c
+++ b/fs/sdcardfs/packagelist.c
@@ -20,8 +20,10 @@
 
 #include "sdcardfs.h"
 #include <linux/hashtable.h>
+#include <linux/ctype.h>
 #include <linux/delay.h>
-
+#include <linux/radix-tree.h>
+#include <linux/dcache.h>
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -29,389 +31,840 @@
 
 #include <linux/configfs.h>
 
-#define STRING_BUF_SIZE		(512)
-
 struct hashtable_entry {
 	struct hlist_node hlist;
-	void *key;
-	unsigned int value;
+	struct hlist_node dlist; /* for deletion cleanup */
+	struct qstr key;
+	atomic_t value;
 };
 
-struct sb_list {
-	struct super_block *sb;
-	struct list_head list;
-};
+static DEFINE_HASHTABLE(package_to_appid, 8);
+static DEFINE_HASHTABLE(package_to_userid, 8);
+static DEFINE_HASHTABLE(ext_to_groupid, 8);
 
-struct packagelist_data {
-	DECLARE_HASHTABLE(package_to_appid,8);
-	struct mutex hashtable_lock;
-
-};
-
-static struct packagelist_data *pkgl_data_all;
 
 static struct kmem_cache *hashtable_entry_cachep;
 
-static unsigned int str_hash(const char *key) {
-	int i;
-	unsigned int h = strlen(key);
-	char *data = (char *)key;
+static unsigned int full_name_case_hash(const unsigned char *name, unsigned int len)
+{
+	unsigned long hash = init_name_hash();
 
-	for (i = 0; i < strlen(key); i++) {
-		h = h * 31 + *data;
-		data++;
-	}
-	return h;
+	while (len--)
+		hash = partial_name_hash(tolower(*name++), hash);
+	return end_name_hash(hash);
 }
 
-appid_t get_appid(void *pkgl_id, const char *app_name)
+static inline void qstr_init(struct qstr *q, const char *name)
 {
-	struct packagelist_data *pkgl_dat = pkgl_data_all;
+	q->name = name;
+	q->len = strlen(q->name);
+	q->hash = full_name_case_hash(q->name, q->len);
+}
+
+static inline int qstr_copy(const struct qstr *src, struct qstr *dest)
+{
+	dest->name = kstrdup(src->name, GFP_KERNEL);
+	dest->hash_len = src->hash_len;
+	return !!dest->name;
+}
+
+
+static appid_t __get_appid(const struct qstr *key)
+{
 	struct hashtable_entry *hash_cur;
-	unsigned int hash = str_hash(app_name);
+	unsigned int hash = key->hash;
 	appid_t ret_id;
 
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
-		if (!strcasecmp(app_name, hash_cur->key)) {
-			ret_id = (appid_t)hash_cur->value;
-			mutex_unlock(&pkgl_dat->hashtable_lock);
+	rcu_read_lock();
+	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			ret_id = atomic_read(&hash_cur->value);
+			rcu_read_unlock();
 			return ret_id;
 		}
 	}
-	mutex_unlock(&pkgl_dat->hashtable_lock);
+	rcu_read_unlock();
 	return 0;
 }
 
+appid_t get_appid(const char *key)
+{
+	struct qstr q;
+
+	qstr_init(&q, key);
+	return __get_appid(&q);
+}
+
+static appid_t __get_ext_gid(const struct qstr *key)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+	appid_t ret_id;
+
+	rcu_read_lock();
+	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			ret_id = atomic_read(&hash_cur->value);
+			rcu_read_unlock();
+			return ret_id;
+		}
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+appid_t get_ext_gid(const char *key)
+{
+	struct qstr q;
+
+	qstr_init(&q, key);
+	return __get_ext_gid(&q);
+}
+
+static appid_t __is_excluded(const struct qstr *app_name, userid_t user)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = app_name->hash;
+
+	rcu_read_lock();
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (atomic_read(&hash_cur->value) == user &&
+				qstr_case_eq(app_name, &hash_cur->key)) {
+			rcu_read_unlock();
+			return 1;
+		}
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+appid_t is_excluded(const char *key, userid_t user)
+{
+	struct qstr q;
+
+	qstr_init(&q, key);
+	return __is_excluded(&q, user);
+}
+
 /* Kernel has already enforced everything we returned through
  * derive_permissions_locked(), so this is used to lock down access
- * even further, such as enforcing that apps hold sdcard_rw. */
-int check_caller_access_to_name(struct inode *parent_node, const char* name) {
+ * even further, such as enforcing that apps hold sdcard_rw.
+ */
+int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name)
+{
+	struct qstr q_autorun = QSTR_LITERAL("autorun.inf");
+	struct qstr q__android_secure = QSTR_LITERAL(".android_secure");
+	struct qstr q_android_secure = QSTR_LITERAL("android_secure");
 
 	/* Always block security-sensitive files at root */
-	if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) {
-		if (!strcasecmp(name, "autorun.inf")
-			|| !strcasecmp(name, ".android_secure")
-			|| !strcasecmp(name, "android_secure")) {
+	if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) {
+		if (qstr_case_eq(name, &q_autorun)
+			|| qstr_case_eq(name, &q__android_secure)
+			|| qstr_case_eq(name, &q_android_secure)) {
 			return 0;
 		}
 	}
 
 	/* Root always has access; access for any other UIDs should always
-	 * be controlled through packages.list. */
-	if (current_fsuid() == 0) {
+	 * be controlled through packages.list.
+	 */
+	if (current_fsuid() == 0)
 		return 1;
-	}
 
 	/* No extra permissions to enforce */
 	return 1;
 }
 
 /* This function is used when file opening. The open flags must be
- * checked before calling check_caller_access_to_name() */
-int open_flags_to_access_mode(int open_flags) {
-	if((open_flags & O_ACCMODE) == O_RDONLY) {
-		return 0; /* R_OK */
-	} else if ((open_flags & O_ACCMODE) == O_WRONLY) {
-		return 1; /* W_OK */
-	} else {
-		/* Probably O_RDRW, but treat as default to be safe */
-		return 1; /* R_OK | W_OK */
-	}
-}
-
-static int insert_str_to_int_lock(struct packagelist_data *pkgl_dat, char *key,
-		unsigned int value)
+ * checked before calling check_caller_access_to_name()
+ */
+int open_flags_to_access_mode(int open_flags)
 {
-	struct hashtable_entry *hash_cur;
-	struct hashtable_entry *new_entry;
-	unsigned int hash = str_hash(key);
-
-	hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
-		if (!strcasecmp(key, hash_cur->key)) {
-			hash_cur->value = value;
-			return 0;
-		}
-	}
-	new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL);
-	if (!new_entry)
-		return -ENOMEM;
-	new_entry->key = kstrdup(key, GFP_KERNEL);
-	new_entry->value = value;
-	hash_add(pkgl_dat->package_to_appid, &new_entry->hlist, hash);
-	return 0;
+	if ((open_flags & O_ACCMODE) == O_RDONLY)
+		return 0; /* R_OK */
+	if ((open_flags & O_ACCMODE) == O_WRONLY)
+		return 1; /* W_OK */
+	/* Probably O_RDRW, but treat as default to be safe */
+		return 1; /* R_OK | W_OK */
 }
 
-static void fixup_perms(struct super_block *sb) {
-	if (sb && sb->s_magic == SDCARDFS_SUPER_MAGIC) {
-		mutex_lock(&sb->s_root->d_inode->i_mutex);
-		get_derive_permissions_recursive(sb->s_root);
-		mutex_unlock(&sb->s_root->d_inode->i_mutex);
-	}
-}
+static struct hashtable_entry *alloc_hashtable_entry(const struct qstr *key,
+		appid_t value)
+{
+	struct hashtable_entry *ret = kmem_cache_alloc(hashtable_entry_cachep,
+			GFP_KERNEL);
+	if (!ret)
+		return NULL;
+	INIT_HLIST_NODE(&ret->dlist);
+	INIT_HLIST_NODE(&ret->hlist);
 
-static int insert_str_to_int(struct packagelist_data *pkgl_dat, char *key,
-		unsigned int value) {
-	int ret;
-	struct sdcardfs_sb_info *sbinfo;
-	mutex_lock(&sdcardfs_super_list_lock);
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	ret = insert_str_to_int_lock(pkgl_dat, key, value);
-	mutex_unlock(&pkgl_dat->hashtable_lock);
-
-	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
-		if (sbinfo) {
-			fixup_perms(sbinfo->sb);
-		}
+	if (!qstr_copy(key, &ret->key)) {
+		kmem_cache_free(hashtable_entry_cachep, ret);
+		return NULL;
 	}
-	mutex_unlock(&sdcardfs_super_list_lock);
+
+	atomic_set(&ret->value, value);
 	return ret;
 }
 
-static void remove_str_to_int_lock(struct hashtable_entry *h_entry) {
-	kfree(h_entry->key);
-	hash_del(&h_entry->hlist);
-	kmem_cache_free(hashtable_entry_cachep, h_entry);
+static int insert_packagelist_appid_entry_locked(const struct qstr *key, appid_t value)
+{
+	struct hashtable_entry *hash_cur;
+	struct hashtable_entry *new_entry;
+	unsigned int hash = key->hash;
+
+	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			atomic_set(&hash_cur->value, value);
+			return 0;
+		}
+	}
+	new_entry = alloc_hashtable_entry(key, value);
+	if (!new_entry)
+		return -ENOMEM;
+	hash_add_rcu(package_to_appid, &new_entry->hlist, hash);
+	return 0;
 }
 
-static void remove_str_to_int(struct packagelist_data *pkgl_dat, const char *key)
+static int insert_ext_gid_entry_locked(const struct qstr *key, appid_t value)
+{
+	struct hashtable_entry *hash_cur;
+	struct hashtable_entry *new_entry;
+	unsigned int hash = key->hash;
+
+	/* An extension can only belong to one gid */
+	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key))
+			return -EINVAL;
+	}
+	new_entry = alloc_hashtable_entry(key, value);
+	if (!new_entry)
+		return -ENOMEM;
+	hash_add_rcu(ext_to_groupid, &new_entry->hlist, hash);
+	return 0;
+}
+
+static int insert_userid_exclude_entry_locked(const struct qstr *key, userid_t value)
+{
+	struct hashtable_entry *hash_cur;
+	struct hashtable_entry *new_entry;
+	unsigned int hash = key->hash;
+
+	/* Only insert if not already present */
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (atomic_read(&hash_cur->value) == value &&
+				qstr_case_eq(key, &hash_cur->key))
+			return 0;
+	}
+	new_entry = alloc_hashtable_entry(key, value);
+	if (!new_entry)
+		return -ENOMEM;
+	hash_add_rcu(package_to_userid, &new_entry->hlist, hash);
+	return 0;
+}
+
+static void fixup_all_perms_name(const struct qstr *key)
 {
 	struct sdcardfs_sb_info *sbinfo;
-	struct hashtable_entry *hash_cur;
-	unsigned int hash = str_hash(key);
+	struct limit_search limit = {
+		.flags = BY_NAME,
+		.name = QSTR_INIT(key->name, key->len),
+	};
+	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+		if (sbinfo_has_sdcard_magic(sbinfo))
+			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
+	}
+}
+
+static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid)
+{
+	struct sdcardfs_sb_info *sbinfo;
+	struct limit_search limit = {
+		.flags = BY_NAME | BY_USERID,
+		.name = QSTR_INIT(key->name, key->len),
+		.userid = userid,
+	};
+	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+		if (sbinfo_has_sdcard_magic(sbinfo))
+			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
+	}
+}
+
+static void fixup_all_perms_userid(userid_t userid)
+{
+	struct sdcardfs_sb_info *sbinfo;
+	struct limit_search limit = {
+		.flags = BY_USERID,
+		.userid = userid,
+	};
+	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+		if (sbinfo_has_sdcard_magic(sbinfo))
+			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
+	}
+}
+
+static int insert_packagelist_entry(const struct qstr *key, appid_t value)
+{
+	int err;
+
 	mutex_lock(&sdcardfs_super_list_lock);
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
-		if (!strcasecmp(key, hash_cur->key)) {
-			remove_str_to_int_lock(hash_cur);
+	err = insert_packagelist_appid_entry_locked(key, value);
+	if (!err)
+		fixup_all_perms_name(key);
+	mutex_unlock(&sdcardfs_super_list_lock);
+
+	return err;
+}
+
+static int insert_ext_gid_entry(const struct qstr *key, appid_t value)
+{
+	int err;
+
+	mutex_lock(&sdcardfs_super_list_lock);
+	err = insert_ext_gid_entry_locked(key, value);
+	mutex_unlock(&sdcardfs_super_list_lock);
+
+	return err;
+}
+
+static int insert_userid_exclude_entry(const struct qstr *key, userid_t value)
+{
+	int err;
+
+	mutex_lock(&sdcardfs_super_list_lock);
+	err = insert_userid_exclude_entry_locked(key, value);
+	if (!err)
+		fixup_all_perms_name_userid(key, value);
+	mutex_unlock(&sdcardfs_super_list_lock);
+
+	return err;
+}
+
+static void free_hashtable_entry(struct hashtable_entry *entry)
+{
+	kfree(entry->key.name);
+	kmem_cache_free(hashtable_entry_cachep, entry);
+}
+
+static void remove_packagelist_entry_locked(const struct qstr *key)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+	struct hlist_node *h_t;
+	HLIST_HEAD(free_list);
+
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			hash_del_rcu(&hash_cur->hlist);
+			hlist_add_head(&hash_cur->dlist, &free_list);
+		}
+	}
+	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			hash_del_rcu(&hash_cur->hlist);
+			hlist_add_head(&hash_cur->dlist, &free_list);
 			break;
 		}
 	}
-	mutex_unlock(&pkgl_dat->hashtable_lock);
-	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
-		if (sbinfo) {
-			fixup_perms(sbinfo->sb);
-		}
-	}
-	mutex_unlock(&sdcardfs_super_list_lock);
-	return;
+	synchronize_rcu();
+	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
+		free_hashtable_entry(hash_cur);
 }
 
-static void remove_all_hashentrys(struct packagelist_data *pkgl_dat)
+static void remove_packagelist_entry(const struct qstr *key)
+{
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_packagelist_entry_locked(key);
+	fixup_all_perms_name(key);
+	mutex_unlock(&sdcardfs_super_list_lock);
+}
+
+static void remove_ext_gid_entry_locked(const struct qstr *key, gid_t group)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+
+	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) {
+			hash_del_rcu(&hash_cur->hlist);
+			synchronize_rcu();
+			free_hashtable_entry(hash_cur);
+			break;
+		}
+	}
+}
+
+static void remove_ext_gid_entry(const struct qstr *key, gid_t group)
+{
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_ext_gid_entry_locked(key, group);
+	mutex_unlock(&sdcardfs_super_list_lock);
+}
+
+static void remove_userid_all_entry_locked(userid_t userid)
 {
 	struct hashtable_entry *hash_cur;
 	struct hlist_node *h_t;
+	HLIST_HEAD(free_list);
 	int i;
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	hash_for_each_safe(pkgl_dat->package_to_appid, i, h_t, hash_cur, hlist)
-		remove_str_to_int_lock(hash_cur);
-	mutex_unlock(&pkgl_dat->hashtable_lock);
-	hash_init(pkgl_dat->package_to_appid);
-}
 
-static struct packagelist_data * packagelist_create(void)
-{
-	struct packagelist_data *pkgl_dat;
-
-	pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO);
-	if (!pkgl_dat) {
-                printk(KERN_ERR "sdcardfs: Failed to create hash\n");
-		return ERR_PTR(-ENOMEM);
+	hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
+		if (atomic_read(&hash_cur->value) == userid) {
+			hash_del_rcu(&hash_cur->hlist);
+			hlist_add_head(&hash_cur->dlist, &free_list);
+		}
 	}
-
-	mutex_init(&pkgl_dat->hashtable_lock);
-	hash_init(pkgl_dat->package_to_appid);
-
-	return pkgl_dat;
+	synchronize_rcu();
+	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) {
+		free_hashtable_entry(hash_cur);
+	}
 }
 
-static void packagelist_destroy(struct packagelist_data *pkgl_dat)
+static void remove_userid_all_entry(userid_t userid)
 {
-	remove_all_hashentrys(pkgl_dat);
-	printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld\n");
-	kfree(pkgl_dat);
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_userid_all_entry_locked(userid);
+	fixup_all_perms_userid(userid);
+	mutex_unlock(&sdcardfs_super_list_lock);
 }
 
-struct package_appid {
+static void remove_userid_exclude_entry_locked(const struct qstr *key, userid_t userid)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key) &&
+				atomic_read(&hash_cur->value) == userid) {
+			hash_del_rcu(&hash_cur->hlist);
+			synchronize_rcu();
+			free_hashtable_entry(hash_cur);
+			break;
+		}
+	}
+}
+
+static void remove_userid_exclude_entry(const struct qstr *key, userid_t userid)
+{
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_userid_exclude_entry_locked(key, userid);
+	fixup_all_perms_name_userid(key, userid);
+	mutex_unlock(&sdcardfs_super_list_lock);
+}
+
+static void packagelist_destroy(void)
+{
+	struct hashtable_entry *hash_cur;
+	struct hlist_node *h_t;
+	HLIST_HEAD(free_list);
+	int i;
+
+	mutex_lock(&sdcardfs_super_list_lock);
+	hash_for_each_rcu(package_to_appid, i, hash_cur, hlist) {
+		hash_del_rcu(&hash_cur->hlist);
+		hlist_add_head(&hash_cur->dlist, &free_list);
+	}
+	hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
+		hash_del_rcu(&hash_cur->hlist);
+		hlist_add_head(&hash_cur->dlist, &free_list);
+	}
+	synchronize_rcu();
+	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
+		free_hashtable_entry(hash_cur);
+	mutex_unlock(&sdcardfs_super_list_lock);
+	pr_info("sdcardfs: destroyed packagelist pkgld\n");
+}
+
+struct package_details {
 	struct config_item item;
-	int add_pid;
+	struct qstr name;
 };
 
-static inline struct package_appid *to_package_appid(struct config_item *item)
+static inline struct package_details *to_package_details(struct config_item *item)
 {
-	return item ? container_of(item, struct package_appid, item) : NULL;
+	return item ? container_of(item, struct package_details, item) : NULL;
 }
 
-static struct configfs_attribute package_appid_attr_add_pid = {
-	.ca_owner = THIS_MODULE,
-	.ca_name = "appid",
-	.ca_mode = S_IRUGO | S_IWUGO,
-};
+CONFIGFS_ATTR_STRUCT(package_details);
+#define PACKAGE_DETAILS_ATTR(_name, _mode, _show, _store)	\
+struct package_details_attribute package_details_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
+#define PACKAGE_DETAILS_ATTRIBUTE(name) (&package_details_attr_##name.attr)
 
-static struct configfs_attribute *package_appid_attrs[] = {
-	&package_appid_attr_add_pid,
-	NULL,
-};
-
-static ssize_t package_appid_attr_show(struct config_item *item,
-				      struct configfs_attribute *attr,
+static ssize_t package_details_appid_show(struct package_details *package_details,
 				      char *page)
 {
-	ssize_t count;
-	count = sprintf(page, "%d\n", get_appid(pkgl_data_all, item->ci_name));
-	return count;
+	return scnprintf(page, PAGE_SIZE, "%u\n", __get_appid(&package_details->name));
 }
 
-static ssize_t package_appid_attr_store(struct config_item *item,
-				       struct configfs_attribute *attr,
+static ssize_t package_details_appid_store(struct package_details *package_details,
 				       const char *page, size_t count)
 {
-	struct package_appid *package_appid = to_package_appid(item);
-	unsigned long tmp;
-	char *p = (char *) page;
+	unsigned int tmp;
 	int ret;
 
-	tmp = simple_strtoul(p, &p, 10);
-	if (!p || (*p && (*p != '\n')))
-		return -EINVAL;
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
 
-	if (tmp > INT_MAX)
-		return -ERANGE;
-	ret = insert_str_to_int(pkgl_data_all, item->ci_name, (unsigned int)tmp);
-	package_appid->add_pid = tmp;
+	ret = insert_packagelist_entry(&package_details->name, tmp);
+
 	if (ret)
 		return ret;
 
 	return count;
 }
 
-static void package_appid_release(struct config_item *item)
+static ssize_t package_details_excluded_userids_show(struct package_details *package_details,
+				      char *page)
 {
-	printk(KERN_INFO "sdcardfs: removing %s\n", item->ci_dentry->d_name.name);
-	/* item->ci_name is freed already, so we rely on the dentry */
-	remove_str_to_int(pkgl_data_all, item->ci_dentry->d_name.name);
-	kfree(to_package_appid(item));
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = package_details->name.hash;
+	int count = 0;
+
+	rcu_read_lock();
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(&package_details->name, &hash_cur->key))
+			count += scnprintf(page + count, PAGE_SIZE - count,
+					"%d ", atomic_read(&hash_cur->value));
+	}
+	rcu_read_unlock();
+	if (count)
+		count--;
+	count += scnprintf(page + count, PAGE_SIZE - count, "\n");
+	return count;
 }
 
-static struct configfs_item_operations package_appid_item_ops = {
-	.release		= package_appid_release,
-	.show_attribute		= package_appid_attr_show,
-	.store_attribute	= package_appid_attr_store,
-};
-
-static struct config_item_type package_appid_type = {
-	.ct_item_ops	= &package_appid_item_ops,
-	.ct_attrs	= package_appid_attrs,
-	.ct_owner	= THIS_MODULE,
-};
-
-
-struct sdcardfs_packages {
-	struct config_group group;
-};
-
-static inline struct sdcardfs_packages *to_sdcardfs_packages(struct config_item *item)
+static ssize_t package_details_excluded_userids_store(struct package_details *package_details,
+				       const char *page, size_t count)
 {
-	return item ? container_of(to_config_group(item), struct sdcardfs_packages, group) : NULL;
+	unsigned int tmp;
+	int ret;
+
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
+
+	ret = insert_userid_exclude_entry(&package_details->name, tmp);
+
+	if (ret)
+		return ret;
+
+	return count;
 }
 
-static struct config_item *sdcardfs_packages_make_item(struct config_group *group, const char *name)
+static ssize_t package_details_clear_userid_store(struct package_details *package_details,
+				       const char *page, size_t count)
 {
-	struct package_appid *package_appid;
+	unsigned int tmp;
+	int ret;
 
-	package_appid = kzalloc(sizeof(struct package_appid), GFP_KERNEL);
-	if (!package_appid)
-		return ERR_PTR(-ENOMEM);
-
-	config_item_init_type_name(&package_appid->item, name,
-				   &package_appid_type);
-
-	package_appid->add_pid = 0;
-
-	return &package_appid->item;
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
+	remove_userid_exclude_entry(&package_details->name, tmp);
+	return count;
 }
 
-static struct configfs_attribute sdcardfs_packages_attr_description = {
-	.ca_owner = THIS_MODULE,
-	.ca_name = "packages_gid.list",
-	.ca_mode = S_IRUGO,
-};
+static void package_details_release(struct config_item *item)
+{
+	struct package_details *package_details = to_package_details(item);
 
-static struct configfs_attribute *sdcardfs_packages_attrs[] = {
-	&sdcardfs_packages_attr_description,
+	pr_info("sdcardfs: removing %s\n", package_details->name.name);
+	remove_packagelist_entry(&package_details->name);
+	kfree(package_details->name.name);
+	kfree(package_details);
+}
+
+PACKAGE_DETAILS_ATTR(appid, S_IRUGO | S_IWUGO, package_details_appid_show, package_details_appid_store);
+PACKAGE_DETAILS_ATTR(excluded_userids, S_IRUGO | S_IWUGO,
+		package_details_excluded_userids_show, package_details_excluded_userids_store);
+PACKAGE_DETAILS_ATTR(clear_userid, S_IWUGO, NULL, package_details_clear_userid_store);
+
+static struct configfs_attribute *package_details_attrs[] = {
+	PACKAGE_DETAILS_ATTRIBUTE(appid),
+	PACKAGE_DETAILS_ATTRIBUTE(excluded_userids),
+	PACKAGE_DETAILS_ATTRIBUTE(clear_userid),
 	NULL,
 };
 
-static ssize_t packages_attr_show(struct config_item *item,
-					 struct configfs_attribute *attr,
+CONFIGFS_ATTR_OPS(package_details);
+
+static struct configfs_item_operations package_details_item_ops = {
+	.release = package_details_release,
+	.show_attribute = package_details_attr_show,
+	.store_attribute = package_details_attr_store,
+};
+
+static struct config_item_type package_appid_type = {
+	.ct_item_ops	= &package_details_item_ops,
+	.ct_attrs	= package_details_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+struct extensions_value {
+	struct config_group group;
+	unsigned int num;
+};
+
+struct extension_details {
+	struct config_item item;
+	struct qstr name;
+	unsigned int num;
+};
+
+static inline struct extensions_value *to_extensions_value(struct config_item *item)
+{
+	return item ? container_of(to_config_group(item), struct extensions_value, group) : NULL;
+}
+
+static inline struct extension_details *to_extension_details(struct config_item *item)
+{
+	return item ? container_of(item, struct extension_details, item) : NULL;
+}
+
+static void extension_details_release(struct config_item *item)
+{
+	struct extension_details *extension_details = to_extension_details(item);
+
+	pr_info("sdcardfs: No longer mapping %s files to gid %d\n",
+			extension_details->name.name, extension_details->num);
+	remove_ext_gid_entry(&extension_details->name, extension_details->num);
+	kfree(extension_details->name.name);
+	kfree(extension_details);
+}
+
+static struct configfs_item_operations extension_details_item_ops = {
+	.release = extension_details_release,
+};
+
+static struct config_item_type extension_details_type = {
+	.ct_item_ops = &extension_details_item_ops,
+	.ct_owner = THIS_MODULE,
+};
+
+static struct config_item *extension_details_make_item(struct config_group *group, const char *name)
+{
+	struct extensions_value *extensions_value = to_extensions_value(&group->cg_item);
+	struct extension_details *extension_details = kzalloc(sizeof(struct extension_details), GFP_KERNEL);
+	const char *tmp;
+	int ret;
+
+	if (!extension_details)
+		return ERR_PTR(-ENOMEM);
+
+	tmp = kstrdup(name, GFP_KERNEL);
+	if (!tmp) {
+		kfree(extension_details);
+		return ERR_PTR(-ENOMEM);
+	}
+	qstr_init(&extension_details->name, tmp);
+	ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num);
+
+	if (ret) {
+		kfree(extension_details->name.name);
+		kfree(extension_details);
+		return ERR_PTR(ret);
+	}
+	config_item_init_type_name(&extension_details->item, name, &extension_details_type);
+
+	return &extension_details->item;
+}
+
+static struct configfs_group_operations extensions_value_group_ops = {
+	.make_item = extension_details_make_item,
+};
+
+static struct config_item_type extensions_name_type = {
+	.ct_group_ops	= &extensions_value_group_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *extensions_make_group(struct config_group *group, const char *name)
+{
+	struct extensions_value *extensions_value;
+	unsigned int tmp;
+	int ret;
+
+	extensions_value = kzalloc(sizeof(struct extensions_value), GFP_KERNEL);
+	if (!extensions_value)
+		return ERR_PTR(-ENOMEM);
+	ret = kstrtouint(name, 10, &tmp);
+	if (ret) {
+		kfree(extensions_value);
+		return ERR_PTR(ret);
+	}
+
+	extensions_value->num = tmp;
+	config_group_init_type_name(&extensions_value->group, name,
+						&extensions_name_type);
+	return &extensions_value->group;
+}
+
+static void extensions_drop_group(struct config_group *group, struct config_item *item)
+{
+	struct extensions_value *value = to_extensions_value(item);
+
+	pr_info("sdcardfs: No longer mapping any files to gid %d\n", value->num);
+	kfree(value);
+}
+
+static struct configfs_group_operations extensions_group_ops = {
+	.make_group	= extensions_make_group,
+	.drop_item	= extensions_drop_group,
+};
+
+static struct config_item_type extensions_type = {
+	.ct_group_ops	= &extensions_group_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+struct config_group extension_group = {
+	.cg_item = {
+		.ci_namebuf = "extensions",
+		.ci_type = &extensions_type,
+	},
+};
+
+struct packages {
+	struct configfs_subsystem subsystem;
+};
+
+static inline struct packages *to_packages(struct config_item *item)
+{
+	return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct packages, subsystem) : NULL;
+}
+
+CONFIGFS_ATTR_STRUCT(packages);
+#define PACKAGES_ATTR(_name, _mode, _show, _store)	\
+struct packages_attribute packages_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
+#define PACKAGES_ATTR_RO(_name, _show)	\
+struct packages_attribute packages_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show)
+
+static struct config_item *packages_make_item(struct config_group *group, const char *name)
+{
+	struct package_details *package_details;
+	const char *tmp;
+
+	package_details = kzalloc(sizeof(struct package_details), GFP_KERNEL);
+	if (!package_details)
+		return ERR_PTR(-ENOMEM);
+	tmp = kstrdup(name, GFP_KERNEL);
+	if (!tmp) {
+		kfree(package_details);
+		return ERR_PTR(-ENOMEM);
+	}
+	qstr_init(&package_details->name, tmp);
+	config_item_init_type_name(&package_details->item, name,
+						&package_appid_type);
+
+	return &package_details->item;
+}
+
+static ssize_t packages_list_show(struct packages *packages,
 					 char *page)
 {
-	struct hashtable_entry *hash_cur;
-	struct hlist_node *h_t;
+	struct hashtable_entry *hash_cur_app;
+	struct hashtable_entry *hash_cur_user;
 	int i;
 	int count = 0, written = 0;
-	char errormsg[] = "<truncated>\n";
+	const char errormsg[] = "<truncated>\n";
+	unsigned int hash;
 
-	mutex_lock(&pkgl_data_all->hashtable_lock);
-	hash_for_each_safe(pkgl_data_all->package_to_appid, i, h_t, hash_cur, hlist) {
-		written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n", (char *)hash_cur->key, hash_cur->value);
-		if (count + written == PAGE_SIZE - sizeof(errormsg)) {
+	rcu_read_lock();
+	hash_for_each_rcu(package_to_appid, i, hash_cur_app, hlist) {
+		written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n",
+					hash_cur_app->key.name, atomic_read(&hash_cur_app->value));
+		hash = hash_cur_app->key.hash;
+		hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) {
+			if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) {
+				written += scnprintf(page + count + written - 1,
+					PAGE_SIZE - sizeof(errormsg) - count - written + 1,
+					" %d\n", atomic_read(&hash_cur_user->value)) - 1;
+			}
+		}
+		if (count + written == PAGE_SIZE - sizeof(errormsg) - 1) {
 			count += scnprintf(page + count, PAGE_SIZE - count, errormsg);
 			break;
 		}
 		count += written;
 	}
-	mutex_unlock(&pkgl_data_all->hashtable_lock);
+	rcu_read_unlock();
 
 	return count;
 }
 
-static void sdcardfs_packages_release(struct config_item *item)
+static ssize_t packages_remove_userid_store(struct packages *packages,
+				       const char *page, size_t count)
 {
+	unsigned int tmp;
+	int ret;
 
-	printk(KERN_INFO "sdcardfs: destroyed something?\n");
-	kfree(to_sdcardfs_packages(item));
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
+	remove_userid_all_entry(tmp);
+	return count;
 }
 
-static struct configfs_item_operations sdcardfs_packages_item_ops = {
-	.release	= sdcardfs_packages_release,
-	.show_attribute	= packages_attr_show,
+struct packages_attribute packages_attr_packages_gid_list = __CONFIGFS_ATTR_RO(packages_gid.list, packages_list_show);
+PACKAGES_ATTR(remove_userid, S_IWUGO, NULL, packages_remove_userid_store);
+
+static struct configfs_attribute *packages_attrs[] = {
+	&packages_attr_packages_gid_list.attr,
+	&packages_attr_remove_userid.attr,
+	NULL,
+};
+
+CONFIGFS_ATTR_OPS(packages)
+static struct configfs_item_operations packages_item_ops = {
+	.show_attribute = packages_attr_show,
+	.store_attribute = packages_attr_store,
 };
 
 /*
  * Note that, since no extra work is required on ->drop_item(),
  * no ->drop_item() is provided.
  */
-static struct configfs_group_operations sdcardfs_packages_group_ops = {
-	.make_item	= sdcardfs_packages_make_item,
+static struct configfs_group_operations packages_group_ops = {
+	.make_item	= packages_make_item,
 };
 
-static struct config_item_type sdcardfs_packages_type = {
-	.ct_item_ops	= &sdcardfs_packages_item_ops,
-	.ct_group_ops	= &sdcardfs_packages_group_ops,
-	.ct_attrs	= sdcardfs_packages_attrs,
+static struct config_item_type packages_type = {
+	.ct_item_ops	= &packages_item_ops,
+	.ct_group_ops	= &packages_group_ops,
+	.ct_attrs	= packages_attrs,
 	.ct_owner	= THIS_MODULE,
 };
 
-static struct configfs_subsystem sdcardfs_packages_subsys = {
-	.su_group = {
-		.cg_item = {
-			.ci_namebuf = "sdcardfs",
-			.ci_type = &sdcardfs_packages_type,
+struct config_group *sd_default_groups[] = {
+	&extension_group,
+	NULL,
+};
+
+static struct packages sdcardfs_packages = {
+	.subsystem = {
+		.su_group = {
+			.cg_item = {
+				.ci_namebuf = "sdcardfs",
+				.ci_type = &packages_type,
+			},
+			.default_groups = sd_default_groups,
 		},
 	},
 };
 
 static int configfs_sdcardfs_init(void)
 {
-	int ret;
-	struct configfs_subsystem *subsys = &sdcardfs_packages_subsys;
+	int ret, i;
+	struct configfs_subsystem *subsys = &sdcardfs_packages.subsystem;
 
+	for (i = 0; sd_default_groups[i]; i++)
+		config_group_init(sd_default_groups[i]);
 	config_group_init(&subsys->su_group);
 	mutex_init(&subsys->su_mutex);
 	ret = configfs_register_subsystem(subsys);
 	if (ret) {
-		printk(KERN_ERR "Error %d while registering subsystem %s\n",
+		pr_err("Error %d while registering subsystem %s\n",
 		       ret,
 		       subsys->su_group.cg_item.ci_namebuf);
 	}
@@ -420,7 +873,7 @@
 
 static void configfs_sdcardfs_exit(void)
 {
-	configfs_unregister_subsystem(&sdcardfs_packages_subsys);
+	configfs_unregister_subsystem(&sdcardfs_packages.subsystem);
 }
 
 int packagelist_init(void)
@@ -429,19 +882,17 @@
 		kmem_cache_create("packagelist_hashtable_entry",
 					sizeof(struct hashtable_entry), 0, 0, NULL);
 	if (!hashtable_entry_cachep) {
-		printk(KERN_ERR "sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
+		pr_err("sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
 		return -ENOMEM;
 	}
 
-	pkgl_data_all = packagelist_create();
 	configfs_sdcardfs_init();
-        return 0;
+	return 0;
 }
 
 void packagelist_exit(void)
 {
 	configfs_sdcardfs_exit();
-	packagelist_destroy(pkgl_data_all);
-	if (hashtable_entry_cachep)
-		kmem_cache_destroy(hashtable_entry_cachep);
+	packagelist_destroy();
+	kmem_cache_destroy(hashtable_entry_cachep);
 }
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index 7f3dee3..3874d40 100755
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -29,6 +29,7 @@
 #include <linux/dcache.h>
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/aio.h>
 #include <linux/mm.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
@@ -52,7 +53,7 @@
 #define SDCARDFS_ROOT_INO     1
 
 /* useful for tracking code reachability */
-#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
+#define UDBG pr_default("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
 
 #define SDCARDFS_DIRENT_SIZE 256
 
@@ -65,71 +66,89 @@
 #define AID_SDCARD_PICS   1033	/* external storage photos access */
 #define AID_SDCARD_AV     1034	/* external storage audio/video access */
 #define AID_SDCARD_ALL    1035	/* access all users external storage */
+#define AID_MEDIA_OBB     1059  /* obb files */
+
+#define AID_SDCARD_IMAGE  1057
 
 #define AID_PACKAGE_INFO  1027
 
-#define fix_derived_permission(x)	\
+
+/*
+ * Permissions are handled by our permission function.
+ * We don't want anyone who happens to look at our inode value to prematurely
+ * block access, so store more permissive values. These are probably never
+ * used.
+ */
+#define fixup_tmp_permissions(x)	\
 	do {						\
-		(x)->i_uid = SDCARDFS_I(x)->d_uid;	\
-		(x)->i_gid = get_gid(SDCARDFS_I(x));	\
-		(x)->i_mode = ((x)->i_mode & S_IFMT) | get_mode(SDCARDFS_I(x));\
+		(x)->i_uid = SDCARDFS_I(x)->data->d_uid;	\
+		(x)->i_gid = AID_SDCARD_RW;	\
+		(x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\
 	} while (0)
 
-
 /* OVERRIDE_CRED() and REVERT_CRED()
- * 	OVERRID_CRED()
- * 		backup original task->cred
- * 		and modifies task->cred->fsuid/fsgid to specified value.
+ *	OVERRIDE_CRED()
+ *		backup original task->cred
+ *		and modifies task->cred->fsuid/fsgid to specified value.
  *	REVERT_CRED()
- * 		restore original task->cred->fsuid/fsgid.
+ *		restore original task->cred->fsuid/fsgid.
  * These two macro should be used in pair, and OVERRIDE_CRED() should be
  * placed at the beginning of a function, right after variable declaration.
  */
-#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred)		\
-	saved_cred = override_fsids(sdcardfs_sbi);	\
-	if (!saved_cred) { return -ENOMEM; }
+#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info)		\
+	do {	\
+		saved_cred = override_fsids(sdcardfs_sbi, info->data);	\
+		if (!saved_cred)	\
+			return -ENOMEM;	\
+	} while (0)
 
-#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred)	\
-	saved_cred = override_fsids(sdcardfs_sbi);	\
-	if (!saved_cred) { return ERR_PTR(-ENOMEM); }
+#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info)	\
+	do {	\
+		saved_cred = override_fsids(sdcardfs_sbi, info->data);	\
+		if (!saved_cred)	\
+			return ERR_PTR(-ENOMEM);	\
+	} while (0)
 
 #define REVERT_CRED(saved_cred)	revert_fsids(saved_cred)
 
-#define DEBUG_CRED()		\
-	printk("KAKJAGI: %s:%d fsuid %d fsgid %d\n", 	\
-		__FUNCTION__, __LINE__, 		\
-		(int)current->cred->fsuid, 		\
-		(int)current->cred->fsgid);
-
 /* Android 5.0 support */
 
 /* Permission mode for a specific node. Controls how file permissions
- * are derived for children nodes. */
+ * are derived for children nodes.
+ */
 typedef enum {
-    /* Nothing special; this node should just inherit from its parent. */
-    PERM_INHERIT,
-    /* This node is one level above a normal root; used for legacy layouts
-     * which use the first level to represent user_id. */
-    PERM_PRE_ROOT,
-    /* This node is "/" */
-    PERM_ROOT,
-    /* This node is "/Android" */
-    PERM_ANDROID,
-    /* This node is "/Android/data" */
-    PERM_ANDROID_DATA,
-    /* This node is "/Android/obb" */
-    PERM_ANDROID_OBB,
-    /* This node is "/Android/media" */
-    PERM_ANDROID_MEDIA,
+	/* Nothing special; this node should just inherit from its parent. */
+	PERM_INHERIT,
+	/* This node is one level above a normal root; used for legacy layouts
+	 * which use the first level to represent user_id.
+	 */
+	PERM_PRE_ROOT,
+	/* This node is "/" */
+	PERM_ROOT,
+	/* This node is "/Android" */
+	PERM_ANDROID,
+	/* This node is "/Android/data" */
+	PERM_ANDROID_DATA,
+	/* This node is "/Android/obb" */
+	PERM_ANDROID_OBB,
+	/* This node is "/Android/media" */
+	PERM_ANDROID_MEDIA,
+	/* This node is "/Android/[data|media|obb]/[package]" */
+	PERM_ANDROID_PACKAGE,
+	/* This node is "/Android/[data|media|obb]/[package]/cache" */
+	PERM_ANDROID_PACKAGE_CACHE,
 } perm_t;
 
 struct sdcardfs_sb_info;
 struct sdcardfs_mount_options;
+struct sdcardfs_inode_info;
+struct sdcardfs_inode_data;
 
 /* Do not directly use this function. Use OVERRIDE_CRED() instead. */
-const struct cred * override_fsids(struct sdcardfs_sb_info* sbi);
+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
+			struct sdcardfs_inode_data *data);
 /* Do not directly use this function, use REVERT_CRED() instead. */
-void revert_fsids(const struct cred * old_cred);
+void revert_fsids(const struct cred *old_cred);
 
 /* operations vectors defined in specific files */
 extern const struct file_operations sdcardfs_main_fops;
@@ -161,14 +180,26 @@
 	const struct vm_operations_struct *lower_vm_ops;
 };
 
-/* sdcardfs inode data in memory */
-struct sdcardfs_inode_info {
-	struct inode *lower_inode;
-	/* state derived based on current position in hierachy */
+struct sdcardfs_inode_data {
+	struct kref refcount;
+	bool abandoned;
+
 	perm_t perm;
 	userid_t userid;
 	uid_t d_uid;
 	bool under_android;
+	bool under_cache;
+	bool under_obb;
+};
+
+/* sdcardfs inode data in memory */
+struct sdcardfs_inode_info {
+	struct inode *lower_inode;
+	/* state derived based on current position in hierarchy */
+	struct sdcardfs_inode_data *data;
+
+	/* top folder for ownership */
+	struct sdcardfs_inode_data *top_data;
 
 	struct inode vfs_inode;
 };
@@ -185,18 +216,25 @@
 	uid_t fs_low_uid;
 	gid_t fs_low_gid;
 	userid_t fs_user_id;
-	gid_t gid;
-	mode_t mask;
 	bool multiuser;
 	unsigned int reserved_mb;
 };
 
+struct sdcardfs_vfsmount_options {
+	gid_t gid;
+	mode_t mask;
+};
+
+extern int parse_options_remount(struct super_block *sb, char *options, int silent,
+		struct sdcardfs_vfsmount_options *vfsopts);
+
 /* sdcardfs super-block data in memory */
 struct sdcardfs_sb_info {
 	struct super_block *sb;
 	struct super_block *lower_sb;
 	/* derived perm policy : some of options have been added
-	 * to sdcardfs_mount_options (Android 4.4 support) */
+	 * to sdcardfs_mount_options (Android 4.4 support)
+	 */
 	struct sdcardfs_mount_options options;
 	spinlock_t lock;	/* protects obbpath */
 	char *obbpath_s;
@@ -307,7 +345,7 @@
 { \
 	struct path pname; \
 	spin_lock(&SDCARDFS_D(dent)->lock); \
-	if(SDCARDFS_D(dent)->pname.dentry) { \
+	if (SDCARDFS_D(dent)->pname.dentry) { \
 		pathcpy(&pname, &SDCARDFS_D(dent)->pname); \
 		SDCARDFS_D(dent)->pname.dentry = NULL; \
 		SDCARDFS_D(dent)->pname.mnt = NULL; \
@@ -321,38 +359,97 @@
 SDCARDFS_DENT_FUNC(lower_path)
 SDCARDFS_DENT_FUNC(orig_path)
 
-static inline int get_gid(struct sdcardfs_inode_info *info) {
-	struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
-	if (sb_info->options.gid == AID_SDCARD_RW) {
+static inline bool sbinfo_has_sdcard_magic(struct sdcardfs_sb_info *sbinfo)
+{
+	return sbinfo && sbinfo->sb
+			&& sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC;
+}
+
+static inline struct sdcardfs_inode_data *data_get(
+		struct sdcardfs_inode_data *data)
+{
+	if (data)
+		kref_get(&data->refcount);
+	return data;
+}
+
+static inline struct sdcardfs_inode_data *top_data_get(
+		struct sdcardfs_inode_info *info)
+{
+	return data_get(info->top_data);
+}
+
+extern void data_release(struct kref *ref);
+
+static inline void data_put(struct sdcardfs_inode_data *data)
+{
+	kref_put(&data->refcount, data_release);
+}
+
+static inline void release_own_data(struct sdcardfs_inode_info *info)
+{
+	/*
+	 * This happens exactly once per inode. At this point, the inode that
+	 * originally held this data is about to be freed, and all references
+	 * to it are held as a top value, and will likely be released soon.
+	 */
+	info->data->abandoned = true;
+	data_put(info->data);
+}
+
+static inline void set_top(struct sdcardfs_inode_info *info,
+			struct sdcardfs_inode_data *top)
+{
+	struct sdcardfs_inode_data *old_top = info->top_data;
+
+	if (top)
+		data_get(top);
+	info->top_data = top;
+	if (old_top)
+		data_put(old_top);
+}
+
+static inline int get_gid(struct vfsmount *mnt,
+		struct sdcardfs_inode_data *data)
+{
+	struct sdcardfs_vfsmount_options *opts = mnt->data;
+
+	if (opts->gid == AID_SDCARD_RW)
 		/* As an optimization, certain trusted system components only run
 		 * as owner but operate across all users. Since we're now handing
 		 * out the sdcard_rw GID only to trusted apps, we're okay relaxing
 		 * the user boundary enforcement for the default view. The UIDs
-		 * assigned to app directories are still multiuser aware. */
+		 * assigned to app directories are still multiuser aware.
+		 */
 		return AID_SDCARD_RW;
-	} else {
-		return multiuser_get_uid(info->userid, sb_info->options.gid);
-	}
+	else
+		return multiuser_get_uid(data->userid, opts->gid);
 }
-static inline int get_mode(struct sdcardfs_inode_info *info) {
+
+static inline int get_mode(struct vfsmount *mnt,
+		struct sdcardfs_inode_info *info,
+		struct sdcardfs_inode_data *data)
+{
 	int owner_mode;
 	int filtered_mode;
-	struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
-	int visible_mode = 0775 & ~sb_info->options.mask;
+	struct sdcardfs_vfsmount_options *opts = mnt->data;
+	int visible_mode = 0775 & ~opts->mask;
 
-	if (info->perm == PERM_PRE_ROOT) {
+
+	if (data->perm == PERM_PRE_ROOT) {
 		/* Top of multi-user view should always be visible to ensure
-		* secondary users can traverse inside. */
+		* secondary users can traverse inside.
+		*/
 		visible_mode = 0711;
-	} else if (info->under_android) {
+	} else if (data->under_android) {
 		/* Block "other" access to Android directories, since only apps
 		* belonging to a specific user should be in there; we still
-		* leave +x open for the default view. */
-		if (sb_info->options.gid == AID_SDCARD_RW) {
+		* leave +x open for the default view.
+		*/
+		if (opts->gid == AID_SDCARD_RW)
 			visible_mode = visible_mode & ~0006;
-		} else {
+		else
 			visible_mode = visible_mode & ~0007;
-		}
 	}
 	owner_mode = info->lower_inode->i_mode & 0700;
 	filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6));
@@ -377,7 +474,7 @@
 	/* in case of a local obb dentry
 	 * the orig_path should be returned
 	 */
-	if(has_graft_path(dent))
+	if (has_graft_path(dent))
 		sdcardfs_get_orig_path(dent, real_lower);
 	else
 		sdcardfs_get_lower_path(dent, real_lower);
@@ -386,7 +483,7 @@
 static inline void sdcardfs_put_real_lower(const struct dentry *dent,
 						struct path *real_lower)
 {
-	if(has_graft_path(dent))
+	if (has_graft_path(dent))
 		sdcardfs_put_orig_path(dent, real_lower);
 	else
 		sdcardfs_put_lower_path(dent, real_lower);
@@ -396,20 +493,32 @@
 extern struct list_head sdcardfs_super_list;
 
 /* for packagelist.c */
-extern appid_t get_appid(void *pkgl_id, const char *app_name);
-extern int check_caller_access_to_name(struct inode *parent_node, const char* name);
+extern appid_t get_appid(const char *app_name);
+extern appid_t get_ext_gid(const char *app_name);
+extern appid_t is_excluded(const char *app_name, userid_t userid);
+extern int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name);
 extern int open_flags_to_access_mode(int open_flags);
 extern int packagelist_init(void);
 extern void packagelist_exit(void);
 
 /* for derived_perm.c */
+#define BY_NAME		(1 << 0)
+#define BY_USERID	(1 << 1)
+struct limit_search {
+	unsigned int flags;
+	struct qstr name;
+	userid_t userid;
+};
+
 extern void setup_derived_state(struct inode *inode, perm_t perm,
-			userid_t userid, uid_t uid, bool under_android);
+		userid_t userid, uid_t uid, bool under_android,
+		struct sdcardfs_inode_data *top);
 extern void get_derived_permission(struct dentry *parent, struct dentry *dentry);
-extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry);
-extern void get_derive_permissions_recursive(struct dentry *parent);
+extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name);
+extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit);
 
 extern void update_derived_permission_lock(struct dentry *dentry);
+void fixup_lower_ownership(struct dentry *dentry, const char *name);
 extern int need_graft_path(struct dentry *dentry);
 extern int is_base_obbpath(struct dentry *dentry);
 extern int is_obbpath_invalid(struct dentry *dentry);
@@ -419,6 +528,7 @@
 static inline struct dentry *lock_parent(struct dentry *dentry)
 {
 	struct dentry *dir = dget_parent(dentry);
+
 	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
 	return dir;
 }
@@ -444,7 +554,7 @@
 		goto out_unlock;
 	}
 
-	err = vfs_mkdir(parent.dentry->d_inode, dent, mode);
+	err = vfs_mkdir2(parent.mnt, parent.dentry->d_inode, dent, mode);
 	if (err) {
 		if (err == -EEXIST)
 			err = 0;
@@ -455,7 +565,7 @@
 	attrs.ia_gid = gid;
 	attrs.ia_valid = ATTR_UID | ATTR_GID;
 	mutex_lock(&dent->d_inode->i_mutex);
-	notify_change(dent, &attrs);
+	notify_change2(parent.mnt, dent, &attrs);
 	mutex_unlock(&dent->d_inode->i_mutex);
 
 out_dput:
@@ -513,12 +623,17 @@
 		return 1;
 }
 
-/* Copies attrs and maintains sdcardfs managed attrs */
+/*
+ * Copies attrs and maintains sdcardfs managed attrs
+ * Since our permission check handles all special permissions, set those to be open
+ */
 static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src)
 {
-	dest->i_mode = (src->i_mode  & S_IFMT) | get_mode(SDCARDFS_I(dest));
-	dest->i_uid = SDCARDFS_I(dest)->d_uid;
-	dest->i_gid = get_gid(SDCARDFS_I(dest));
+
+	dest->i_mode = (src->i_mode  & S_IFMT) | S_IRWXU | S_IRWXG |
+			S_IROTH | S_IXOTH; /* 0775 */
+	dest->i_uid = SDCARDFS_I(dest)->data->d_uid;
+	dest->i_gid = AID_SDCARD_RW;
 	dest->i_rdev = src->i_rdev;
 	dest->i_atime = src->i_atime;
 	dest->i_mtime = src->i_mtime;
@@ -527,4 +642,22 @@
 	dest->i_flags = src->i_flags;
 	set_nlink(dest, src->i_nlink);
 }
+
+static inline bool str_case_eq(const char *s1, const char *s2)
+{
+	return !strcasecmp(s1, s2);
+}
+
+static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len)
+{
+	return !strncasecmp(s1, s2, len);
+}
+
+static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
+{
+	return q1->len == q2->len && str_case_eq(q1->name, q2->name);
+}
+
+#define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1)
+
 #endif	/* not _SDCARDFS_H_ */
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index 1d64901..7f4539b 100755
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -26,6 +26,23 @@
  */
 static struct kmem_cache *sdcardfs_inode_cachep;
 
+/*
+ * To support the top references, we must track some data separately.
+ * An sdcardfs_inode_info always has a reference to its data, and once set up,
+ * also has a reference to its top. The top may be itself, in which case it
+ * holds two references to its data. When top is changed, it takes a ref to the
+ * new data and then drops the ref to the old data.
+ */
+static struct kmem_cache *sdcardfs_inode_data_cachep;
+
+void data_release(struct kref *ref)
+{
+	struct sdcardfs_inode_data *data =
+		container_of(ref, struct sdcardfs_inode_data, refcount);
+
+	kmem_cache_free(sdcardfs_inode_data_cachep, data);
+}
+
 /* final actions when unmounting a file system */
 static void sdcardfs_put_super(struct super_block *sb)
 {
@@ -36,7 +53,7 @@
 	if (!spd)
 		return;
 
-	if(spd->obbpath_s) {
+	if (spd->obbpath_s) {
 		kfree(spd->obbpath_s);
 		path_put(&spd->obbpath);
 	}
@@ -64,7 +81,7 @@
 	if (sbi->options.reserved_mb) {
 		/* Invalid statfs informations. */
 		if (buf->f_bsize == 0) {
-			printk(KERN_ERR "Returned block size is zero.\n");
+			pr_err("Returned block size is zero.\n");
 			return -EINVAL;
 		}
 
@@ -100,8 +117,7 @@
 	 * SILENT, but anything else left over is an error.
 	 */
 	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) {
-		printk(KERN_ERR
-		       "sdcardfs: remount flags 0x%x unsupported\n", *flags);
+		pr_err("sdcardfs: remount flags 0x%x unsupported\n", *flags);
 		err = -EINVAL;
 	}
 
@@ -109,6 +125,54 @@
 }
 
 /*
+ * @mnt: mount point we are remounting
+ * @sb: superblock we are remounting
+ * @flags: numeric mount options
+ * @options: mount options string
+ */
+static int sdcardfs_remount_fs2(struct vfsmount *mnt, struct super_block *sb,
+						int *flags, char *options)
+{
+	int err = 0;
+
+	/*
+	 * The VFS will take care of "ro" and "rw" flags among others.  We
+	 * can safely accept a few flags (RDONLY, MANDLOCK), and honor
+	 * SILENT, but anything else left over is an error.
+	 */
+	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT | MS_REMOUNT)) != 0) {
+		pr_err("sdcardfs: remount flags 0x%x unsupported\n", *flags);
+		err = -EINVAL;
+	}
+	pr_info("Remount options were %s for vfsmnt %p.\n", options, mnt);
+	err = parse_options_remount(sb, options, *flags & ~MS_SILENT, mnt->data);
+
+
+	return err;
+}
+
+static void *sdcardfs_clone_mnt_data(void *data)
+{
+	struct sdcardfs_vfsmount_options *opt = kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
+	struct sdcardfs_vfsmount_options *old = data;
+
+	if (!opt)
+		return NULL;
+	opt->gid = old->gid;
+	opt->mask = old->mask;
+	return opt;
+}
+
+static void sdcardfs_copy_mnt_data(void *data, void *newdata)
+{
+	struct sdcardfs_vfsmount_options *old = data;
+	struct sdcardfs_vfsmount_options *new = newdata;
+
+	old->gid = new->gid;
+	old->mask = new->mask;
+}
+
+/*
  * Called by iput() when the inode reference count reached zero
  * and the inode is not hashed anywhere.  Used to clear anything
  * that needs to be, before the inode is completely destroyed and put
@@ -119,6 +183,7 @@
 	struct inode *lower_inode;
 
 	truncate_inode_pages(&inode->i_data, 0);
+	set_top(SDCARDFS_I(inode), NULL);
 	clear_inode(inode);
 	/*
 	 * Decrement a reference to a lower_inode, which was incremented
@@ -132,6 +197,7 @@
 static struct inode *sdcardfs_alloc_inode(struct super_block *sb)
 {
 	struct sdcardfs_inode_info *i;
+	struct sdcardfs_inode_data *d;
 
 	i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL);
 	if (!i)
@@ -140,13 +206,31 @@
 	/* memset everything up to the inode to 0 */
 	memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode));
 
+	d = kmem_cache_alloc(sdcardfs_inode_data_cachep,
+					GFP_KERNEL | __GFP_ZERO);
+	if (!d) {
+		kmem_cache_free(sdcardfs_inode_cachep, i);
+		return NULL;
+	}
+
+	i->data = d;
+	kref_init(&d->refcount);
+
 	i->vfs_inode.i_version = 1;
 	return &i->vfs_inode;
 }
 
+static void i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+
+	release_own_data(SDCARDFS_I(inode));
+	kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
+}
+
 static void sdcardfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
+	call_rcu(&inode->i_rcu, i_callback);
 }
 
 /* sdcardfs inode cache constructor */
@@ -159,22 +243,31 @@
 
 int sdcardfs_init_inode_cache(void)
 {
-	int err = 0;
-
 	sdcardfs_inode_cachep =
 		kmem_cache_create("sdcardfs_inode_cache",
 				  sizeof(struct sdcardfs_inode_info), 0,
 				  SLAB_RECLAIM_ACCOUNT, init_once);
+
 	if (!sdcardfs_inode_cachep)
-		err = -ENOMEM;
-	return err;
+		return -ENOMEM;
+
+	sdcardfs_inode_data_cachep =
+		kmem_cache_create("sdcardfs_inode_data_cache",
+				  sizeof(struct sdcardfs_inode_data), 0,
+				  SLAB_RECLAIM_ACCOUNT, NULL);
+	if (!sdcardfs_inode_data_cachep) {
+		kmem_cache_destroy(sdcardfs_inode_cachep);
+		return -ENOMEM;
+	}
+
+	return 0;
 }
 
 /* sdcardfs inode cache destructor */
 void sdcardfs_destroy_inode_cache(void)
 {
-	if (sdcardfs_inode_cachep)
-		kmem_cache_destroy(sdcardfs_inode_cachep);
+	kmem_cache_destroy(sdcardfs_inode_data_cachep);
+	kmem_cache_destroy(sdcardfs_inode_cachep);
 }
 
 /*
@@ -190,19 +283,25 @@
 		lower_sb->s_op->umount_begin(lower_sb);
 }
 
-static int sdcardfs_show_options(struct seq_file *m, struct dentry *root)
+static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m,
+			struct dentry *root)
 {
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(root->d_sb);
 	struct sdcardfs_mount_options *opts = &sbi->options;
+	struct sdcardfs_vfsmount_options *vfsopts = mnt->data;
 
 	if (opts->fs_low_uid != 0)
-		seq_printf(m, ",uid=%u", opts->fs_low_uid);
+		seq_printf(m, ",fsuid=%u", opts->fs_low_uid);
 	if (opts->fs_low_gid != 0)
-		seq_printf(m, ",gid=%u", opts->fs_low_gid);
-
+		seq_printf(m, ",fsgid=%u", opts->fs_low_gid);
+	if (vfsopts->gid != 0)
+		seq_printf(m, ",gid=%u", vfsopts->gid);
 	if (opts->multiuser)
-		seq_printf(m, ",multiuser");
-
+		seq_puts(m, ",multiuser");
+	if (vfsopts->mask)
+		seq_printf(m, ",mask=%u", vfsopts->mask);
+	if (opts->fs_user_id)
+		seq_printf(m, ",userid=%u", opts->fs_user_id);
 	if (opts->reserved_mb != 0)
 		seq_printf(m, ",reserved=%uMB", opts->reserved_mb);
 
@@ -213,9 +312,12 @@
 	.put_super	= sdcardfs_put_super,
 	.statfs		= sdcardfs_statfs,
 	.remount_fs	= sdcardfs_remount_fs,
+	.remount_fs2	= sdcardfs_remount_fs2,
+	.clone_mnt_data	= sdcardfs_clone_mnt_data,
+	.copy_mnt_data	= sdcardfs_copy_mnt_data,
 	.evict_inode	= sdcardfs_evict_inode,
 	.umount_begin	= sdcardfs_umount_begin,
-	.show_options	= sdcardfs_show_options,
+	.show_options2	= sdcardfs_show_options,
 	.alloc_inode	= sdcardfs_alloc_inode,
 	.destroy_inode	= sdcardfs_destroy_inode,
 	.drop_inode	= generic_delete_inode,
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index ffb093e..6dd158a 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -26,34 +26,6 @@
 	  If unsure, say N.
 
 choice
-	prompt "File decompression options"
-	depends on SQUASHFS
-	help
-	  Squashfs now supports two options for decompressing file
-	  data.  Traditionally Squashfs has decompressed into an
-	  intermediate buffer and then memcopied it into the page cache.
-	  Squashfs now supports the ability to decompress directly into
-	  the page cache.
-
-	  If unsure, select "Decompress file data into an intermediate buffer"
-
-config SQUASHFS_FILE_CACHE
-	bool "Decompress file data into an intermediate buffer"
-	help
-	  Decompress file data into an intermediate buffer and then
-	  memcopy it into the page cache.
-
-config SQUASHFS_FILE_DIRECT
-	bool "Decompress files directly into the page cache"
-	help
-	  Directly decompress file data into the page cache.
-	  Doing so can significantly improve performance because
-	  it eliminates a memcpy and it also removes the lock contention
-	  on the single buffer.
-
-endchoice
-
-choice
 	prompt "Decompressor parallelisation options"
 	depends on SQUASHFS
 	help
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index 246a6f3..fe51f15 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -5,8 +5,7 @@
 obj-$(CONFIG_SQUASHFS) += squashfs.o
 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
 squashfs-y += namei.o super.o symlink.o decompressor.o
-squashfs-$(CONFIG_SQUASHFS_FILE_CACHE) += file_cache.o
-squashfs-$(CONFIG_SQUASHFS_FILE_DIRECT) += file_direct.o page_actor.o
+squashfs-y += file_direct.o page_actor.o
 squashfs-$(CONFIG_SQUASHFS_DECOMP_SINGLE) += decompressor_single.o
 squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI) += decompressor_multi.o
 squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU) += decompressor_multi_percpu.o
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 0cea9b9..a775b75 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -28,9 +28,12 @@
 
 #include <linux/fs.h>
 #include <linux/vfs.h>
+#include <linux/bio.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/pagemap.h>
 #include <linux/buffer_head.h>
+#include <linux/workqueue.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -38,45 +41,379 @@
 #include "decompressor.h"
 #include "page_actor.h"
 
-/*
- * Read the metadata block length, this is stored in the first two
- * bytes of the metadata block.
- */
-static struct buffer_head *get_block_length(struct super_block *sb,
-			u64 *cur_index, int *offset, int *length)
+static struct workqueue_struct *squashfs_read_wq;
+
+struct squashfs_read_request {
+	struct super_block *sb;
+	u64 index;
+	int length;
+	int compressed;
+	int offset;
+	u64 read_end;
+	struct squashfs_page_actor *output;
+	enum {
+		SQUASHFS_COPY,
+		SQUASHFS_DECOMPRESS,
+		SQUASHFS_METADATA,
+	} data_processing;
+	bool synchronous;
+
+	/*
+	 * If the read is synchronous, it is possible to retrieve information
+	 * about the request by setting these pointers.
+	 */
+	int *res;
+	int *bytes_read;
+	int *bytes_uncompressed;
+
+	int nr_buffers;
+	struct buffer_head **bh;
+	struct work_struct offload;
+};
+
+struct squashfs_bio_request {
+	struct buffer_head **bh;
+	int nr_buffers;
+};
+
+static int squashfs_bio_submit(struct squashfs_read_request *req);
+
+int squashfs_init_read_wq(void)
 {
-	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	struct buffer_head *bh;
+	squashfs_read_wq = create_workqueue("SquashFS read wq");
+	return !!squashfs_read_wq;
+}
 
-	bh = sb_bread(sb, *cur_index);
-	if (bh == NULL)
-		return NULL;
+void squashfs_destroy_read_wq(void)
+{
+	flush_workqueue(squashfs_read_wq);
+	destroy_workqueue(squashfs_read_wq);
+}
 
-	if (msblk->devblksize - *offset == 1) {
-		*length = (unsigned char) bh->b_data[*offset];
-		put_bh(bh);
-		bh = sb_bread(sb, ++(*cur_index));
-		if (bh == NULL)
-			return NULL;
-		*length |= (unsigned char) bh->b_data[0] << 8;
-		*offset = 1;
-	} else {
-		*length = (unsigned char) bh->b_data[*offset] |
-			(unsigned char) bh->b_data[*offset + 1] << 8;
-		*offset += 2;
+static void free_read_request(struct squashfs_read_request *req, int error)
+{
+	if (!req->synchronous)
+		squashfs_page_actor_free(req->output, error);
+	if (req->res)
+		*(req->res) = error;
+	kfree(req->bh);
+	kfree(req);
+}
 
-		if (*offset == msblk->devblksize) {
-			put_bh(bh);
-			bh = sb_bread(sb, ++(*cur_index));
-			if (bh == NULL)
-				return NULL;
-			*offset = 0;
+static void squashfs_process_blocks(struct squashfs_read_request *req)
+{
+	int error = 0;
+	int bytes, i, length;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+	struct squashfs_page_actor *actor = req->output;
+	struct buffer_head **bh = req->bh;
+	int nr_buffers = req->nr_buffers;
+
+	for (i = 0; i < nr_buffers; ++i) {
+		if (!bh[i])
+			continue;
+		wait_on_buffer(bh[i]);
+		if (!buffer_uptodate(bh[i]))
+			error = -EIO;
+	}
+	if (error)
+		goto cleanup;
+
+	if (req->data_processing == SQUASHFS_METADATA) {
+		/* Extract the length of the metadata block */
+		if (req->offset != msblk->devblksize - 1)
+			length = *((u16 *)(bh[0]->b_data + req->offset));
+		else {
+			length = bh[0]->b_data[req->offset];
+			length |= bh[1]->b_data[0] << 8;
+		}
+		req->compressed = SQUASHFS_COMPRESSED(length);
+		req->data_processing = req->compressed ? SQUASHFS_DECOMPRESS
+						       : SQUASHFS_COPY;
+		length = SQUASHFS_COMPRESSED_SIZE(length);
+		if (req->index + length + 2 > req->read_end) {
+			for (i = 0; i < nr_buffers; ++i)
+				put_bh(bh[i]);
+			kfree(bh);
+			req->length = length;
+			req->index += 2;
+			squashfs_bio_submit(req);
+			return;
+		}
+		req->length = length;
+		req->offset = (req->offset + 2) % PAGE_SIZE;
+		if (req->offset < 2) {
+			put_bh(bh[0]);
+			++bh;
+			--nr_buffers;
+		}
+	}
+	if (req->bytes_read)
+		*(req->bytes_read) = req->length;
+
+	if (req->data_processing == SQUASHFS_COPY) {
+		squashfs_bh_to_actor(bh, nr_buffers, req->output, req->offset,
+			req->length, msblk->devblksize);
+	} else if (req->data_processing == SQUASHFS_DECOMPRESS) {
+		req->length = squashfs_decompress(msblk, bh, nr_buffers,
+			req->offset, req->length, actor);
+		if (req->length < 0) {
+			error = -EIO;
+			goto cleanup;
 		}
 	}
 
-	return bh;
+	/* Last page may have trailing bytes not filled */
+	bytes = req->length % PAGE_SIZE;
+	if (bytes && actor->page[actor->pages - 1])
+		zero_user_segment(actor->page[actor->pages - 1], bytes,
+				  PAGE_SIZE);
+
+cleanup:
+	if (req->bytes_uncompressed)
+		*(req->bytes_uncompressed) = req->length;
+	if (error) {
+		for (i = 0; i < nr_buffers; ++i)
+			if (bh[i])
+				put_bh(bh[i]);
+	}
+	free_read_request(req, error);
 }
 
+static void read_wq_handler(struct work_struct *work)
+{
+	squashfs_process_blocks(container_of(work,
+		    struct squashfs_read_request, offload));
+}
+
+static void squashfs_bio_end_io(struct bio *bio, int error)
+{
+	int i;
+	struct squashfs_bio_request *bio_req = bio->bi_private;
+
+	bio_put(bio);
+
+	for (i = 0; i < bio_req->nr_buffers; ++i) {
+		if (!bio_req->bh[i])
+			continue;
+		if (!error)
+			set_buffer_uptodate(bio_req->bh[i]);
+		else
+			clear_buffer_uptodate(bio_req->bh[i]);
+		unlock_buffer(bio_req->bh[i]);
+	}
+	kfree(bio_req);
+}
+
+static int bh_is_optional(struct squashfs_read_request *req, int idx)
+{
+	int start_idx, end_idx;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+
+	start_idx = (idx * msblk->devblksize - req->offset) / PAGE_SIZE;
+	end_idx = ((idx + 1) * msblk->devblksize - req->offset + 1) / PAGE_SIZE;
+	if (start_idx >= req->output->pages)
+		return 1;
+	if (start_idx < 0)
+		start_idx = end_idx;
+	if (end_idx >= req->output->pages)
+		end_idx = start_idx;
+	return !req->output->page[start_idx] && !req->output->page[end_idx];
+}
+
+static int actor_getblks(struct squashfs_read_request *req, u64 block)
+{
+	int i;
+
+	req->bh = kmalloc_array(req->nr_buffers, sizeof(*(req->bh)), GFP_NOIO);
+	if (!req->bh)
+		return -ENOMEM;
+
+	for (i = 0; i < req->nr_buffers; ++i) {
+		/*
+		 * When dealing with an uncompressed block, the actor may
+		 * contains NULL pages. There's no need to read the buffers
+		 * associated with these pages.
+		 */
+		if (!req->compressed && bh_is_optional(req, i)) {
+			req->bh[i] = NULL;
+			continue;
+		}
+		req->bh[i] = sb_getblk(req->sb, block + i);
+		if (!req->bh[i]) {
+			while (--i) {
+				if (req->bh[i])
+					put_bh(req->bh[i]);
+			}
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int squashfs_bio_submit(struct squashfs_read_request *req)
+{
+	struct bio *bio = NULL;
+	struct buffer_head *bh;
+	struct squashfs_bio_request *bio_req = NULL;
+	int b = 0, prev_block = 0;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+
+	u64 read_start = round_down(req->index, msblk->devblksize);
+	u64 read_end = round_up(req->index + req->length, msblk->devblksize);
+	sector_t block = read_start >> msblk->devblksize_log2;
+	sector_t block_end = read_end >> msblk->devblksize_log2;
+	int offset = read_start - round_down(req->index, PAGE_SIZE);
+	int nr_buffers = block_end - block;
+	int blksz = msblk->devblksize;
+	int bio_max_pages = nr_buffers > BIO_MAX_PAGES ? BIO_MAX_PAGES
+						       : nr_buffers;
+
+	/* Setup the request */
+	req->read_end = read_end;
+	req->offset = req->index - read_start;
+	req->nr_buffers = nr_buffers;
+	if (actor_getblks(req, block) < 0)
+		goto getblk_failed;
+
+	/* Create and submit the BIOs */
+	for (b = 0; b < nr_buffers; ++b, offset += blksz) {
+		bh = req->bh[b];
+		if (!bh || !trylock_buffer(bh))
+			continue;
+		if (buffer_uptodate(bh)) {
+			unlock_buffer(bh);
+			continue;
+		}
+		offset %= PAGE_SIZE;
+
+		/* Append the buffer to the current BIO if it is contiguous */
+		if (bio && bio_req && prev_block + 1 == b) {
+			if (bio_add_page(bio, bh->b_page, blksz, offset)) {
+				bio_req->nr_buffers += 1;
+				prev_block = b;
+				continue;
+			}
+		}
+
+		/* Otherwise, submit the current BIO and create a new one */
+		if (bio)
+			submit_bio(READ, bio);
+		bio_req = kcalloc(1, sizeof(struct squashfs_bio_request),
+				  GFP_NOIO);
+		if (!bio_req)
+			goto req_alloc_failed;
+		bio_req->bh = &req->bh[b];
+		bio = bio_alloc(GFP_NOIO, bio_max_pages);
+		if (!bio)
+			goto bio_alloc_failed;
+		bio->bi_bdev = req->sb->s_bdev;
+		bio->bi_sector = (block + b)
+				       << (msblk->devblksize_log2 - 9);
+		bio->bi_private = bio_req;
+		bio->bi_end_io = squashfs_bio_end_io;
+
+		bio_add_page(bio, bh->b_page, blksz, offset);
+		bio_req->nr_buffers += 1;
+		prev_block = b;
+	}
+	if (bio)
+		submit_bio(READ, bio);
+
+	if (req->synchronous)
+		squashfs_process_blocks(req);
+	else {
+		INIT_WORK(&req->offload, read_wq_handler);
+		schedule_work(&req->offload);
+	}
+	return 0;
+
+bio_alloc_failed:
+	kfree(bio_req);
+req_alloc_failed:
+	unlock_buffer(bh);
+	while (--nr_buffers >= b)
+		if (req->bh[nr_buffers])
+			put_bh(req->bh[nr_buffers]);
+	while (--b >= 0)
+		if (req->bh[b])
+			wait_on_buffer(req->bh[b]);
+getblk_failed:
+	free_read_request(req, -ENOMEM);
+	return -ENOMEM;
+}
+
+static int read_metadata_block(struct squashfs_read_request *req,
+			       u64 *next_index)
+{
+	int ret, error, bytes_read = 0, bytes_uncompressed = 0;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+
+	if (req->index + 2 > msblk->bytes_used) {
+		free_read_request(req, -EINVAL);
+		return -EINVAL;
+	}
+	req->length = 2;
+
+	/* Do not read beyond the end of the device */
+	if (req->index + req->length > msblk->bytes_used)
+		req->length = msblk->bytes_used - req->index;
+	req->data_processing = SQUASHFS_METADATA;
+
+	/*
+	 * Reading metadata is always synchronous because we don't know the
+	 * length in advance and the function is expected to update
+	 * 'next_index' and return the length.
+	 */
+	req->synchronous = true;
+	req->res = &error;
+	req->bytes_read = &bytes_read;
+	req->bytes_uncompressed = &bytes_uncompressed;
+
+	TRACE("Metadata block @ 0x%llx, %scompressed size %d, src size %d\n",
+	      req->index, req->compressed ? "" : "un", bytes_read,
+	      req->output->length);
+
+	ret = squashfs_bio_submit(req);
+	if (ret)
+		return ret;
+	if (error)
+		return error;
+	if (next_index)
+		*next_index += 2 + bytes_read;
+	return bytes_uncompressed;
+}
+
+static int read_data_block(struct squashfs_read_request *req, int length,
+			   u64 *next_index, bool synchronous)
+{
+	int ret, error = 0, bytes_uncompressed = 0, bytes_read = 0;
+
+	req->compressed = SQUASHFS_COMPRESSED_BLOCK(length);
+	req->length = length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
+	req->data_processing = req->compressed ? SQUASHFS_DECOMPRESS
+					       : SQUASHFS_COPY;
+
+	req->synchronous = synchronous;
+	if (synchronous) {
+		req->res = &error;
+		req->bytes_read = &bytes_read;
+		req->bytes_uncompressed = &bytes_uncompressed;
+	}
+
+	TRACE("Data block @ 0x%llx, %scompressed size %d, src size %d\n",
+	      req->index, req->compressed ? "" : "un", req->length,
+	      req->output->length);
+
+	ret = squashfs_bio_submit(req);
+	if (ret)
+		return ret;
+	if (synchronous)
+		ret = error ? error : bytes_uncompressed;
+	if (next_index)
+		*next_index += length;
+	return ret;
+}
 
 /*
  * Read and decompress a metadata block or datablock.  Length is non-zero
@@ -87,128 +424,50 @@
  * generated a larger block - this does occasionally happen with compression
  * algorithms).
  */
-int squashfs_read_data(struct super_block *sb, u64 index, int length,
-		u64 *next_index, struct squashfs_page_actor *output)
+static int __squashfs_read_data(struct super_block *sb, u64 index, int length,
+	u64 *next_index, struct squashfs_page_actor *output, bool sync)
 {
-	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	struct buffer_head **bh;
-	int offset = index & ((1 << msblk->devblksize_log2) - 1);
-	u64 cur_index = index >> msblk->devblksize_log2;
-	int bytes, compressed, b = 0, k = 0, avail, i;
+	struct squashfs_read_request *req;
 
-	bh = kcalloc(((output->length + msblk->devblksize - 1)
-		>> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL);
-	if (bh == NULL)
+	req = kcalloc(1, sizeof(struct squashfs_read_request), GFP_KERNEL);
+	if (!req) {
+		if (!sync)
+			squashfs_page_actor_free(output, -ENOMEM);
 		return -ENOMEM;
-
-	if (length) {
-		/*
-		 * Datablock.
-		 */
-		bytes = -offset;
-		compressed = SQUASHFS_COMPRESSED_BLOCK(length);
-		length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
-		if (next_index)
-			*next_index = index + length;
-
-		TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n",
-			index, compressed ? "" : "un", length, output->length);
-
-		if (length < 0 || length > output->length ||
-				(index + length) > msblk->bytes_used)
-			goto read_failure;
-
-		for (b = 0; bytes < length; b++, cur_index++) {
-			bh[b] = sb_getblk(sb, cur_index);
-			if (bh[b] == NULL)
-				goto block_release;
-			bytes += msblk->devblksize;
-		}
-		ll_rw_block(READ, b, bh);
-	} else {
-		/*
-		 * Metadata block.
-		 */
-		if ((index + 2) > msblk->bytes_used)
-			goto read_failure;
-
-		bh[0] = get_block_length(sb, &cur_index, &offset, &length);
-		if (bh[0] == NULL)
-			goto read_failure;
-		b = 1;
-
-		bytes = msblk->devblksize - offset;
-		compressed = SQUASHFS_COMPRESSED(length);
-		length = SQUASHFS_COMPRESSED_SIZE(length);
-		if (next_index)
-			*next_index = index + length + 2;
-
-		TRACE("Block @ 0x%llx, %scompressed size %d\n", index,
-				compressed ? "" : "un", length);
-
-		if (length < 0 || length > output->length ||
-					(index + length) > msblk->bytes_used)
-			goto block_release;
-
-		for (; bytes < length; b++) {
-			bh[b] = sb_getblk(sb, ++cur_index);
-			if (bh[b] == NULL)
-				goto block_release;
-			bytes += msblk->devblksize;
-		}
-		ll_rw_block(READ, b - 1, bh + 1);
 	}
 
-	for (i = 0; i < b; i++) {
-		wait_on_buffer(bh[i]);
-		if (!buffer_uptodate(bh[i]))
-			goto block_release;
+	req->sb = sb;
+	req->index = index;
+	req->output = output;
+
+	if (next_index)
+		*next_index = index;
+
+	if (length)
+		length = read_data_block(req, length, next_index, sync);
+	else
+		length = read_metadata_block(req, next_index);
+
+	if (length < 0) {
+		ERROR("squashfs_read_data failed to read block 0x%llx\n",
+		      (unsigned long long)index);
+		return -EIO;
 	}
 
-	if (compressed) {
-		length = squashfs_decompress(msblk, bh, b, offset, length,
-			output);
-		if (length < 0)
-			goto read_failure;
-	} else {
-		/*
-		 * Block is uncompressed.
-		 */
-		int in, pg_offset = 0;
-		void *data = squashfs_first_page(output);
-
-		for (bytes = length; k < b; k++) {
-			in = min(bytes, msblk->devblksize - offset);
-			bytes -= in;
-			while (in) {
-				if (pg_offset == PAGE_CACHE_SIZE) {
-					data = squashfs_next_page(output);
-					pg_offset = 0;
-				}
-				avail = min_t(int, in, PAGE_CACHE_SIZE -
-						pg_offset);
-				memcpy(data + pg_offset, bh[k]->b_data + offset,
-						avail);
-				in -= avail;
-				pg_offset += avail;
-				offset += avail;
-			}
-			offset = 0;
-			put_bh(bh[k]);
-		}
-		squashfs_finish_page(output);
-	}
-
-	kfree(bh);
 	return length;
+}
 
-block_release:
-	for (; k < b; k++)
-		put_bh(bh[k]);
+int squashfs_read_data(struct super_block *sb, u64 index, int length,
+	u64 *next_index, struct squashfs_page_actor *output)
+{
+	return __squashfs_read_data(sb, index, length, next_index, output,
+				    true);
+}
 
-read_failure:
-	ERROR("squashfs_read_data failed to read block 0x%llx\n",
-					(unsigned long long) index);
-	kfree(bh);
-	return -EIO;
+int squashfs_read_data_async(struct super_block *sb, u64 index, int length,
+	u64 *next_index, struct squashfs_page_actor *output)
+{
+
+	return __squashfs_read_data(sb, index, length, next_index, output,
+				    false);
 }
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
index 1cb70a0..6785d08 100644
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.c
@@ -209,17 +209,14 @@
  */
 void squashfs_cache_delete(struct squashfs_cache *cache)
 {
-	int i, j;
+	int i;
 
 	if (cache == NULL)
 		return;
 
 	for (i = 0; i < cache->entries; i++) {
-		if (cache->entry[i].data) {
-			for (j = 0; j < cache->pages; j++)
-				kfree(cache->entry[i].data[j]);
-			kfree(cache->entry[i].data);
-		}
+		if (cache->entry[i].page)
+			free_page_array(cache->entry[i].page, cache->pages);
 		kfree(cache->entry[i].actor);
 	}
 
@@ -236,7 +233,7 @@
 struct squashfs_cache *squashfs_cache_init(char *name, int entries,
 	int block_size)
 {
-	int i, j;
+	int i;
 	struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL);
 
 	if (cache == NULL) {
@@ -268,22 +265,13 @@
 		init_waitqueue_head(&cache->entry[i].wait_queue);
 		entry->cache = cache;
 		entry->block = SQUASHFS_INVALID_BLK;
-		entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL);
-		if (entry->data == NULL) {
+		entry->page = alloc_page_array(cache->pages, GFP_KERNEL);
+		if (!entry->page) {
 			ERROR("Failed to allocate %s cache entry\n", name);
 			goto cleanup;
 		}
-
-		for (j = 0; j < cache->pages; j++) {
-			entry->data[j] = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
-			if (entry->data[j] == NULL) {
-				ERROR("Failed to allocate %s buffer\n", name);
-				goto cleanup;
-			}
-		}
-
-		entry->actor = squashfs_page_actor_init(entry->data,
-						cache->pages, 0);
+		entry->actor = squashfs_page_actor_init(entry->page,
+			cache->pages, 0, NULL);
 		if (entry->actor == NULL) {
 			ERROR("Failed to allocate %s cache entry\n", name);
 			goto cleanup;
@@ -314,18 +302,20 @@
 		return min(length, entry->length - offset);
 
 	while (offset < entry->length) {
-		void *buff = entry->data[offset / PAGE_CACHE_SIZE]
-				+ (offset % PAGE_CACHE_SIZE);
+		void *buff = kmap_atomic(entry->page[offset / PAGE_CACHE_SIZE])
+			     + (offset % PAGE_CACHE_SIZE);
 		int bytes = min_t(int, entry->length - offset,
 				PAGE_CACHE_SIZE - (offset % PAGE_CACHE_SIZE));
 
 		if (bytes >= remaining) {
 			memcpy(buffer, buff, remaining);
+			kunmap_atomic(buff);
 			remaining = 0;
 			break;
 		}
 
 		memcpy(buffer, buff, bytes);
+		kunmap_atomic(buff);
 		buffer += bytes;
 		remaining -= bytes;
 		offset += bytes;
@@ -416,43 +406,38 @@
 void *squashfs_read_table(struct super_block *sb, u64 block, int length)
 {
 	int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	int i, res;
-	void *table, *buffer, **data;
+	struct page **page;
+	void *buff;
+	int res;
 	struct squashfs_page_actor *actor;
 
-	table = buffer = kmalloc(length, GFP_KERNEL);
-	if (table == NULL)
+	page = alloc_page_array(pages, GFP_KERNEL);
+	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
-	if (data == NULL) {
+	actor = squashfs_page_actor_init(page, pages, length, NULL);
+	if (actor == NULL) {
 		res = -ENOMEM;
 		goto failed;
 	}
 
-	actor = squashfs_page_actor_init(data, pages, length);
-	if (actor == NULL) {
-		res = -ENOMEM;
-		goto failed2;
-	}
-
-	for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
-		data[i] = buffer;
-
 	res = squashfs_read_data(sb, block, length |
 		SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, actor);
 
-	kfree(data);
-	kfree(actor);
-
 	if (res < 0)
-		goto failed;
+		goto failed2;
 
-	return table;
+	buff = kmalloc(length, GFP_KERNEL);
+	if (!buff)
+		goto failed2;
+	squashfs_actor_to_buf(actor, buff, length);
+	squashfs_page_actor_free(actor, 0);
+	free_page_array(page, pages);
+	return buff;
 
 failed2:
-	kfree(data);
+	squashfs_page_actor_free(actor, 0);
 failed:
-	kfree(table);
+	free_page_array(page, pages);
 	return ERR_PTR(res);
 }
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index e9034bf..7de35bf 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -24,7 +24,8 @@
 #include <linux/types.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/buffer_head.h>
+#include <linux/highmem.h>
+#include <linux/fs.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -94,40 +95,44 @@
 static void *get_comp_opts(struct super_block *sb, unsigned short flags)
 {
 	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	void *buffer = NULL, *comp_opts;
+	void *comp_opts, *buffer = NULL;
+	struct page *page;
 	struct squashfs_page_actor *actor = NULL;
 	int length = 0;
 
+	if (!SQUASHFS_COMP_OPTS(flags))
+		return squashfs_comp_opts(msblk, buffer, length);
+
 	/*
 	 * Read decompressor specific options from file system if present
 	 */
-	if (SQUASHFS_COMP_OPTS(flags)) {
-		buffer = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
-		if (buffer == NULL) {
-			comp_opts = ERR_PTR(-ENOMEM);
-			goto out;
-		}
 
-		actor = squashfs_page_actor_init(&buffer, 1, 0);
-		if (actor == NULL) {
-			comp_opts = ERR_PTR(-ENOMEM);
-			goto out;
-		}
+	page = alloc_page(GFP_KERNEL);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
 
-		length = squashfs_read_data(sb,
-			sizeof(struct squashfs_super_block), 0, NULL, actor);
-
-		if (length < 0) {
-			comp_opts = ERR_PTR(length);
-			goto out;
-		}
+	actor = squashfs_page_actor_init(&page, 1, 0, NULL);
+	if (actor == NULL) {
+		comp_opts = ERR_PTR(-ENOMEM);
+		goto actor_error;
 	}
 
-	comp_opts = squashfs_comp_opts(msblk, buffer, length);
+	length = squashfs_read_data(sb,
+		sizeof(struct squashfs_super_block), 0, NULL, actor);
 
-out:
-	kfree(actor);
-	kfree(buffer);
+	if (length < 0) {
+		comp_opts = ERR_PTR(length);
+		goto read_error;
+	}
+
+	buffer = kmap_atomic(page);
+	comp_opts = squashfs_comp_opts(msblk, buffer, length);
+	kunmap_atomic(buffer);
+
+read_error:
+	squashfs_page_actor_free(actor, 0);
+actor_error:
+	__free_page(page);
 	return comp_opts;
 }
 
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
index e5c9689..db62535 100644
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.c
@@ -53,6 +53,9 @@
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
 
+// Backported from 4.5
+#define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
+
 /*
  * Locate cache slot in range [offset, index] for specified inode.  If
  * there's more than one return the slot closest to index.
@@ -438,6 +441,21 @@
 	return res;
 }
 
+static int squashfs_readpages_fragment(struct page *page,
+	struct list_head *readahead_pages, struct address_space *mapping)
+{
+	if (!page) {
+		page = lru_to_page(readahead_pages);
+		list_del(&page->lru);
+		if (add_to_page_cache_lru(page, mapping, page->index,
+			GFP_KERNEL)) {
+			put_page(page);
+			return 0;
+		}
+	}
+	return squashfs_readpage_fragment(page);
+}
+
 static int squashfs_readpage_sparse(struct page *page, int index, int file_end)
 {
 	struct inode *inode = page->mapping->host;
@@ -450,54 +468,105 @@
 	return 0;
 }
 
-static int squashfs_readpage(struct file *file, struct page *page)
+static int squashfs_readpages_sparse(struct page *page,
+	struct list_head *readahead_pages, int index, int file_end,
+	struct address_space *mapping)
 {
-	struct inode *inode = page->mapping->host;
+	if (!page) {
+		page = lru_to_page(readahead_pages);
+		list_del(&page->lru);
+		if (add_to_page_cache_lru(page, mapping, page->index,
+			GFP_KERNEL)) {
+			put_page(page);
+			return 0;
+		}
+	}
+	return squashfs_readpage_sparse(page, index, file_end);
+}
+
+static int __squashfs_readpages(struct file *file, struct page *page,
+	struct list_head *readahead_pages, unsigned int nr_pages,
+	struct address_space *mapping)
+{
+	struct inode *inode = mapping->host;
 	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
-	int index = page->index >> (msblk->block_log - PAGE_CACHE_SHIFT);
 	int file_end = i_size_read(inode) >> msblk->block_log;
 	int res;
-	void *pageaddr;
+
+	do {
+		struct page *cur_page = page ? page
+					     : lru_to_page(readahead_pages);
+		int page_index = cur_page->index;
+		int index = page_index >> (msblk->block_log - PAGE_CACHE_SHIFT);
+
+		if (page_index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+						PAGE_CACHE_SHIFT))
+			return 1;
+
+		if (index < file_end || squashfs_i(inode)->fragment_block ==
+						SQUASHFS_INVALID_BLK) {
+			u64 block = 0;
+			int bsize = read_blocklist(inode, index, &block);
+
+			if (bsize < 0)
+				return -1;
+
+			if (bsize == 0) {
+				res = squashfs_readpages_sparse(page,
+					readahead_pages, index, file_end,
+					mapping);
+			} else {
+				res = squashfs_readpages_block(page,
+					readahead_pages, &nr_pages, mapping,
+					page_index, block, bsize);
+			}
+		} else {
+			res = squashfs_readpages_fragment(page,
+				readahead_pages, mapping);
+		}
+		if (res)
+			return 0;
+		page = NULL;
+	} while (readahead_pages && !list_empty(readahead_pages));
+
+	return 0;
+}
+
+static int squashfs_readpage(struct file *file, struct page *page)
+{
+	int ret;
 
 	TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
-				page->index, squashfs_i(inode)->start);
+	      page->index, squashfs_i(page->mapping->host)->start);
 
-	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
-					PAGE_CACHE_SHIFT))
-		goto out;
+	get_page(page);
 
-	if (index < file_end || squashfs_i(inode)->fragment_block ==
-					SQUASHFS_INVALID_BLK) {
-		u64 block = 0;
-		int bsize = read_blocklist(inode, index, &block);
-		if (bsize < 0)
-			goto error_out;
-
-		if (bsize == 0)
-			res = squashfs_readpage_sparse(page, index, file_end);
+	ret = __squashfs_readpages(file, page, NULL, 1, page->mapping);
+	if (ret) {
+		flush_dcache_page(page);
+		if (ret < 0)
+			SetPageError(page);
 		else
-			res = squashfs_readpage_block(page, block, bsize);
-	} else
-		res = squashfs_readpage_fragment(page);
+			SetPageUptodate(page);
+		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+		unlock_page(page);
+		put_page(page);
+	}
 
-	if (!res)
-		return 0;
+	return 0;
+}
 
-error_out:
-	SetPageError(page);
-out:
-	pageaddr = kmap_atomic(page);
-	memset(pageaddr, 0, PAGE_CACHE_SIZE);
-	kunmap_atomic(pageaddr);
-	flush_dcache_page(page);
-	if (!PageError(page))
-		SetPageUptodate(page);
-	unlock_page(page);
-
+static int squashfs_readpages(struct file *file, struct address_space *mapping,
+			      struct list_head *pages, unsigned int nr_pages)
+{
+	TRACE("Entered squashfs_readpages, %u pages, first page index %lx\n",
+		nr_pages, lru_to_page(pages)->index);
+	__squashfs_readpages(file, NULL, pages, nr_pages, mapping);
 	return 0;
 }
 
 
 const struct address_space_operations squashfs_aops = {
-	.readpage = squashfs_readpage
+	.readpage = squashfs_readpage,
+	.readpages = squashfs_readpages,
 };
diff --git a/fs/squashfs/file_cache.c b/fs/squashfs/file_cache.c
deleted file mode 100644
index f2310d2..0000000
--- a/fs/squashfs/file_cache.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013
- * Phillip Lougher <phillip@squashfs.org.uk>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include <linux/fs.h>
-#include <linux/vfs.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/pagemap.h>
-#include <linux/mutex.h>
-
-#include "squashfs_fs.h"
-#include "squashfs_fs_sb.h"
-#include "squashfs_fs_i.h"
-#include "squashfs.h"
-
-/* Read separately compressed datablock and memcopy into page cache */
-int squashfs_readpage_block(struct page *page, u64 block, int bsize)
-{
-	struct inode *i = page->mapping->host;
-	struct squashfs_cache_entry *buffer = squashfs_get_datablock(i->i_sb,
-		block, bsize);
-	int res = buffer->error;
-
-	if (res)
-		ERROR("Unable to read page, block %llx, size %x\n", block,
-			bsize);
-	else
-		squashfs_copy_cache(page, buffer, buffer->length, 0);
-
-	squashfs_cache_put(buffer);
-	return res;
-}
diff --git a/fs/squashfs/file_direct.c b/fs/squashfs/file_direct.c
index 43e7a7e..b0b31c0 100644
--- a/fs/squashfs/file_direct.c
+++ b/fs/squashfs/file_direct.c
@@ -20,157 +20,139 @@
 #include "squashfs.h"
 #include "page_actor.h"
 
-static int squashfs_read_cache(struct page *target_page, u64 block, int bsize,
-	int pages, struct page **page);
+// Backported from 4.5
+#define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
 
-/* Read separately compressed datablock directly into page cache */
-int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
-
+static void release_actor_pages(struct page **page, int pages, int error)
 {
-	struct inode *inode = target_page->mapping->host;
-	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	int i;
 
-	int file_end = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
-	int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
-	int start_index = target_page->index & ~mask;
-	int end_index = start_index | mask;
-	int i, n, pages, missing_pages, bytes, res = -ENOMEM;
+	for (i = 0; i < pages; i++) {
+		if (!page[i])
+			continue;
+		flush_dcache_page(page[i]);
+		if (!error)
+			SetPageUptodate(page[i]);
+		else {
+			SetPageError(page[i]);
+			zero_user_segment(page[i], 0, PAGE_CACHE_SIZE);
+		}
+		unlock_page(page[i]);
+		put_page(page[i]);
+	}
+	kfree(page);
+}
+
+/*
+ * Create a "page actor" which will kmap and kunmap the
+ * page cache pages appropriately within the decompressor
+ */
+static struct squashfs_page_actor *actor_from_page_cache(
+	unsigned int actor_pages, struct page *target_page,
+	struct list_head *rpages, unsigned int *nr_pages, int start_index,
+	struct address_space *mapping)
+{
 	struct page **page;
 	struct squashfs_page_actor *actor;
-	void *pageaddr;
+	int i, n;
+	gfp_t gfp = GFP_KERNEL;
 
-	if (end_index > file_end)
-		end_index = file_end;
+	page = kmalloc_array(actor_pages, sizeof(void *), GFP_KERNEL);
+	if (!page)
+		return NULL;
 
-	pages = end_index - start_index + 1;
+	for (i = 0, n = start_index; i < actor_pages; i++, n++) {
+		if (target_page == NULL && rpages && !list_empty(rpages)) {
+			struct page *cur_page = lru_to_page(rpages);
 
-	page = kmalloc_array(pages, sizeof(void *), GFP_KERNEL);
-	if (page == NULL)
-		return res;
+			if (cur_page->index < start_index + actor_pages) {
+				list_del(&cur_page->lru);
+				--(*nr_pages);
+				if (add_to_page_cache_lru(cur_page, mapping,
+							  cur_page->index, gfp))
+					put_page(cur_page);
+				else
+					target_page = cur_page;
+			} else
+				rpages = NULL;
+		}
 
-	/*
-	 * Create a "page actor" which will kmap and kunmap the
-	 * page cache pages appropriately within the decompressor
-	 */
-	actor = squashfs_page_actor_init_special(page, pages, 0);
-	if (actor == NULL)
-		goto out;
-
-	/* Try to grab all the pages covered by the Squashfs block */
-	for (missing_pages = 0, i = 0, n = start_index; i < pages; i++, n++) {
-		page[i] = (n == target_page->index) ? target_page :
-			grab_cache_page_nowait(target_page->mapping, n);
-
-		if (page[i] == NULL) {
-			missing_pages++;
-			continue;
+		if (target_page && target_page->index == n) {
+			page[i] = target_page;
+			target_page = NULL;
+		} else {
+			page[i] = grab_cache_page_nowait(mapping, n);
+			if (page[i] == NULL)
+				continue;
 		}
 
 		if (PageUptodate(page[i])) {
 			unlock_page(page[i]);
 			page_cache_release(page[i]);
 			page[i] = NULL;
-			missing_pages++;
 		}
 	}
 
-	if (missing_pages) {
-		/*
-		 * Couldn't get one or more pages, this page has either
-		 * been VM reclaimed, but others are still in the page cache
-		 * and uptodate, or we're racing with another thread in
-		 * squashfs_readpage also trying to grab them.  Fall back to
-		 * using an intermediate buffer.
-		 */
-		res = squashfs_read_cache(target_page, block, bsize, pages,
-								page);
-		if (res < 0)
-			goto mark_errored;
-
-		goto out;
+	actor = squashfs_page_actor_init(page, actor_pages, 0,
+			release_actor_pages);
+	if (!actor) {
+		release_actor_pages(page, actor_pages, -ENOMEM);
+		kfree(page);
+		return NULL;
 	}
-
-	/* Decompress directly into the page cache buffers */
-	res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
-	if (res < 0)
-		goto mark_errored;
-
-	/* Last page may have trailing bytes not filled */
-	bytes = res % PAGE_CACHE_SIZE;
-	if (bytes) {
-		pageaddr = kmap_atomic(page[pages - 1]);
-		memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
-		kunmap_atomic(pageaddr);
-	}
-
-	/* Mark pages as uptodate, unlock and release */
-	for (i = 0; i < pages; i++) {
-		flush_dcache_page(page[i]);
-		SetPageUptodate(page[i]);
-		unlock_page(page[i]);
-		if (page[i] != target_page)
-			page_cache_release(page[i]);
-	}
-
-	kfree(actor);
-	kfree(page);
-
-	return 0;
-
-mark_errored:
-	/* Decompression failed, mark pages as errored.  Target_page is
-	 * dealt with by the caller
-	 */
-	for (i = 0; i < pages; i++) {
-		if (page[i] == NULL || page[i] == target_page)
-			continue;
-		flush_dcache_page(page[i]);
-		SetPageError(page[i]);
-		unlock_page(page[i]);
-		page_cache_release(page[i]);
-	}
-
-out:
-	kfree(actor);
-	kfree(page);
-	return res;
+	return actor;
 }
 
+int squashfs_readpages_block(struct page *target_page,
+			     struct list_head *readahead_pages,
+			     unsigned int *nr_pages,
+			     struct address_space *mapping,
+			     int page_index, u64 block, int bsize)
 
-static int squashfs_read_cache(struct page *target_page, u64 block, int bsize,
-	int pages, struct page **page)
 {
-	struct inode *i = target_page->mapping->host;
-	struct squashfs_cache_entry *buffer = squashfs_get_datablock(i->i_sb,
-						 block, bsize);
-	int bytes = buffer->length, res = buffer->error, n, offset = 0;
-	void *pageaddr;
+	struct squashfs_page_actor *actor;
+	struct inode *inode = mapping->host;
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	int start_index, end_index, file_end, actor_pages, res;
+	int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
 
-	if (res) {
-		ERROR("Unable to read page, block %llx, size %x\n", block,
-			bsize);
-		goto out;
+	/*
+	 * If readpage() is called on an uncompressed datablock, we can just
+	 * read the pages instead of fetching the whole block.
+	 * This greatly improves the performance when a process keep doing
+	 * random reads because we only fetch the necessary data.
+	 * The readahead algorithm will take care of doing speculative reads
+	 * if necessary.
+	 * We can't read more than 1 block even if readahead provides use more
+	 * pages because we don't know yet if the next block is compressed or
+	 * not.
+	 */
+	if (bsize && !SQUASHFS_COMPRESSED_BLOCK(bsize)) {
+		u64 block_end = block + msblk->block_size;
+
+		block += (page_index & mask) * PAGE_SIZE;
+		actor_pages = (block_end - block) / PAGE_SIZE;
+		if (*nr_pages < actor_pages)
+			actor_pages = *nr_pages;
+		start_index = page_index;
+		bsize = min_t(int, bsize, (PAGE_SIZE * actor_pages)
+					  | SQUASHFS_COMPRESSED_BIT_BLOCK);
+	} else {
+		file_end = (i_size_read(inode) - 1) >> PAGE_SHIFT;
+		start_index = page_index & ~mask;
+		end_index = start_index | mask;
+		if (end_index > file_end)
+			end_index = file_end;
+		actor_pages = end_index - start_index + 1;
 	}
 
-	for (n = 0; n < pages && bytes > 0; n++,
-			bytes -= PAGE_CACHE_SIZE, offset += PAGE_CACHE_SIZE) {
-		int avail = min_t(int, bytes, PAGE_CACHE_SIZE);
+	actor = actor_from_page_cache(actor_pages, target_page,
+				      readahead_pages, nr_pages, start_index,
+				      mapping);
+	if (!actor)
+		return -ENOMEM;
 
-		if (page[n] == NULL)
-			continue;
-
-		pageaddr = kmap_atomic(page[n]);
-		squashfs_copy_data(pageaddr, buffer, offset, avail);
-		memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
-		kunmap_atomic(pageaddr);
-		flush_dcache_page(page[n]);
-		SetPageUptodate(page[n]);
-		unlock_page(page[n]);
-		if (page[n] != target_page)
-			page_cache_release(page[n]);
-	}
-
-out:
-	squashfs_cache_put(buffer);
-	return res;
+	res = squashfs_read_data_async(inode->i_sb, block, bsize, NULL,
+				       actor);
+	return res < 0 ? res : 0;
 }
diff --git a/fs/squashfs/lz4_wrapper.c b/fs/squashfs/lz4_wrapper.c
index c31e2bc..df4fa3c 100644
--- a/fs/squashfs/lz4_wrapper.c
+++ b/fs/squashfs/lz4_wrapper.c
@@ -94,39 +94,17 @@
 	struct buffer_head **bh, int b, int offset, int length,
 	struct squashfs_page_actor *output)
 {
-	struct squashfs_lz4 *stream = strm;
-	void *buff = stream->input, *data;
-	int avail, i, bytes = length, res;
+	int res;
 	size_t dest_len = output->length;
+	struct squashfs_lz4 *stream = strm;
 
-	for (i = 0; i < b; i++) {
-		avail = min(bytes, msblk->devblksize - offset);
-		memcpy(buff, bh[i]->b_data + offset, avail);
-		buff += avail;
-		bytes -= avail;
-		offset = 0;
-		put_bh(bh[i]);
-	}
-
+	squashfs_bh_to_buf(bh, b, stream->input, offset, length,
+		msblk->devblksize);
 	res = lz4_decompress_unknownoutputsize(stream->input, length,
 					stream->output, &dest_len);
 	if (res)
 		return -EIO;
-
-	bytes = dest_len;
-	data = squashfs_first_page(output);
-	buff = stream->output;
-	while (data) {
-		if (bytes <= PAGE_CACHE_SIZE) {
-			memcpy(data, buff, bytes);
-			break;
-		}
-		memcpy(data, buff, PAGE_CACHE_SIZE);
-		buff += PAGE_CACHE_SIZE;
-		bytes -= PAGE_CACHE_SIZE;
-		data = squashfs_next_page(output);
-	}
-	squashfs_finish_page(output);
+	squashfs_buf_to_actor(stream->output, output, dest_len);
 
 	return dest_len;
 }
diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c
index 244b9fb..2c844d5 100644
--- a/fs/squashfs/lzo_wrapper.c
+++ b/fs/squashfs/lzo_wrapper.c
@@ -79,45 +79,19 @@
 	struct buffer_head **bh, int b, int offset, int length,
 	struct squashfs_page_actor *output)
 {
-	struct squashfs_lzo *stream = strm;
-	void *buff = stream->input, *data;
-	int avail, i, bytes = length, res;
+	int res;
 	size_t out_len = output->length;
+	struct squashfs_lzo *stream = strm;
 
-	for (i = 0; i < b; i++) {
-		avail = min(bytes, msblk->devblksize - offset);
-		memcpy(buff, bh[i]->b_data + offset, avail);
-		buff += avail;
-		bytes -= avail;
-		offset = 0;
-		put_bh(bh[i]);
-	}
-
+	squashfs_bh_to_buf(bh, b, stream->input, offset, length,
+		msblk->devblksize);
 	res = lzo1x_decompress_safe(stream->input, (size_t)length,
 					stream->output, &out_len);
 	if (res != LZO_E_OK)
-		goto failed;
+		return -EIO;
+	squashfs_buf_to_actor(stream->output, output, out_len);
 
-	res = bytes = (int)out_len;
-	data = squashfs_first_page(output);
-	buff = stream->output;
-	while (data) {
-		if (bytes <= PAGE_CACHE_SIZE) {
-			memcpy(data, buff, bytes);
-			break;
-		} else {
-			memcpy(data, buff, PAGE_CACHE_SIZE);
-			buff += PAGE_CACHE_SIZE;
-			bytes -= PAGE_CACHE_SIZE;
-			data = squashfs_next_page(output);
-		}
-	}
-	squashfs_finish_page(output);
-
-	return res;
-
-failed:
-	return -EIO;
+	return out_len;
 }
 
 const struct squashfs_decompressor squashfs_lzo_comp_ops = {
diff --git a/fs/squashfs/page_actor.c b/fs/squashfs/page_actor.c
index 5a1c11f..ee1ade2 100644
--- a/fs/squashfs/page_actor.c
+++ b/fs/squashfs/page_actor.c
@@ -9,92 +9,145 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/buffer_head.h>
 #include "page_actor.h"
 
-/*
- * This file contains implementations of page_actor for decompressing into
- * an intermediate buffer, and for decompressing directly into the
- * page cache.
- *
- * Calling code should avoid sleeping between calls to squashfs_first_page()
- * and squashfs_finish_page().
- */
-
-/* Implementation of page_actor for decompressing into intermediate buffer */
-static void *cache_first_page(struct squashfs_page_actor *actor)
-{
-	actor->next_page = 1;
-	return actor->buffer[0];
-}
-
-static void *cache_next_page(struct squashfs_page_actor *actor)
-{
-	if (actor->next_page == actor->pages)
-		return NULL;
-
-	return actor->buffer[actor->next_page++];
-}
-
-static void cache_finish_page(struct squashfs_page_actor *actor)
-{
-	/* empty */
-}
-
-struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
-	int pages, int length)
+struct squashfs_page_actor *squashfs_page_actor_init(struct page **page,
+	int pages, int length, void (*release_pages)(struct page **, int, int))
 {
 	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
 
 	if (actor == NULL)
 		return NULL;
 
-	actor->length = length ? : pages * PAGE_CACHE_SIZE;
-	actor->buffer = buffer;
-	actor->pages = pages;
-	actor->next_page = 0;
-	actor->squashfs_first_page = cache_first_page;
-	actor->squashfs_next_page = cache_next_page;
-	actor->squashfs_finish_page = cache_finish_page;
-	return actor;
-}
-
-/* Implementation of page_actor for decompressing directly into page cache. */
-static void *direct_first_page(struct squashfs_page_actor *actor)
-{
-	actor->next_page = 1;
-	return actor->pageaddr = kmap_atomic(actor->page[0]);
-}
-
-static void *direct_next_page(struct squashfs_page_actor *actor)
-{
-	if (actor->pageaddr)
-		kunmap_atomic(actor->pageaddr);
-
-	return actor->pageaddr = actor->next_page == actor->pages ? NULL :
-		kmap_atomic(actor->page[actor->next_page++]);
-}
-
-static void direct_finish_page(struct squashfs_page_actor *actor)
-{
-	if (actor->pageaddr)
-		kunmap_atomic(actor->pageaddr);
-}
-
-struct squashfs_page_actor *squashfs_page_actor_init_special(struct page **page,
-	int pages, int length)
-{
-	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
-
-	if (actor == NULL)
-		return NULL;
-
-	actor->length = length ? : pages * PAGE_CACHE_SIZE;
+	actor->length = length ? : pages * PAGE_SIZE;
 	actor->page = page;
 	actor->pages = pages;
 	actor->next_page = 0;
 	actor->pageaddr = NULL;
-	actor->squashfs_first_page = direct_first_page;
-	actor->squashfs_next_page = direct_next_page;
-	actor->squashfs_finish_page = direct_finish_page;
+	actor->release_pages = release_pages;
 	return actor;
 }
+
+void squashfs_page_actor_free(struct squashfs_page_actor *actor, int error)
+{
+	if (!actor)
+		return;
+
+	if (actor->release_pages)
+		actor->release_pages(actor->page, actor->pages, error);
+	kfree(actor);
+}
+
+void squashfs_actor_to_buf(struct squashfs_page_actor *actor, void *buf,
+	int length)
+{
+	void *pageaddr;
+	int i, avail, pos = 0;
+
+	for (i = 0; i < actor->pages && pos < length; ++i) {
+		avail = min_t(int, length - pos, PAGE_SIZE);
+		if (actor->page[i]) {
+			pageaddr = kmap_atomic(actor->page[i]);
+			memcpy(buf + pos, pageaddr, avail);
+			kunmap_atomic(pageaddr);
+		}
+		pos += avail;
+	}
+}
+
+void squashfs_buf_to_actor(void *buf, struct squashfs_page_actor *actor,
+	int length)
+{
+	void *pageaddr;
+	int i, avail, pos = 0;
+
+	for (i = 0; i < actor->pages && pos < length; ++i) {
+		avail = min_t(int, length - pos, PAGE_SIZE);
+		if (actor->page[i]) {
+			pageaddr = kmap_atomic(actor->page[i]);
+			memcpy(pageaddr, buf + pos, avail);
+			kunmap_atomic(pageaddr);
+		}
+		pos += avail;
+	}
+}
+
+void squashfs_bh_to_actor(struct buffer_head **bh, int nr_buffers,
+	struct squashfs_page_actor *actor, int offset, int length, int blksz)
+{
+	void *kaddr = NULL;
+	int bytes = 0, pgoff = 0, b = 0, p = 0, i, avail;
+
+	while (bytes < length) {
+		if (actor->page[p]) {
+			kaddr = kmap_atomic(actor->page[p]);
+			while (pgoff < PAGE_SIZE && bytes < length) {
+				avail = min_t(int, blksz - offset,
+						PAGE_SIZE - pgoff);
+				memcpy(kaddr + pgoff, bh[b]->b_data + offset,
+				       avail);
+				pgoff += avail;
+				bytes += avail;
+				offset = (offset + avail) % blksz;
+				if (!offset) {
+					put_bh(bh[b]);
+					++b;
+				}
+			}
+			kunmap_atomic(kaddr);
+			pgoff = 0;
+		} else {
+			for (i = 0; i < PAGE_SIZE / blksz; ++i) {
+				if (bh[b])
+					put_bh(bh[b]);
+				++b;
+			}
+			bytes += PAGE_SIZE;
+		}
+		++p;
+	}
+}
+
+void squashfs_bh_to_buf(struct buffer_head **bh, int nr_buffers, void *buf,
+	int offset, int length, int blksz)
+{
+	int i, avail, bytes = 0;
+
+	for (i = 0; i < nr_buffers && bytes < length; ++i) {
+		avail = min_t(int, length - bytes, blksz - offset);
+		if (bh[i]) {
+			memcpy(buf + bytes, bh[i]->b_data + offset, avail);
+			put_bh(bh[i]);
+		}
+		bytes += avail;
+		offset = 0;
+	}
+}
+
+void free_page_array(struct page **page, int nr_pages)
+{
+	int i;
+
+	for (i = 0; i < nr_pages; ++i)
+		__free_page(page[i]);
+	kfree(page);
+}
+
+struct page **alloc_page_array(int nr_pages, int gfp_mask)
+{
+	int i;
+	struct page **page;
+
+	page = kcalloc(nr_pages, sizeof(struct page *), gfp_mask);
+	if (!page)
+		return NULL;
+	for (i = 0; i < nr_pages; ++i) {
+		page[i] = alloc_page(gfp_mask);
+		if (!page[i]) {
+			free_page_array(page, i);
+			return NULL;
+		}
+	}
+	return page;
+}
diff --git a/fs/squashfs/page_actor.h b/fs/squashfs/page_actor.h
index 26dd820..c228de9 100644
--- a/fs/squashfs/page_actor.h
+++ b/fs/squashfs/page_actor.h
@@ -8,74 +8,58 @@
  * the COPYING file in the top-level directory.
  */
 
-#ifndef CONFIG_SQUASHFS_FILE_DIRECT
 struct squashfs_page_actor {
-	void	**page;
+	struct page	**page;
+	void	*pageaddr;
 	int	pages;
 	int	length;
 	int	next_page;
+	void	(*release_pages)(struct page **, int, int);
 };
 
-static inline struct squashfs_page_actor *squashfs_page_actor_init(void **page,
-	int pages, int length)
-{
-	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
+extern struct squashfs_page_actor *squashfs_page_actor_init(struct page **,
+	int, int, void (*)(struct page **, int, int));
+extern void squashfs_page_actor_free(struct squashfs_page_actor *, int);
 
-	if (actor == NULL)
-		return NULL;
+extern void squashfs_actor_to_buf(struct squashfs_page_actor *, void *, int);
+extern void squashfs_buf_to_actor(void *, struct squashfs_page_actor *, int);
+extern void squashfs_bh_to_actor(struct buffer_head **, int,
+	struct squashfs_page_actor *, int, int, int);
+extern void squashfs_bh_to_buf(struct buffer_head **, int, void *, int, int,
+	int);
 
-	actor->length = length ? : pages * PAGE_CACHE_SIZE;
-	actor->page = page;
-	actor->pages = pages;
-	actor->next_page = 0;
-	return actor;
-}
-
+/*
+ * Calling code should avoid sleeping between calls to squashfs_first_page()
+ * and squashfs_finish_page().
+ */
 static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
 {
 	actor->next_page = 1;
-	return actor->page[0];
+	return actor->pageaddr = actor->page[0] ? kmap_atomic(actor->page[0])
+						: NULL;
 }
 
 static inline void *squashfs_next_page(struct squashfs_page_actor *actor)
 {
-	return actor->next_page == actor->pages ? NULL :
-		actor->page[actor->next_page++];
+	if (!IS_ERR_OR_NULL(actor->pageaddr))
+		kunmap_atomic(actor->pageaddr);
+
+	if (actor->next_page == actor->pages)
+		return actor->pageaddr = ERR_PTR(-ENODATA);
+
+	actor->pageaddr = actor->page[actor->next_page] ?
+	    kmap_atomic(actor->page[actor->next_page]) : NULL;
+	++actor->next_page;
+	return actor->pageaddr;
 }
 
 static inline void squashfs_finish_page(struct squashfs_page_actor *actor)
 {
-	/* empty */
+	if (!IS_ERR_OR_NULL(actor->pageaddr))
+		kunmap_atomic(actor->pageaddr);
 }
-#else
-struct squashfs_page_actor {
-	union {
-		void		**buffer;
-		struct page	**page;
-	};
-	void	*pageaddr;
-	void    *(*squashfs_first_page)(struct squashfs_page_actor *);
-	void    *(*squashfs_next_page)(struct squashfs_page_actor *);
-	void    (*squashfs_finish_page)(struct squashfs_page_actor *);
-	int	pages;
-	int	length;
-	int	next_page;
-};
 
-extern struct squashfs_page_actor *squashfs_page_actor_init(void **, int, int);
-extern struct squashfs_page_actor *squashfs_page_actor_init_special(struct page
-							 **, int, int);
-static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
-{
-	return actor->squashfs_first_page(actor);
-}
-static inline void *squashfs_next_page(struct squashfs_page_actor *actor)
-{
-	return actor->squashfs_next_page(actor);
-}
-static inline void squashfs_finish_page(struct squashfs_page_actor *actor)
-{
-	actor->squashfs_finish_page(actor);
-}
-#endif
+extern struct page **alloc_page_array(int, int);
+extern void free_page_array(struct page **, int);
+
 #endif
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 887d6d2..bb28f16 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -28,8 +28,14 @@
 #define WARNING(s, args...)	pr_warn("SQUASHFS: "s, ## args)
 
 /* block.c */
+extern int squashfs_init_read_wq(void);
 extern int squashfs_read_data(struct super_block *, u64, int, u64 *,
 				struct squashfs_page_actor *);
+extern void squashfs_destroy_read_wq(void);
+extern int squashfs_read_data(struct super_block *, u64, int, u64 *,
+	struct squashfs_page_actor *);
+extern int squashfs_read_data_async(struct super_block *, u64, int, u64 *,
+	struct squashfs_page_actor *);
 
 /* cache.c */
 extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
@@ -70,8 +76,9 @@
 void squashfs_copy_cache(struct page *, struct squashfs_cache_entry *, int,
 				int);
 
-/* file_xxx.c */
-extern int squashfs_readpage_block(struct page *, u64, int);
+/* file_direct.c */
+extern int squashfs_readpages_block(struct page *, struct list_head *,
+	unsigned int *, struct address_space *, int, u64, int);
 
 /* id.c */
 extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1da565c..8a6995d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -49,7 +49,7 @@
 	int			num_waiters;
 	wait_queue_head_t	wait_queue;
 	struct squashfs_cache	*cache;
-	void			**data;
+	struct page		**page;
 	struct squashfs_page_actor	*actor;
 };
 
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 5056bab..61cd0b3 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -444,9 +444,15 @@
 	if (err)
 		return err;
 
+	if (!squashfs_init_read_wq()) {
+		destroy_inodecache();
+		return -ENOMEM;
+        }
+
 	err = register_filesystem(&squashfs_fs_type);
 	if (err) {
 		destroy_inodecache();
+		squashfs_destroy_read_wq();
 		return err;
 	}
 
@@ -460,6 +466,7 @@
 {
 	unregister_filesystem(&squashfs_fs_type);
 	destroy_inodecache();
+	squashfs_destroy_read_wq();
 }
 
 
diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c
index c609624..2f7be1f 100644
--- a/fs/squashfs/xz_wrapper.c
+++ b/fs/squashfs/xz_wrapper.c
@@ -55,7 +55,7 @@
 	struct comp_opts *opts;
 	int err = 0, n;
 
-	opts = kmalloc(sizeof(*opts), GFP_KERNEL);
+	opts = kmalloc(sizeof(*opts), GFP_ATOMIC);
 	if (opts == NULL) {
 		err = -ENOMEM;
 		goto out2;
@@ -136,12 +136,13 @@
 	enum xz_ret xz_err;
 	int avail, total = 0, k = 0;
 	struct squashfs_xz *stream = strm;
+	void *buf = NULL;
 
 	xz_dec_reset(stream->state);
 	stream->buf.in_pos = 0;
 	stream->buf.in_size = 0;
 	stream->buf.out_pos = 0;
-	stream->buf.out_size = PAGE_CACHE_SIZE;
+	stream->buf.out_size = PAGE_SIZE;
 	stream->buf.out = squashfs_first_page(output);
 
 	do {
@@ -156,12 +157,20 @@
 
 		if (stream->buf.out_pos == stream->buf.out_size) {
 			stream->buf.out = squashfs_next_page(output);
-			if (stream->buf.out != NULL) {
+			if (!IS_ERR(stream->buf.out)) {
 				stream->buf.out_pos = 0;
-				total += PAGE_CACHE_SIZE;
+				total += PAGE_SIZE;
 			}
 		}
 
+		if (!stream->buf.out) {
+			if (!buf) {
+				buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+				if (!buf)
+					goto out;
+			}
+			stream->buf.out = buf;
+		}
 		xz_err = xz_dec_run(stream->state, &stream->buf);
 
 		if (stream->buf.in_pos == stream->buf.in_size && k < b)
@@ -173,11 +182,13 @@
 	if (xz_err != XZ_STREAM_END || k < b)
 		goto out;
 
+	kfree(buf);
 	return total + stream->buf.out_pos;
 
 out:
 	for (; k < b; k++)
 		put_bh(bh[k]);
+	kfree(buf);
 
 	return -EIO;
 }
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
index 8727cab..d917c72 100644
--- a/fs/squashfs/zlib_wrapper.c
+++ b/fs/squashfs/zlib_wrapper.c
@@ -66,10 +66,11 @@
 	struct buffer_head **bh, int b, int offset, int length,
 	struct squashfs_page_actor *output)
 {
+	void *buf = NULL;
 	int zlib_err, zlib_init = 0, k = 0;
 	z_stream *stream = strm;
 
-	stream->avail_out = PAGE_CACHE_SIZE;
+	stream->avail_out = PAGE_SIZE;
 	stream->next_out = squashfs_first_page(output);
 	stream->avail_in = 0;
 
@@ -84,8 +85,17 @@
 
 		if (stream->avail_out == 0) {
 			stream->next_out = squashfs_next_page(output);
-			if (stream->next_out != NULL)
-				stream->avail_out = PAGE_CACHE_SIZE;
+			if (!IS_ERR(stream->next_out))
+				stream->avail_out = PAGE_SIZE;
+		}
+
+		if (!stream->next_out) {
+			if (!buf) {
+				buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+				if (!buf)
+					goto out;
+			}
+			stream->next_out = buf;
 		}
 
 		if (!zlib_init) {
@@ -115,11 +125,13 @@
 	if (k < b)
 		goto out;
 
+	kfree(buf);
 	return stream->total_out;
 
 out:
 	for (; k < b; k++)
 		put_bh(bh[k]);
+	kfree(buf);
 
 	return -EIO;
 }
diff --git a/fs/super.c b/fs/super.c
index 4659bf4..c40b464 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -693,7 +693,8 @@
 }
 
 /**
- *	do_remount_sb - asks filesystem to change mount options.
+ *	do_remount_sb2 - asks filesystem to change mount options.
+ *	@mnt:   mount we are looking at
  *	@sb:	superblock in question
  *	@flags:	numeric part of options
  *	@data:	the rest of options
@@ -701,7 +702,7 @@
  *
  *	Alters the mount options of a mounted file system.
  */
-int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+int do_remount_sb2(struct vfsmount *mnt, struct super_block *sb, int flags, void *data, int force)
 {
 	int retval;
 	int remount_ro;
@@ -733,7 +734,16 @@
 		}
 	}
 
-	if (sb->s_op->remount_fs) {
+	if (mnt && sb->s_op->remount_fs2) {
+		retval = sb->s_op->remount_fs2(mnt, sb, &flags, data);
+		if (retval) {
+			if (!force)
+				goto cancel_readonly;
+			/* If forced remount, go ahead despite any errors */
+			WARN(1, "forced remount of a %s fs returned %i\n",
+			     sb->s_type->name, retval);
+		}
+	} else if (sb->s_op->remount_fs) {
 		retval = sb->s_op->remount_fs(sb, &flags, data);
 		if (retval) {
 			if (!force)
@@ -765,6 +775,11 @@
 	return retval;
 }
 
+int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+{
+	return do_remount_sb2(NULL, sb, flags, data, force);
+}
+
 static void do_emergency_remount(struct work_struct *work)
 {
 	struct super_block *sb, *p = NULL;
@@ -1084,7 +1099,7 @@
 EXPORT_SYMBOL(mount_single);
 
 struct dentry *
-mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
+mount_fs(struct file_system_type *type, int flags, const char *name, struct vfsmount *mnt, void *data)
 {
 	struct dentry *root;
 	struct super_block *sb;
@@ -1101,7 +1116,10 @@
 			goto out_free_secdata;
 	}
 
-	root = type->mount(type, flags, name, data);
+	if (type->mount2)
+		root = type->mount2(mnt, type, flags, name, data);
+	else
+		root = type->mount(type, flags, name, data);
 	if (IS_ERR(root)) {
 		error = PTR_ERR(root);
 		goto out_free_secdata;
diff --git a/fs/utimes.c b/fs/utimes.c
index f4fb7ec..7216a07 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -96,13 +96,13 @@
 			goto mnt_drop_write_and_out;
 
 		if (!inode_owner_or_capable(inode)) {
-			error = inode_permission(inode, MAY_WRITE);
+			error = inode_permission2(path->mnt, inode, MAY_WRITE);
 			if (error)
 				goto mnt_drop_write_and_out;
 		}
 	}
 	mutex_lock(&inode->i_mutex);
-	error = notify_change(path->dentry, &newattrs);
+	error = notify_change2(path->mnt, path->dentry, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 
 mnt_drop_write_and_out:
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 04421e8..7290f37 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -121,6 +121,7 @@
 	kernel_cap_t	cap_permitted;	/* caps we're permitted */
 	kernel_cap_t	cap_effective;	/* caps we can actually use */
 	kernel_cap_t	cap_bset;	/* capability bounding set */
+	kernel_cap_t	cap_ambient;	/* Ambient capability set */
 #ifdef CONFIG_KEYS
 	unsigned char	jit_keyring;	/* default keyring to attach requested
 					 * keys to */
@@ -196,6 +197,13 @@
 }
 #endif
 
+static inline bool cap_ambient_invariant_ok(const struct cred *cred)
+{
+	return cap_issubset(cred->cap_ambient,
+			    cap_intersect(cred->cap_permitted,
+					  cred->cap_inheritable));
+}
+
 /**
  * get_new_cred - Get a reference on a new set of credentials
  * @cred: The new credentials to reference
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9c72e5d..0b3e7de 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1469,13 +1469,20 @@
  * VFS helper functions..
  */
 extern int vfs_create(struct inode *, struct dentry *, umode_t, bool);
+extern int vfs_create2(struct vfsmount *, struct inode *, struct dentry *, umode_t, bool);
 extern int vfs_mkdir(struct inode *, struct dentry *, umode_t);
+extern int vfs_mkdir2(struct vfsmount *, struct inode *, struct dentry *, umode_t);
 extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
+extern int vfs_mknod2(struct vfsmount *, struct inode *, struct dentry *, umode_t, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
+extern int vfs_link2(struct vfsmount *, struct dentry *, struct inode *, struct dentry *);
 extern int vfs_rmdir(struct inode *, struct dentry *);
+extern int vfs_rmdir2(struct vfsmount *, struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *);
+extern int vfs_unlink2(struct vfsmount *, struct inode *, struct dentry *);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+extern int vfs_rename2(struct vfsmount *, struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 /*
  * VFS dentry helper functions.
@@ -1579,6 +1586,7 @@
 	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
 	void * (*follow_link) (struct dentry *, struct nameidata *);
 	int (*permission) (struct inode *, int);
+	int (*permission2) (struct vfsmount *, struct inode *, int);
 	struct posix_acl * (*get_acl)(struct inode *, int);
 
 	int (*readlink) (struct dentry *, char __user *,int);
@@ -1594,6 +1602,7 @@
 	int (*rename) (struct inode *, struct dentry *,
 			struct inode *, struct dentry *);
 	int (*setattr) (struct dentry *, struct iattr *);
+	int (*setattr2) (struct vfsmount *, struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
@@ -1633,9 +1642,13 @@
 	int (*unfreeze_fs) (struct super_block *);
 	int (*statfs) (struct dentry *, struct kstatfs *);
 	int (*remount_fs) (struct super_block *, int *, char *);
+	int (*remount_fs2) (struct vfsmount *, struct super_block *, int *, char *);
+	void *(*clone_mnt_data) (void *);
+	void (*copy_mnt_data) (void *, void *);
 	void (*umount_begin) (struct super_block *);
 
 	int (*show_options)(struct seq_file *, struct dentry *);
+	int (*show_options2)(struct vfsmount *,struct seq_file *, struct dentry *);
 	int (*show_devname)(struct seq_file *, struct dentry *);
 	int (*show_path)(struct seq_file *, struct dentry *);
 	int (*show_stats)(struct seq_file *, struct dentry *);
@@ -1842,6 +1855,9 @@
 #define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
 	struct dentry *(*mount) (struct file_system_type *, int,
 		       const char *, void *);
+	struct dentry *(*mount2) (struct vfsmount *, struct file_system_type *, int,
+			       const char *, void *);
+	void *(*alloc_mnt_data) (void);
 	void (*kill_sb) (struct super_block *);
 	struct module *owner;
 	struct file_system_type * next;
@@ -2030,6 +2046,8 @@
 extern long vfs_truncate(struct path *, loff_t);
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
 		       struct file *filp);
+extern int do_truncate2(struct vfsmount *, struct dentry *, loff_t start,
+			unsigned int time_attrs, struct file *filp);
 extern int do_fallocate(struct file *file, int mode, loff_t offset,
 			loff_t len);
 extern long do_sys_open(int dfd, const char __user *filename, int flags,
@@ -2237,7 +2255,9 @@
 extern sector_t bmap(struct inode *, sector_t);
 #endif
 extern int notify_change(struct dentry *, struct iattr *);
+extern int notify_change2(struct vfsmount *, struct dentry *, struct iattr *);
 extern int inode_permission(struct inode *, int);
+extern int inode_permission2(struct vfsmount *, struct inode *, int);
 extern int generic_permission(struct inode *, int);
 
 static inline bool execute_ok(struct inode *inode)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 17e06f1..1414bcb 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -17,6 +17,7 @@
 	__s32		dad_transmits;
 	__s32		rtr_solicits;
 	__s32		rtr_solicit_interval;
+	__s32		rtr_solicit_max_interval;
 	__s32		rtr_solicit_delay;
 	__s32		force_mld_version;
 #ifdef CONFIG_IPV6_PRIVACY
@@ -33,6 +34,7 @@
 	__s32		accept_ra_rtr_pref;
 	__s32		rtr_probe_interval;
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	__s32		accept_ra_rt_info_min_plen;
 	__s32		accept_ra_rt_info_max_plen;
 #endif
 #endif
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 73005f9..52c74a0 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -44,15 +44,19 @@
 #define MNT_SHARED_MASK	(MNT_UNBINDABLE)
 #define MNT_PROPAGATION_MASK	(MNT_SHARED | MNT_UNBINDABLE)
 
+#define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
+			    MNT_MARKED)
 
 #define MNT_INTERNAL	0x4000
 
 #define MNT_LOCK_READONLY	0x400000
+#define MNT_MARKED		0x4000000
 
 struct vfsmount {
 	struct dentry *mnt_root;	/* root of the mounted tree */
 	struct super_block *mnt_sb;	/* pointer to superblock */
 	int mnt_flags;
+	void *data;
 };
 
 struct file; /* forward dec */
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 5a5ff57..f10c7f2 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -74,6 +74,7 @@
 			   const char *, unsigned int, struct path *);
 
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_len2(const char *, struct vfsmount *mnt, struct dentry *, int);
 
 extern int follow_down_one(struct path *);
 extern int follow_down(struct path *);
diff --git a/include/linux/netfilter/xt_qtaguid.h b/include/linux/netfilter/xt_qtaguid.h
index ca60fbd..1c67155 100644
--- a/include/linux/netfilter/xt_qtaguid.h
+++ b/include/linux/netfilter/xt_qtaguid.h
@@ -10,4 +10,5 @@
 #define XT_QTAGUID_SOCKET XT_OWNER_SOCKET
 #define xt_qtaguid_match_info xt_owner_match_info
 
+int qtaguid_untag(struct socket *sock, bool kernel);
 #endif /* _XT_QTAGUID_MATCH_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 17e1888..afb3d29 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -2423,7 +2423,7 @@
 				      unsigned long arg4,
 				      unsigned long arg5)
 {
-	return cap_task_prctl(option, arg2, arg3, arg3, arg5);
+	return cap_task_prctl(option, arg2, arg3, arg4, arg5);
 }
 
 static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 2cbf0ba..5de60f8 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -1,8 +1,9 @@
 #ifndef _ADDRCONF_H
 #define _ADDRCONF_H
 
-#define MAX_RTR_SOLICITATIONS		3
+#define MAX_RTR_SOLICITATIONS		-1		/* unlimited */
 #define RTR_SOLICITATION_INTERVAL	(4*HZ)
+#define RTR_SOLICITATION_MAX_INTERVAL	(3600*HZ)	/* 1 hour */
 
 #define MIN_VALID_LIFETIME		(2*3600)	/* 2 hours */
 
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 4ac12e1..21666fb 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -8,6 +8,11 @@
 #include <net/flow.h>
 #include <net/rtnetlink.h>
 
+struct fib_kuid_range {
+	kuid_t start;
+	kuid_t end;
+};
+
 struct fib_rule {
 	struct list_head	list;
 	atomic_t		refcnt;
@@ -23,8 +28,7 @@
 	struct fib_rule __rcu	*ctarget;
 	char			iifname[IFNAMSIZ];
 	char			oifname[IFNAMSIZ];
-	kuid_t			uid_start;
-	kuid_t			uid_end;
+	struct fib_kuid_range	uid_range;
 	struct rcu_head		rcu;
 	struct net *		fr_net;
 };
@@ -83,8 +87,7 @@
 	[FRA_FWMASK]	= { .type = NLA_U32 }, \
 	[FRA_TABLE]     = { .type = NLA_U32 }, \
 	[FRA_GOTO]	= { .type = NLA_U32 }, \
-	[FRA_UID_START]	= { .type = NLA_U32 }, \
-	[FRA_UID_END]	= { .type = NLA_U32 }
+	[FRA_UID_RANGE]	= { .len = sizeof(struct fib_rule_uid_range) }
 
 static inline void fib_rule_get(struct fib_rule *rule)
 {
diff --git a/include/net/flow.h b/include/net/flow.h
index 1426681f..15ecdd0 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -32,7 +32,7 @@
 #define FLOWI_FLAG_CAN_SLEEP		0x02
 #define FLOWI_FLAG_KNOWN_NH		0x04
 	__u32	flowic_secid;
-	kuid_t	flowic_uid;
+	kuid_t  flowic_uid;
 };
 
 union flowi_uli {
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 100fb8c..cc4a879 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -195,6 +195,9 @@
 	struct inet6_dev	*next;
 	struct ipv6_devconf	cnf;
 	struct ipv6_devstat	stats;
+
+	__s32			rs_interval;	/* in jiffies */
+
 	unsigned long		tstamp; /* ipv6InterfaceTable update timestamp */
 	struct rcu_head		rcu;
 };
diff --git a/include/net/ip.h b/include/net/ip.h
index 56960c9..2dfba79 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -164,7 +164,7 @@
 	return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
 }
 
-void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
+void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
 			   __be32 saddr, const struct ip_reply_arg *arg,
 			   unsigned int len);
 
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index ca32756..e4efdb4 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -134,7 +134,8 @@
 			    int oif, u32 mark, kuid_t uid);
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
 			       __be32 mtu);
-extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+			 kuid_t uid);
 extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 0dd6f0b..4f6c720 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -43,6 +43,7 @@
 	struct inet_peer_base	*peers;
 	struct tcpm_hash_bucket	*tcp_metrics_hash;
 	unsigned int		tcp_metrics_hash_log;
+	struct sock  * __percpu	*tcp_sk;
 	struct netns_frags	frags;
 #ifdef CONFIG_NETFILTER
 	struct xt_table		*iptable_filter;
diff --git a/include/net/route.h b/include/net/route.h
index 647bb2a..4fe6762 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -142,7 +142,7 @@
 	flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
 			   RT_SCOPE_UNIVERSE, proto,
 			   sk ? inet_sk_flowi_flags(sk) : 0,
-			   daddr, saddr, dport, sport, sk ? sock_i_uid(sk) : 0);
+			   daddr, saddr, dport, sport, sock_net_uid(net, sk));
 	if (sk)
 		security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
 	return ip_route_output_flow(net, fl4, sk);
@@ -254,7 +254,7 @@
 
 	flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
 			   protocol, flow_flags, dst, src, dport, sport,
-			   sock_i_uid(sk));
+			   sk->sk_uid);
 }
 
 static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
diff --git a/include/net/sock.h b/include/net/sock.h
index be058cd..2c5d9ad 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -393,6 +393,7 @@
 	void			*sk_security;
 #endif
 	__u32			sk_mark;
+	kuid_t			sk_uid;
 	u32			sk_classid;
 	struct cg_proto		*sk_cgrp;
 	void			(*sk_state_change)(struct sock *sk);
@@ -1703,6 +1704,7 @@
 	sk->sk_wq = parent->wq;
 	parent->sk = sk;
 	sk_set_socket(sk, parent);
+	sk->sk_uid = SOCK_INODE(parent)->i_uid;
 	security_sock_graft(sk, parent);
 	write_unlock_bh(&sk->sk_callback_lock);
 }
@@ -1710,6 +1712,11 @@
 extern kuid_t sock_i_uid(struct sock *sk);
 extern unsigned long sock_i_ino(struct sock *sk);
 
+static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
+{
+	return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
+}
+
 static inline struct dst_entry *
 __sk_dst_get(struct sock *sk)
 {
diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index c653800..12d9e51 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -32,6 +32,8 @@
 	BINDER_TYPE_HANDLE	= B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
 	BINDER_TYPE_WEAK_HANDLE	= B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
 	BINDER_TYPE_FD		= B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
+	BINDER_TYPE_FDA		= B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
+	BINDER_TYPE_PTR		= B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
 };
 
 enum {
@@ -47,6 +49,14 @@
 typedef __u64 binder_uintptr_t;
 #endif
 
+/**
+ * struct binder_object_header - header shared by all binder metadata objects.
+ * @type:	type of the object
+ */
+struct binder_object_header {
+	__u32        type;
+};
+
 /*
  * This is the flattened representation of a Binder object for transfer
  * between processes.  The 'offsets' supplied as part of a binder transaction
@@ -55,9 +65,8 @@
  * between processes.
  */
 struct flat_binder_object {
-	/* 8 bytes for large_flat_header. */
-	__u32	type;
-	__u32	flags;
+	struct binder_object_header	hdr;
+	__u32				flags;
 
 	/* 8 bytes of data. */
 	union {
@@ -69,6 +78,86 @@
 	binder_uintptr_t	cookie;
 };
 
+/**
+ * struct binder_fd_object - describes a filedescriptor to be fixed up.
+ * @hdr:	common header structure
+ * @pad_flags:	padding to remain compatible with old userspace code
+ * @pad_binder:	padding to remain compatible with old userspace code
+ * @fd:		file descriptor
+ * @cookie:	opaque data, used by user-space
+ */
+struct binder_fd_object {
+	struct binder_object_header	hdr;
+	__u32				pad_flags;
+	union {
+		binder_uintptr_t	pad_binder;
+		__u32			fd;
+	};
+
+	binder_uintptr_t		cookie;
+};
+
+/* struct binder_buffer_object - object describing a userspace buffer
+ * @hdr:		common header structure
+ * @flags:		one or more BINDER_BUFFER_* flags
+ * @buffer:		address of the buffer
+ * @length:		length of the buffer
+ * @parent:		index in offset array pointing to parent buffer
+ * @parent_offset:	offset in @parent pointing to this buffer
+ *
+ * A binder_buffer object represents an object that the
+ * binder kernel driver can copy verbatim to the target
+ * address space. A buffer itself may be pointed to from
+ * within another buffer, meaning that the pointer inside
+ * that other buffer needs to be fixed up as well. This
+ * can be done by setting the BINDER_BUFFER_FLAG_HAS_PARENT
+ * flag in @flags, by setting @parent buffer to the index
+ * in the offset array pointing to the parent binder_buffer_object,
+ * and by setting @parent_offset to the offset in the parent buffer
+ * at which the pointer to this buffer is located.
+ */
+struct binder_buffer_object {
+	struct binder_object_header	hdr;
+	__u32				flags;
+	binder_uintptr_t		buffer;
+	binder_size_t			length;
+	binder_size_t			parent;
+	binder_size_t			parent_offset;
+};
+
+enum {
+	BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
+};
+
+/* struct binder_fd_array_object - object describing an array of fds in a buffer
+ * @hdr:		common header structure
+ * @pad:		padding to ensure correct alignment
+ * @num_fds:		number of file descriptors in the buffer
+ * @parent:		index in offset array to buffer holding the fd array
+ * @parent_offset:	start offset of fd array in the buffer
+ *
+ * A binder_fd_array object represents an array of file
+ * descriptors embedded in a binder_buffer_object. It is
+ * different from a regular binder_buffer_object because it
+ * describes a list of file descriptors to fix up, not an opaque
+ * blob of memory, and hence the kernel needs to treat it differently.
+ *
+ * An example of how this would be used is with Android's
+ * native_handle_t object, which is a struct with a list of integers
+ * and a list of file descriptors. The native_handle_t struct itself
+ * will be represented by a struct binder_buffer_objct, whereas the
+ * embedded list of file descriptors is represented by a
+ * struct binder_fd_array_object with that binder_buffer_object as
+ * a parent.
+ */
+struct binder_fd_array_object {
+	struct binder_object_header	hdr;
+	__u32				pad;
+	binder_size_t			num_fds;
+	binder_size_t			parent;
+	binder_size_t			parent_offset;
+};
+
 /*
  * On 64-bit platforms where user code may run in 32-bits the driver must
  * translate the buffer (and local binder) addresses appropriately.
@@ -161,6 +250,11 @@
 	} data;
 };
 
+struct binder_transaction_data_sg {
+	struct binder_transaction_data transaction_data;
+	binder_size_t buffers_size;
+};
+
 struct binder_ptr_cookie {
 	binder_uintptr_t ptr;
 	binder_uintptr_t cookie;
@@ -343,6 +437,12 @@
 	/*
 	 * void *: cookie
 	 */
+
+	BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
+	BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
+	/*
+	 * binder_transaction_data_sg: the sent command.
+	 */
 };
 
 #endif /* _UAPI_LINUX_BINDER_H */
diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h
index 9dcdb62..209abc4 100644
--- a/include/uapi/linux/fib_rules.h
+++ b/include/uapi/linux/fib_rules.h
@@ -29,6 +29,11 @@
 	__u32		flags;
 };
 
+struct fib_rule_uid_range {
+	__u32		start;
+	__u32		end;
+};
+
 enum {
 	FRA_UNSPEC,
 	FRA_DST,	/* destination address */
@@ -49,8 +54,9 @@
 	FRA_TABLE,	/* Extended table id */
 	FRA_FWMASK,	/* mask for netfilter mark */
 	FRA_OIFNAME,
-	FRA_UID_START,	/* UID range */
-	FRA_UID_END,
+	FRA_PAD,
+	FRA_L3MDEV,	/* iif or oif is l3mdev goto its table */
+	FRA_UID_RANGE,	/* UID range */
 	__FRA_MAX
 };
 
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index 15ac588..daa6fff 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -161,8 +161,26 @@
 	DEVCONF_FORCE_TLLAO,
 	DEVCONF_NDISC_NOTIFY,
 	DEVCONF_ACCEPT_RA_RT_TABLE,
+	DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
+	DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
+	DEVCONF_SUPPRESS_FRAG_NDISC,
+	DEVCONF_ACCEPT_RA_FROM_LOCAL,
 	DEVCONF_USE_OPTIMISTIC,
+	DEVCONF_ACCEPT_RA_MTU,
+	DEVCONF_STABLE_SECRET,
 	DEVCONF_USE_OIF_ADDRS_ONLY,
+	DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
+	DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN,
+	DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
+	DEVCONF_DROP_UNSOLICITED_NA,
+	DEVCONF_KEEP_ADDR_ON_DOWN,
+	DEVCONF_RTR_SOLICIT_MAX_INTERVAL,
+	DEVCONF_SEG6_ENABLED,
+	DEVCONF_SEG6_REQUIRE_HMAC,
+	DEVCONF_ENHANCED_DAD,
+	DEVCONF_ADDR_GEN_MODE,
+	DEVCONF_DISABLE_POLICY,
+	DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN,
 	DEVCONF_MAX
 };
 
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index 04c5ff2..fc9697a 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -52,7 +52,7 @@
 #define REISER2FS_SUPER_MAGIC_STRING	"ReIsEr2Fs"
 #define REISER2FS_JR_SUPER_MAGIC_STRING	"ReIsEr3Fs"
 
-#define SDCARDFS_SUPER_MAGIC	0xb550ca10
+#define SDCARDFS_SUPER_MAGIC	0x5dca2df5
 
 #define SMB_SUPER_MAGIC		0x517B
 #define CGROUP_SUPER_MAGIC	0x27e0eb
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 28bb0b3..5210e82 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -158,4 +158,11 @@
 #define PR_SET_VMA		0x53564d41
 # define PR_SET_VMA_ANON_NAME		0
 
+/* Control the ambient capability set */
+#define PR_CAP_AMBIENT			47
+# define PR_CAP_AMBIENT_IS_SET		1
+# define PR_CAP_AMBIENT_RAISE		2
+# define PR_CAP_AMBIENT_LOWER		3
+# define PR_CAP_AMBIENT_CLEAR_ALL	4
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 07c1146..99c4df8 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -297,6 +297,13 @@
 	RTA_TABLE,
 	RTA_MARK,
 	RTA_MFC_STATS,
+	RTA_VIA,
+	RTA_NEWDST,
+	RTA_PREF,
+	RTA_ENCAP_TYPE,
+	RTA_ENCAP,
+	RTA_EXPIRES,
+	RTA_PAD,
 	RTA_UID,
 	__RTA_MAX
 };
diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h
index 6d67213..bd07cd6 100644
--- a/include/uapi/linux/sysctl.h
+++ b/include/uapi/linux/sysctl.h
@@ -568,6 +568,8 @@
 	NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22,
 	NET_IPV6_PROXY_NDP=23,
 	NET_IPV6_ACCEPT_SOURCE_ROUTE=25,
+	NET_IPV6_ACCEPT_RA_FROM_LOCAL=26,
+	NET_IPV6_ACCEPT_RA_RT_INFO_MIN_PLEN=27,
 	__NET_IPV6_MAX
 };
 
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index e4e47f6..85b4f52 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -754,7 +754,7 @@
 	}
 
 	mode &= ~current_umask();
-	ret = vfs_create(dir, path->dentry, mode, true);
+	ret = vfs_create2(path->mnt, dir, path->dentry, mode, true);
 	path->dentry->d_fsdata = NULL;
 	if (ret)
 		return ERR_PTR(ret);
@@ -770,7 +770,7 @@
 	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
 		return ERR_PTR(-EINVAL);
 	acc = oflag2acc[oflag & O_ACCMODE];
-	if (inode_permission(path->dentry->d_inode, acc))
+	if (inode_permission2(path->mnt, path->dentry->d_inode, acc))
 		return ERR_PTR(-EACCES);
 	return dentry_open(path, oflag, current_cred());
 }
@@ -803,7 +803,7 @@
 	ro = mnt_want_write(mnt);	/* we'll drop it in any case */
 	error = 0;
 	mutex_lock(&root->d_inode->i_mutex);
-	path.dentry = lookup_one_len(name->name, root, strlen(name->name));
+	path.dentry = lookup_one_len2(name->name, mnt, root, strlen(name->name));
 	if (IS_ERR(path.dentry)) {
 		error = PTR_ERR(path.dentry);
 		goto out_putfd;
@@ -872,7 +872,7 @@
 	if (err)
 		goto out_name;
 	mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT);
-	dentry = lookup_one_len(name->name, mnt->mnt_root,
+	dentry = lookup_one_len2(name->name, mnt, mnt->mnt_root,
 				strlen(name->name));
 	if (IS_ERR(dentry)) {
 		err = PTR_ERR(dentry);
@@ -884,7 +884,7 @@
 		err = -ENOENT;
 	} else {
 		ihold(inode);
-		err = vfs_unlink(dentry->d_parent->d_inode, dentry);
+		err = vfs_unlink2(mnt, dentry->d_parent->d_inode, dentry);
 	}
 	dput(dentry);
 
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index ba54fc2..18d57c7 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -339,24 +339,24 @@
 		put_seccomp_filter(thread);
 		smp_store_release(&thread->seccomp.filter,
 				  caller->seccomp.filter);
+
+		/*
+		 * Don't let an unprivileged task work around
+		 * the no_new_privs restriction by creating
+		 * a thread that sets it up, enters seccomp,
+		 * then dies.
+		 */
+		if (task_no_new_privs(caller))
+			task_set_no_new_privs(thread);
+
 		/*
 		 * Opt the other thread into seccomp if needed.
 		 * As threads are considered to be trust-realm
 		 * equivalent (see ptrace_may_access), it is safe to
 		 * allow one thread to transition the other.
 		 */
-		if (thread->seccomp.mode == SECCOMP_MODE_DISABLED) {
-			/*
-			 * Don't let an unprivileged task work around
-			 * the no_new_privs restriction by creating
-			 * a thread that sets it up, enters seccomp,
-			 * then dies.
-			 */
-			if (task_no_new_privs(caller))
-				task_set_no_new_privs(thread);
-
+		if (thread->seccomp.mode == SECCOMP_MODE_DISABLED)
 			seccomp_assign_mode(thread, SECCOMP_MODE_FILTER);
-		}
 	}
 }
 
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 9064b91..3b9de83 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -38,6 +38,7 @@
 	cred->cap_inheritable = CAP_EMPTY_SET;
 	cred->cap_permitted = CAP_FULL_SET;
 	cred->cap_effective = CAP_FULL_SET;
+	cred->cap_ambient = CAP_EMPTY_SET;
 	cred->cap_bset = CAP_FULL_SET;
 #ifdef CONFIG_KEYS
 	key_put(cred->request_key_auth);
diff --git a/mm/mmap.c b/mm/mmap.c
index 6d6618b..c6e1e9d 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1888,7 +1888,7 @@
 	struct vm_area_struct *vma, *prev;
 	struct vm_unmapped_area_info info;
 
-	if (len > TASK_SIZE)
+	if (len > TASK_SIZE - mmap_min_addr)
 		return -ENOMEM;
 
 	if (flags & MAP_FIXED)
@@ -1937,7 +1937,7 @@
 	struct vm_unmapped_area_info info;
 
 	/* requested length too big for entire address space */
-	if (len > TASK_SIZE)
+	if (len > TASK_SIZE - mmap_min_addr)
 		return -ENOMEM;
 
 	if (flags & MAP_FIXED)
@@ -1955,7 +1955,7 @@
 
 	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
 	info.length = len;
-	info.low_limit = PAGE_SIZE;
+	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
 	info.high_limit = mm->mmap_base;
 	info.align_mask = 0;
 	addr = vm_unmapped_area(&info);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index a40a876..31a12f2 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -17,6 +17,11 @@
 #include <net/sock.h>
 #include <net/fib_rules.h>
 
+static const struct fib_kuid_range fib_kuid_range_unset = {
+	KUIDT_INIT(0),
+	KUIDT_INIT(~0),
+};
+
 int fib_default_rule_add(struct fib_rules_ops *ops,
 			 u32 pref, u32 table, u32 flags)
 {
@@ -31,9 +36,8 @@
 	r->pref = pref;
 	r->table = table;
 	r->flags = flags;
-	r->uid_start = INVALID_UID;
-	r->uid_end = INVALID_UID;
 	r->fr_net = hold_net(ops->fro_net);
+	r->uid_range = fib_kuid_range_unset;
 
 	/* The lock is not required here, the list in unreacheable
 	 * at the moment this function is called */
@@ -181,21 +185,32 @@
 }
 EXPORT_SYMBOL_GPL(fib_rules_unregister);
 
-static inline kuid_t fib_nl_uid(struct nlattr *nla)
+static int uid_range_set(struct fib_kuid_range *range)
 {
-	return make_kuid(current_user_ns(), nla_get_u32(nla));
+	return uid_valid(range->start) && uid_valid(range->end);
 }
 
-static int nla_put_uid(struct sk_buff *skb, int idx, kuid_t uid)
+static struct fib_kuid_range nla_get_kuid_range(struct nlattr **tb)
 {
-	return nla_put_u32(skb, idx, from_kuid_munged(current_user_ns(), uid));
+	struct fib_rule_uid_range *in;
+	struct fib_kuid_range out;
+
+	in = (struct fib_rule_uid_range *)nla_data(tb[FRA_UID_RANGE]);
+
+	out.start = make_kuid(current_user_ns(), in->start);
+	out.end = make_kuid(current_user_ns(), in->end);
+
+	return out;
 }
 
-static int fib_uid_range_match(struct flowi *fl, struct fib_rule *rule)
+static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
 {
-	return (!uid_valid(rule->uid_start) && !uid_valid(rule->uid_end)) ||
-	       (uid_gte(fl->flowi_uid, rule->uid_start) &&
-		uid_lte(fl->flowi_uid, rule->uid_end));
+	struct fib_rule_uid_range out = {
+		from_kuid_munged(current_user_ns(), range->start),
+		from_kuid_munged(current_user_ns(), range->end)
+	};
+
+	return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out);
 }
 
 static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
@@ -212,7 +227,8 @@
 	if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)
 		goto out;
 
-	if (!fib_uid_range_match(fl, rule))
+	if (uid_lt(fl->flowi_uid, rule->uid_range.start) ||
+	    uid_gt(fl->flowi_uid, rule->uid_range.end))
 		goto out;
 
 	ret = ops->match(rule, fl, flags);
@@ -385,17 +401,19 @@
 	} else if (rule->action == FR_ACT_GOTO)
 		goto errout_free;
 
-	/* UID start and end must either both be valid or both unspecified. */
-	rule->uid_start = rule->uid_end = INVALID_UID;
-	if (tb[FRA_UID_START] || tb[FRA_UID_END]) {
-		if (tb[FRA_UID_START] && tb[FRA_UID_END]) {
-			rule->uid_start = fib_nl_uid(tb[FRA_UID_START]);
-			rule->uid_end = fib_nl_uid(tb[FRA_UID_END]);
+	if (tb[FRA_UID_RANGE]) {
+		if (current_user_ns() != net->user_ns) {
+			err = -EPERM;
+			goto errout_free;
 		}
-		if (!uid_valid(rule->uid_start) ||
-		    !uid_valid(rule->uid_end) ||
-		    !uid_lte(rule->uid_start, rule->uid_end))
-		goto errout_free;
+
+		rule->uid_range = nla_get_kuid_range(tb);
+
+		if (!uid_range_set(&rule->uid_range) ||
+		    !uid_lte(rule->uid_range.start, rule->uid_range.end))
+			goto errout_free;
+	} else {
+		rule->uid_range = fib_kuid_range_unset;
 	}
 
 	err = ops->configure(rule, skb, frh, tb);
@@ -457,6 +475,7 @@
 	struct fib_rules_ops *ops = NULL;
 	struct fib_rule *rule, *tmp;
 	struct nlattr *tb[FRA_MAX+1];
+	struct fib_kuid_range range;
 	int err = -EINVAL;
 
 	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
@@ -476,6 +495,14 @@
 	if (err < 0)
 		goto errout;
 
+	if (tb[FRA_UID_RANGE]) {
+		range = nla_get_kuid_range(tb);
+		if (!uid_range_set(&range))
+			goto errout;
+	} else {
+		range = fib_kuid_range_unset;
+	}
+
 	list_for_each_entry(rule, &ops->rules_list, list) {
 		if (frh->action && (frh->action != rule->action))
 			continue;
@@ -504,12 +531,9 @@
 		    (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))
 			continue;
 
-		if (tb[FRA_UID_START] &&
-		    !uid_eq(rule->uid_start, fib_nl_uid(tb[FRA_UID_START])))
-			continue;
-
-		if (tb[FRA_UID_END] &&
-		    !uid_eq(rule->uid_end, fib_nl_uid(tb[FRA_UID_END])))
+		if (uid_range_set(&range) &&
+		    (!uid_eq(rule->uid_range.start, range.start) ||
+		     !uid_eq(rule->uid_range.end, range.end)))
 			continue;
 
 		if (!ops->compare(rule, frh, tb))
@@ -569,8 +593,7 @@
 			 + nla_total_size(4) /* FRA_TABLE */
 			 + nla_total_size(4) /* FRA_FWMARK */
 			 + nla_total_size(4) /* FRA_FWMASK */
-			 + nla_total_size(4) /* FRA_UID_START */
-			 + nla_total_size(4); /* FRA_UID_END */
+			 + nla_total_size(sizeof(struct fib_kuid_range));
 
 	if (ops->nlmsg_payload)
 		payload += ops->nlmsg_payload(rule);
@@ -625,10 +648,8 @@
 	     nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) ||
 	    (rule->target &&
 	     nla_put_u32(skb, FRA_GOTO, rule->target)) ||
-	    (uid_valid(rule->uid_start) &&
-	     nla_put_uid(skb, FRA_UID_START, rule->uid_start)) ||
-	    (uid_valid(rule->uid_end) &&
-	     nla_put_uid(skb, FRA_UID_END, rule->uid_end)))
+	    (uid_range_set(&rule->uid_range) &&
+	     nla_put_uid_range(skb, &rule->uid_range)))
 		goto nla_put_failure;
 	if (ops->fill(rule, skb, frh) < 0)
 		goto nla_put_failure;
diff --git a/net/core/sock.c b/net/core/sock.c
index b467927..b27a6c0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2243,8 +2243,11 @@
 		sk->sk_type	=	sock->type;
 		sk->sk_wq	=	sock->wq;
 		sock->sk	=	sk;
-	} else
+		sk->sk_uid	=	SOCK_INODE(sock)->i_uid;
+	} else {
 		sk->sk_wq	=	NULL;
+		sk->sk_uid	=	make_kuid(sock_net(sk)->user_ns, 0);
+	}
 
 	spin_lock_init(&sk->sk_dst_lock);
 	rwlock_init(&sk->sk_callback_lock);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f022e0e..a068d6c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -89,6 +89,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/random.h>
 #include <linux/slab.h>
+#include <linux/netfilter/xt_qtaguid.h>
 
 #include <asm/uaccess.h>
 
@@ -443,6 +444,9 @@
 	if (sk) {
 		long timeout;
 
+#ifdef CONFIG_NETFILTER_XT_MATCH_QTAGUID
+		qtaguid_untag(sock, true);
+#endif
 		sock_rps_reset_flow(sk);
 
 		/* Applications forget to leave groups before exiting */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index cc38f44..cc76f5b 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -364,6 +364,7 @@
 	fl4.daddr = daddr;
 	fl4.saddr = saddr;
 	fl4.flowi4_mark = mark;
+	fl4.flowi4_uid = sock_net_uid(net, NULL);
 	fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
 	fl4.flowi4_proto = IPPROTO_ICMP;
 	security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
@@ -395,6 +396,7 @@
 		      param->replyopts.opt.opt.faddr : iph->saddr);
 	fl4->saddr = saddr;
 	fl4->flowi4_mark = mark;
+	fl4->flowi4_uid = sock_net_uid(net, NULL);
 	fl4->flowi4_tos = RT_TOS(tos);
 	fl4->flowi4_proto = IPPROTO_ICMP;
 	fl4->fl4_icmp_type = type;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index b7a3d6b..316a3c0 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -423,7 +423,7 @@
 			   flags,
 			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr,
 			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport,
-			   sock_i_uid(sk));
+			   sk->sk_uid);
 	security_req_classify_flow(req, flowi4_to_flowi(fl4));
 	rt = ip_route_output_flow(net, fl4, sk);
 	if (IS_ERR(rt))
@@ -460,7 +460,7 @@
 			   sk->sk_protocol, inet_sk_flowi_flags(sk),
 			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr,
 			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport,
-			   sock_i_uid(sk));
+			   sk->sk_uid);
 	security_req_classify_flow(req, flowi4_to_flowi(fl4));
 	rt = ip_route_output_flow(net, fl4, sk);
 	if (IS_ERR(rt))
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 91e3b15..fc07301 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1455,23 +1455,8 @@
 /*
  *	Generic function to send a packet as reply to another packet.
  *	Used to send some TCP resets/acks so far.
- *
- *	Use a fake percpu inet socket to avoid false sharing and contention.
  */
-static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
-	.sk = {
-		.__sk_common = {
-			.skc_refcnt = ATOMIC_INIT(1),
-		},
-		.sk_wmem_alloc	= ATOMIC_INIT(1),
-		.sk_allocation	= GFP_ATOMIC,
-		.sk_flags	= (1UL << SOCK_USE_WRITE_QUEUE),
-	},
-	.pmtudisc	= IP_PMTUDISC_WANT,
-	.uc_ttl		= -1,
-};
-
-void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
+void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
 			   __be32 saddr, const struct ip_reply_arg *arg,
 			   unsigned int len)
 {
@@ -1479,9 +1464,9 @@
 	struct ipcm_cookie ipc;
 	struct flowi4 fl4;
 	struct rtable *rt = skb_rtable(skb);
+	struct net *net = sock_net(sk);
 	struct sk_buff *nskb;
-	struct sock *sk;
-	struct inet_sock *inet;
+	int err;
 
 	if (ip_options_echo(&replyopts.opt.opt, skb))
 		return;
@@ -1510,18 +1495,19 @@
 	if (IS_ERR(rt))
 		return;
 
-	inet = &get_cpu_var(unicast_sock);
+	inet_sk(sk)->tos = arg->tos;
 
-	inet->tos = arg->tos;
-	sk = &inet->sk;
 	sk->sk_priority = skb->priority;
 	sk->sk_protocol = ip_hdr(skb)->protocol;
 	sk->sk_bound_dev_if = arg->bound_dev_if;
-	sock_net_set(sk, net);
-	__skb_queue_head_init(&sk->sk_write_queue);
 	sk->sk_sndbuf = sysctl_wmem_default;
-	ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
-		       &ipc, &rt, MSG_DONTWAIT);
+	err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
+			     len, 0, &ipc, &rt, MSG_DONTWAIT);
+	if (unlikely(err)) {
+		ip_flush_pending_frames(sk);
+		goto out;
+	}
+
 	nskb = skb_peek(&sk->sk_write_queue);
 	if (nskb) {
 		if (arg->csumoffset >= 0)
@@ -1529,13 +1515,10 @@
 			  arg->csumoffset) = csum_fold(csum_add(nskb->csum,
 								arg->csum));
 		nskb->ip_summed = CHECKSUM_NONE;
-		skb_orphan(nskb);
 		skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb));
 		ip_push_pending_frames(sk, &fl4);
 	}
-
-	put_cpu_var(unicast_sock);
-
+out:
 	ip_rt_put(rt);
 }
 
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 0656041..6800548 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -338,7 +338,8 @@
 			   be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos),
 			   RT_SCOPE_UNIVERSE,
 			   IPPROTO_IPIP, 0,
-			   dst, tiph->saddr, 0, 0);
+			   dst, tiph->saddr, 0, 0,
+			   sock_net_uid(dev_net(dev), NULL));
 	rt = ip_route_output_key(dev_net(dev), &fl4);
 	if (IS_ERR(rt)) {
 		dev->stats.tx_carrier_errors++;
@@ -404,7 +405,8 @@
 				   be32_to_cpu(tunnel->parms.i_key),
 				   RT_TOS(iph->tos), RT_SCOPE_UNIVERSE,
 				   IPPROTO_IPIP, 0,
-				   iph->daddr, iph->saddr, 0, 0);
+				   iph->daddr, iph->saddr, 0, 0,
+				   sock_net_uid(dev_net(dev), NULL));
 		rt = ip_route_output_key(dev_net(dev), &fl4);
 		if (!IS_ERR(rt)) {
 			tdev = rt->dst.dev;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index ec9a7e5..cb46b71 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -782,7 +782,7 @@
 	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
 			   RT_SCOPE_UNIVERSE, sk->sk_protocol,
 			   inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
-			   sock_i_uid(sk));
+			   sk->sk_uid);
 
 	security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
 	rt = ip_route_output_flow(net, &fl4, sk);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 169d72a..9e4bf23 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -573,8 +573,7 @@
 			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 			   inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP |
 			    (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
-			   daddr, saddr, 0, 0,
-			   sock_i_uid(sk));
+			   daddr, saddr, 0, 0, sk->sk_uid);
 
 	if (!inet->hdrincl) {
 		err = raw_probe_proto_opt(&fl4, msg);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 836cd19..c5e2f9c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -500,7 +500,8 @@
 }
 EXPORT_SYMBOL(__ip_select_ident);
 
-static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
+static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
+			     const struct sock *sk,
 			     const struct iphdr *iph,
 			     int oif, u8 tos,
 			     u8 prot, u32 mark, int flow_flags)
@@ -517,22 +518,23 @@
 			   RT_SCOPE_UNIVERSE, prot,
 			   flow_flags,
 			   iph->daddr, iph->saddr, 0, 0,
-			   sk ? sock_i_uid(sk) : 0);
+			   sock_net_uid(net, sk));
 }
 
 static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
-			       struct sock *sk)
+			       const struct sock *sk)
 {
+	const struct net *net = dev_net(skb->dev);
 	const struct iphdr *iph = ip_hdr(skb);
 	int oif = skb->dev->ifindex;
 	u8 tos = RT_TOS(iph->tos);
 	u8 prot = iph->protocol;
 	u32 mark = skb->mark;
 
-	__build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
+	__build_flow_key(net, fl4, sk, iph, oif, tos, prot, mark, 0);
 }
 
-static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
+static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
 {
 	const struct inet_sock *inet = inet_sk(sk);
 	const struct ip_options_rcu *inet_opt;
@@ -546,12 +548,11 @@
 			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
 			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 			   inet_sk_flowi_flags(sk),
-			   daddr, inet->inet_saddr, 0, 0,
-			   sock_i_uid(sk));
+			   daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
 	rcu_read_unlock();
 }
 
-static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk,
+static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk,
 				 const struct sk_buff *skb)
 {
 	if (skb)
@@ -747,7 +748,7 @@
 
 	rt = (struct rtable *) dst;
 
-	__build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
+	__build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0);
 	__ip_do_redirect(rt, skb, &fl4, true);
 }
 
@@ -961,7 +962,7 @@
 	if (!mark)
 		mark = IP4_REPLY_MARK(net, skb->mark);
 
-	__build_flow_key(&fl4, NULL, iph, oif,
+	__build_flow_key(net, &fl4, NULL, iph, oif,
 			 RT_TOS(iph->tos), protocol, mark, flow_flags);
 	rt = __ip_route_output_key(net, &fl4);
 	if (!IS_ERR(rt)) {
@@ -977,7 +978,7 @@
 	struct flowi4 fl4;
 	struct rtable *rt;
 
-	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+	__build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0);
 
 	if (!fl4.flowi4_mark)
 		fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
@@ -996,6 +997,7 @@
 	struct rtable *rt;
 	struct dst_entry *dst;
 	bool new = false;
+	struct net *net = sock_net(sk);
 
 	bh_lock_sock(sk);
 	rt = (struct rtable *) __sk_dst_get(sk);
@@ -1005,7 +1007,7 @@
 		goto out;
 	}
 
-	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+	__build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
 
 	if (!__sk_dst_check(sk, 0)) {
 		rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
@@ -1044,7 +1046,7 @@
 	struct flowi4 fl4;
 	struct rtable *rt;
 
-	__build_flow_key(&fl4, NULL, iph, oif,
+	__build_flow_key(net, &fl4, NULL, iph, oif,
 			 RT_TOS(iph->tos), protocol, mark, flow_flags);
 	rt = __ip_route_output_key(net, &fl4);
 	if (!IS_ERR(rt)) {
@@ -1059,9 +1061,10 @@
 	const struct iphdr *iph = (const struct iphdr *) skb->data;
 	struct flowi4 fl4;
 	struct rtable *rt;
+	struct net *net = sock_net(sk);
 
-	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
-	rt = __ip_route_output_key(sock_net(sk), &fl4);
+	__build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
+	rt = __ip_route_output_key(net, &fl4);
 	if (!IS_ERR(rt)) {
 		__ip_do_redirect(rt, skb, &fl4, false);
 		ip_rt_put(rt);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index c94032b..296a0a4 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -353,8 +353,7 @@
 			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
 			   inet_sk_flowi_flags(sk),
 			   (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
-			   ireq->loc_addr, th->source, th->dest,
-			   sock_i_uid(sk));
+			   ireq->loc_addr, th->source, th->dest, sk->sk_uid);
 	security_req_classify_flow(req, flowi4_to_flowi(&fl4));
 	rt = ip_route_output_key(sock_net(sk), &fl4);
 	if (IS_ERR(rt)) {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1e0bc92..331e7ce 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -646,6 +646,7 @@
 	arg.iov[0].iov_base = (unsigned char *)&rep;
 	arg.iov[0].iov_len  = sizeof(rep.th);
 
+	net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
 #ifdef CONFIG_TCP_MD5SIG
 	hash_location = tcp_parse_md5sig_option(th);
 	if (!sk && hash_location) {
@@ -656,7 +657,7 @@
 		 * Incoming packet is checked with md5 hash with finding key,
 		 * no RST generated if md5 hash doesn't match.
 		 */
-		sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
+		sk1 = __inet_lookup_listener(net,
 					     &tcp_hashinfo, ip_hdr(skb)->saddr,
 					     th->source, ip_hdr(skb)->daddr,
 					     ntohs(th->source), inet_iif(skb));
@@ -704,9 +705,10 @@
 	if (sk)
 		arg.bound_dev_if = sk->sk_bound_dev_if;
 
-	net = dev_net(skb_dst(skb)->dev);
 	arg.tos = ip_hdr(skb)->tos;
-	ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr,
+	arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
+	ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
+			      skb, ip_hdr(skb)->saddr,
 			      ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
 
 	TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
@@ -725,7 +727,8 @@
    outside socket context is ugly, certainly. What can I do?
  */
 
-static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+static void tcp_v4_send_ack(const struct sock *sk, struct sk_buff *skb,
+			    u32 seq, u32 ack,
 			    u32 win, u32 tsval, u32 tsecr, int oif,
 			    struct tcp_md5sig_key *key,
 			    int reply_flags, u8 tos)
@@ -740,7 +743,7 @@
 			];
 	} rep;
 	struct ip_reply_arg arg;
-	struct net *net = dev_net(skb_dst(skb)->dev);
+	struct net *net = sock_net(sk);
 
 	memset(&rep.th, 0, sizeof(struct tcphdr));
 	memset(&arg, 0, sizeof(arg));
@@ -789,7 +792,9 @@
 	if (oif)
 		arg.bound_dev_if = oif;
 	arg.tos = tos;
-	ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr,
+	arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
+	ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
+			      skb, ip_hdr(skb)->saddr,
 			      ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
 
 	TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
@@ -800,7 +805,7 @@
 	struct inet_timewait_sock *tw = inet_twsk(sk);
 	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-	tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+	tcp_v4_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 			tcp_time_stamp + tcptw->tw_ts_offset,
 			tcptw->tw_ts_recent,
@@ -819,7 +824,7 @@
 	/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
 	 * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
 	 */
-	tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
+	tcp_v4_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
 			tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
 			tcp_rsk(req)->rcv_nxt, req->rcv_wnd,
 			tcp_time_stamp,
@@ -2899,14 +2904,39 @@
 };
 EXPORT_SYMBOL(tcp_prot);
 
-static int __net_init tcp_sk_init(struct net *net)
-{
-	net->ipv4.sysctl_tcp_ecn = 2;
-	return 0;
-}
-
 static void __net_exit tcp_sk_exit(struct net *net)
 {
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu));
+	free_percpu(net->ipv4.tcp_sk);
+}
+
+static int __net_init tcp_sk_init(struct net *net)
+{
+	int res, cpu;
+
+	net->ipv4.tcp_sk = alloc_percpu(struct sock *);
+	if (!net->ipv4.tcp_sk)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		struct sock *sk;
+
+		res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
+					   IPPROTO_TCP, net);
+		if (res)
+			goto fail;
+		*per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk;
+	}
+	net->ipv4.sysctl_tcp_ecn = 2;
+	return 0;
+
+fail:
+	tcp_sk_exit(net);
+
+	return res;
 }
 
 static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index f6b0ce7..c4b4e69 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -964,7 +964,7 @@
 				   RT_SCOPE_UNIVERSE, sk->sk_protocol,
 				   inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP,
 				   faddr, saddr, dport, inet->inet_sport,
-				   sock_i_uid(sk));
+				   sk->sk_uid);
 
 		security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
 		rt = ip_route_output_flow(net, fl4, sk);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index cd2339a..3ea34a3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -111,6 +111,27 @@
 	return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
 }
 
+static inline s32 rfc3315_s14_backoff_init(s32 irt)
+{
+	/* multiply 'initial retransmission time' by 0.9 .. 1.1 */
+	u64 tmp = (900000 + prandom_u32() % 200001) * (u64)irt;
+	do_div(tmp, 1000000);
+	return (s32)tmp;
+}
+
+static inline s32 rfc3315_s14_backoff_update(s32 rt, s32 mrt)
+{
+	/* multiply 'retransmission timeout' by 1.9 .. 2.1 */
+	u64 tmp = (1900000 + prandom_u32() % 200001) * (u64)rt;
+	do_div(tmp, 1000000);
+	if ((s32)tmp > mrt) {
+		/* multiply 'maximum retransmission time' by 0.9 .. 1.1 */
+		tmp = (900000 + prandom_u32() % 200001) * (u64)mrt;
+		do_div(tmp, 1000000);
+	}
+	return (s32)tmp;
+}
+
 #ifdef CONFIG_SYSCTL
 static void addrconf_sysctl_register(struct inet6_dev *idev);
 static void addrconf_sysctl_unregister(struct inet6_dev *idev);
@@ -180,6 +201,7 @@
 	.dad_transmits		= 1,
 	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
 	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
+	.rtr_solicit_max_interval = RTR_SOLICITATION_MAX_INTERVAL,
 	.rtr_solicit_delay	= MAX_RTR_SOLICITATION_DELAY,
 #ifdef CONFIG_IPV6_PRIVACY
 	.use_tempaddr 		= 0,
@@ -195,6 +217,7 @@
 	.accept_ra_rtr_pref	= 1,
 	.rtr_probe_interval	= 60 * HZ,
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	.accept_ra_rt_info_min_plen = 0,
 	.accept_ra_rt_info_max_plen = 0,
 #endif
 #endif
@@ -216,6 +239,7 @@
 	.dad_transmits		= 1,
 	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
 	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
+	.rtr_solicit_max_interval = RTR_SOLICITATION_MAX_INTERVAL,
 	.rtr_solicit_delay	= MAX_RTR_SOLICITATION_DELAY,
 #ifdef CONFIG_IPV6_PRIVACY
 	.use_tempaddr		= 0,
@@ -231,6 +255,7 @@
 	.accept_ra_rtr_pref	= 1,
 	.rtr_probe_interval	= 60 * HZ,
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	.accept_ra_rt_info_min_plen = 0,
 	.accept_ra_rt_info_max_plen = 0,
 #endif
 #endif
@@ -3233,12 +3258,14 @@
 		goto out;
 
 	spin_lock(&ifp->lock);
-	if (ifp->probes++ < idev->cnf.rtr_solicits) {
+	if (ifp->probes++ < idev->cnf.rtr_solicits || idev->cnf.rtr_solicits < 0) {
+		idev->rs_interval = rfc3315_s14_backoff_update(
+			idev->rs_interval, idev->cnf.rtr_solicit_max_interval);
 		/* The wait after the last probe can be shorter */
 		addrconf_mod_timer(ifp, AC_RS,
 				   (ifp->probes == idev->cnf.rtr_solicits) ?
 				   idev->cnf.rtr_solicit_delay :
-				   idev->cnf.rtr_solicit_interval);
+				   idev->rs_interval);
 		spin_unlock(&ifp->lock);
 
 		ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
@@ -3395,7 +3422,7 @@
 	 */
 
 	if (ipv6_accept_ra(ifp->idev) &&
-	    ifp->idev->cnf.rtr_solicits > 0 &&
+	    ifp->idev->cnf.rtr_solicits != 0 &&
 	    (dev->flags&IFF_LOOPBACK) == 0 &&
 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
 		/*
@@ -3406,9 +3433,11 @@
 		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
 
 		spin_lock_bh(&ifp->lock);
+		ifp->idev->rs_interval = rfc3315_s14_backoff_init(
+			ifp->idev->cnf.rtr_solicit_interval);
 		ifp->probes = 1;
 		ifp->idev->if_flags |= IF_RS_SENT;
-		addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval);
+		addrconf_mod_timer(ifp, AC_RS, ifp->idev->rs_interval);
 		spin_unlock_bh(&ifp->lock);
 	}
 }
@@ -4244,6 +4273,8 @@
 	array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
 	array[DEVCONF_RTR_SOLICIT_INTERVAL] =
 		jiffies_to_msecs(cnf->rtr_solicit_interval);
+	array[DEVCONF_RTR_SOLICIT_MAX_INTERVAL] =
+		jiffies_to_msecs(cnf->rtr_solicit_max_interval);
 	array[DEVCONF_RTR_SOLICIT_DELAY] =
 		jiffies_to_msecs(cnf->rtr_solicit_delay);
 	array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
@@ -4262,6 +4293,7 @@
 	array[DEVCONF_RTR_PROBE_INTERVAL] =
 		jiffies_to_msecs(cnf->rtr_probe_interval);
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	array[DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN] = cnf->accept_ra_rt_info_min_plen;
 	array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
 #endif
 #endif
@@ -4425,7 +4457,7 @@
 		return -EINVAL;
 	if (!ipv6_accept_ra(idev))
 		return -EINVAL;
-	if (idev->cnf.rtr_solicits <= 0)
+	if (idev->cnf.rtr_solicits == 0)
 		return -EINVAL;
 
 	write_lock_bh(&idev->lock);
@@ -4880,6 +4912,13 @@
 			.proc_handler	= proc_dointvec_jiffies,
 		},
 		{
+			.procname	= "router_solicitation_max_interval",
+			.data		= &ipv6_devconf.rtr_solicit_max_interval,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec_jiffies,
+		},
+		{
 			.procname	= "router_solicitation_delay",
 			.data		= &ipv6_devconf.rtr_solicit_delay,
 			.maxlen		= sizeof(int),
@@ -4968,6 +5007,13 @@
 		},
 #ifdef CONFIG_IPV6_ROUTE_INFO
 		{
+			.procname	= "accept_ra_rt_info_min_plen",
+			.data		= &ipv6_devconf.accept_ra_rt_info_min_plen,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec,
+		},
+		{
 			.procname	= "accept_ra_rt_info_max_plen",
 			.data		= &ipv6_devconf.accept_ra_rt_info_max_plen,
 			.maxlen		= sizeof(int),
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 04e88b5..e3a2601 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -696,7 +696,7 @@
 		fl6.flowi6_mark = sk->sk_mark;
 		fl6.fl6_dport = inet->inet_dport;
 		fl6.fl6_sport = inet->inet_sport;
-		fl6.flowi6_uid = sock_i_uid(sk);
+		fl6.flowi6_uid = sk->sk_uid;
 		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
 		rcu_read_lock();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index b903e19..15e41c5 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -628,9 +628,9 @@
 		return;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, 0, 0);
+		ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 }
 
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 7e36b4b..ea4f05f 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -162,7 +162,7 @@
 	fl6.flowi6_mark = sk->sk_mark;
 	fl6.fl6_dport = inet->inet_dport;
 	fl6.fl6_sport = inet->inet_sport;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
 		fl6.flowi6_oif = np->mcast_oif;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index fdc81cb..4ad6525 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -447,9 +447,9 @@
 		return;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, 0, 0);
+		ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 }
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 92307d1..10b7a93 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -90,9 +90,9 @@
 	struct net *net = dev_net(skb->dev);
 
 	if (type == ICMPV6_PKT_TOOBIG)
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	else if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, 0, 0);
+		ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
 
 	if (!(type & ICMPV6_INFOMSG_MASK))
 		if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
@@ -467,6 +467,7 @@
 	fl6.flowi6_oif = iif;
 	fl6.fl6_icmp_type = type;
 	fl6.fl6_icmp_code = code;
+	fl6.flowi6_uid = sock_net_uid(net, NULL);
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	sk = icmpv6_xmit_lock(net);
@@ -572,6 +573,7 @@
 	fl6.flowi6_oif = skb->dev->ifindex;
 	fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
 	fl6.flowi6_mark = mark;
+	fl6.flowi6_uid = sock_net_uid(net, NULL);
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	sk = icmpv6_xmit_lock(net);
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 157f2b2..a2072a8 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -86,7 +86,7 @@
 	fl6->flowi6_mark = inet_rsk(req)->ir_mark;
 	fl6->fl6_dport = inet_rsk(req)->rmt_port;
 	fl6->fl6_sport = inet_rsk(req)->loc_port;
-	fl6->flowi6_uid = sock_i_uid(sk);
+	fl6->flowi6_uid = sk->sk_uid;
 	security_req_classify_flow(req, flowi6_to_flowi(fl6));
 
 	dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
@@ -214,7 +214,7 @@
 	fl6->flowi6_mark = sk->sk_mark;
 	fl6->fl6_sport = inet->inet_sport;
 	fl6->fl6_dport = inet->inet_dport;
-	fl6->flowi6_uid = sock_i_uid(sk);
+	fl6->flowi6_uid = sk->sk_uid;
 	security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
 
 	rcu_read_lock();
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 46848d5..b1588bf 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -799,6 +799,8 @@
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
 	err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
@@ -849,6 +851,8 @@
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
 	err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		if (err == -EMSGSIZE)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 0516ebb..f04cf29 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1068,6 +1068,8 @@
 	memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
 	fl6.flowi6_proto = IPPROTO_IPIP;
 
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
 	dsfield = ipv4_get_dsfield(iph);
 
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
@@ -1119,6 +1121,7 @@
 
 	memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
 	fl6.flowi6_proto = IPPROTO_IPV6;
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
 
 	dsfield = ipv6_get_dsfield(ipv6h);
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index a1beb59..a4a4e1c 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -76,9 +76,9 @@
 		return;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, 0, 0);
+		ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 }
 
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 05f3613..1fc0e50 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1286,6 +1286,8 @@
 			    ri->prefix_len == 0)
 				continue;
 #endif
+			if (ri->prefix_len < in6_dev->cnf.accept_ra_rt_info_min_plen)
+				continue;
 			if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
 				continue;
 			rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 95f3f1d..b222bc9 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -27,6 +27,7 @@
 	struct flowi6 fl6 = {
 		.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
 		.flowi6_mark = skb->mark,
+		.flowi6_uid = sock_net_uid(net, skb->sk),
 		.daddr = iph->daddr,
 		.saddr = iph->saddr,
 	};
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 27de137..6a38935 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -167,7 +167,7 @@
 	fl6.daddr = *daddr;
 	fl6.flowi6_oif = oif;
 	fl6.flowi6_mark = sk->sk_mark;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 	fl6.fl6_icmp_type = user_icmph.icmp6_type;
 	fl6.fl6_icmp_code = user_icmph.icmp6_code;
 	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5693cf2..c9ccdd7 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -760,7 +760,7 @@
 	memset(&fl6, 0, sizeof(fl6));
 
 	fl6.flowi6_mark = sk->sk_mark;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (sin6) {
 		if (addr_len < SIN6_LEN_RFC2133)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7b71541..a25af77 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -726,7 +726,10 @@
 		prefix = &prefix_buf;
 	}
 
-	rt = rt6_get_route_info(dev, prefix, rinfo->prefix_len, gwaddr);
+	if (rinfo->prefix_len == 0)
+		rt = rt6_get_dflt_router(gwaddr, dev);
+	else
+		rt = rt6_get_route_info(dev, prefix, rinfo->prefix_len, gwaddr);
 
 	if (rt && !lifetime) {
 		ip6_del_rt(rt);
@@ -1172,11 +1175,12 @@
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
 {
 	ip6_update_pmtu(skb, sock_net(sk), mtu,
-			sk->sk_bound_dev_if, sk->sk_mark, sock_i_uid(sk));
+			sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
 
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+		  kuid_t uid)
 {
 	const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
 	struct dst_entry *dst;
@@ -1189,6 +1193,7 @@
 	fl6.daddr = iph->daddr;
 	fl6.saddr = iph->saddr;
 	fl6.flowlabel = ip6_flowinfo(iph);
+	fl6.flowi6_uid = uid;
 
 	dst = ip6_route_output(net, NULL, &fl6);
 	if (!dst->error)
@@ -1199,7 +1204,8 @@
 
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
-	ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
+	ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
+		     sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 701d065..0428544 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -243,7 +243,7 @@
 		fl6.flowi6_mark = ireq->ir_mark;
 		fl6.fl6_dport = inet_rsk(req)->rmt_port;
 		fl6.fl6_sport = inet_sk(sk)->inet_sport;
-		fl6.flowi6_uid = sock_i_uid(sk);
+		fl6.flowi6_uid = sk->sk_uid;
 		security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
 		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 7f13d7c..bdd90f2 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -253,7 +253,7 @@
 	fl6.flowi6_mark = sk->sk_mark;
 	fl6.fl6_dport = usin->sin6_port;
 	fl6.fl6_sport = inet->inet_sport;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 	final_p = fl6_update_dst(&fl6, opt, &final);
@@ -722,15 +722,15 @@
 };
 #endif
 
-static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
-				 u32 tsval, u32 tsecr,
+static void tcp_v6_send_response(struct sock *sk, struct sk_buff *skb, u32 seq,
+				 u32 ack, u32 win, u32 tsval, u32 tsecr,
 				 struct tcp_md5sig_key *key, int rst, u8 tclass)
 {
 	const struct tcphdr *th = tcp_hdr(skb);
 	struct tcphdr *t1;
 	struct sk_buff *buff;
 	struct flowi6 fl6;
-	struct net *net = dev_net(skb_dst(skb)->dev);
+	struct net *net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
 	struct sock *ctl_sk = net->ipv6.tcp_sk;
 	unsigned int tot_len = sizeof(struct tcphdr);
 	struct dst_entry *dst;
@@ -798,6 +798,7 @@
 	fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
 	fl6.fl6_dport = t1->dest;
 	fl6.fl6_sport = t1->source;
+	fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	/* Pass a socket to ip6_dst_lookup either it is for RST
@@ -872,7 +873,7 @@
 		ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
 			  (th->doff << 2);
 
-	tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, key, 1, 0);
+	tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, key, 1, 0);
 
 #ifdef CONFIG_TCP_MD5SIG
 release_sk1:
@@ -883,11 +884,12 @@
 #endif
 }
 
-static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
-			    u32 win, u32 tsval, u32 tsecr,
+static void tcp_v6_send_ack(struct sock *sk, struct sk_buff *skb,
+			    u32 seq, u32 ack, u32 win, u32 tsval, u32 tsecr,
 			    struct tcp_md5sig_key *key, u8 tclass)
 {
-	tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, key, 0, tclass);
+	tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, key, 0,
+			     tclass);
 }
 
 static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
@@ -895,7 +897,7 @@
 	struct inet_timewait_sock *tw = inet_twsk(sk);
 	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-	tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+	tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 			tcp_time_stamp + tcptw->tw_ts_offset,
 			tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
@@ -907,7 +909,7 @@
 static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
 				  struct request_sock *req)
 {
-	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1,
+	tcp_v6_send_ack(sk, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1,
 			req->rcv_wnd, tcp_time_stamp, req->ts_recent,
 			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
 }
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d8e8886..b760342 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1150,7 +1150,7 @@
 		fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
 
 	fl6.flowi6_mark = sk->sk_mark;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (msg->msg_controllen) {
 		opt = &opt_space;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ab8bd2c..ed660a3 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -65,6 +65,10 @@
 	} dump;
 };
 
+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
+			       xfrm_address_t *saddr, xfrm_address_t *daddr,
+			       u16 *family);
+
 static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
 {
 	return (struct pfkey_sock *)sk;
@@ -1900,19 +1904,14 @@
 
 	/* addresses present only in tunnel mode */
 	if (t->mode == XFRM_MODE_TUNNEL) {
-		u8 *sa = (u8 *) (rq + 1);
-		int family, socklen;
+		int err;
 
-		family = pfkey_sockaddr_extract((struct sockaddr *)sa,
-						&t->saddr);
-		if (!family)
-			return -EINVAL;
-
-		socklen = pfkey_sockaddr_len(family);
-		if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
-					   &t->id.daddr) != family)
-			return -EINVAL;
-		t->encap_family = family;
+		err = parse_sockaddr_pair(
+			(struct sockaddr *)(rq + 1),
+			rq->sadb_x_ipsecrequest_len - sizeof(*rq),
+			&t->saddr, &t->id.daddr, &t->encap_family);
+		if (err)
+			return err;
 	} else
 		t->encap_family = xp->family;
 
@@ -1932,7 +1931,11 @@
 	if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
 		return -EINVAL;
 
-	while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+	while (len >= sizeof(*rq)) {
+		if (len < rq->sadb_x_ipsecrequest_len ||
+		    rq->sadb_x_ipsecrequest_len < sizeof(*rq))
+			return -EINVAL;
+
 		if ((err = parse_ipsecrequest(xp, rq)) < 0)
 			return err;
 		len -= rq->sadb_x_ipsecrequest_len;
@@ -2403,7 +2406,6 @@
 	return err;
 }
 
-#ifdef CONFIG_NET_KEY_MIGRATE
 static int pfkey_sockaddr_pair_size(sa_family_t family)
 {
 	return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
@@ -2415,7 +2417,7 @@
 {
 	int af, socklen;
 
-	if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
+	if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
 		return -EINVAL;
 
 	af = pfkey_sockaddr_extract(sa, saddr);
@@ -2431,6 +2433,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET_KEY_MIGRATE
 static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
 				    struct xfrm_migrate *m)
 {
@@ -2438,13 +2441,14 @@
 	struct sadb_x_ipsecrequest *rq2;
 	int mode;
 
-	if (len <= sizeof(struct sadb_x_ipsecrequest) ||
-	    len < rq1->sadb_x_ipsecrequest_len)
+	if (len < sizeof(*rq1) ||
+	    len < rq1->sadb_x_ipsecrequest_len ||
+	    rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
 		return -EINVAL;
 
 	/* old endoints */
 	err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
-				  rq1->sadb_x_ipsecrequest_len,
+				  rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
 				  &m->old_saddr, &m->old_daddr,
 				  &m->old_family);
 	if (err)
@@ -2453,13 +2457,14 @@
 	rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
 	len -= rq1->sadb_x_ipsecrequest_len;
 
-	if (len <= sizeof(struct sadb_x_ipsecrequest) ||
-	    len < rq2->sadb_x_ipsecrequest_len)
+	if (len <= sizeof(*rq2) ||
+	    len < rq2->sadb_x_ipsecrequest_len ||
+	    rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
 		return -EINVAL;
 
 	/* new endpoints */
 	err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
-				  rq2->sadb_x_ipsecrequest_len,
+				  rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
 				  &m->new_saddr, &m->new_daddr,
 				  &m->new_family);
 	if (err)
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 19705cb..e0d1c86 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -515,6 +515,7 @@
 	memset(&fl6, 0, sizeof(fl6));
 
 	fl6.flowi6_mark = sk->sk_mark;
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (lsa) {
 		if (addr_len < SIN6_LEN_RFC2133)
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 58a4607..60210cc 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -320,7 +320,7 @@
 			 st_entry->tag,
 			 get_uid_from_tag(st_entry->tag));
 		rb_erase(&st_entry->sock_node, st_to_free_tree);
-		sockfd_put(st_entry->socket);
+		sock_put(st_entry->sk);
 		kfree(st_entry);
 	}
 }
@@ -1806,8 +1806,11 @@
 }
 
 #ifdef DDEBUG
-/* This function is not in xt_qtaguid_print.c because of locks visibility */
-static void prdebug_full_state(int indent_level, const char *fmt, ...)
+/*
+ * This function is not in xt_qtaguid_print.c because of locks visibility.
+ * The lock of sock_tag_list must be aquired before calling this function
+ */
+static void prdebug_full_state_locked(int indent_level, const char *fmt, ...)
 {
 	va_list args;
 	char *fmt_buff;
@@ -1828,16 +1831,12 @@
 	kfree(buff);
 	va_end(args);
 
-	spin_lock_bh(&sock_tag_list_lock);
 	prdebug_sock_tag_tree(indent_level, &sock_tag_tree);
-	spin_unlock_bh(&sock_tag_list_lock);
 
-	spin_lock_bh(&sock_tag_list_lock);
 	spin_lock_bh(&uid_tag_data_tree_lock);
 	prdebug_uid_tag_data_tree(indent_level, &uid_tag_data_tree);
 	prdebug_proc_qtu_data_tree(indent_level, &proc_qtu_data_tree);
 	spin_unlock_bh(&uid_tag_data_tree_lock);
-	spin_unlock_bh(&sock_tag_list_lock);
 
 	spin_lock_bh(&iface_stat_list_lock);
 	prdebug_iface_stat_list(indent_level, &iface_stat_list);
@@ -1846,7 +1845,7 @@
 	pr_debug("qtaguid: %s(): }\n", __func__);
 }
 #else
-static void prdebug_full_state(int indent_level, const char *fmt, ...) {}
+static void prdebug_full_state_locked(int indent_level, const char *fmt, ...) {}
 #endif
 
 struct proc_ctrl_print_info {
@@ -1922,12 +1921,12 @@
 {
 	struct sock_tag *sock_tag_entry = v;
 	uid_t uid;
-	long f_count;
 
 	CT_DEBUG("qtaguid: proc ctrl pid=%u tgid=%u uid=%u\n",
 		 current->pid, current->tgid, current_fsuid());
 
 	if (sock_tag_entry != SEQ_START_TOKEN) {
+		int sk_ref_count;
 		uid = get_uid_from_tag(sock_tag_entry->tag);
 		CT_DEBUG("qtaguid: proc_read(): sk=%p tag=0x%llx (uid=%u) "
 			 "pid=%u\n",
@@ -1936,13 +1935,13 @@
 			 uid,
 			 sock_tag_entry->pid
 			);
-		f_count = atomic_long_read(
-			&sock_tag_entry->socket->file->f_count);
+		sk_ref_count = atomic_read(
+			&sock_tag_entry->sk->sk_refcnt);
 		seq_printf(m, "sock=%pK tag=0x%llx (uid=%u) pid=%u "
-			   "f_count=%lu\n",
+			   "f_count=%d\n",
 			   sock_tag_entry->sk,
 			   sock_tag_entry->tag, uid,
-			   sock_tag_entry->pid, f_count);
+			   sock_tag_entry->pid, sk_ref_count);
 	} else {
 		seq_printf(m, "events: sockets_tagged=%llu "
 			   "sockets_untagged=%llu "
@@ -1969,8 +1968,11 @@
 			   (u64)atomic64_read(&qtu_events.match_no_sk),
 			   (u64)atomic64_read(&qtu_events.match_no_sk_file));
 
-		/* Count the following as part of the last item_index */
-		prdebug_full_state(0, "proc ctrl");
+		/* Count the following as part of the last item_index. No need
+		 * to lock the sock_tag_list here since it is already locked when
+		 * starting the seq_file operation
+		 */
+		prdebug_full_state_locked(0, "proc ctrl");
 	}
 
 	return 0;
@@ -2230,8 +2232,8 @@
 			current_fsuid());
 		goto err;
 	}
-	CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->f_count=%ld ->sk=%p\n",
-		 input, atomic_long_read(&el_socket->file->f_count),
+	CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->sk_refcnt=%d ->sk=%p\n",
+		 input, atomic_read(&el_socket->sk->sk_refcnt),
 		 el_socket->sk);
 	if (argc < 3) {
 		acct_tag = make_atag_from_value(0);
@@ -2272,16 +2274,9 @@
 		struct tag_ref *prev_tag_ref_entry;
 
 		CT_DEBUG("qtaguid: ctrl_tag(%s): retag for sk=%p "
-			 "st@%p ...->f_count=%ld\n",
+			 "st@%p ...->sk_refcnt=%d\n",
 			 input, el_socket->sk, sock_tag_entry,
-			 atomic_long_read(&el_socket->file->f_count));
-		/*
-		 * This is a re-tagging, so release the sock_fd that was
-		 * locked at the time of the 1st tagging.
-		 * There is still the ref from this call's sockfd_lookup() so
-		 * it can be done within the spinlock.
-		 */
-		sockfd_put(sock_tag_entry->socket);
+			 atomic_read(&el_socket->sk->sk_refcnt));
 		prev_tag_ref_entry = lookup_tag_ref(sock_tag_entry->tag,
 						    &uid_tag_data_entry);
 		BUG_ON(IS_ERR_OR_NULL(prev_tag_ref_entry));
@@ -2301,8 +2296,12 @@
 			res = -ENOMEM;
 			goto err_tag_unref_put;
 		}
+		/*
+		 * Hold the sk refcount here to make sure the sk pointer cannot
+		 * be freed and reused
+		 */
+		sock_hold(el_socket->sk);
 		sock_tag_entry->sk = el_socket->sk;
-		sock_tag_entry->socket = el_socket;
 		sock_tag_entry->pid = current->tgid;
 		sock_tag_entry->tag = combine_atag_with_uid(acct_tag,
 							    uid);
@@ -2330,10 +2329,11 @@
 		atomic64_inc(&qtu_events.sockets_tagged);
 	}
 	spin_unlock_bh(&sock_tag_list_lock);
-	/* We keep the ref to the socket (file) until it is untagged */
-	CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->f_count=%ld\n",
+	/* We keep the ref to the sk until it is untagged */
+	CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->sk_refcnt=%d\n",
 		 input, sock_tag_entry,
-		 atomic_long_read(&el_socket->file->f_count));
+		 atomic_read(&el_socket->sk->sk_refcnt));
+	sockfd_put(el_socket);
 	return 0;
 
 err_tag_unref_put:
@@ -2341,8 +2341,8 @@
 	tag_ref_entry->num_sock_tags--;
 	free_tag_ref_from_utd_entry(tag_ref_entry, uid_tag_data_entry);
 err_put:
-	CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->f_count=%ld\n",
-		 input, atomic_long_read(&el_socket->file->f_count) - 1);
+	CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->sk_refcnt=%d\n",
+		 input, atomic_read(&el_socket->sk->sk_refcnt) - 1);
 	/* Release the sock_fd that was grabbed by sockfd_lookup(). */
 	sockfd_put(el_socket);
 	return res;
@@ -2358,17 +2358,13 @@
 	int sock_fd = 0;
 	struct socket *el_socket;
 	int res, argc;
-	struct sock_tag *sock_tag_entry;
-	struct tag_ref *tag_ref_entry;
-	struct uid_tag_data *utd_entry;
-	struct proc_qtu_data *pqd_entry;
 
 	argc = sscanf(input, "%c %d", &cmd, &sock_fd);
 	CT_DEBUG("qtaguid: ctrl_untag(%s): argc=%d cmd=%c sock_fd=%d\n",
 		 input, argc, cmd, sock_fd);
 	if (argc < 2) {
 		res = -EINVAL;
-		goto err;
+		return res;
 	}
 	el_socket = sockfd_lookup(sock_fd, &res);  /* This locks the file */
 	if (!el_socket) {
@@ -2376,17 +2372,31 @@
 			" sock_fd=%d err=%d pid=%u tgid=%u uid=%u\n",
 			input, sock_fd, res, current->pid, current->tgid,
 			current_fsuid());
-		goto err;
+		return res;
 	}
 	CT_DEBUG("qtaguid: ctrl_untag(%s): socket->...->f_count=%ld ->sk=%p\n",
 		 input, atomic_long_read(&el_socket->file->f_count),
 		 el_socket->sk);
+	res = qtaguid_untag(el_socket, false);
+	sockfd_put(el_socket);
+	return res;
+}
+
+int qtaguid_untag(struct socket *el_socket, bool kernel)
+{
+	int res;
+	pid_t pid;
+	struct sock_tag *sock_tag_entry;
+	struct tag_ref *tag_ref_entry;
+	struct uid_tag_data *utd_entry;
+	struct proc_qtu_data *pqd_entry;
+
 	spin_lock_bh(&sock_tag_list_lock);
 	sock_tag_entry = get_sock_stat_nl(el_socket->sk);
 	if (!sock_tag_entry) {
 		spin_unlock_bh(&sock_tag_list_lock);
 		res = -EINVAL;
-		goto err_put;
+		return res;
 	}
 	/*
 	 * The socket already belongs to the current process
@@ -2398,20 +2408,26 @@
 	BUG_ON(!tag_ref_entry);
 	BUG_ON(tag_ref_entry->num_sock_tags <= 0);
 	spin_lock_bh(&uid_tag_data_tree_lock);
+	if (kernel)
+		pid = sock_tag_entry->pid;
+	else
+		pid = current->tgid;
 	pqd_entry = proc_qtu_data_tree_search(
-		&proc_qtu_data_tree, current->tgid);
+		&proc_qtu_data_tree, pid);
 	/*
 	 * TODO: remove if, and start failing.
 	 * At first, we want to catch user-space code that is not
 	 * opening the /dev/xt_qtaguid.
 	 */
-	if (IS_ERR_OR_NULL(pqd_entry))
+	if (IS_ERR_OR_NULL(pqd_entry) || !sock_tag_entry->list.next) {
 		pr_warn_once("qtaguid: %s(): "
 			     "User space forgot to open /dev/xt_qtaguid? "
-			     "pid=%u tgid=%u uid=%u\n", __func__,
-			     current->pid, current->tgid, current_fsuid());
-	else
+			     "pid=%u tgid=%u sk_pid=%u, uid=%u\n", __func__,
+			     current->pid, current->tgid, sock_tag_entry->pid,
+			     from_kuid(&init_user_ns, current_fsuid()));
+	} else {
 		list_del(&sock_tag_entry->list);
+	}
 	spin_unlock_bh(&uid_tag_data_tree_lock);
 	/*
 	 * We don't free tag_ref from the utd_entry here,
@@ -2420,30 +2436,17 @@
 	tag_ref_entry->num_sock_tags--;
 	spin_unlock_bh(&sock_tag_list_lock);
 	/*
-	 * Release the sock_fd that was grabbed at tag time,
-	 * and once more for the sockfd_lookup() here.
+	 * Release the sock_fd that was grabbed at tag time.
 	 */
-	sockfd_put(sock_tag_entry->socket);
-	CT_DEBUG("qtaguid: ctrl_untag(%s): done. st@%p ...->f_count=%ld\n",
-		 input, sock_tag_entry,
-		 atomic_long_read(&el_socket->file->f_count) - 1);
-	sockfd_put(el_socket);
+	sock_put(sock_tag_entry->sk);
+	CT_DEBUG("qtaguid: done. st@%p ...->sk_refcnt=%d\n",
+		 sock_tag_entry,
+		 atomic_read(&el_socket->sk->sk_refcnt));
 
 	kfree(sock_tag_entry);
 	atomic64_inc(&qtu_events.sockets_untagged);
 
 	return 0;
-
-err_put:
-	CT_DEBUG("qtaguid: ctrl_untag(%s): done. socket->...->f_count=%ld\n",
-		 input, atomic_long_read(&el_socket->file->f_count) - 1);
-	/* Release the sock_fd that was grabbed by sockfd_lookup(). */
-	sockfd_put(el_socket);
-	return res;
-
-err:
-	CT_DEBUG("qtaguid: ctrl_untag(%s): done.\n", input);
-	return res;
 }
 
 static ssize_t qtaguid_ctrl_parse(const char *input, size_t count)
@@ -2873,8 +2876,10 @@
 
 	sock_tag_tree_erase(&st_to_free_tree);
 
-	prdebug_full_state(0, "%s(): pid=%u tgid=%u", __func__,
+	spin_lock_bh(&sock_tag_list_lock);
+	prdebug_full_state_locked(0, "%s(): pid=%u tgid=%u", __func__,
 			   current->pid, current->tgid);
+	spin_unlock_bh(&sock_tag_list_lock);
 	return 0;
 }
 
diff --git a/net/netfilter/xt_qtaguid_internal.h b/net/netfilter/xt_qtaguid_internal.h
index 6dc14a9..8178fbd 100644
--- a/net/netfilter/xt_qtaguid_internal.h
+++ b/net/netfilter/xt_qtaguid_internal.h
@@ -256,8 +256,6 @@
 struct sock_tag {
 	struct rb_node sock_node;
 	struct sock *sk;  /* Only used as a number, never dereferenced */
-	/* The socket is needed for sockfd_put() */
-	struct socket *socket;
 	/* Used to associate with a given pid */
 	struct list_head list;   /* in proc_qtu_data.sock_tag_list */
 	pid_t pid;
diff --git a/net/netfilter/xt_qtaguid_print.c b/net/netfilter/xt_qtaguid_print.c
index f6a00a3..2a7190d 100644
--- a/net/netfilter/xt_qtaguid_print.c
+++ b/net/netfilter/xt_qtaguid_print.c
@@ -24,7 +24,7 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/spinlock_types.h>
-
+#include <net/sock.h>
 
 #include "xt_qtaguid_internal.h"
 #include "xt_qtaguid_print.h"
@@ -237,10 +237,10 @@
 	tag_str = pp_tag_t(&st->tag);
 	res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
 			"sock_node=rb_node{...}, "
-			"sk=%p socket=%p (f_count=%lu), list=list_head{...}, "
+			"sk=%p (f_count=%d), list=list_head{...}, "
 			"pid=%u, tag=%s}",
-			st, st->sk, st->socket, atomic_long_read(
-				&st->socket->file->f_count),
+			st, st->sk, atomic_read(
+				&st->sk->sk_refcnt),
 			st->pid, tag_str);
 	_bug_on_err_or_null(res);
 	kfree(tag_str);
diff --git a/net/socket.c b/net/socket.c
index db0a2e4..38aaf0e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -514,9 +514,23 @@
 	return used;
 }
 
+int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	int err = simple_setattr(dentry, iattr);
+
+	if (!err && (iattr->ia_valid & ATTR_UID)) {
+		struct socket *sock = SOCKET_I(dentry->d_inode);
+
+		sock->sk->sk_uid = iattr->ia_uid;
+	}
+
+	return err;
+}
+
 static const struct inode_operations sockfs_inode_ops = {
 	.getxattr = sockfs_getxattr,
 	.listxattr = sockfs_listxattr,
+	.setattr = sockfs_setattr,
 };
 
 /**
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index ab4ef72..daed579 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -220,7 +220,7 @@
 
 	.uinfo = {
 		.auth = {
-			.icv_truncbits = 96,
+			.icv_truncbits = 128,
 			.icv_fullbits = 256,
 		}
 	},
diff --git a/security/commoncap.c b/security/commoncap.c
index 5870fdc..1741c37 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -283,6 +283,16 @@
 	new->cap_effective   = *effective;
 	new->cap_inheritable = *inheritable;
 	new->cap_permitted   = *permitted;
+
+	/*
+	 * Mask off ambient bits that are no longer both permitted and
+	 * inheritable.
+	 */
+	new->cap_ambient = cap_intersect(new->cap_ambient,
+					 cap_intersect(*permitted,
+						       *inheritable));
+	if (WARN_ON(!cap_ambient_invariant_ok(new)))
+		return -EINVAL;
 	return 0;
 }
 
@@ -363,6 +373,7 @@
 
 		/*
 		 * pP' = (X & fP) | (pI & fI)
+		 * The addition of pA' is handled later.
 		 */
 		new->cap_permitted.cap[i] =
 			(new->cap_bset.cap[i] & permitted) |
@@ -491,10 +502,13 @@
 {
 	const struct cred *old = current_cred();
 	struct cred *new = bprm->cred;
-	bool effective, has_cap = false;
+	bool effective, has_cap = false, is_setid;
 	int ret;
 	kuid_t root_uid;
 
+	if (WARN_ON(!cap_ambient_invariant_ok(old)))
+		return -EPERM;
+
 	effective = false;
 	ret = get_file_caps(bprm, &effective, &has_cap);
 	if (ret < 0)
@@ -539,8 +553,9 @@
 	 *
 	 * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
 	 */
-	if ((!uid_eq(new->euid, old->uid) ||
-	     !gid_eq(new->egid, old->gid) ||
+	is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid);
+
+	if ((is_setid ||
 	     !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
 	    bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
 		/* downgrade; they get no more than they had, and maybe less */
@@ -556,10 +571,28 @@
 	new->suid = new->fsuid = new->euid;
 	new->sgid = new->fsgid = new->egid;
 
+	/* File caps or setid cancels ambient. */
+	if (has_cap || is_setid)
+		cap_clear(new->cap_ambient);
+
+	/*
+	 * Now that we've computed pA', update pP' to give:
+	 *   pP' = (X & fP) | (pI & fI) | pA'
+	 */
+	new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient);
+
+	/*
+	 * Set pE' = (fE ? pP' : pA').  Because pA' is zero if fE is set,
+	 * this is the same as pE' = (fE ? pP' : 0) | pA'.
+	 */
 	if (effective)
 		new->cap_effective = new->cap_permitted;
 	else
-		cap_clear(new->cap_effective);
+		new->cap_effective = new->cap_ambient;
+
+	if (WARN_ON(!cap_ambient_invariant_ok(new)))
+		return -EPERM;
+
 	bprm->cap_effective = effective;
 
 	/*
@@ -574,7 +607,7 @@
 	 * Number 1 above might fail if you don't have a full bset, but I think
 	 * that is interesting information to audit.
 	 */
-	if (!cap_isclear(new->cap_effective)) {
+	if (!cap_issubset(new->cap_effective, new->cap_ambient)) {
 		if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
 		    !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
 		    issecure(SECURE_NOROOT)) {
@@ -585,6 +618,10 @@
 	}
 
 	new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
+
+	if (WARN_ON(!cap_ambient_invariant_ok(new)))
+		return -EPERM;
+
 	return 0;
 }
 
@@ -606,7 +643,7 @@
 	if (!uid_eq(cred->uid, root_uid)) {
 		if (bprm->cap_effective)
 			return 1;
-		if (!cap_isclear(cred->cap_permitted))
+		if (!cap_issubset(cred->cap_permitted, cred->cap_ambient))
 			return 1;
 	}
 
@@ -708,10 +745,18 @@
 	     uid_eq(old->suid, root_uid)) &&
 	    (!uid_eq(new->uid, root_uid) &&
 	     !uid_eq(new->euid, root_uid) &&
-	     !uid_eq(new->suid, root_uid)) &&
-	    !issecure(SECURE_KEEP_CAPS)) {
-		cap_clear(new->cap_permitted);
-		cap_clear(new->cap_effective);
+	     !uid_eq(new->suid, root_uid))) {
+		if (!issecure(SECURE_KEEP_CAPS)) {
+			cap_clear(new->cap_permitted);
+			cap_clear(new->cap_effective);
+		}
+
+		/*
+		 * Pre-ambient programs expect setresuid to nonroot followed
+		 * by exec to drop capabilities.  We should make sure that
+		 * this remains the case.
+		 */
+		cap_clear(new->cap_ambient);
 	}
 	if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
 		cap_clear(new->cap_effective);
@@ -833,15 +878,20 @@
  * Implement PR_CAPBSET_DROP.  Attempt to remove the specified capability from
  * the current task's bounding set.  Returns 0 on success, -ve on error.
  */
-static long cap_prctl_drop(struct cred *new, unsigned long cap)
+static int cap_prctl_drop(unsigned long cap)
 {
-	if (!capable(CAP_SETPCAP))
+	struct cred *new;
+
+	if (!ns_capable(current_user_ns(), CAP_SETPCAP))
 		return -EPERM;
 	if (!cap_valid(cap))
 		return -EINVAL;
 
+	new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
 	cap_lower(new->cap_bset, cap);
-	return 0;
+	return commit_creds(new);
 }
 
 /**
@@ -859,26 +909,17 @@
 int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 		   unsigned long arg4, unsigned long arg5)
 {
+	const struct cred *old = current_cred();
 	struct cred *new;
-	long error = 0;
-
-	new = prepare_creds();
-	if (!new)
-		return -ENOMEM;
 
 	switch (option) {
 	case PR_CAPBSET_READ:
-		error = -EINVAL;
 		if (!cap_valid(arg2))
-			goto error;
-		error = !!cap_raised(new->cap_bset, arg2);
-		goto no_change;
+			return -EINVAL;
+		return !!cap_raised(old->cap_bset, arg2);
 
 	case PR_CAPBSET_DROP:
-		error = cap_prctl_drop(new, arg2);
-		if (error < 0)
-			goto error;
-		goto changed;
+		return cap_prctl_drop(arg2);
 
 	/*
 	 * The next four prctl's remain to assist with transitioning a
@@ -900,10 +941,9 @@
 	 * capability-based-privilege environment.
 	 */
 	case PR_SET_SECUREBITS:
-		error = -EPERM;
-		if ((((new->securebits & SECURE_ALL_LOCKS) >> 1)
-		     & (new->securebits ^ arg2))			/*[1]*/
-		    || ((new->securebits & SECURE_ALL_LOCKS & ~arg2))	/*[2]*/
+		if ((((old->securebits & SECURE_ALL_LOCKS) >> 1)
+		     & (old->securebits ^ arg2))			/*[1]*/
+		    || ((old->securebits & SECURE_ALL_LOCKS & ~arg2))	/*[2]*/
 		    || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS))	/*[3]*/
 		    || (cap_capable(current_cred(),
 				    current_cred()->user_ns, CAP_SETPCAP,
@@ -917,46 +957,76 @@
 			 */
 		    )
 			/* cannot change a locked bit */
-			goto error;
+			return -EPERM;
+
+		new = prepare_creds();
+		if (!new)
+			return -ENOMEM;
 		new->securebits = arg2;
-		goto changed;
+		return commit_creds(new);
 
 	case PR_GET_SECUREBITS:
-		error = new->securebits;
-		goto no_change;
+		return old->securebits;
 
 	case PR_GET_KEEPCAPS:
-		if (issecure(SECURE_KEEP_CAPS))
-			error = 1;
-		goto no_change;
+		return !!issecure(SECURE_KEEP_CAPS);
 
 	case PR_SET_KEEPCAPS:
-		error = -EINVAL;
 		if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
-			goto error;
-		error = -EPERM;
+			return -EINVAL;
 		if (issecure(SECURE_KEEP_CAPS_LOCKED))
-			goto error;
+			return -EPERM;
+
+		new = prepare_creds();
+		if (!new)
+			return -ENOMEM;
 		if (arg2)
 			new->securebits |= issecure_mask(SECURE_KEEP_CAPS);
 		else
 			new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
-		goto changed;
+		return commit_creds(new);
+
+	case PR_CAP_AMBIENT:
+		if (arg2 == PR_CAP_AMBIENT_CLEAR_ALL) {
+			if (arg3 | arg4 | arg5)
+				return -EINVAL;
+
+			new = prepare_creds();
+			if (!new)
+				return -ENOMEM;
+			cap_clear(new->cap_ambient);
+			return commit_creds(new);
+		}
+
+		if (((!cap_valid(arg3)) | arg4 | arg5))
+			return -EINVAL;
+
+		if (arg2 == PR_CAP_AMBIENT_IS_SET) {
+			return !!cap_raised(current_cred()->cap_ambient, arg3);
+		} else if (arg2 != PR_CAP_AMBIENT_RAISE &&
+			   arg2 != PR_CAP_AMBIENT_LOWER) {
+			return -EINVAL;
+		} else {
+			if (arg2 == PR_CAP_AMBIENT_RAISE &&
+			    (!cap_raised(current_cred()->cap_permitted, arg3) ||
+			     !cap_raised(current_cred()->cap_inheritable,
+					 arg3)))
+				return -EPERM;
+
+			new = prepare_creds();
+			if (!new)
+				return -ENOMEM;
+			if (arg2 == PR_CAP_AMBIENT_RAISE)
+				cap_raise(new->cap_ambient, arg3);
+			else
+				cap_lower(new->cap_ambient, arg3);
+			return commit_creds(new);
+		}
 
 	default:
 		/* No functionality available - continue with default */
-		error = -ENOSYS;
-		goto error;
+		return -ENOSYS;
 	}
-
-	/* Functionality provided */
-changed:
-	return commit_creds(new);
-
-no_change:
-error:
-	abort_creds(new);
-	return error;
 }
 
 /**
diff --git a/security/inode.c b/security/inode.c
index 43ce6e1..94466a5e 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -105,7 +105,7 @@
 	dir = parent->d_inode;
 
 	mutex_lock(&dir->i_mutex);
-	dentry = lookup_one_len(name, parent, strlen(name));
+	dentry = lookup_one_len2(name, mount, parent, strlen(name));
 	if (IS_ERR(dentry))
 		goto out;
 
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index cd871dc..28380e5 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -847,6 +847,7 @@
 	new->cap_inheritable	= old->cap_inheritable;
 	new->cap_permitted	= old->cap_permitted;
 	new->cap_effective	= old->cap_effective;
+	new->cap_ambient	= old->cap_ambient;
 	new->cap_bset		= old->cap_bset;
 
 	new->jit_keyring	= old->jit_keyring;