ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/linux/tools/testing/selftests/android/Makefile b/marvell/linux/tools/testing/selftests/android/Makefile
new file mode 100644
index 0000000..7c46271
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/Makefile
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only
+SUBDIRS := ion
+
+TEST_PROGS := run.sh
+
+.PHONY: all clean
+
+include ../lib.mk
+
+all:
+	@for DIR in $(SUBDIRS); do		\
+		BUILD_TARGET=$(OUTPUT)/$$DIR;	\
+		mkdir $$BUILD_TARGET  -p;	\
+		make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
+		#SUBDIR test prog name should be in the form: SUBDIR_test.sh \
+		TEST=$$DIR"_test.sh"; \
+		if [ -e $$DIR/$$TEST ]; then \
+			rsync -a $$DIR/$$TEST $$BUILD_TARGET/; \
+		fi \
+	done
+
+override define INSTALL_RULE
+	mkdir -p $(INSTALL_PATH)
+	install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
+
+	@for SUBDIR in $(SUBDIRS); do \
+		BUILD_TARGET=$(OUTPUT)/$$SUBDIR;	\
+		mkdir $$BUILD_TARGET  -p;	\
+		$(MAKE) OUTPUT=$$BUILD_TARGET -C $$SUBDIR INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR install; \
+	done;
+endef
+
+override define CLEAN
+	@for DIR in $(SUBDIRS); do		\
+		BUILD_TARGET=$(OUTPUT)/$$DIR;	\
+		mkdir $$BUILD_TARGET  -p;	\
+		make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
+	done
+endef
diff --git a/marvell/linux/tools/testing/selftests/android/config b/marvell/linux/tools/testing/selftests/android/config
new file mode 100644
index 0000000..b4ad748
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/config
@@ -0,0 +1,5 @@
+CONFIG_ANDROID=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
+CONFIG_DRM_VGEM=y
diff --git a/marvell/linux/tools/testing/selftests/android/ion/.gitignore b/marvell/linux/tools/testing/selftests/android/ion/.gitignore
new file mode 100644
index 0000000..95e8f45
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/.gitignore
@@ -0,0 +1,3 @@
+ionapp_export
+ionapp_import
+ionmap_test
diff --git a/marvell/linux/tools/testing/selftests/android/ion/Makefile b/marvell/linux/tools/testing/selftests/android/ion/Makefile
new file mode 100644
index 0000000..0eb7ab6
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/Makefile
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+INCLUDEDIR := -I. -I../../../../../drivers/staging/android/uapi/ -I../../../../../usr/include/
+CFLAGS := $(CFLAGS) $(INCLUDEDIR) -Wall -O2 -g
+
+TEST_GEN_FILES := ionapp_export ionapp_import ionmap_test
+
+all: $(TEST_GEN_FILES)
+
+$(TEST_GEN_FILES): ipcsocket.c ionutils.c
+
+TEST_PROGS := ion_test.sh
+
+KSFT_KHDR_INSTALL := 1
+top_srcdir = ../../../../..
+include ../../lib.mk
+
+$(OUTPUT)/ionapp_export: ionapp_export.c ipcsocket.c ionutils.c
+$(OUTPUT)/ionapp_import: ionapp_import.c ipcsocket.c ionutils.c
+$(OUTPUT)/ionmap_test: ionmap_test.c ionutils.c
diff --git a/marvell/linux/tools/testing/selftests/android/ion/README b/marvell/linux/tools/testing/selftests/android/ion/README
new file mode 100644
index 0000000..21783e9
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/README
@@ -0,0 +1,101 @@
+ION BUFFER SHARING UTILITY
+==========================
+File: ion_test.sh : Utility to test ION driver buffer sharing mechanism.
+Author: Pintu Kumar <pintu.ping@gmail.com>
+
+Introduction:
+-------------
+This is a test utility to verify ION buffer sharing in user space
+between 2 independent processes.
+It uses unix domain socket (with SCM_RIGHTS) as IPC to transfer an FD to
+another process to share the same buffer.
+This utility demonstrates how ION buffer sharing can be implemented between
+two user space processes, using various heap types.
+The following heap types are supported by ION driver.
+ION_HEAP_TYPE_SYSTEM (0)
+ION_HEAP_TYPE_SYSTEM_CONTIG (1)
+ION_HEAP_TYPE_CARVEOUT (2)
+ION_HEAP_TYPE_CHUNK (3)
+ION_HEAP_TYPE_DMA (4)
+
+By default only the SYSTEM and SYSTEM_CONTIG heaps are supported.
+Each heap is associated with the respective heap id.
+This utility is designed in the form of client/server program.
+The server part (ionapp_export) is the exporter of the buffer.
+It is responsible for creating an ION client, allocating the buffer based on
+the heap id, writing some data to this buffer and then exporting the FD
+(associated with this buffer) to another process using socket IPC.
+This FD is called as buffer FD (which is different than the ION client FD).
+
+The client part (ionapp_import) is the importer of the buffer.
+It retrives the FD from the socket data and installs into its address space.
+This new FD internally points to the same kernel buffer.
+So first it reads the data that is stored in this buffer and prints it.
+Then it writes the different size of data (it could be different data) to the
+same buffer.
+Finally the buffer FD must be closed by both the exporter and importer.
+Thus the same kernel buffer is shared among two user space processes using
+ION driver and only one time allocation.
+
+Prerequisite:
+-------------
+This utility works only if /dev/ion interface is present.
+The following configs needs to be enabled in kernel to include ion driver.
+CONFIG_ANDROID=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
+
+This utility requires to be run as root user.
+
+
+Compile and test:
+-----------------
+This utility is made to be run as part of kselftest framework in kernel.
+To compile and run using kselftest you can simply do the following from the
+kernel top directory.
+linux$ make TARGETS=android kselftest
+Or you can also use:
+linux$ make -C tools/testing/selftests TARGETS=android run_tests
+Using the selftest it can directly execute the ion_test.sh script to test the
+buffer sharing using ion system heap.
+Currently the heap size is hard coded as just 10 bytes inside this script.
+You need to be a root user to run under selftest.
+
+You can also compile and test manually using the following steps:
+ion$ make
+These will generate 2 executable: ionapp_export, ionapp_import
+Now you can run the export and import manually by specifying the heap type
+and the heap size.
+You can also directly execute the shell script to run the test automatically.
+Simply use the following command to run the test.
+ion$ sudo ./ion_test.sh
+
+Test Results:
+-------------
+The utility is verified on Ubuntu-32 bit system with Linux Kernel 4.14.
+Here is the snapshot of the test result using kselftest.
+
+linux# make TARGETS=android kselftest
+heap_type: 0, heap_size: 10
+--------------------------------------
+heap type: 0
+  heap id: 1
+heap name: ion_system_heap
+--------------------------------------
+Fill buffer content:
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
+Sharing fd: 6, Client fd: 5
+<ion_close_buffer_fd>: buffer release successfully....
+Received buffer fd: 4
+Read buffer content:
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0x0 0x0 0x0 0x0 0x0 0x0
+0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+Fill buffer content:
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
+0xfd 0xfd
+<ion_close_buffer_fd>: buffer release successfully....
+ion_test.sh: heap_type: 0 - [PASS]
+
+ion_test.sh: done
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ion.h b/marvell/linux/tools/testing/selftests/android/ion/ion.h
new file mode 100644
index 0000000..33db230
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ion.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ion.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+/* This file is copied from drivers/staging/android/uapi/ion.h
+ * This local copy is required for the selftest to pass, when build
+ * outside the kernel source tree.
+ * Please keep this file in sync with its original file until the
+ * ion driver is moved outside the staging tree.
+ */
+
+#ifndef _UAPI_LINUX_ION_H
+#define _UAPI_LINUX_ION_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * enum ion_heap_types - list of all possible types of heaps
+ * @ION_HEAP_TYPE_SYSTEM:	 memory allocated via vmalloc
+ * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
+ * @ION_HEAP_TYPE_CARVEOUT:	 memory allocated from a prereserved
+ *				 carveout heap, allocations are physically
+ *				 contiguous
+ * @ION_HEAP_TYPE_DMA:		 memory allocated via DMA API
+ * @ION_NUM_HEAPS:		 helper for iterating over heaps, a bit mask
+ *				 is used to identify the heaps, so only 32
+ *				 total heap types are supported
+ */
+enum ion_heap_type {
+	ION_HEAP_TYPE_SYSTEM,
+	ION_HEAP_TYPE_SYSTEM_CONTIG,
+	ION_HEAP_TYPE_CARVEOUT,
+	ION_HEAP_TYPE_CHUNK,
+	ION_HEAP_TYPE_DMA,
+	ION_HEAP_TYPE_CUSTOM, /*
+			       * must be last so device specific heaps always
+			       * are at the end of this enum
+			       */
+};
+
+#define ION_NUM_HEAP_IDS		(sizeof(unsigned int) * 8)
+
+/**
+ * allocation flags - the lower 16 bits are used by core ion, the upper 16
+ * bits are reserved for use by the heaps themselves.
+ */
+
+/*
+ * mappings of this buffer should be cached, ion will do cache maintenance
+ * when the buffer is mapped for dma
+ */
+#define ION_FLAG_CACHED 1
+
+/**
+ * DOC: Ion Userspace API
+ *
+ * create a client by opening /dev/ion
+ * most operations handled via following ioctls
+ *
+ */
+
+/**
+ * struct ion_allocation_data - metadata passed from userspace for allocations
+ * @len:		size of the allocation
+ * @heap_id_mask:	mask of heap ids to allocate from
+ * @flags:		flags passed to heap
+ * @handle:		pointer that will be populated with a cookie to use to
+ *			refer to this allocation
+ *
+ * Provided by userspace as an argument to the ioctl
+ */
+struct ion_allocation_data {
+	__u64 len;
+	__u32 heap_id_mask;
+	__u32 flags;
+	__u32 fd;
+	__u32 unused;
+};
+
+#define MAX_HEAP_NAME			32
+
+/**
+ * struct ion_heap_data - data about a heap
+ * @name - first 32 characters of the heap name
+ * @type - heap type
+ * @heap_id - heap id for the heap
+ */
+struct ion_heap_data {
+	char name[MAX_HEAP_NAME];
+	__u32 type;
+	__u32 heap_id;
+	__u32 reserved0;
+	__u32 reserved1;
+	__u32 reserved2;
+};
+
+/**
+ * struct ion_heap_query - collection of data about all heaps
+ * @cnt - total number of heaps to be copied
+ * @heaps - buffer to copy heap data
+ */
+struct ion_heap_query {
+	__u32 cnt; /* Total number of heaps to be copied */
+	__u32 reserved0; /* align to 64bits */
+	__u64 heaps; /* buffer to be populated */
+	__u32 reserved1;
+	__u32 reserved2;
+};
+
+#define ION_IOC_MAGIC		'I'
+
+/**
+ * DOC: ION_IOC_ALLOC - allocate memory
+ *
+ * Takes an ion_allocation_data struct and returns it with the handle field
+ * populated with the opaque handle for the allocation.
+ */
+#define ION_IOC_ALLOC		_IOWR(ION_IOC_MAGIC, 0, \
+				      struct ion_allocation_data)
+
+/**
+ * DOC: ION_IOC_HEAP_QUERY - information about available heaps
+ *
+ * Takes an ion_heap_query structure and populates information about
+ * available Ion heaps.
+ */
+#define ION_IOC_HEAP_QUERY     _IOWR(ION_IOC_MAGIC, 8, \
+					struct ion_heap_query)
+
+#endif /* _UAPI_LINUX_ION_H */
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ion_test.sh b/marvell/linux/tools/testing/selftests/android/ion/ion_test.sh
new file mode 100755
index 0000000..69e676c
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ion_test.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+heapsize=4096
+TCID="ion_test.sh"
+errcode=0
+
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+run_test()
+{
+	heaptype=$1
+	./ionapp_export -i $heaptype -s $heapsize &
+	sleep 1
+	./ionapp_import
+	if [ $? -ne 0 ]; then
+		echo "$TCID: heap_type: $heaptype - [FAIL]"
+		errcode=1
+	else
+		echo "$TCID: heap_type: $heaptype - [PASS]"
+	fi
+	sleep 1
+	echo ""
+}
+
+check_root()
+{
+	uid=$(id -u)
+	if [ $uid -ne 0 ]; then
+		echo $TCID: must be run as root >&2
+		exit $ksft_skip
+	fi
+}
+
+check_device()
+{
+	DEVICE=/dev/ion
+	if [ ! -e $DEVICE ]; then
+		echo $TCID: No $DEVICE device found >&2
+		echo $TCID: May be CONFIG_ION is not set >&2
+		exit $ksft_skip
+	fi
+}
+
+main_function()
+{
+	check_device
+	check_root
+
+	# ION_SYSTEM_HEAP TEST
+	run_test 0
+	# ION_SYSTEM_CONTIG_HEAP TEST
+	run_test 1
+}
+
+main_function
+echo "$TCID: done"
+exit $errcode
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ionapp_export.c b/marvell/linux/tools/testing/selftests/android/ion/ionapp_export.c
new file mode 100644
index 0000000..063b783
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ionapp_export.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ionapp_export.c
+ *
+ * It is a user space utility to create and export android
+ * ion memory buffer fd to another process using unix domain socket as IPC.
+ * This acts like a server for ionapp_import(client).
+ * So, this server has to be started first before the client.
+ *
+ * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "ionutils.h"
+#include "ipcsocket.h"
+
+
+void print_usage(int argc, char *argv[])
+{
+	printf("Usage: %s [-h <help>] [-i <heap id>] [-s <size in bytes>]\n",
+		argv[0]);
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, ret, status, heapid;
+	int sockfd, client_fd, shared_fd;
+	unsigned char *map_buf;
+	unsigned long map_len, heap_type, heap_size, flags;
+	struct ion_buffer_info info;
+	struct socket_info skinfo;
+
+	if (argc < 2) {
+		print_usage(argc, argv);
+		return -1;
+	}
+
+	heap_size = 0;
+	flags = 0;
+	heap_type = ION_HEAP_TYPE_SYSTEM;
+
+	while ((opt = getopt(argc, argv, "hi:s:")) != -1) {
+		switch (opt) {
+		case 'h':
+			print_usage(argc, argv);
+			exit(0);
+			break;
+		case 'i':
+			heapid = atoi(optarg);
+			switch (heapid) {
+			case 0:
+				heap_type = ION_HEAP_TYPE_SYSTEM;
+				break;
+			case 1:
+				heap_type = ION_HEAP_TYPE_SYSTEM_CONTIG;
+				break;
+			default:
+				printf("ERROR: heap type not supported\n");
+				exit(1);
+			}
+			break;
+		case 's':
+			heap_size = atoi(optarg);
+			break;
+		default:
+			print_usage(argc, argv);
+			exit(1);
+			break;
+		}
+	}
+
+	if (heap_size <= 0) {
+		printf("heap_size cannot be 0\n");
+		print_usage(argc, argv);
+		exit(1);
+	}
+
+	printf("heap_type: %ld, heap_size: %ld\n", heap_type, heap_size);
+	info.heap_type = heap_type;
+	info.heap_size = heap_size;
+	info.flag_type = flags;
+
+	/* This is server: open the socket connection first */
+	/* Here; 1 indicates server or exporter */
+	status = opensocket(&sockfd, SOCKET_NAME, 1);
+	if (status < 0) {
+		fprintf(stderr, "<%s>: Failed opensocket.\n", __func__);
+		goto err_socket;
+	}
+	skinfo.sockfd = sockfd;
+
+	ret = ion_export_buffer_fd(&info);
+	if (ret < 0) {
+		fprintf(stderr, "FAILED: ion_get_buffer_fd\n");
+		goto err_export;
+	}
+	client_fd = info.ionfd;
+	shared_fd = info.buffd;
+	map_buf = info.buffer;
+	map_len = info.buflen;
+	write_buffer(map_buf, map_len);
+
+	/* share ion buf fd with other user process */
+	printf("Sharing fd: %d, Client fd: %d\n", shared_fd, client_fd);
+	skinfo.datafd = shared_fd;
+	skinfo.buflen = map_len;
+
+	ret = socket_send_fd(&skinfo);
+	if (ret < 0) {
+		fprintf(stderr, "FAILED: socket_send_fd\n");
+		goto err_send;
+	}
+
+err_send:
+err_export:
+	ion_close_buffer_fd(&info);
+
+err_socket:
+	closesocket(sockfd, SOCKET_NAME);
+
+	return 0;
+}
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ionapp_import.c b/marvell/linux/tools/testing/selftests/android/ion/ionapp_import.c
new file mode 100644
index 0000000..54b580c
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ionapp_import.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ionapp_import.c
+ *
+ * It is a user space utility to receive android ion memory buffer fd
+ * over unix domain socket IPC that can be exported by ionapp_export.
+ * This acts like a client for ionapp_export.
+ *
+ * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "ionutils.h"
+#include "ipcsocket.h"
+
+
+int main(void)
+{
+	int ret, status;
+	int sockfd, shared_fd;
+	unsigned char *map_buf;
+	unsigned long map_len;
+	struct ion_buffer_info info;
+	struct socket_info skinfo;
+
+	/* This is the client part. Here 0 means client or importer */
+	status = opensocket(&sockfd, SOCKET_NAME, 0);
+	if (status < 0) {
+		fprintf(stderr, "No exporter exists...\n");
+		ret = status;
+		goto err_socket;
+	}
+
+	skinfo.sockfd = sockfd;
+
+	ret = socket_receive_fd(&skinfo);
+	if (ret < 0) {
+		fprintf(stderr, "Failed: socket_receive_fd\n");
+		goto err_recv;
+	}
+
+	shared_fd = skinfo.datafd;
+	printf("Received buffer fd: %d\n", shared_fd);
+	if (shared_fd <= 0) {
+		fprintf(stderr, "ERROR: improper buf fd\n");
+		ret = -1;
+		goto err_fd;
+	}
+
+	memset(&info, 0, sizeof(info));
+	info.buffd = shared_fd;
+	info.buflen = ION_BUFFER_LEN;
+
+	ret = ion_import_buffer_fd(&info);
+	if (ret < 0) {
+		fprintf(stderr, "Failed: ion_use_buffer_fd\n");
+		goto err_import;
+	}
+
+	map_buf = info.buffer;
+	map_len = info.buflen;
+	read_buffer(map_buf, map_len);
+
+	/* Write probably new data to the same buffer again */
+	map_len = ION_BUFFER_LEN;
+	write_buffer(map_buf, map_len);
+
+err_import:
+	ion_close_buffer_fd(&info);
+err_fd:
+err_recv:
+err_socket:
+	closesocket(sockfd, SOCKET_NAME);
+
+	return ret;
+}
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ionmap_test.c b/marvell/linux/tools/testing/selftests/android/ion/ionmap_test.c
new file mode 100644
index 0000000..dab36b0
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ionmap_test.c
@@ -0,0 +1,136 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/dma-buf.h>
+
+#include <drm/drm.h>
+
+#include "ion.h"
+#include "ionutils.h"
+
+int check_vgem(int fd)
+{
+	drm_version_t version = { 0 };
+	char name[5];
+	int ret;
+
+	version.name_len = 4;
+	version.name = name;
+
+	ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
+	if (ret)
+		return 1;
+
+	return strcmp(name, "vgem");
+}
+
+int open_vgem(void)
+{
+	int i, fd;
+	const char *drmstr = "/dev/dri/card";
+
+	fd = -1;
+	for (i = 0; i < 16; i++) {
+		char name[80];
+
+		sprintf(name, "%s%u", drmstr, i);
+
+		fd = open(name, O_RDWR);
+		if (fd < 0)
+			continue;
+
+		if (check_vgem(fd)) {
+			close(fd);
+			continue;
+		} else {
+			break;
+		}
+
+	}
+	return fd;
+}
+
+int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
+{
+	struct drm_prime_handle import_handle = { 0 };
+	int ret;
+
+	import_handle.fd = dma_buf_fd;
+	import_handle.flags = 0;
+	import_handle.handle = 0;
+
+	ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
+	if (ret == 0)
+		*handle = import_handle.handle;
+	return ret;
+}
+
+void close_handle(int vgem_fd, uint32_t handle)
+{
+	struct drm_gem_close close = { 0 };
+
+	close.handle = handle;
+	ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
+}
+
+int main()
+{
+	int ret, vgem_fd;
+	struct ion_buffer_info info;
+	uint32_t handle = 0;
+	struct dma_buf_sync sync = { 0 };
+
+	info.heap_type = ION_HEAP_TYPE_SYSTEM;
+	info.heap_size = 4096;
+	info.flag_type = ION_FLAG_CACHED;
+
+	ret = ion_export_buffer_fd(&info);
+	if (ret < 0) {
+		printf("ion buffer alloc failed\n");
+		return -1;
+	}
+
+	vgem_fd = open_vgem();
+	if (vgem_fd < 0) {
+		ret = vgem_fd;
+		printf("Failed to open vgem\n");
+		goto out_ion;
+	}
+
+	ret = import_vgem_fd(vgem_fd, info.buffd, &handle);
+
+	if (ret < 0) {
+		printf("Failed to import buffer\n");
+		goto out_vgem;
+	}
+
+	sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
+	ret = ioctl(info.buffd, DMA_BUF_IOCTL_SYNC, &sync);
+	if (ret)
+		printf("sync start failed %d\n", errno);
+
+	memset(info.buffer, 0xff, 4096);
+
+	sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+	ret = ioctl(info.buffd, DMA_BUF_IOCTL_SYNC, &sync);
+	if (ret)
+		printf("sync end failed %d\n", errno);
+
+	close_handle(vgem_fd, handle);
+	ret = 0;
+
+out_vgem:
+	close(vgem_fd);
+out_ion:
+	ion_close_buffer_fd(&info);
+	printf("done.\n");
+	return ret;
+}
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ionutils.c b/marvell/linux/tools/testing/selftests/android/ion/ionutils.c
new file mode 100644
index 0000000..7d1d37c
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ionutils.c
@@ -0,0 +1,253 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+//#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "ionutils.h"
+#include "ipcsocket.h"
+
+
+void write_buffer(void *buffer, unsigned long len)
+{
+	int i;
+	unsigned char *ptr = (unsigned char *)buffer;
+
+	if (!ptr) {
+		fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
+		return;
+	}
+
+	printf("Fill buffer content:\n");
+	memset(ptr, 0xfd, len);
+	for (i = 0; i < len; i++)
+		printf("0x%x ", ptr[i]);
+	printf("\n");
+}
+
+void read_buffer(void *buffer, unsigned long len)
+{
+	int i;
+	unsigned char *ptr = (unsigned char *)buffer;
+
+	if (!ptr) {
+		fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
+		return;
+	}
+
+	printf("Read buffer content:\n");
+	for (i = 0; i < len; i++)
+		printf("0x%x ", ptr[i]);
+	printf("\n");
+}
+
+int ion_export_buffer_fd(struct ion_buffer_info *ion_info)
+{
+	int i, ret, ionfd, buffer_fd;
+	unsigned int heap_id;
+	unsigned long maplen;
+	unsigned char *map_buffer;
+	struct ion_allocation_data alloc_data;
+	struct ion_heap_query query;
+	struct ion_heap_data heap_data[MAX_HEAP_COUNT];
+
+	if (!ion_info) {
+		fprintf(stderr, "<%s>: Invalid ion info\n", __func__);
+		return -1;
+	}
+
+	/* Create an ION client */
+	ionfd = open(ION_DEVICE, O_RDWR);
+	if (ionfd < 0) {
+		fprintf(stderr, "<%s>: Failed to open ion client: %s\n",
+			__func__, strerror(errno));
+		return -1;
+	}
+
+	memset(&query, 0, sizeof(query));
+	query.cnt = MAX_HEAP_COUNT;
+	query.heaps = (unsigned long int)&heap_data[0];
+	/* Query ION heap_id_mask from ION heap */
+	ret = ioctl(ionfd, ION_IOC_HEAP_QUERY, &query);
+	if (ret < 0) {
+		fprintf(stderr, "<%s>: Failed: ION_IOC_HEAP_QUERY: %s\n",
+			__func__, strerror(errno));
+		goto err_query;
+	}
+
+	heap_id = MAX_HEAP_COUNT + 1;
+	for (i = 0; i < query.cnt; i++) {
+		if (heap_data[i].type == ion_info->heap_type) {
+			heap_id = heap_data[i].heap_id;
+			break;
+		}
+	}
+
+	if (heap_id > MAX_HEAP_COUNT) {
+		fprintf(stderr, "<%s>: ERROR: heap type does not exists\n",
+			__func__);
+		goto err_heap;
+	}
+
+	alloc_data.len = ion_info->heap_size;
+	alloc_data.heap_id_mask = 1 << heap_id;
+	alloc_data.flags = ion_info->flag_type;
+
+	/* Allocate memory for this ION client as per heap_type */
+	ret = ioctl(ionfd, ION_IOC_ALLOC, &alloc_data);
+	if (ret < 0) {
+		fprintf(stderr, "<%s>: Failed: ION_IOC_ALLOC: %s\n",
+			__func__, strerror(errno));
+		goto err_alloc;
+	}
+
+	/* This will return a valid buffer fd */
+	buffer_fd = alloc_data.fd;
+	maplen = alloc_data.len;
+
+	if (buffer_fd < 0 || maplen <= 0) {
+		fprintf(stderr, "<%s>: Invalid map data, fd: %d, len: %ld\n",
+			__func__, buffer_fd, maplen);
+		goto err_fd_data;
+	}
+
+	/* Create memory mapped buffer for the buffer fd */
+	map_buffer = (unsigned char *)mmap(NULL, maplen, PROT_READ|PROT_WRITE,
+			MAP_SHARED, buffer_fd, 0);
+	if (map_buffer == MAP_FAILED) {
+		fprintf(stderr, "<%s>: Failed: mmap: %s\n",
+			__func__, strerror(errno));
+		goto err_mmap;
+	}
+
+	ion_info->ionfd = ionfd;
+	ion_info->buffd = buffer_fd;
+	ion_info->buffer = map_buffer;
+	ion_info->buflen = maplen;
+
+	return 0;
+
+	munmap(map_buffer, maplen);
+
+err_fd_data:
+err_mmap:
+	/* in case of error: close the buffer fd */
+	if (buffer_fd)
+		close(buffer_fd);
+
+err_query:
+err_heap:
+err_alloc:
+	/* In case of error: close the ion client fd */
+	if (ionfd)
+		close(ionfd);
+
+	return -1;
+}
+
+int ion_import_buffer_fd(struct ion_buffer_info *ion_info)
+{
+	int buffd;
+	unsigned char *map_buf;
+	unsigned long map_len;
+
+	if (!ion_info) {
+		fprintf(stderr, "<%s>: Invalid ion info\n", __func__);
+		return -1;
+	}
+
+	map_len = ion_info->buflen;
+	buffd = ion_info->buffd;
+
+	if (buffd < 0 || map_len <= 0) {
+		fprintf(stderr, "<%s>: Invalid map data, fd: %d, len: %ld\n",
+			__func__, buffd, map_len);
+		goto err_buffd;
+	}
+
+	map_buf = (unsigned char *)mmap(NULL, map_len, PROT_READ|PROT_WRITE,
+			MAP_SHARED, buffd, 0);
+	if (map_buf == MAP_FAILED) {
+		printf("<%s>: Failed - mmap: %s\n",
+			__func__, strerror(errno));
+		goto err_mmap;
+	}
+
+	ion_info->buffer = map_buf;
+	ion_info->buflen = map_len;
+
+	return 0;
+
+err_mmap:
+	if (buffd)
+		close(buffd);
+
+err_buffd:
+	return -1;
+}
+
+void ion_close_buffer_fd(struct ion_buffer_info *ion_info)
+{
+	if (ion_info) {
+		/* unmap the buffer properly in the end */
+		munmap(ion_info->buffer, ion_info->buflen);
+		/* close the buffer fd */
+		if (ion_info->buffd > 0)
+			close(ion_info->buffd);
+		/* Finally, close the client fd */
+		if (ion_info->ionfd > 0)
+			close(ion_info->ionfd);
+	}
+}
+
+int socket_send_fd(struct socket_info *info)
+{
+	int status;
+	int fd, sockfd;
+	struct socketdata skdata;
+
+	if (!info) {
+		fprintf(stderr, "<%s>: Invalid socket info\n", __func__);
+		return -1;
+	}
+
+	sockfd = info->sockfd;
+	fd = info->datafd;
+	memset(&skdata, 0, sizeof(skdata));
+	skdata.data = fd;
+	skdata.len = sizeof(skdata.data);
+	status = sendtosocket(sockfd, &skdata);
+	if (status < 0) {
+		fprintf(stderr, "<%s>: Failed: sendtosocket\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int socket_receive_fd(struct socket_info *info)
+{
+	int status;
+	int fd, sockfd;
+	struct socketdata skdata;
+
+	if (!info) {
+		fprintf(stderr, "<%s>: Invalid socket info\n", __func__);
+		return -1;
+	}
+
+	sockfd = info->sockfd;
+	memset(&skdata, 0, sizeof(skdata));
+	status = receivefromsocket(sockfd, &skdata);
+	if (status < 0) {
+		fprintf(stderr, "<%s>: Failed: receivefromsocket\n", __func__);
+		return -1;
+	}
+
+	fd = (int)skdata.data;
+	info->datafd = fd;
+
+	return status;
+}
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ionutils.h b/marvell/linux/tools/testing/selftests/android/ion/ionutils.h
new file mode 100644
index 0000000..9941eb8
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ionutils.h
@@ -0,0 +1,55 @@
+#ifndef __ION_UTILS_H
+#define __ION_UTILS_H
+
+#include "ion.h"
+
+#define SOCKET_NAME "ion_socket"
+#define ION_DEVICE "/dev/ion"
+
+#define ION_BUFFER_LEN	4096
+#define MAX_HEAP_COUNT	ION_HEAP_TYPE_CUSTOM
+
+struct socket_info {
+	int sockfd;
+	int datafd;
+	unsigned long buflen;
+};
+
+struct ion_buffer_info {
+	int ionfd;
+	int buffd;
+	unsigned int heap_type;
+	unsigned int flag_type;
+	unsigned long heap_size;
+	unsigned long buflen;
+	unsigned char *buffer;
+};
+
+
+/* This is used to fill the data into the mapped buffer */
+void write_buffer(void *buffer, unsigned long len);
+
+/* This is used to read the data from the exported buffer */
+void read_buffer(void *buffer, unsigned long len);
+
+/* This is used to create an ION buffer FD for the kernel buffer
+ * So you can export this same buffer to others in the form of FD
+ */
+int ion_export_buffer_fd(struct ion_buffer_info *ion_info);
+
+/* This is used to import or map an exported FD.
+ * So we point to same buffer without making a copy. Hence zero-copy.
+ */
+int ion_import_buffer_fd(struct ion_buffer_info *ion_info);
+
+/* This is used to close all references for the ION client */
+void ion_close_buffer_fd(struct ion_buffer_info *ion_info);
+
+/* This is used to send FD to another process using socket IPC */
+int socket_send_fd(struct socket_info *skinfo);
+
+/* This is used to receive FD from another process using socket IPC */
+int socket_receive_fd(struct socket_info *skinfo);
+
+
+#endif
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ipcsocket.c b/marvell/linux/tools/testing/selftests/android/ion/ipcsocket.c
new file mode 100644
index 0000000..7dc5210
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ipcsocket.c
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#include "ipcsocket.h"
+
+
+int opensocket(int *sockfd, const char *name, int connecttype)
+{
+	int ret, temp = 1;
+
+	if (!name || strlen(name) > MAX_SOCK_NAME_LEN) {
+		fprintf(stderr, "<%s>: Invalid socket name.\n", __func__);
+		return -1;
+	}
+
+	ret = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (ret < 0) {
+		fprintf(stderr, "<%s>: Failed socket: <%s>\n",
+			__func__, strerror(errno));
+		return ret;
+	}
+
+	*sockfd = ret;
+	if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
+		(char *)&temp, sizeof(int)) < 0) {
+		fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n",
+		__func__, strerror(errno));
+		goto err;
+	}
+
+	sprintf(sock_name, "/tmp/%s", name);
+
+	if (connecttype == 1) {
+		/* This is for Server connection */
+		struct sockaddr_un skaddr;
+		int clientfd;
+		socklen_t sklen;
+
+		unlink(sock_name);
+		memset(&skaddr, 0, sizeof(skaddr));
+		skaddr.sun_family = AF_LOCAL;
+		strcpy(skaddr.sun_path, sock_name);
+
+		ret = bind(*sockfd, (struct sockaddr *)&skaddr,
+			SUN_LEN(&skaddr));
+		if (ret < 0) {
+			fprintf(stderr, "<%s>: Failed bind: <%s>\n",
+			__func__, strerror(errno));
+			goto err;
+		}
+
+		ret = listen(*sockfd, 5);
+		if (ret < 0) {
+			fprintf(stderr, "<%s>: Failed listen: <%s>\n",
+			__func__, strerror(errno));
+			goto err;
+		}
+
+		memset(&skaddr, 0, sizeof(skaddr));
+		sklen = sizeof(skaddr);
+
+		ret = accept(*sockfd, (struct sockaddr *)&skaddr,
+			(socklen_t *)&sklen);
+		if (ret < 0) {
+			fprintf(stderr, "<%s>: Failed accept: <%s>\n",
+			__func__, strerror(errno));
+			goto err;
+		}
+
+		clientfd = ret;
+		*sockfd = clientfd;
+	} else {
+		/* This is for client connection */
+		struct sockaddr_un skaddr;
+
+		memset(&skaddr, 0, sizeof(skaddr));
+		skaddr.sun_family = AF_LOCAL;
+		strcpy(skaddr.sun_path, sock_name);
+
+		ret = connect(*sockfd, (struct sockaddr *)&skaddr,
+			SUN_LEN(&skaddr));
+		if (ret < 0) {
+			fprintf(stderr, "<%s>: Failed connect: <%s>\n",
+			__func__, strerror(errno));
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	if (*sockfd)
+		close(*sockfd);
+
+	return ret;
+}
+
+int sendtosocket(int sockfd, struct socketdata *skdata)
+{
+	int ret, buffd;
+	unsigned int len;
+	char cmsg_b[CMSG_SPACE(sizeof(int))];
+	struct cmsghdr *cmsg;
+	struct msghdr msgh;
+	struct iovec iov;
+	struct timeval timeout;
+	fd_set selFDs;
+
+	if (!skdata) {
+		fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
+		return -1;
+	}
+
+	FD_ZERO(&selFDs);
+	FD_SET(0, &selFDs);
+	FD_SET(sockfd, &selFDs);
+	timeout.tv_sec = 20;
+	timeout.tv_usec = 0;
+
+	ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout);
+	if (ret < 0) {
+		fprintf(stderr, "<%s>: Failed select: <%s>\n",
+		__func__, strerror(errno));
+		return -1;
+	}
+
+	if (FD_ISSET(sockfd, &selFDs)) {
+		buffd = skdata->data;
+		len = skdata->len;
+		memset(&msgh, 0, sizeof(msgh));
+		msgh.msg_control = &cmsg_b;
+		msgh.msg_controllen = CMSG_LEN(len);
+		iov.iov_base = "OK";
+		iov.iov_len = 2;
+		msgh.msg_iov = &iov;
+		msgh.msg_iovlen = 1;
+		cmsg = CMSG_FIRSTHDR(&msgh);
+		cmsg->cmsg_level = SOL_SOCKET;
+		cmsg->cmsg_type = SCM_RIGHTS;
+		cmsg->cmsg_len = CMSG_LEN(len);
+		memcpy(CMSG_DATA(cmsg), &buffd, len);
+
+		ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT);
+		if (ret < 0) {
+			fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n",
+			__func__, strerror(errno));
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int receivefromsocket(int sockfd, struct socketdata *skdata)
+{
+	int ret, buffd;
+	unsigned int len = 0;
+	char cmsg_b[CMSG_SPACE(sizeof(int))];
+	struct cmsghdr *cmsg;
+	struct msghdr msgh;
+	struct iovec iov;
+	fd_set recvFDs;
+	char data[32];
+
+	if (!skdata) {
+		fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
+		return -1;
+	}
+
+	FD_ZERO(&recvFDs);
+	FD_SET(0, &recvFDs);
+	FD_SET(sockfd, &recvFDs);
+
+	ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "<%s>: Failed select: <%s>\n",
+		__func__, strerror(errno));
+		return -1;
+	}
+
+	if (FD_ISSET(sockfd, &recvFDs)) {
+		len = sizeof(buffd);
+		memset(&msgh, 0, sizeof(msgh));
+		msgh.msg_control = &cmsg_b;
+		msgh.msg_controllen = CMSG_LEN(len);
+		iov.iov_base = data;
+		iov.iov_len = sizeof(data)-1;
+		msgh.msg_iov = &iov;
+		msgh.msg_iovlen = 1;
+		cmsg = CMSG_FIRSTHDR(&msgh);
+		cmsg->cmsg_level = SOL_SOCKET;
+		cmsg->cmsg_type = SCM_RIGHTS;
+		cmsg->cmsg_len = CMSG_LEN(len);
+
+		ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT);
+		if (ret < 0) {
+			fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n",
+			__func__, strerror(errno));
+			return -1;
+		}
+
+		memcpy(&buffd, CMSG_DATA(cmsg), len);
+		skdata->data = buffd;
+		skdata->len = len;
+	}
+	return 0;
+}
+
+int closesocket(int sockfd, char *name)
+{
+	char sockname[MAX_SOCK_NAME_LEN];
+
+	if (sockfd)
+		close(sockfd);
+	sprintf(sockname, "/tmp/%s", name);
+	unlink(sockname);
+	shutdown(sockfd, 2);
+
+	return 0;
+}
diff --git a/marvell/linux/tools/testing/selftests/android/ion/ipcsocket.h b/marvell/linux/tools/testing/selftests/android/ion/ipcsocket.h
new file mode 100644
index 0000000..b3e8449
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/ion/ipcsocket.h
@@ -0,0 +1,35 @@
+
+#ifndef _IPCSOCKET_H
+#define _IPCSOCKET_H
+
+
+#define MAX_SOCK_NAME_LEN	64
+
+char sock_name[MAX_SOCK_NAME_LEN];
+
+/* This structure is responsible for holding the IPC data
+ * data: hold the buffer fd
+ * len: just the length of 32-bit integer fd
+ */
+struct socketdata {
+	int data;
+	unsigned int len;
+};
+
+/* This API is used to open the IPC socket connection
+ * name: implies a unique socket name in the system
+ * connecttype: implies server(0) or client(1)
+ */
+int opensocket(int *sockfd, const char *name, int connecttype);
+
+/* This is the API to send socket data over IPC socket */
+int sendtosocket(int sockfd, struct socketdata *data);
+
+/* This is the API to receive socket data over IPC socket */
+int receivefromsocket(int sockfd, struct socketdata *data);
+
+/* This is the API to close the socket connection */
+int closesocket(int sockfd, char *name);
+
+
+#endif
diff --git a/marvell/linux/tools/testing/selftests/android/run.sh b/marvell/linux/tools/testing/selftests/android/run.sh
new file mode 100755
index 0000000..dd8edf2
--- /dev/null
+++ b/marvell/linux/tools/testing/selftests/android/run.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+(cd ion; ./ion_test.sh)