Merge "lib: zlib_inflate: Fix decompress function bugs"
diff --git a/AndroidBoot.mk b/AndroidBoot.mk
index 06647a9..b158dec 100644
--- a/AndroidBoot.mk
+++ b/AndroidBoot.mk
@@ -25,7 +25,10 @@
 
 ifneq ($(TARGET_BUILD_VARIANT),user)
   DEVICE_STATUS := DEFAULT_UNLOCK=true
-  USER_BUILD_VARIANT=true
+endif
+
+ifeq ($(TARGET_BUILD_VARIANT),user)
+  BUILD_VARIANT := USER_BUILD_VARIANT=true
 endif
 
 ifeq ($(TARGET_BOARD_PLATFORM),msm8660)
@@ -42,7 +45,7 @@
 # ELF binary for ABOOT
 TARGET_ABOOT_ELF := $(PRODUCT_OUT)/aboot.elf
 $(TARGET_ABOOT_ELF): ABOOT_CLEAN | $(ABOOT_OUT)
-	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(ABOOT_OUT) $(BOOTLOADER_PLATFORM) $(EMMC_BOOT) $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS)
+	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(ABOOT_OUT) $(BOOTLOADER_PLATFORM) $(EMMC_BOOT) $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS) $(BUILD_VARIANT)
 
 # NAND variant output
 TARGET_NAND_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
@@ -71,7 +74,7 @@
 
 # Top level for eMMC variant targets
 $(TARGET_EMMC_BOOTLOADER): emmc_appsbootldr_clean | $(EMMC_BOOTLOADER_OUT) $(INSTALLED_KEYSTOREIMAGE_TARGET)
-	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS)
+	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS) $(BUILD_VARIANT)
 
 # Keep build NAND & eMMC as default for targets still using TARGET_BOOTLOADER
 TARGET_BOOTLOADER := $(PRODUCT_OUT)/EMMCBOOT.MBN
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 0bae069..1498e98 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -57,6 +57,7 @@
 #include <boot_device.h>
 #include <boot_verifier.h>
 #include <image_verify.h>
+#include <decompress.h>
 #if USE_RPMB_FOR_DEVINFO
 #include <rpmb.h>
 #endif
@@ -142,6 +143,7 @@
 static const char *battchg_pause = " androidboot.mode=charger";
 static const char *auth_kernel = " androidboot.authorized_kernel=true";
 static const char *secondary_gpt_enable = " gpt";
+static const char *mdtp_activated_flag = " mdtp";
 
 static const char *baseband_apq     = " androidboot.baseband=apq";
 static const char *baseband_msm     = " androidboot.baseband=msm";
@@ -161,6 +163,7 @@
 static bool boot_into_ffbm;
 static char target_boot_params[64];
 static bool boot_reason_alarm;
+static bool devinfo_present = true;
 
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
@@ -246,6 +249,10 @@
 	bool gpt_exists = partition_gpt_exists();
 	int have_target_boot_params = 0;
 	char *boot_dev_buf = NULL;
+    bool is_mdtp_activated = 0;
+#ifdef MDTP_SUPPORT
+    mdtp_activated(&is_mdtp_activated);
+#endif /* MDTP_SUPPORT */
 
 	if (cmdline && cmdline[0]) {
 		cmdline_len = strlen(cmdline);
@@ -267,6 +274,9 @@
 	if (boot_into_recovery && gpt_exists)
 		cmdline_len += strlen(secondary_gpt_enable);
 
+	if(is_mdtp_activated)
+		cmdline_len += strlen(mdtp_activated_flag);
+
 	if (boot_into_ffbm) {
 		cmdline_len += strlen(androidboot_mode);
 		cmdline_len += strlen(ffbm_mode_string);
@@ -395,6 +405,12 @@
 			while ((*dst++ = *src++));
 		}
 
+		if (is_mdtp_activated) {
+			src = mdtp_activated_flag;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
 		if (boot_into_ffbm) {
 			src = androidboot_mode;
 			if (have_cmdline) --dst;
@@ -629,7 +645,7 @@
 
 #if VERIFIED_BOOT
 	/* Write protect the device info */
-	if (target_build_variant_user() && mmc_write_protect("devinfo", 1))
+	if (target_build_variant_user() && devinfo_present && mmc_write_protect("devinfo", 1))
 	{
 		dprintf(INFO, "Failed to write protect dev info\n");
 		ASSERT(0);
@@ -858,6 +874,14 @@
 	unsigned imagesize_actual;
 	unsigned second_actual = 0;
 
+	unsigned int out_len = 0;
+	unsigned int out_avai_len = 0;
+	unsigned char *out_addr = NULL;
+	uint32_t dtb_offset = 0;
+	unsigned char *kernel_start_addr = NULL;
+	unsigned int kernel_size = 0;
+	int rc;
+
 #if DEVICE_TREE
 	struct dt_table *table;
 	struct dt_entry dt_entry;
@@ -865,8 +889,7 @@
 	uint32_t dt_actual;
 	uint32_t dt_hdr_size;
 #endif
-	BUF_DMA_ALIGN(kbuf, BOOT_IMG_MAX_PAGE_SIZE);
-	struct kernel64_hdr *kptr = (void*) kbuf;
+	struct kernel64_hdr *kptr = NULL;
 
 	if (check_format_bit())
 		boot_into_recovery = 1;
@@ -927,45 +950,50 @@
 		page_mask = page_size - 1;
 	}
 
-	/* Read the next page to get kernel Image header
-	 * which lives in the second page for arm64 targets.
-	 */
-
-	if (mmc_read(ptn + page_size, (uint32_t *) kbuf, page_size)) {
-		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
-                return -1;
-	}
-
-	/*
-	 * Update the kernel/ramdisk/tags address if the boot image header
-	 * has default values, these default values come from mkbootimg when
-	 * the boot image is flashed using fastboot flash:raw
-	 */
-	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
-
-	/* Get virtual addresses since the hdr saves physical addresses. */
-	hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
-	hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
-	hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
-
 	kernel_actual  = ROUND_TO_PAGE(hdr->kernel_size,  page_mask);
 	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
 
-	/* Check if the addresses in the header are valid. */
-	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
-		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	image_addr = (unsigned char *)target_get_scratch_address();
+
+#if DEVICE_TREE
+	dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
+	imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+#else
+	imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
+#endif
+
+#if VERIFIED_BOOT
+	boot_verifier_init();
+#endif
+
+	if (check_aboot_addr_range_overlap((uint32_t) image_addr, imagesize_actual))
 	{
-		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
 		return -1;
 	}
 
-#ifndef DEVICE_TREE
-	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	/*
+	 * Update loading flow of bootimage to support compressed/uncompressed
+	 * bootimage on both 64bit and 32bit platform.
+	 * 1. Load bootimage from emmc partition onto DDR.
+	 * 2. Check if bootimage is gzip format. If yes, decompress compressed kernel
+	 * 3. Check kernel header and update kernel load addr for 64bit and 32bit
+	 *    platform accordingly.
+	 * 4. Sanity Check on kernel_addr and ramdisk_addr and copy data.
+	 */
+
+	dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
+	bs_set_timestamp(BS_KERNEL_LOAD_START);
+
+	/* Read image without signature */
+	if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
 	{
-		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
 		return -1;
 	}
-#endif
+
+	dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
+	bs_set_timestamp(BS_KERNEL_LOAD_DONE);
 
 	/* Authenticate Kernel */
 	dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
@@ -973,51 +1001,9 @@
 		device.is_unlocked,
 		device.is_tampered);
 
-#if VERIFIED_BOOT
-	boot_verifier_init();
-#endif
-
 	if(target_use_signed_kernel() && (!device.is_unlocked))
 	{
-		offset = 0;
-
-		image_addr = (unsigned char *)target_get_scratch_address();
-
-#if DEVICE_TREE
-		dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
-
-		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
-		{
-			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-			return -1;
-		}
-#else
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
-
-#endif
-
-		dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_START);
-
-		if (check_aboot_addr_range_overlap((uint32_t)image_addr, imagesize_actual))
-		{
-			dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
-			return -1;
-		}
-
-		/* Read image without signature */
-		if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
-		{
-			dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
-				return -1;
-		}
-
-		dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
-
 		offset = imagesize_actual;
-
 		if (check_aboot_addr_range_overlap((uint32_t)image_addr + offset, page_size))
 		{
 			dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
@@ -1032,147 +1018,120 @@
 		}
 
 		verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
-
-		/* Move kernel, ramdisk and device tree to correct address */
-		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
-		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
-
-		#if DEVICE_TREE
-		if(hdr->dt_size) {
-			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
-			table = (struct dt_table*) dt_table_offset;
-
-			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
-				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
-				return -1;
-			}
-
-			/* Find index of device tree within device tree table */
-			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
-				dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
-				return -1;
-			}
-
-			/* Validate and Read device device tree in the "tags_add */
-			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
-			{
-				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-				return -1;
-			}
-
-			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
-		} else {
-			/*
-			 * If appended dev tree is found, update the atags with
-			 * memory address to the DTB appended location on RAM.
-			 * Else update with the atags address in the kernel header
-			 */
-			void *dtb;
-			dtb = dev_tree_appended((void*) hdr->kernel_addr,
-						hdr->kernel_size,
-						(void *)hdr->tags_addr);
-			if (!dtb) {
-				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
-				return -1;
-			}
-		}
-		#endif
-	}
-	else
-	{
+	} else {
 		second_actual  = ROUND_TO_PAGE(hdr->second_size,  page_mask);
+		#ifdef TZ_SAVE_KERNEL_HASH
+		aboot_save_boot_hash_mmc((uint32_t) image_addr, imagesize_actual);
+		#endif /* TZ_SAVE_KERNEL_HASH */
+	}
 
-		image_addr = (unsigned char *)target_get_scratch_address();
-#if DEVICE_TREE
-		dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+	/*
+	 * Check if the kernel image is a gzip package. If yes, need to decompress it.
+	 * If not, continue booting.
+	 */
+	if (is_gzip_package((unsigned char *)(image_addr + page_size), hdr->kernel_size))
+	{
+		out_addr = (unsigned char *)(image_addr + imagesize_actual + page_size);
+		out_avai_len = target_get_max_flash_size() - imagesize_actual - page_size;
+		dprintf(INFO, "decompress image start\n");
+		rc = decompress((unsigned char *)(image_addr + page_size),
+				hdr->kernel_size, out_addr, out_avai_len,
+				&dtb_offset, &out_len);
+		if (rc)
+		{
+			dprintf(INFO, "decompress image failed!!!\n");
+			ASSERT(0);
+		}
 
-		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
+		dprintf(INFO, "decompressed image finished.\n");
+		kptr = (struct kernel64_hdr *)out_addr;
+		kernel_start_addr = out_addr;
+		kernel_size = out_len;
+	} else {
+		kptr = (struct kernel64_hdr *)(image_addr + page_size);
+		kernel_start_addr = (unsigned char *)(image_addr + page_size);
+		kernel_size = hdr->kernel_size;
+	}
+
+	/*
+	 * Update the kernel/ramdisk/tags address if the boot image header
+	 * has default values, these default values come from mkbootimg when
+	 * the boot image is flashed using fastboot flash:raw
+	 */
+	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
+
+	/* Get virtual addresses since the hdr saves physical addresses. */
+	hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
+	hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
+	hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
+
+	kernel_size = ROUND_TO_PAGE(kernel_size,  page_mask);
+	/* Check if the addresses in the header are valid. */
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
+		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	{
+		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+
+#ifndef DEVICE_TREE
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+#endif
+
+	/* Move kernel, ramdisk and device tree to correct address */
+	memmove((void*) hdr->kernel_addr, kernel_start_addr, kernel_size);
+	memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+
+	#if DEVICE_TREE
+	if(hdr->dt_size) {
+		dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
+		table = (struct dt_table*) dt_table_offset;
+
+		if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
+			dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
+			return -1;
+		}
+
+		/* Find index of device tree within device tree table */
+		if(dev_tree_get_entry_info(table, &dt_entry) != 0){
+			dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
+			return -1;
+		}
+
+		/* Validate and Read device device tree in the tags_addr */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
 		{
 			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
 			return -1;
 		}
-#else
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
 
-#endif
-		if (check_aboot_addr_range_overlap((uint32_t) image_addr, imagesize_actual))
+		memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
+	} else {
+		/* Validate the tags_addr */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
 		{
-			dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
+			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
 			return -1;
 		}
-
-		dprintf(INFO, "Loading boot image (%d): start\n",
-				imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_START);
-
-		offset = 0;
-
-		/* Load the entire boot image */
-		if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual)) {
-			dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
-					return -1;
+		/*
+		 * If appended dev tree is found, update the atags with
+		 * memory address to the DTB appended location on RAM.
+		 * Else update with the atags address in the kernel header
+		 */
+		void *dtb;
+		dtb = dev_tree_appended((void*)(image_addr + page_size),
+					hdr->kernel_size, dtb_offset,
+					(void *)hdr->tags_addr);
+		if (!dtb) {
+			dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+			return -1;
 		}
-
-		dprintf(INFO, "Loading boot image (%d): done\n",
-				imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
-
-		#ifdef TZ_SAVE_KERNEL_HASH
-		aboot_save_boot_hash_mmc((uint32_t) image_addr, imagesize_actual);
-		#endif /* TZ_SAVE_KERNEL_HASH */
-
-		/* Move kernel, ramdisk and device tree to correct address */
-		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
-		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
-
-		#if DEVICE_TREE
-		if(hdr->dt_size) {
-			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
-			table = (struct dt_table*) dt_table_offset;
-
-			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
-				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
-				return -1;
-			}
-
-			/* Find index of device tree within device tree table */
-			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
-				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
-				return -1;
-			}
-
-			/* Validate and Read device device tree in the tags_addr */
-			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
-			{
-				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-				return -1;
-			}
-
-			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
-		} else {
-			/* Validate the tags_addr */
-			if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
-			{
-				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-				return -1;
-			}
-			/*
-			 * If appended dev tree is found, update the atags with
-			 * memory address to the DTB appended location on RAM.
-			 * Else update with the atags address in the kernel header
-			 */
-			void *dtb;
-			dtb = dev_tree_appended((void*) hdr->kernel_addr,
-						kernel_actual,
-						(void *)hdr->tags_addr);
-			if (!dtb) {
-				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
-				return -1;
-			}
-		}
-		#endif
 	}
+	#endif
 
 	if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
 		target_load_ssd_keystore();
@@ -1328,8 +1287,8 @@
 		verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
 
 		/* Move kernel and ramdisk to correct address */
-		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
-		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+		memmove((void*) hdr->kernel_addr, (char*) (image_addr + page_size), hdr->kernel_size);
+		memmove((void*) hdr->ramdisk_addr, (char*) (image_addr + page_size + kernel_actual), hdr->ramdisk_size);
 #if DEVICE_TREE
 		/* Validate and Read device device tree in the "tags_add */
 		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
@@ -1449,18 +1408,16 @@
 void write_device_info_mmc(device_info *dev)
 {
 	unsigned long long ptn = 0;
-#if !VERIFIED_BOOT
 	unsigned long long size;
-#endif
 	int index = INVALID_PTN;
 	uint32_t blocksize;
 	uint8_t lun = 0;
+	uint32_t ret = 0;
 
-#if VERIFIED_BOOT
-	index = partition_get_index("devinfo");
-#else
-	index = partition_get_index("aboot");
-#endif
+	if (devinfo_present)
+		index = partition_get_index("devinfo");
+	else
+		index = partition_get_index("aboot");
 
 	ptn = partition_get_offset(index);
 	if(ptn == 0)
@@ -1471,17 +1428,15 @@
 	lun = partition_get_lun(index);
 	mmc_set_lun(lun);
 
-#if !VERIFIED_BOOT
 	size = partition_get_size(index);
-#endif
 
 	blocksize = mmc_get_device_blocksize();
 
-#if VERIFIED_BOOT
-	if(mmc_write(ptn, blocksize, (void *)dev))
-#else
-	if(mmc_write((ptn + size - blocksize), blocksize, (void *)dev))
-#endif
+	if (devinfo_present)
+		ret = mmc_write(ptn, blocksize, (void *)info_buf);
+	else
+		ret = mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf);
+	if (ret)
 	{
 		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
 		return;
@@ -1491,17 +1446,16 @@
 void read_device_info_mmc(struct device_info *info)
 {
 	unsigned long long ptn = 0;
-#if !VERIFIED_BOOT
 	unsigned long long size;
-#endif
 	int index = INVALID_PTN;
 	uint32_t blocksize;
+	uint32_t ret  = 0;
 
-#if VERIFIED_BOOT
-	index = partition_get_index("devinfo");
-#else
-	index = partition_get_index("aboot");
-#endif
+	if ((index = partition_get_index("devinfo")) < 0)
+	{
+		devinfo_present = false;
+		index = partition_get_index("aboot");
+	}
 
 	ptn = partition_get_offset(index);
 	if(ptn == 0)
@@ -1511,17 +1465,15 @@
 
 	mmc_set_lun(partition_get_lun(index));
 
-#if !VERIFIED_BOOT
 	size = partition_get_size(index);
-#endif
 
 	blocksize = mmc_get_device_blocksize();
 
-#if VERIFIED_BOOT
-	if(mmc_read(ptn, (void *)info, blocksize))
-#else
-	if(mmc_read((ptn + size - blocksize), (void *)info, blocksize))
-#endif
+	if (devinfo_present)
+		ret = mmc_read(ptn, (void *)info_buf, blocksize);
+	else
+		ret = mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize);
+	if (ret)
 	{
 		dprintf(CRITICAL, "ERROR: Cannot read device info\n");
 		return;
@@ -1674,7 +1626,6 @@
 	struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
 
 	if(hdr->dt_size != 0) {
-
 		/* add kernel offset */
 		dt_image_offset += page_size;
 		n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
@@ -1729,11 +1680,18 @@
 	uint32_t image_actual;
 	uint32_t dt_actual = 0;
 	uint32_t sig_actual = SIGNATURE_SIZE;
-	struct boot_img_hdr *hdr;
-	struct kernel64_hdr *kptr;
+	struct boot_img_hdr *hdr = NULL;
+	struct kernel64_hdr *kptr = NULL;
 	char *ptr = ((char*) data);
 	int ret = 0;
 	uint8_t dtb_copied = 0;
+	unsigned int out_len = 0;
+	unsigned int out_avai_len = 0;
+	unsigned char *out_addr = NULL;
+	uint32_t dtb_offset = 0;
+	unsigned char *kernel_start_addr = NULL;
+	unsigned int kernel_size = 0;
+
 
 #ifdef MDTP_SUPPORT
 	/* Go through Firmware Lock verification before continue with boot process */
@@ -1793,11 +1751,39 @@
 		verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
 
 	/*
+	 * Check if the kernel image is a gzip package. If yes, need to decompress it.
+	 * If not, continue booting.
+	 */
+	if (is_gzip_package((unsigned char *)(data + page_size), hdr->kernel_size))
+	{
+		out_addr = (unsigned char *)target_get_scratch_address();
+		out_addr = (unsigned char *)(out_addr + image_actual + page_size);
+		out_avai_len = target_get_max_flash_size() - image_actual - page_size;
+		dprintf(INFO, "decompress image start\n");
+		ret = decompress((unsigned char *)(ptr + page_size),
+				hdr->kernel_size, out_addr, out_avai_len,
+				&dtb_offset, &out_len);
+		if (ret)
+		{
+			dprintf(INFO, "decompress image failed!!!\n");
+			ASSERT(0);
+		}
+
+		dprintf(INFO, "decompressed image finished.\n");
+		kptr = (struct kernel64_hdr *)out_addr;
+		kernel_start_addr = out_addr;
+		kernel_size = out_len;
+	} else {
+		kptr = (struct kernel64_hdr*)((char *)data + page_size);
+		kernel_start_addr = (unsigned char *)((char *)data + page_size);
+		kernel_size = hdr->kernel_size;
+	}
+
+	/*
 	 * Update the kernel/ramdisk/tags address if the boot image header
 	 * has default values, these default values come from mkbootimg when
 	 * the boot image is flashed using fastboot flash:raw
 	 */
-	kptr = (struct kernel64_hdr*)((char*) data + page_size);
 	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
 
 	/* Get virtual addresses since the hdr saves physical addresses. */
@@ -1805,8 +1791,9 @@
 	hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
 	hdr->tags_addr = VA(hdr->tags_addr);
 
+	kernel_size  = ROUND_TO_PAGE(kernel_size,  page_mask);
 	/* Check if the addresses in the header are valid. */
-	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
 		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
 	{
 		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
@@ -1828,9 +1815,15 @@
 
 	/* Load ramdisk & kernel */
 	memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
-	memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
+	memmove((void*) hdr->kernel_addr, (char*) (kernel_start_addr), kernel_size);
 
 #if DEVICE_TREE
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return;
+	}
+
 	/*
 	 * If dtb is not found look for appended DTB in the kernel.
 	 * If appended dev tree is found, update the atags with
@@ -1839,7 +1832,8 @@
 	 */
 	if (!dtb_copied) {
 		void *dtb;
-		dtb = dev_tree_appended((void *)hdr->kernel_addr, hdr->kernel_size,
+		dtb = dev_tree_appended((void*)(ptr + page_size),
+					hdr->kernel_size, dtb_offset,
 					(void *)hdr->tags_addr);
 		if (!dtb) {
 			fastboot_fail("dtb not found");
@@ -1848,14 +1842,6 @@
 	}
 #endif
 
-#ifndef DEVICE_TREE
-	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
-	{
-		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
-		return;
-	}
-#endif
-
 	fastboot_okay("");
 	fastboot_stop();
 
diff --git a/app/aboot/mdtp.c b/app/aboot/mdtp.c
index 9ae9890..160f6c8 100644
--- a/app/aboot/mdtp.c
+++ b/app/aboot/mdtp.c
@@ -47,6 +47,7 @@
 static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified);
 static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip);
 
+static int is_mdtp_activated = -1;
 /********************************************************************************/
 
 /* Read the DIP from EMMC */
@@ -417,6 +418,7 @@
 			dprintf(CRITICAL, "mdtp: verify_all_partitions: Failed partition verification\n");
 			return 0;
 		}
+		is_mdtp_activated = 1;
 
 	}
 
@@ -512,6 +514,9 @@
 	int ret;
 	bool enabled;
 
+	/* sets the default value of this global to be MDTP not activated */
+	is_mdtp_activated = 0;
+
 	ret = mdtp_fuse_get_enabled(&enabled);
 	if(ret)
 	{
@@ -527,6 +532,18 @@
 
 	return 0;
 }
+/********************************************************************************/
+
+/** Indicates whether the MDTP is currently in ACTIVATED state **/
+int mdtp_activated(bool * activated){
+	if(is_mdtp_activated < 0){
+		/* mdtp_fwlock_verify_lock was not called before, the value is not valid */
+		return is_mdtp_activated;
+	}
+
+	*activated = is_mdtp_activated;
+	return 0;
+}
 
 /********************************************************************************/
 
diff --git a/app/aboot/mdtp.h b/app/aboot/mdtp.h
index d40807a..865c791 100644
--- a/app/aboot/mdtp.h
+++ b/app/aboot/mdtp.h
@@ -163,4 +163,16 @@
  */
 void display_error_msg();
 
+/**
+ * mdtp_activated
+ *
+ * Indicates whether the MDTP is currently in ACTIVATED state.
+ * You must call this function only after calling to mdtp_fwlock_verify_lock();
+ *
+ * @param[out] activated: MDTP is in ACTIVATED state (TRUE/FALSE).
+ *
+ * @return - negative value for an error, 0 for success.
+ */
+int mdtp_activated(bool * activated);
+
 #endif
diff --git a/app/aboot/mdtp_fuse.c b/app/aboot/mdtp_fuse.c
index c4abd19..1487057 100644
--- a/app/aboot/mdtp_fuse.c
+++ b/app/aboot/mdtp_fuse.c
@@ -41,6 +41,8 @@
 #define MAX_METADATA_SIZE       (0x1000)
 #define QFPROM_ADDR_SPACE_RAW   (0)
 
+char metadata_block[MAX_METADATA_SIZE] = {0};
+
 /********************************************************************************/
 
 typedef union
@@ -116,7 +118,6 @@
 {
 	unsigned long long ptn = 0;
 	uint32_t actual_size;
-	char metadata_block[MAX_METADATA_SIZE];
 	int index = INVALID_PTN;
 	uint32_t block_size = mmc_get_device_blocksize();
 
@@ -128,21 +129,21 @@
 		return -1;
 	}
 
-	if (sizeof(metadata_t) > MAX_METADATA_SIZE)
+	actual_size = ROUNDUP(sizeof(metadata_t), block_size);
+
+	if (actual_size > MAX_METADATA_SIZE)
 	{
-		dprintf(CRITICAL, "mdtp: read_metadata: ERROR, meta data size %d too big\n", sizeof(metadata_t));
+		dprintf(CRITICAL, "mdtp: read_metadata: ERROR, meta data size %d too big\n", actual_size);
 		return -1;
 	}
 
-	actual_size = ROUNDUP(MAX_METADATA_SIZE, block_size);
-
 	if(mmc_read(ptn, (void *)metadata_block, actual_size))
 	{
 		dprintf(CRITICAL, "mdtp: read_metadata: ERROR, cannot read mdtp info\n");
 		return -1;
 	}
 
-	memcpy(metadata, metadata_block, sizeof(metadata_t));
+	memscpy((uint8_t*)metadata, sizeof(metadata_t), (uint8_t*)(&(metadata_block[0])), MAX_METADATA_SIZE);
 
 	dprintf(INFO, "mdtp: read_metadata: SUCCESS, read %d bytes\n", actual_size);
 
diff --git a/app/aboot/rules.mk b/app/aboot/rules.mk
index 95a8865..7774788 100644
--- a/app/aboot/rules.mk
+++ b/app/aboot/rules.mk
@@ -1,9 +1,11 @@
 LOCAL_DIR := $(GET_LOCAL_DIR)
 
-INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include
+INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include -I$(LK_TOP_DIR)/lib/zlib_inflate
 
 DEFINES += ASSERT_ON_TAMPER=1
 
+MODULES += lib/zlib_inflate
+
 OBJS += \
 	$(LOCAL_DIR)/aboot.o \
 	$(LOCAL_DIR)/fastboot.o \
diff --git a/dev/gcdb/display/include/panel_r61318_hd_video.h b/dev/gcdb/display/include/panel_r61318_hd_video.h
index 7662312..5ac2c74 100644
--- a/dev/gcdb/display/include/panel_r61318_hd_video.h
+++ b/dev/gcdb/display/include/panel_r61318_hd_video.h
@@ -172,7 +172,7 @@
 
 static char r61318_hd_video_on_cmd17[] = {
 	0x02, 0x00, 0x29, 0xC0,
-	0xD4, 0x50, 0xFF, 0xFF,
+	0xD4, 0x4D, 0xFF, 0xFF,
 };
 
 static char r61318_hd_video_on_cmd18[] = {
diff --git a/dev/pmic/pm8x41/pm8x41.c b/dev/pmic/pm8x41/pm8x41.c
index 1784534..baf7b24 100644
--- a/dev/pmic/pm8x41/pm8x41.c
+++ b/dev/pmic/pm8x41/pm8x41.c
@@ -33,7 +33,7 @@
 #include <string.h>
 #include <pm8x41_hw.h>
 #include <pm8x41.h>
-#include <rpm-smd.h>
+#include <rpm-ipc.h>
 #include <regulator.h>
 #include <platform/timer.h>
 
diff --git a/makefile b/makefile
index 252903e..1e818a8 100644
--- a/makefile
+++ b/makefile
@@ -105,6 +105,10 @@
   endif
 endif
 
+ifeq ($(USER_BUILD_VARIANT),true)
+  DEFINES += USER_BUILD_VARIANT=1
+endif
+
 # these need to be filled out by the project/target/platform rules.mk files
 TARGET :=
 PLATFORM :=
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 0abf723..27296b4 100755
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -414,7 +414,7 @@
  * Return Value: DTB address : If appended device tree is found
  *               'NULL'         : Otherwise
  */
-void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags)
+void *dev_tree_appended(void *kernel, uint32_t kernel_size, uint32_t dtb_offset, void *tags)
 {
 	void *kernel_end = kernel + kernel_size;
 	uint32_t app_dtb_offset = 0;
@@ -437,8 +437,10 @@
 	}
 	list_initialize(&dt_entry_queue->node);
 
-
-	memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
+	if (dtb_offset)
+		app_dtb_offset = dtb_offset;
+	else
+		memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
 
 	if (((uintptr_t)kernel + (uintptr_t)app_dtb_offset) < (uintptr_t)kernel) {
 		return NULL;
diff --git a/platform/msm_shared/glink/glink_api.c b/platform/msm_shared/glink/glink_api.c
new file mode 100644
index 0000000..24f777d
--- /dev/null
+++ b/platform/msm_shared/glink/glink_api.c
@@ -0,0 +1,1532 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include <glink.h>
+#include <glink_rpm.h>
+#include <glink_os_utils.h>
+#include <glink_internal.h>
+#include <glink_vector.h>
+#include <glink_channel_migration.h>
+#include <smem_list.h>
+#include <smem_type.h>
+
+#define GLINK_NOT_INITIALIZED 0
+#define GLINK_INITIALIZED     1
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+int glink_core_status = GLINK_NOT_INITIALIZED;
+
+os_cs_type *glink_transport_q_cs;
+os_cs_type *glink_mem_log_cs;
+
+glink_mem_log_entry_type glink_mem_log_arr[GLINK_MEM_LOG_SIZE];
+uint32 glink_mem_log_idx = 0;
+
+/* Keep a list of registered transport for each edge allowed for this host */
+smem_list_type glink_registered_transports[GLINK_NUM_HOSTS];
+
+smem_list_type glink_link_notif_list;
+
+/* List of supported hosts */
+const char* glink_hosts_supported[]   = { "apss",
+                                          "mpss",
+                                          "lpass",
+                                          "dsps",
+                                          "wcnss",
+                                          "tz",
+                                          "rpm",
+                                        };
+
+/* Forward function declarations */
+void glinki_free_intents(glink_channel_ctx_type *open_ch_ctx);
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+glink_err_type glinki_add_ch_to_xport
+(
+  glink_transport_if_type  *if_ptr,
+  glink_transport_if_type  *req_if_ptr,
+  glink_channel_ctx_type   *ch_ctx,
+  glink_channel_ctx_type   **allocated_ch_ctx,
+  unsigned int              local_open,
+  boolean                      migration_state,
+  glink_xport_priority      migrated_ch_prio
+)
+{
+  glink_err_type             status = 0;
+  glink_channel_ctx_type     *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx = if_ptr->glink_core_priv;
+
+  /* See if channel already exists in open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if (strcmp(open_ch_ctx->name, ch_ctx->name) == 0)
+    {
+      /* We've found a channel name is already in the list of open channel */
+      /* increase reference open count for channel */
+      *allocated_ch_ctx = open_ch_ctx;
+      open_ch_ctx->ref_count++;
+
+      /* Case A: Channel was opened before on the same host */
+      if((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) && local_open) {
+
+        open_ch_ctx->req_if_ptr = req_if_ptr;
+
+        /* Copy local open ctx params */
+        open_ch_ctx->notify_rx = ch_ctx->notify_rx;
+        open_ch_ctx->notify_rxv = ch_ctx->notify_rxv;
+        open_ch_ctx->notify_tx_done = ch_ctx->notify_tx_done;
+        open_ch_ctx->notify_state = ch_ctx->notify_state;
+        open_ch_ctx->notify_rx_intent_req = ch_ctx->notify_rx_intent_req;
+        open_ch_ctx->notify_rx_intent = ch_ctx->notify_rx_intent;
+        open_ch_ctx->notify_rx_sigs = ch_ctx->notify_rx_sigs;
+        open_ch_ctx->priv = ch_ctx->priv;
+        open_ch_ctx->ch_open_options = ch_ctx->ch_open_options;
+
+        /* release lock before context switch otherwise it is causing
+         * deadlock */
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        /* Send open cmd to transport */
+        status = if_ptr->tx_cmd_ch_open(if_ptr,
+                      open_ch_ctx->lcid, open_ch_ctx->name,
+                      open_ch_ctx->req_if_ptr->glink_priority);
+      }
+      else if ((open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN) &&
+               (!local_open))
+      {
+        /* Case B: Channel was opened on this end and we got a remote open */
+        open_ch_ctx->rcid = ch_ctx->rcid;
+
+        status = xport_ctx->channel_init(open_ch_ctx);
+
+        /* release lock before context switch otherwise it is causing deadlock */
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        if (status == GLINK_STATUS_SUCCESS)
+        {
+          /* Send ACK to transport */
+          if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, open_ch_ctx->rcid, migrated_ch_prio);
+        }
+      } else if ((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE)
+                  && (local_open)) {
+        /* Allocate new channel context */
+        break; /* code would break out of loop and create new ch ctx */
+      } else {
+        /* Can't handle this state */
+        ASSERT(0);
+      }
+
+      break;
+    } /* end if match found */
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  if (open_ch_ctx != NULL)
+  {
+    glink_os_free(ch_ctx);
+
+    /* connect channel here if state is local open and remote open request
+     * comes up and channel migration is done; channel will be connected in
+     * remote_open_ack if channel state is remote open and local open
+     * request comes up */
+    if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN &&
+       migration_state == FALSE && status == GLINK_STATUS_SUCCESS)
+    {
+      /* Set the channel state to OPEN */
+      open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+      /* Inform the client */
+      open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+                                GLINK_CONNECTED);
+    }
+  }
+  else
+  {
+    /* Channel not in the list - it was not previously opened */
+    ch_ctx->if_ptr = if_ptr;
+    *allocated_ch_ctx = ch_ctx;
+
+    /* Set channel state */
+    if (local_open) {
+      /* This is a local open */
+      ch_ctx->state      = GLINK_CH_STATE_LOCAL_OPEN;
+      ch_ctx->req_if_ptr = req_if_ptr;
+    }
+    else {
+      ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN;
+    }
+
+    glink_os_cs_init(&ch_ctx->tx_cs);
+
+    /* Append the channel to the transport interface's open_list */
+    ch_ctx->ref_count++;
+    ch_ctx->lcid = xport_ctx->free_lcid;
+    xport_ctx->free_lcid++;
+    smem_list_append(&if_ptr->glink_core_priv->open_list, ch_ctx);
+
+    /* release lock before context switch otherwise it is causing deadlock */
+    glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+    /* Send the OPEN command to transport */
+    if (local_open)
+    {
+      status = if_ptr->tx_cmd_ch_open(if_ptr, ch_ctx->lcid,
+                                      ch_ctx->name,
+                                      ch_ctx->req_if_ptr->glink_priority);
+    }
+    else
+    {
+      /* initialize channel resources */
+      status = xport_ctx->channel_init(ch_ctx);
+
+      /* ACK the transport for remote open */
+      if (status == GLINK_STATUS_SUCCESS)
+      {
+        if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, ch_ctx->rcid,
+                                          migrated_ch_prio);
+      }
+    }
+
+    if (status != GLINK_STATUS_SUCCESS)
+    {
+      /* Remove the channel from the transport interface's open_list */
+      xport_ctx->free_lcid--;
+
+      glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+      smem_list_delete(&if_ptr->glink_core_priv->open_list, ch_ctx);
+      glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+      /* free the ch_ctx structure and return */
+      xport_ctx->channel_cleanup(ch_ctx);
+      glink_os_free(ch_ctx);
+    }
+  }
+
+  return status;
+}
+
+/** Default implementation of optional callbacks */
+
+static void glink_default_notify_rx_sigs
+(
+  glink_handle_type  handle,
+  const void         *priv,
+  uint32             prev,
+  uint32             curr
+)
+{
+  return;
+}
+
+static void glinki_call_link_notifier
+(
+  glink_link_notif_data_type *link_notif_data,
+  glink_core_xport_ctx_type  *xport_ctx,
+  glink_link_state_type      state
+)
+{
+  glink_link_info_type link_info;
+
+  ASSERT(xport_ctx);
+  ASSERT(link_notif_data);
+
+  link_info.xport = xport_ctx->xport;
+  link_info.remote_ss = xport_ctx->remote_ss;
+  link_info.link_state = state;
+  link_notif_data->link_notifier(&link_info, link_notif_data->priv);
+}
+
+static uint32 glinki_find_remote_host
+(
+  const char *remote_ss
+)
+{
+  uint32 remote_host;
+  ASSERT(remote_ss);
+
+  for(remote_host = 0;
+      remote_host < sizeof(glink_hosts_supported)/sizeof(char *);
+      remote_host++) {
+    if( 0 == strcmp(glink_hosts_supported[remote_host], remote_ss) ) {
+      /* Match found, break out of loop */
+      break;
+    }
+  }
+  return remote_host;
+}
+
+static void glinki_check_xport_and_notify
+(
+  glink_link_notif_data_type *link_notif_data,
+  glink_core_xport_ctx_type  *xport_ctx,
+  glink_link_state_type      state
+)
+{
+  glink_link_info_type link_info;
+
+  ASSERT(xport_ctx);
+  ASSERT(link_notif_data);
+
+  link_info.xport = xport_ctx->xport;
+  link_info.remote_ss = xport_ctx->remote_ss;
+  link_info.link_state = state;
+
+  if(link_notif_data->xport == NULL ||
+     0 == strcmp(xport_ctx->xport, link_notif_data->xport)) {
+    /* xport not specified, or it is specified and matches the current xport */
+    /* Invoke registered callback */
+    link_notif_data->link_notifier(&link_info, link_notif_data->priv);
+  }
+}
+
+
+static void glinki_scan_xports_and_notify
+(
+  glink_link_notif_data_type *link_notif_data
+)
+{
+  unsigned int remote_host;
+  glink_transport_if_type *if_ptr;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(link_notif_data);
+
+  /* Find matching subsystem */
+  if(link_notif_data->remote_ss) {
+    remote_host = glinki_find_remote_host(link_notif_data->remote_ss);
+
+    /* Find the xport and give link UP notification */
+    if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+    if(if_ptr == NULL) {
+      /* No registered xports at this time, return without doing anything */
+      return;
+    }
+
+    if(link_notif_data->xport) {
+      do {
+        xport_ctx = if_ptr->glink_core_priv;
+        if( 0 == strcmp(xport_ctx->xport, link_notif_data->xport) ) {
+          /* Match found, break out of loop */
+          break;
+        }
+      }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+
+      if((if_ptr != NULL) && (xport_ctx->status == GLINK_XPORT_LINK_UP)) {
+        /* Invoke registered callback */
+        glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                  GLINK_LINK_STATE_UP);
+      }
+    } else {
+      /* No xport has been specified, invoke notifier for all registered
+       * xports */
+      do {
+        xport_ctx = if_ptr->glink_core_priv;
+        if(xport_ctx->status == GLINK_XPORT_LINK_UP) {
+          /* Invoke registered callback */
+          glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                    GLINK_LINK_STATE_UP);
+        }
+      }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+    }
+  } else {
+    /* No remote ss is specified, invoke notifier for all remote_ss */
+    for(remote_host = 0;
+        remote_host < sizeof(glink_hosts_supported)/sizeof(char *);
+        remote_host++) {
+      /* Find the xport and give link UP notification */
+      if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+      if(if_ptr == NULL) {
+        /* No registered xports at this time, continue with next remote_ss */
+        continue;
+      }
+
+      if(link_notif_data->xport) {
+        do {
+          xport_ctx = if_ptr->glink_core_priv;
+          if( 0 == strcmp(xport_ctx->xport, link_notif_data->xport) ) {
+            /* Match found, break out of loop */
+            break;
+          }
+        }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+
+        if((if_ptr != NULL) && (xport_ctx->status == GLINK_XPORT_LINK_UP)) {
+          /* Invoke registered callback */
+          glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                    GLINK_LINK_STATE_UP);
+        }
+      } else {
+        /* No xport has been specified, invoke notifier for all registered
+         * xports */
+        do {
+          xport_ctx = if_ptr->glink_core_priv;
+          if(xport_ctx->status == GLINK_XPORT_LINK_UP) {
+            /* Invoke registered callback */
+            glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                      GLINK_LINK_STATE_UP);
+          }
+        }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+      }
+    } /* end for remote_host */
+  }/* end if else (link_notif_data->remote_ss) */
+} /* glinki_scan_xports_and_notify */
+
+void glinki_scan_notif_list_and_notify
+(
+  glink_transport_if_type *if_ptr,
+  glink_link_state_type state
+)
+{
+  glink_link_notif_data_type *link_notif_data;
+  glink_core_xport_ctx_type  *xport_ctx = if_ptr->glink_core_priv;
+
+  link_notif_data = smem_list_first(&glink_link_notif_list);
+
+  if(link_notif_data == NULL) {
+    /* list empty */
+    return;
+  }
+
+  do {
+      if(link_notif_data->remote_ss &&
+         0 == strcmp(xport_ctx->remote_ss, link_notif_data->remote_ss)) {
+        /* remote_ss specified and matches */
+        glinki_check_xport_and_notify(link_notif_data, xport_ctx, state);
+      } else if(link_notif_data->remote_ss == NULL) {
+        /* remote_ss not specified, invoke link notif for any remote_ss */
+        if(link_notif_data->xport) {
+          glinki_check_xport_and_notify(link_notif_data, xport_ctx, state);
+        } /* if else link_notif_data->xport */
+      } /* if else link_notif_data->remote_ss */
+  } while ( (link_notif_data = smem_list_next(link_notif_data)) != NULL);
+
+} /* glinki_scan_notif_list_and_notify */
+
+void glinki_scan_channels_and_notify_discon
+(
+  glink_transport_if_type *if_ptr
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    /* Found channel, transition it to appropriate state based
+     * on current state */
+    if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+      open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN;
+
+      /* Inform the client */
+      open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+          GLINK_REMOTE_DISCONNECTED);
+    } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
+      /* Local side never opened the channel */
+      /* Free channel resources */
+      xport_ctx->channel_cleanup(open_ch_ctx);
+
+      smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+
+      glink_os_free(open_ch_ctx);
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+  glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+void glink_ssr(const char* remote_ss)
+{
+  unsigned int remote_host;
+  glink_transport_if_type *if_ptr;
+
+  remote_host = glinki_find_remote_host(remote_ss);
+
+  /* Scan through the registered interfaces with the crashing ss
+     and let the clients know about the crash via LINK_DOWN
+     notification followed by REMOTE_DISCONNECT */
+  if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+
+  while(if_ptr != NULL) {
+    /* Invoke LINK_DOWN notification for any registered notifiers */
+    glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_DOWN);
+
+    /* Invoke REMOTE_DISCONNECT for all channels associated with if_ptr */
+    glinki_scan_channels_and_notify_discon(if_ptr);
+
+    /* Let the xport know about ssr */
+    if_ptr->ssr(if_ptr);
+
+    if_ptr = smem_list_next(if_ptr);
+  }
+}
+
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_init
+
+DESCRIPTION   Initializes the GLink core library.
+
+ARGUMENTS     None
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_init(void)
+{
+  uint32 i;
+
+  glink_mem_log_cs = glink_os_cs_create();
+
+  glink_core_status = GLINK_INITIALIZED;
+
+  /* Create/Initalize crtitical sections */
+  glink_transport_q_cs = glink_os_cs_create();
+  if(glink_transport_q_cs == NULL) {
+    return;
+  }
+
+  glink_os_cs_acquire(glink_transport_q_cs);
+  for(i= 0; i < sizeof(glink_registered_transports)/sizeof(smem_list_type);
+      i++)
+  {
+    smem_list_init(&glink_registered_transports[i]);
+  }
+  glink_os_cs_release(glink_transport_q_cs);
+}
+
+/*===========================================================================
+FUNCTION      glink_core_register_transport
+
+DESCRIPTION   Transport calls this API to register its interface with GLINK
+              Core
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            *cfg      Pointer to transport configuration structure.
+
+RETURN VALUE  Standard GLINK error codes.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_err_type glink_core_register_transport
+(
+  glink_transport_if_type       *if_ptr,
+  glink_core_transport_cfg_type *cfg
+)
+{
+  unsigned int remote_host = 0;
+  glink_core_xport_ctx_type *xport_ctx;
+  /* Param validation */
+  if(if_ptr == NULL || cfg == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  if(cfg->name == NULL       ||
+     cfg->remote_ss == NULL  ||
+     cfg->version == NULL    ||
+     cfg->version_count == 0 ||
+     cfg->max_cid == 0)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+
+  if(if_ptr->tx_cmd_version == NULL             ||
+     if_ptr->tx_cmd_version_ack == NULL         ||
+     if_ptr->set_version == NULL                ||
+     if_ptr->tx_cmd_ch_open == NULL             ||
+     if_ptr->tx_cmd_ch_close == NULL            ||
+     if_ptr->tx_cmd_ch_remote_open_ack == NULL  ||
+     if_ptr->tx_cmd_ch_remote_close_ack == NULL ||
+     if_ptr->tx_cmd_set_sigs  == NULL           ||
+     if_ptr->ssr  == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+        cfg->remote_ss, GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;;
+  }
+
+
+  /* Allocate/fill out the GLink Core interface structure */
+  {
+    glink_core_if_type *core_if = glink_os_calloc(sizeof(glink_core_if_type));
+    if(core_if == NULL) {
+      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+      return GLINK_STATUS_OUT_OF_RESOURCES;
+    }
+    core_if->link_up = glink_link_up;
+    core_if->rx_cmd_version = glink_rx_cmd_version;
+    core_if->rx_cmd_version_ack = glink_rx_cmd_version_ack;
+    core_if->rx_cmd_ch_remote_open = glink_rx_cmd_ch_remote_open;
+    core_if->rx_cmd_ch_open_ack = glink_rx_cmd_ch_open_ack;
+    core_if->rx_cmd_ch_close_ack = glink_rx_cmd_ch_close_ack;
+    core_if->rx_cmd_ch_remote_close = glink_rx_cmd_ch_remote_close;
+    core_if->ch_state_local_trans = glink_ch_state_local_trans;
+    core_if->rx_put_pkt_ctx = glink_rx_put_pkt_ctx;
+    core_if->rx_cmd_remote_sigs = glink_rx_cmd_remote_sigs;
+    core_if->tx_resume = glink_tx_resume;
+    core_if->set_core_version = glink_set_core_version;
+
+    /* Set the glink_core_if_ptr to point to the allocated structure */
+    if_ptr->glink_core_if_ptr = core_if;
+  }
+
+  /* Allocate/fill out the GLink private context data */
+  {
+     xport_ctx = glink_os_calloc(sizeof(glink_core_xport_ctx_type));
+    if(xport_ctx == NULL) {
+      /* Free previously allocated memory */
+      glink_os_free(if_ptr->glink_core_if_ptr);
+
+      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+
+      return GLINK_STATUS_OUT_OF_RESOURCES;
+    }
+
+    glink_os_string_copy(xport_ctx->xport, cfg->name,
+        sizeof(xport_ctx->xport));
+    glink_os_string_copy(xport_ctx->remote_ss, cfg->remote_ss,
+        sizeof(xport_ctx->xport));
+    xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */
+    xport_ctx->version_array = cfg->version;
+    xport_ctx->version_indx = cfg->version_count - 1;
+
+    glink_os_cs_init(&xport_ctx->channel_q_cs);
+    glink_os_cs_init(&xport_ctx->liid_cs);
+
+    glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+    smem_list_init(&xport_ctx->open_list);
+    glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+    /* Set the glink_core_if_ptr to point to the allocated structure */
+    if_ptr->glink_core_priv = xport_ctx;
+    xport_ctx->status = GLINK_XPORT_REGISTERED;
+  }
+
+  /* Push the transport interface into appropriate queue */
+  remote_host = glinki_find_remote_host(cfg->remote_ss);
+
+  if(remote_host == GLINK_NUM_HOSTS ) {
+    /* Unknown transport name trying to register with GLink */
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
+           xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
+
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+  glink_os_cs_acquire(glink_transport_q_cs);
+  smem_list_append(&glink_registered_transports[remote_host], if_ptr);
+  glink_os_cs_release(glink_transport_q_cs);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Regsiters a client specified callback to be invoked when the specified
+ * transport (link) is up/down.
+ *
+ * @param[in]    link_id  Pointer to the configuration structure for the
+ *                        xport(link) to be monitored. See glink.h
+ * @param[in]    priv     Callback data returned to client when callback
+ *                        is invoked.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Puts the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_register_link_state_cb
+(
+  glink_link_id_type *link_id,
+  void*              priv
+)
+{
+  glink_link_notif_data_type* link_notif_data;
+  unsigned int remote_host;
+
+  /* Input validation */
+  ASSERT(link_id != NULL);
+
+  /* Make sure client provided us with the correct version of the input
+   * structure */
+  if(link_id->version != GLINK_LINK_ID_VER || link_id->link_notifier == NULL) {
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Save the callback on the notification list */
+  if((link_notif_data = glink_os_malloc(sizeof(glink_link_notif_data_type)))
+       == NULL) {
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  /* Check for remote_ss validity */
+  if(link_id->remote_ss != NULL) {
+    remote_host = glinki_find_remote_host(link_id->remote_ss);
+
+    if(remote_host == sizeof(glink_hosts_supported)/sizeof(char *)) {
+      glink_os_free(link_notif_data);
+      return GLINK_STATUS_INVALID_PARAM;
+    }
+  }
+
+  link_notif_data->xport = link_id->xport;
+  link_notif_data->remote_ss = link_id->remote_ss;
+  link_notif_data->link_notifier = link_id->link_notifier;
+  link_notif_data->priv = priv; /* private client data */
+
+  /* Append the request to the list for link UP/DOWN notifications */
+  smem_list_append(&glink_link_notif_list, link_notif_data);
+
+  /* Scan the list of available transport to see if this link is already up */
+  glinki_scan_xports_and_notify(link_notif_data);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Degsiter the link UP/DOWN notification callback associated with the
+ * provided handle.
+ *
+ * @param[in]    handle  Callback handler returned by
+ *                       glink_register_link_state_cb
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Removes the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_deregister_link_state_cb
+(
+  glink_link_handle_type handle
+)
+{
+  ASSERT(handle);
+
+  smem_list_delete(&glink_link_notif_list,
+                   (glink_link_notif_data_type*)handle);
+
+  glink_os_free(handle);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * This function gives best available transport for give edge
+ *
+ * @param[in]    remote_host  Index into glink_registered_transports array of
+ *                            registered transports list per edge
+ *
+ * @return       pointer to glink_transport_if_type
+ *
+ * @sideeffects  NONE
+ */
+glink_transport_if_type* glink_get_best_xport
+(
+  unsigned int remote_host
+)
+{
+  glink_transport_if_type   *if_ptr    = NULL, *best_if_ptr = NULL;
+  glink_xport_priority       priority  = GLINK_MIN_PRIORITY;
+  glink_core_xport_ctx_type *xport_ctx = NULL;
+
+  best_if_ptr = if_ptr = smem_list_first(
+                          &glink_registered_transports[remote_host]);
+
+  while(if_ptr != NULL)
+  {
+    /* check if priority of current transport is higher than
+     * current highest priority (0 = highest priority)
+     */
+    xport_ctx = if_ptr->glink_core_priv;
+    if( xport_ctx->status == GLINK_XPORT_LINK_UP &&
+        if_ptr->glink_priority < priority )
+    {
+      best_if_ptr = if_ptr;
+      priority    = if_ptr->glink_priority;
+    }
+
+    if_ptr    = smem_list_next(if_ptr);
+  } /* end while() */
+
+  return best_if_ptr;
+}
+
+/**
+ * Opens a logical GLink based on the specified config params
+ *
+ * @param[in]    cfg_ptr  Pointer to the configuration structure for the
+ *                        GLink. See glink.h
+ * @param[out]   handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Allocates channel resources and informs remote host about
+ *               channel open.
+ */
+glink_err_type glink_open
+(
+  glink_open_config_type *cfg_ptr,
+  glink_handle_type      *handle
+)
+{
+  glink_transport_if_type *if_ptr, *req_if_ptr;
+  glink_channel_ctx_type  *ch_ctx;
+  unsigned int            remote_host;
+
+  /* Param validation */
+  if(cfg_ptr == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  if(cfg_ptr->remote_ss == NULL             ||
+     cfg_ptr->name == NULL                  ||
+     cfg_ptr->notify_state == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Evaluate the equivalent edge name->enum for future use */
+  remote_host = glinki_find_remote_host(cfg_ptr->remote_ss);
+
+  if(remote_host == GLINK_NUM_HOSTS ) {
+    /* Unknown transport name trying to register with GLink */
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, cfg_ptr->name, "",
+        cfg_ptr->remote_ss, GLINK_STATUS_INVALID_PARAM);
+
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Allocate and initialize channel info structure */
+  ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
+  if(ch_ctx == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, "",
+        "", GLINK_STATUS_OUT_OF_RESOURCES);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  /* Fill in the channel info structure */
+  glink_os_string_copy(ch_ctx->name, cfg_ptr->name, sizeof(ch_ctx->name));
+  ch_ctx->priv = cfg_ptr->priv;
+  ch_ctx->notify_rx = cfg_ptr->notify_rx;
+  ch_ctx->notify_rxv = cfg_ptr->notify_rxv;
+  ch_ctx->notify_tx_done = cfg_ptr->notify_tx_done;
+  ch_ctx->notify_state = cfg_ptr->notify_state;
+  ch_ctx->notify_rx_intent_req = cfg_ptr->notify_rx_intent_req;
+  ch_ctx->notify_rx_intent = cfg_ptr->notify_rx_intent;
+  ch_ctx->notify_rx_sigs = cfg_ptr->notify_rx_sigs;
+  ch_ctx->ch_open_options = cfg_ptr->options;
+  ch_ctx->notify_rx_abort = cfg_ptr->notify_rx_abort;
+  ch_ctx->notify_tx_abort = cfg_ptr->notify_tx_abort;
+
+  if (ch_ctx->notify_rx_sigs == NULL) {
+    /* set default callback */
+    ch_ctx->notify_rx_sigs = glink_default_notify_rx_sigs;
+  }
+
+  glink_os_cs_acquire(glink_transport_q_cs);
+
+  /* Check to see if requested transport is available */
+  for (if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+       if_ptr != NULL;
+       if_ptr = smem_list_next(if_ptr))
+  {
+    glink_core_xport_ctx_type *xport_ctx = if_ptr->glink_core_priv;
+    glink_channel_ctx_type    *allocated_ch_ctx;
+
+    if (xport_ctx->status == GLINK_XPORT_LINK_UP &&
+        (cfg_ptr->transport == NULL ||
+         0 == strcmp(cfg_ptr->transport, xport_ctx->xport)) &&
+        xport_ctx->verify_open_cfg(ch_ctx))
+    {
+      glink_err_type status;
+
+      if(cfg_ptr->transport == NULL)
+      {
+        /* get best available transport */
+        if_ptr = req_if_ptr = glink_get_best_xport(remote_host);
+      }
+      else
+      {
+        if(cfg_ptr->options & GLINK_OPT_INITIAL_XPORT)
+        {
+          /* xport suggested by client is optional.
+           * get best available xport */
+          req_if_ptr = glink_get_best_xport(remote_host);
+        }
+        else
+        {
+          req_if_ptr = if_ptr;
+        }
+      }
+      /* Xport match found */
+      status = glinki_add_ch_to_xport( if_ptr,
+                                       req_if_ptr,
+                                       ch_ctx,
+                                       &allocated_ch_ctx,
+                                       TRUE,
+                                       TRUE,
+                                       if_ptr->glink_priority );
+
+      if (status == GLINK_STATUS_SUCCESS) {
+        /* Set the handle and return */
+        *handle = allocated_ch_ctx;
+      }
+      else {
+        *handle = NULL;
+      }
+
+      glink_os_cs_release(glink_transport_q_cs);
+
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, ch_ctx->name, xport_ctx->xport,
+        xport_ctx->remote_ss, status);
+      return status;
+    }
+  } /* end for() */
+
+  glink_os_cs_release(glink_transport_q_cs);
+
+  /* Code gets here if we are not able to find reqeusted transport */
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, cfg_ptr->transport,
+      cfg_ptr->remote_ss, GLINK_STATUS_NO_TRANSPORT);
+  glink_os_free(ch_ctx);
+  return GLINK_STATUS_NO_TRANSPORT;
+}
+
+/**
+ * Closes the GLink logical channel specified by the handle.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Closes local end of the channel and informs remote host
+ */
+glink_err_type glink_close
+(
+  glink_handle_type handle
+)
+{
+  glink_err_type status;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+  glink_ch_state_type ch_state;
+
+  if(handle == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  ch_state = handle->state;
+
+  /* Check to see if channel is in open/opening state */
+  if (ch_state != GLINK_CH_STATE_OPEN &&
+      ch_state != GLINK_CH_STATE_LOCAL_OPEN &&
+      ch_state != GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE &&
+      ch_state != GLINK_CH_STATE_REMOTE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, ch_state);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Transition to closing */
+  //handle->state = GLINK_CH_STATE_CLOSING;
+
+  /* Send CLOSE cmd to the transport interface */
+  status = handle->if_ptr->tx_cmd_ch_close(handle->if_ptr, handle->lcid);
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, status);
+  return status;
+
+}
+
+/**
+ * Transmit the provided buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *data      Pointer to the data buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   req_intent Whether to block and request for remote rx intent in
+ *                         case it is not available for this pkt tx
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_tx
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  const void        *data,
+  size_t            size,
+  uint32            options
+)
+{
+  return glink_txv(handle, pkt_priv, (void*)data, size,
+                   &glink_dummy_tx_vprovider, NULL, options);
+
+}
+
+/**
+ * Transmit the provided vector buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *iovec     Pointer to the vector buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   vprovider  Buffer provider for virtual space
+ *
+ * @param[in]   pprovider  Buffer provider for physical space
+ *
+ * @param[in]   req_intent Whether to block and request for remote rx intent in
+ *                         case it is not available for this pkt tx
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_txv
+(
+  glink_handle_type        handle,
+  const void               *pkt_priv,
+  void                     *iovec,
+  size_t                   size,
+  glink_buffer_provider_fn vprovider,
+  glink_buffer_provider_fn pprovider,
+  uint32                   options
+)
+{
+  glink_err_type         status;
+  glink_core_tx_pkt_type pctx;
+  boolean                req_intent = options & GLINK_TX_REQ_INTENT;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+
+  /* Input validation */
+  if(handle == NULL || iovec == NULL || size == 0 ||
+     (vprovider == NULL && pprovider == NULL)) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN )
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Protect the entire tx operation under a lock as a client may call
+     tx in different thread context */
+  glink_os_cs_acquire(&handle->tx_cs);
+
+  pctx.pkt_priv = pkt_priv;
+  pctx.size = size;
+  pctx.size_remaining = size;
+  pctx.vprovider = vprovider;
+  pctx.pprovider = pprovider;
+
+  if (vprovider == &glink_dummy_tx_vprovider)
+  {
+    pctx.data = (void*)iovec;
+    pctx.iovec = &pctx;
+  }
+  else
+  {
+    pctx.data = (void*)iovec;
+    pctx.iovec = iovec;
+  }
+
+  status = xport_ctx->use_rm_intent(handle, &pctx, req_intent);
+
+  /* Call transport API to transmit data */
+  while (pctx.size_remaining != 0 && status == GLINK_STATUS_SUCCESS)
+  {
+    status = handle->if_ptr->tx(handle->if_ptr, handle->lcid, &pctx);
+  }
+
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, status);
+
+  glink_os_cs_release(&handle->tx_cs);
+  return status;
+}
+
+/**
+ * Queue one or more Rx intent for the logical GPIC Link channel.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv Per packet private data
+ *
+ * @param[in]   size      Size of buffer
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL allocates rx buffers for receiving packets
+ */
+glink_err_type glink_queue_rx_intent
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  size_t            size
+)
+{
+  glink_err_type         status;
+  glink_rx_intent_type   *lc_intent;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+  size_t tmp;
+
+  /* Input validation */
+  if(handle == NULL || size == 0) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* short circuit for intentless mode */
+  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Allocate an intent structure */
+  lc_intent = glink_os_calloc(sizeof(glink_rx_intent_type));
+  if(lc_intent == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+        xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  glink_os_cs_acquire(&handle->if_ptr->glink_core_priv->liid_cs);
+
+  /* Call transport API to allocate rx intent buffer */
+  status = handle->if_ptr->allocate_rx_intent(handle->if_ptr, size, lc_intent);
+  if(status != GLINK_STATUS_SUCCESS) {
+    glink_os_free(lc_intent);
+    glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+        xport_ctx->remote_ss, status);
+    return status;
+  }
+
+  if (handle->notify_rxv == NULL &&
+     (lc_intent->vprovider(lc_intent->iovec, 0, &tmp) == NULL || tmp < size)) {
+    /* Allocate bounce buffer for non-vectored Rx */
+    lc_intent->data = glink_os_malloc(size);
+
+    if(lc_intent->data == NULL) {
+      handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+      glink_os_free(lc_intent);
+      glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name,
+        xport_ctx->xport, xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+      return GLINK_STATUS_OUT_OF_RESOURCES;
+    }
+  }
+
+  /* push the intent on local queue. Do this before calling tx cmd
+     as transport may try to read data into the newly queued rx_buffer */
+  lc_intent->iid = handle->if_ptr->glink_core_priv->liid;
+  lc_intent->size = size;
+  lc_intent->pkt_priv = pkt_priv;
+  glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+  smem_list_append(&handle->pintents->local_intent_q, lc_intent);
+  glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+  /* Call transport API to queue rx intent */
+  /* Increment the local intent ID counter associated with this channel */
+  handle->if_ptr->glink_core_priv->liid++;
+
+  status = handle->if_ptr->tx_cmd_local_rx_intent(handle->if_ptr,
+              handle->lcid, size, lc_intent->iid);
+  if(status != GLINK_STATUS_SUCCESS) {
+    /* Failure */
+    glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+    smem_list_delete(&handle->pintents->local_intent_q, lc_intent);
+    glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+    handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+    glink_os_free(lc_intent->data);
+    glink_os_free(lc_intent);
+  }
+  glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, status);
+  return status;
+}
+
+/**
+ * Client uses this to signal to GLink layer that it is done with the received
+ * data buffer. This API should be called to free up the receive buffer, which,
+ * in zero-copy mode is actually remote-side's transmit buffer.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *ptr      Pointer to the received buffer
+ *
+ * @param[in]   reuse    Reuse intent
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL frees the Rx buffer
+ */
+glink_err_type glink_rx_done
+(
+  glink_handle_type handle,
+  const void        *ptr,
+  boolean           reuse
+)
+{
+  glink_rx_intent_type      *lc_intent;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+
+  /* Input validation */
+  if(handle == NULL || ptr == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* short circuit for intentless mode */
+  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
+    return GLINK_STATUS_SUCCESS;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Free the intent */
+  lc_intent = smem_list_first(&handle->pintents->local_intent_client_q);
+  while(lc_intent != NULL) {
+    size_t tmp;
+
+    if(lc_intent->iovec == ptr || (handle->notify_rxv == NULL &&
+       (lc_intent->data == ptr ||
+       ptr == lc_intent->vprovider(lc_intent->iovec, 0, &tmp)))) {
+
+      uint32 iid;
+
+      /* Found intent, delete it */
+      glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+      smem_list_delete(&handle->pintents->local_intent_client_q, lc_intent);
+      glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+      iid = lc_intent->iid;
+
+      if (reuse)
+      {
+        lc_intent->used = 0;
+
+        glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+        smem_list_append(&handle->pintents->local_intent_q, lc_intent);
+        glink_os_cs_release(&handle->pintents->intent_q_cs);
+      }
+      else
+      {
+        /* Free the intent */
+        handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+        if(lc_intent->data) {
+          /* Free the bounce buffer if we had allocated one */
+          glink_os_free(lc_intent->data);
+        }
+        glink_os_free(lc_intent);
+      }
+
+      /* Note that the actual buffer, lc_intent->data, was allocated by the
+      * transport and should be freed by the xport. We should not touch it */
+      /* Let the xport know we are done with the buffer */
+      handle->if_ptr->tx_cmd_local_rx_done(handle->if_ptr, handle->lcid,
+                                           iid, reuse);
+
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+          xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+      return GLINK_STATUS_SUCCESS;
+    }
+    lc_intent = smem_list_next(lc_intent);
+  }
+
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
+  return GLINK_STATUS_INVALID_PARAM;
+}
+
+/**
+ * Set the 32 bit control signal field. Depending on the transport, it may
+ * take appropriate actions on the set bit-mask, or transmit the entire
+ * 32-bit value to the remote host.
+ *
+ * @param[in]   handle     GLink handle associated with the logical channel
+ *
+ * @param[in]   sig_value  32 bit signal word
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_set
+(
+  glink_handle_type handle,
+  uint32            sig_value
+)
+{
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+  glink_err_type status;
+
+  /* Input validation */
+  if(handle == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_SET, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_SET, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  status = handle->if_ptr->tx_cmd_set_sigs(handle->if_ptr, handle->lcid,
+                                           sig_value);
+  if(GLINK_STATUS_SUCCESS == status) {
+    /* Update local copy of local control signal state */
+    handle->local_sigs = sig_value;
+  }
+
+  return status;
+}
+
+/**
+ * Get the local 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_local_get
+(
+  glink_handle_type handle,
+  uint32            *sig_value
+)
+{
+  /* Input validation */
+  if(handle == NULL || sig_value == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_L_GET, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  *sig_value = handle->local_sigs;
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Get the remote 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_remote_get
+(
+  glink_handle_type handle,
+  uint32            *sig_value
+)
+{
+  /* Input validation */
+  if(handle == NULL || sig_value == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_R_GET, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  *sig_value = handle->remote_sigs;
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*================= RESTRICTED API ==========================*/
+
+/**
+ * This API allows the RPM client to poll the transport for any new data
+ * that might have come in. It would *usually* be used when incoming interrupts
+ * are disabled.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_rx_poll
+(
+  glink_handle_type handle
+)
+{
+  ASSERT(handle);
+
+  if(handle->if_ptr->poll) {
+    return handle->if_ptr->poll(handle->if_ptr);
+  }
+  return GLINK_STATUS_FAILURE;
+}
+
+/**
+ * This API allows the RPM client to mask/unmask rx interrupts
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[in]   mask        Whether to mask or un-mask the incoming interrupt
+ *
+ * @param[in]   platform_struct Any platform specific into that transport may
+                                require
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_mask_rx_interrupt
+(
+  glink_handle_type handle,
+  boolean           mask,
+  void              *platform_struct
+)
+{
+  ASSERT(handle);
+
+  if(handle->if_ptr->mask_rx_irq) {
+    return handle->if_ptr->mask_rx_irq(handle->if_ptr, mask);
+  }
+  return GLINK_STATUS_FAILURE;
+}
+
+/**
+ * This API waits until link is down.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_wait_link_down
+(
+  glink_handle_type handle
+)
+{
+  ASSERT(handle && handle->if_ptr && handle->if_ptr->wait_link_down);
+
+  return handle->if_ptr->wait_link_down(handle->if_ptr) ?
+         GLINK_STATUS_SUCCESS : GLINK_STATUS_FAILURE;
+}
+
+/* ============ Internal Logging API ================ */
+void glink_mem_log
+(
+  const char *func,
+  uint32 line,
+  glink_log_event_type type,
+  const char *msg,
+  const char *xport,
+  const char *remote_ss,
+  uint32 param
+)
+{
+#ifdef DEBUG_GLINK
+  dprintf(INFO, "%s:%u, event:%d, msg:%s, xport:%s, remote_ss:%s, param:%u\n", func, line, type, msg, xport, remote_ss, param);
+#endif
+}
diff --git a/platform/msm_shared/glink/glink_core_if.c b/platform/msm_shared/glink/glink_core_if.c
new file mode 100644
index 0000000..3c66369
--- /dev/null
+++ b/platform/msm_shared/glink/glink_core_if.c
@@ -0,0 +1,983 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+#include "glink_os_utils.h"
+#include "glink.h"
+#include "glink_internal.h"
+#include "glink_core_if.h"
+#include "smem_list.h"
+#include "glink_channel_migration.h"
+
+
+#define FEATURE_CH_MIGRATION_FREE
+
+void glinki_scan_notif_list_and_notify
+(
+  glink_transport_if_type *if_ptr,
+  glink_link_state_type state
+);
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+                     LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_process_negotiation_complete
+===========================================================================*/
+/**
+
+  This is called when negotiation is complete.
+  It will set the version and call link up callback to notify
+
+
+  @param[in]    xport_ctx    transport context
+
+  @param[in]    if_ptr       Pointer to interface instance; must be unique
+                             for each edge
+
+  @param[in]    version      negotiated version
+
+  @param[in]    features     negotiated with local side
+
+  @return        None
+  @sideeffects   None.
+  @dependencies  None.
+*/
+/*=========================================================================*/
+static void glink_process_negotiation_complete
+(
+  glink_core_xport_ctx_type *xport_ctx,
+  glink_transport_if_type   *if_ptr,
+  uint32                    version,
+  uint32                    features
+)
+{
+  /* Version/Feautre can be negotiated both in ver_req and ver_ack
+   * Only go through process once in case they are negotiated
+   * in ver_req before receiving ver_ack */
+  if( xport_ctx->status == GLINK_XPORT_LINK_UP )
+  {
+    return;
+  }
+
+  /* setup core based on transport capabilities*/
+  xport_ctx->xport_capabilities = if_ptr->set_version( if_ptr,
+                                                       version,
+                                                       features );
+  glink_core_setup(if_ptr);
+
+  /* transport is ready to open channels */
+  if_ptr->glink_core_priv->status = GLINK_XPORT_LINK_UP;
+
+  /* Scan the notification list to check is we have to let any registered
+  * clients know that link came online */
+  glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_UP);
+}
+
+static void glink_dummy_ch_migration_notification_cb
+(
+  glink_handle_type         handle,
+  const void               *priv,
+  glink_channel_event_type event
+)
+{
+}
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_link_up
+
+DESCRIPTION   Indicates that transport is now ready to start negotiation
+              using the v0 configuration
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_link_up
+(
+  glink_transport_if_type *if_ptr
+)
+{
+  const glink_core_version_type *version_array;
+  glink_core_xport_ctx_type *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  version_array = xport_ctx->version_array;
+
+  /* Update the transport state */
+  if_ptr->glink_core_priv->status = GLINK_XPORT_NEGOTIATING;
+
+  /* Start the negtiation */
+  if_ptr->tx_cmd_version(if_ptr, version_array->version,
+      version_array->features);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_LINK_UP, NULL, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version
+
+DESCRIPTION   Receive transport version for remote-initiated version
+              negotiation
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version  Remote Version
+
+            features Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+)
+{
+  const glink_core_version_type *ver;
+  uint32 negotiated_features;
+  glink_core_xport_ctx_type *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* The version to use must be a subset of supported version and features
+   * on this host and remote host */
+  ver = &xport_ctx->version_array[xport_ctx->version_indx];
+  ASSERT(ver);
+
+  if (version == ver->version)
+  {
+    /* Call the transport's negotiation function */
+    negotiated_features = ver->negotiate_features(if_ptr, ver, features);
+
+    /* If negotiated features match the provided features, version nogetiation
+     * is complete */
+    if(negotiated_features == features)
+    {
+      /* send version ack before allowing to open channels */
+      if_ptr->tx_cmd_version_ack(if_ptr, version, features);
+
+      glink_process_negotiation_complete( xport_ctx, if_ptr,
+                                          version, features );
+      return;
+    }
+    else
+    {
+      if_ptr->tx_cmd_version_ack(if_ptr, version, negotiated_features);
+    }
+  }
+  else
+  {
+    /* Next time use older version */
+    ver = &xport_ctx->version_array[xport_ctx->version_indx];
+
+    /* Versions don't match, return ACK with the feature set that we support */
+    if_ptr->tx_cmd_version_ack(if_ptr, ver->version, ver->features);
+  }
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version_ack
+
+DESCRIPTION   Receive ACK to previous glink_transport_if::tx_cmd_version
+              command
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version  Remote Version
+
+            features Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+)
+{
+  const glink_core_version_type* ver;
+  uint32 negotiated_features;
+  glink_core_xport_ctx_type *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Check to see if version returned by remote end is supported by
+   * this host. Remote side would have acked only when the version/features
+   * sent by this host did not match the remote */
+
+  ver = &xport_ctx->version_array[xport_ctx->version_indx];
+  ASSERT(ver);
+
+  if (ver->version == version)
+  {
+    /* Call the transport's negotiation function */
+    negotiated_features = ver->negotiate_features(if_ptr, ver, features);
+
+    if(negotiated_features != features)
+    {
+      /* Continue negotiating */
+      if_ptr->tx_cmd_version(if_ptr, version, negotiated_features);
+    }
+    else
+    {
+      glink_process_negotiation_complete( xport_ctx, if_ptr,
+                                          version, features );
+    }
+  }
+  else
+  {
+    while (ver->version > version)
+    {
+      /* Next time use older version */
+      ASSERT(xport_ctx->version_indx > 0);
+      xport_ctx->version_indx--;
+      ver = &xport_ctx->version_array[xport_ctx->version_indx];
+    }
+
+    /* Versions don't match, return ACK with the feature set that we support */
+    if_ptr->tx_cmd_version(if_ptr, ver->version, ver->features);
+  }
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_open
+
+DESCRIPTION   Receive remote channel open request; Calls
+              glink_transport_if:: tx_cmd_ch_remote_open_ack as a result
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid     Remote Channel ID
+
+            *name    String name for logical channel
+
+            prio     xport priority requested by remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_open
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  rcid,
+  const char              *name,
+  glink_xport_priority    priority
+)
+{
+  glink_channel_ctx_type *remote_ch_ctx;
+  glink_channel_ctx_type  *allocated_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+  glink_err_type status;
+  glink_xport_priority negotiated_prio;
+  boolean migration_state = TRUE;
+
+  ASSERT(if_ptr != NULL);
+  ASSERT(name != NULL);
+
+#ifndef FEATURE_CH_MIGRATION_FREE
+  glink_transport_if_type *present_if_ptr = NULL;
+  boolean channel_exist = FALSE;
+  glink_channel_ctx_type *present_ch_ctx = NULL;
+  /* search if channel with given name exists locally */
+  channel_exist = glinki_local_channel_exists(if_ptr, &present_if_ptr, name, &present_ch_ctx, TRUE);
+
+  /* start channel migration negotiation only if channel exists on local side
+   * for negotiation AND channel is willing to migrate */
+  if(channel_exist &&
+     (present_ch_ctx->ch_open_options & GLINK_OPT_INITIAL_XPORT))
+  {
+    /* channel exists on one of the xports for given remote ss */
+    current_prio =  present_ch_ctx->req_if_ptr->glink_priority;
+    negotiated_prio = glinki_negotiate_ch_migration(priority, current_prio);
+
+    /* if current channel is open in same xport as negotiated xport
+     * local side wont migrate. Set migration flag to FALSE */
+    if(negotiated_prio == present_if_ptr->glink_priority)
+    {
+      migration_state = FALSE;
+    }
+  }
+  else if(channel_exist)
+  {
+    /* channel exists but channel does not want to be moved to another xport.
+       channel is set in stone */
+    negotiated_prio = present_if_ptr->glink_priority;
+    migration_state = FALSE;
+  }
+  else
+  {
+    /* channel does not exist on local side as yet
+     * return negotiated prio as current xport prio on which
+     * remote open request is received */
+    negotiated_prio = if_ptr->glink_priority;
+    migration_state = FALSE;
+  }
+#else
+  negotiated_prio = if_ptr->glink_priority;
+    migration_state = FALSE;
+#endif
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Allocate and initialize channel info structure */
+  remote_ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
+  if(remote_ch_ctx == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_RM_CH_OPEN, name, xport_ctx->xport,
+        xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+    ASSERT(0);
+  }
+
+  /* Fill in the channel info structure */
+  glink_os_string_copy(remote_ch_ctx->name, name, sizeof(remote_ch_ctx->name));
+  remote_ch_ctx->rcid = rcid;
+
+  status = glinki_add_ch_to_xport(if_ptr, NULL, remote_ch_ctx,
+                                  &allocated_ch_ctx, FALSE,
+                                  migration_state, negotiated_prio);
+  ASSERT(status == GLINK_STATUS_SUCCESS);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_RM_CH_OPEN, name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+#ifndef FEATURE_CH_MIGRATION_FREE
+
+  /* We are done with channel migration negotiation at this stage
+   * Tag all channels with given name on xports other than negotiated
+   * xport for deletion */
+  glinki_tag_ch_for_deletion(if_ptr, name, negotiated_prio);
+
+    if(migration_state == TRUE)
+    {
+      glink_channel_ctx_type *new_ch_ctx;
+
+    /* create a new channel context as current channel will be migrated */
+    new_ch_ctx = (glink_channel_ctx_type *)
+                   glink_os_calloc(sizeof(glink_channel_ctx_type));
+
+    /* Fill in the channel info structure */
+    new_ch_ctx->req_if_ptr =
+             glinki_get_xport_from_prio(negotiated_prio,
+                                          if_ptr->glink_core_priv->remote_ss);
+    glink_os_string_copy(new_ch_ctx->name, present_ch_ctx->name,
+                         sizeof(present_ch_ctx->name));
+    new_ch_ctx->priv = present_ch_ctx->priv;
+    new_ch_ctx->notify_rx = present_ch_ctx->notify_rx;
+    new_ch_ctx->notify_rxv = present_ch_ctx->notify_rxv;
+    new_ch_ctx->notify_tx_done = present_ch_ctx->notify_tx_done;
+    new_ch_ctx->notify_state = present_ch_ctx->notify_state;
+    new_ch_ctx->notify_rx_intent_req = present_ch_ctx->notify_rx_intent_req;
+    new_ch_ctx->notify_rx_intent = present_ch_ctx->notify_rx_intent;
+    new_ch_ctx->notify_rx_sigs = present_ch_ctx->notify_rx_sigs;
+    new_ch_ctx->ch_open_options = present_ch_ctx->ch_open_options;
+
+//      glink_os_cs_init(&new_ch_ctx->intent_q_cs);
+
+    /* close current channel */
+    present_ch_ctx->notify_state = glink_dummy_ch_migration_notification_cb;
+    if_ptr->tx_cmd_ch_close( if_ptr, present_ch_ctx->lcid );
+
+    /* add new channel context on negotiated xport */
+    glinki_add_ch_to_xport(new_ch_ctx->req_if_ptr,
+                           new_ch_ctx->req_if_ptr,
+                           new_ch_ctx,
+                           &allocated_ch_ctx,
+                           TRUE,
+                           TRUE,
+                           new_ch_ctx->req_if_ptr->glink_priority);
+  }
+#endif
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_open_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if:: tx_cmd_ch_open
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid     Local Channel ID
+
+            prio     Negotiated xport priority from remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_open_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  lcid,
+  glink_xport_priority    migrated_ch_prio
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Move to closed state. Implies we clean up the channel from the
+   * open list */
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->lcid == lcid) {
+#ifndef FEATURE_CH_MIGRATION_FREE
+      glink_transport_if_type *present_if_ptr = NULL;
+      glink_channel_ctx_type  *present_ch_ctx = NULL;
+      boolean channel_exist;
+      /* find the channel in all xport list */
+      channel_exist = glinki_local_channel_exists(if_ptr,
+                                                  &present_if_ptr,
+                                                  open_ch_ctx->name,
+                                                  &present_ch_ctx,
+                                                  FALSE);
+
+      if(if_ptr->glink_priority == migrated_ch_prio && !channel_exist)
+      {
+        /* only local side has opened the channel. Remote side has not come up yet
+         * which implies negotiation did not take place on remote side */
+        /* DO NOTHING */
+      }
+      else if(if_ptr->glink_priority == migrated_ch_prio)
+      {
+        /* remote channel exists. channel migration negotiation happened
+         * on remote side and negotitated xport is same as current xport */
+        if(present_ch_ctx->ref_count == 1)
+        {
+          /* remote channel is present on different xport than negotiated one.
+           * remote side will migrate its channel to negotiated xport */
+          /* DO NOTHING */
+        }
+        else if(present_ch_ctx->ref_count == 2)
+        {
+          /* remote channel is open on same xport as current xport.
+           * change channel state to GLINK_CH_STATE_OPEN and notify client */
+          open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+          open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+                                    GLINK_CONNECTED);
+        }
+        else
+        {
+          /* something went wrong in updating ref_count of channel */
+          ASSERT(0);
+        }
+      }
+      else
+      {
+
+        /* migrated xport priority <> current xport priority */
+        /* check if remote channel is opened on negotiated xport already */
+          if(migrated_ch_prio == present_if_ptr->glink_priority &&
+             (open_ch_ctx->ch_open_options & GLINK_OPT_INITIAL_XPORT))
+          {
+            /* remote channel is already on negotiated xport. remote channel
+             * will not migrate. Local side should migrate */
+
+            glink_channel_ctx_type *new_ch_ctx =
+              (glink_channel_ctx_type *)glink_os_calloc(
+                                       sizeof(glink_channel_ctx_type));
+
+            /* Fill in the channel info structure */
+            glink_os_string_copy(new_ch_ctx->name,
+                                 open_ch_ctx->name,
+                                 sizeof(open_ch_ctx->name));
+            new_ch_ctx->priv = open_ch_ctx->priv;
+            new_ch_ctx->notify_rx = open_ch_ctx->notify_rx;
+            new_ch_ctx->notify_rxv = open_ch_ctx->notify_rxv;
+            new_ch_ctx->notify_tx_done = open_ch_ctx->notify_tx_done;
+            new_ch_ctx->notify_state = open_ch_ctx->notify_state;
+            new_ch_ctx->notify_rx_intent_req =
+                                            open_ch_ctx->notify_rx_intent_req;
+            new_ch_ctx->notify_rx_intent = open_ch_ctx->notify_rx_intent;
+            new_ch_ctx->notify_rx_sigs = open_ch_ctx->notify_rx_sigs;
+            new_ch_ctx->ch_open_options = open_ch_ctx->ch_open_options;
+
+            present_ch_ctx->notify_state = glink_dummy_ch_migration_notification_cb;
+            if_ptr->tx_cmd_ch_close( if_ptr, present_ch_ctx->lcid );
+
+            /* migrate to negotiated xport */
+            glinki_add_ch_to_xport(present_if_ptr,
+                                   present_if_ptr,
+                                   new_ch_ctx,
+                                   NULL,
+                                   TRUE,
+                                   TRUE,
+                                   present_if_ptr->glink_priority);
+          }
+          else
+          {
+            /* Either our transport is "set in stone"  OR */
+            /* remote side will migrate to negotiated xport and will call
+             * remote open on this side which will cause channel migration
+             * negotiation and this side will ultimately migrate */
+            /* DO NOTHING */
+          }
+        }
+#else
+        if(open_ch_ctx->ref_count == 2)
+        {
+          /* remote channel is open on same xport as current xport.
+           * change channel state to GLINK_CH_STATE_OPEN and notify client */
+          open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+          open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+                                    GLINK_CONNECTED);
+        }
+#endif
+
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN_ACK, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, lcid);
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }
+  /* We are here in case we could not find the channel in the open list. */
+  ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_close_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if_type:: tx_cmd_ch_close
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid      Local Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_close_ack
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid     /* Local channel ID */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Move to closed state. Implies we clean up the channel from the
+   * open list */
+
+  /* Find channel in the open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->lcid == lcid) {
+      /* Found channel */
+      open_ch_ctx->ref_count--;
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE_ACK, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, lcid);
+
+      /* Transition state */
+      if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+        /* this side initiated close procedure */
+        open_ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE;
+      } else if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN ||
+                open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE ||
+                open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
+        /* Other side never opened the port, or closed from its end */
+        /* Clear everything */
+        if(open_ch_ctx->ref_count == 0)
+        {
+          xport_ctx->channel_cleanup(open_ch_ctx);
+          /* re-use channel id if it can be done */
+          if(lcid == (xport_ctx->free_lcid-1)) {
+            /* If channel being closed is the last opened channel
+               re-use the lcid of this channel for any new channels */
+            xport_ctx->free_lcid--;
+          }
+          smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+
+          /* Notify the client */
+          open_ch_ctx->notify_state( open_ch_ctx, open_ch_ctx->priv,
+                                     GLINK_LOCAL_DISCONNECTED);
+          glink_os_free(open_ch_ctx);
+        }
+      } else {
+        /* Unsupported state */
+        ASSERT(0);
+      }
+
+      glink_os_cs_release(&xport_ctx->channel_q_cs);
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  /* We are here in case we could not find the channel in the open list. */
+  ASSERT(0);
+
+  glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_close
+
+DESCRIPTION   Remote channel close request; will result in sending
+              glink_transport_if_type:: tx_cmd_ch_remote_close_ack
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_close
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->rcid == rcid) {
+        GLINK_LOG_EVENT(GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
+            xport_ctx->xport, xport_ctx->remote_ss, rcid);
+      /* Found channel, transition it to appropriate state based
+       * on current state */
+      open_ch_ctx->ref_count--;
+
+      if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+         open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE;
+
+        /* Inform the client */
+        open_ch_ctx->notify_state( open_ch_ctx, open_ch_ctx->priv,
+                                   GLINK_REMOTE_DISCONNECTED);
+
+        /* Send the remote close ACK back to the other side */
+        if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+
+        /* Free channel resources */
+        xport_ctx->channel_cleanup(open_ch_ctx);
+
+        GLINK_LOG_EVENT(GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
+            xport_ctx->xport, xport_ctx->remote_ss, rcid);
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        return;
+      } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN ||
+                 open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE) {
+        /* Local side never opened the channel OR it opened it but closed it */
+        /* Free channel resources */
+        xport_ctx->channel_cleanup(open_ch_ctx);
+
+        /* Send the remote close ACK back to the other side */
+        if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+
+        if(open_ch_ctx->ref_count == 0)
+        {
+          /* re-use channel id if it can be done */
+          if (open_ch_ctx->lcid == (xport_ctx->free_lcid - 1)) {
+            /* If channel being closed is the last opened channel
+            re-use the lcid of this channel for any new channels */
+            xport_ctx->free_lcid--;
+          }
+          smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+          glink_os_free(open_ch_ctx);
+        }
+
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        return;
+      } else {
+        /* SHould not get this callback for a channel in any other state */
+
+        //OS_LOG_ERROR(3, "GLINK_RX_CMD_CH_REMOTE_CLOSE: received close cmd for invalid state"
+        //                "[channel ctx: 0x%x][current channel state: %d]",
+        //                open_ch_ctx, open_ch_ctx->state );
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+        if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+        return;
+      }
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  /* We are here in case we could not find the channel in the open list
+   * or OPEN state. */
+  ASSERT(0);
+
+  glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+/*===========================================================================
+FUNCTION      glink_ch_state_local_trans
+
+DESCRIPTION   Process local state transition
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_ch_state_local_trans
+(
+  glink_transport_if_type  *if_ptr,  /* Pointer to the interface instance */
+  uint32                   lcid,     /* Local channel ID */
+  glink_ch_state_type      new_state /* New local channel state */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->lcid == lcid) {
+      /* Found channel, transition it to appropriate state */
+      open_ch_ctx->state = new_state;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_STATE_TRANS, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, new_state);
+    return;
+  }/* end while */
+
+  /* We are here in case we could not find the channel in the open list
+   * or OPEN state. */
+  ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_put_pkt_ctx
+
+DESCRIPTION   Transport invokes this call to receive a packet fragment (must
+              have previously received an rx_cmd_rx_data packet)
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            *intent_ptr  Pointer to the intent fragment
+
+            complete     True if pkt is complete
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_put_pkt_ctx
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  glink_rx_intent_type    *intent_ptr, /* Fragment ptr */
+  boolean                 complete     /* True if pkt is complete */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL && intent_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->rcid == rcid) {
+      /* Found channel */
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_PUT_PKT_CTX, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, intent_ptr->iid);
+
+      xport_ctx->channel_receive_pkt(open_ch_ctx, intent_ptr);
+
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  /* We end up here if we don't find the channel */
+  ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_remote_sigs
+
+DESCRIPTION   Transport invokes this call to inform GLink of remote side
+              changing its control signals
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            remote_sigs  Remote signal state.
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_remote_sigs
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  rcid,       /* Remote channel ID */
+  uint32                  remote_sigs /* Remote control signals */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  uint32 prev_sigs;
+
+  ASSERT(if_ptr != NULL);
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->rcid == rcid) {
+      /* Found channel, let client know of new remote signal state */
+      prev_sigs = open_ch_ctx->remote_sigs;
+      open_ch_ctx->remote_sigs = remote_sigs;
+      open_ch_ctx->notify_rx_sigs(open_ch_ctx, open_ch_ctx->priv,
+                                  prev_sigs, remote_sigs);
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }
+
+  /* We end up here if we don't find the channel */
+  ASSERT(0);
+}
+
+
+/*===========================================================================
+FUNCTION      glink_tx_resume
+
+DESCRIPTION   If transport was full and could not continue a transmit
+              operation, then it will call this function to notify the core
+              that it is ready to resume transmission.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_tx_resume
+(
+  glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+)
+{
+  /* Not sure what to do here */
+}
+
+
+/*===========================================================================
+FUNCTION      glink_set_core_version
+
+DESCRIPTION   Sets the core version used by the transport; called after
+              completing negotiation.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+             version   Negotiated transport version
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_set_core_version
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version  /* Version */
+)
+{
+}
diff --git a/platform/msm_shared/glink/glink_core_intentless_xport.c b/platform/msm_shared/glink/glink_core_intentless_xport.c
new file mode 100644
index 0000000..289ef18
--- /dev/null
+++ b/platform/msm_shared/glink/glink_core_intentless_xport.c
@@ -0,0 +1,131 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*===========================================================================
+INCLUDE FILES
+===========================================================================*/
+
+#include "glink.h"
+#include "glink_internal.h"
+
+/*===========================================================================
+LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+  FUNCTION      glink_core_stub_intentless
+===========================================================================*/
+/**
+
+  Stub for intentless transport functionality.
+
+  @return     GLINK_STATUS_SUCCESS.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+
+static glink_err_type glink_core_stub_intentless(void)
+{
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+  FUNCTION      glink_verify_open_cfg_intentless
+===========================================================================*/
+/**
+
+  Verifies open config for an intentless transport
+
+  @param[in]  open_ch_ctx   Channel context.
+
+  @return     TRUE if config is good.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+static boolean glink_verify_open_cfg_intentless
+(
+glink_channel_ctx_type   *ch_ctx
+)
+{
+  return (ch_ctx->notify_rxv != NULL);
+}
+
+/*===========================================================================
+  FUNCTION      glink_channel_receive_pkt
+===========================================================================*/
+/**
+
+  Precesses Rx packet for the channel
+
+  @param[in]  open_ch_ctx   Channel context.
+  @param[in]  intent_ptr    Packet descriptor
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+static void glink_channel_receive_pkt_intentless
+(
+  glink_channel_ctx_type *open_ch_ctx,
+  glink_rx_intent_type *intent_ptr
+)
+{
+  open_ch_ctx->notify_rxv(open_ch_ctx, open_ch_ctx->priv,
+    NULL, intent_ptr->iovec, intent_ptr->pkt_sz, 0,
+    intent_ptr->vprovider, intent_ptr->pprovider);
+}
+
+/*===========================================================================
+EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+  FUNCTION      glink_core_setup_intentless_xport
+===========================================================================*/
+/**
+
+  Initializes internal core functions for the intentless transport.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr)
+{
+  if_ptr->glink_core_priv->verify_open_cfg = glink_verify_open_cfg_intentless;
+  if_ptr->glink_core_priv->channel_init = (channel_init_fn)glink_core_stub_intentless;
+  if_ptr->glink_core_priv->channel_cleanup = (channel_cleanup_fn)glink_core_stub_intentless;
+  if_ptr->glink_core_priv->use_rm_intent = (use_rm_intent_fn)glink_core_stub_intentless;
+  if_ptr->glink_core_priv->channel_receive_pkt = glink_channel_receive_pkt_intentless;
+}
diff --git a/platform/msm_shared/glink/glink_os_utils_dal.c b/platform/msm_shared/glink/glink_os_utils_dal.c
new file mode 100644
index 0000000..7ad6fb7
--- /dev/null
+++ b/platform/msm_shared/glink/glink_os_utils_dal.c
@@ -0,0 +1,358 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+#include "glink_os_utils.h"
+#include <arch/defines.h>
+#include <malloc.h>
+#include <kernel/thread.h>
+#include <string.h>
+#include <kernel/event.h>
+#include <platform/irqs.h>
+#include <platform/interrupts.h>
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+
+#define OS_LOG_BUFFER_SIZE  ( 16384 )
+
+/*===========================================================================
+                           TYPE DEFINITIONS
+===========================================================================*/
+typedef void (*glink_os_thread_fn_type)(void* param);
+
+typedef struct _glink_os_thread_info_type {
+  glink_os_thread_fn_type thread_fn;
+  void                    *param;
+}glink_os_thread_info_type;
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_init
+===========================================================================*/
+/**
+  Initializes a Critical Section
+
+  @param[in]  cs   pointer to critical section object allocated by caller.
+
+  @return
+  TRUE if critical section was initialized, FALSE otherwise
+*/
+/*=========================================================================*/
+boolean glink_os_cs_init( os_cs_type *cs )
+{
+  boolean return_value = TRUE;
+
+  /* Create the new critical section */
+
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_cs_deinit
+===========================================================================*/
+/**
+  This function de-initializes a critical section.
+
+  @param[in]  cs         Pointer to the critical section to be de-initialized.
+
+  @return
+  TRUE if critical section was initialized, FALSE otherwise
+
+*/
+/*=========================================================================*/
+boolean glink_os_cs_deinit( os_cs_type *cs )
+{
+  /* Deinitialize the critical section */
+
+  return TRUE;
+}
+
+/*===========================================================================
+FUNCTION      glink_os_cs_acquire
+===========================================================================*/
+/**
+  Lock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_acquire( os_cs_type *cs )
+{
+  enter_critical_section();
+}
+
+/*===========================================================================
+FUNCTION      glink_os_cs_release
+===========================================================================*/
+/**
+  Unlock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_release( os_cs_type *cs )
+{
+  exit_critical_section();
+}
+
+/*===========================================================================
+FUNCTION      glink_os_cs_destroy
+===========================================================================*/
+/**
+  Destroys a Critical Section
+
+  @return     none.
+*/
+/*=========================================================================*/
+void glink_os_cs_destroy( os_cs_type *cs )
+{
+  /* Initialize the critical section */
+  return;
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_malloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap.  The region should be
+  freed using \c glink_os_free when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+
+void *glink_os_malloc( size_t size )
+{
+  void *pMem;
+
+  pMem = malloc(size);
+  if (pMem == NULL)
+      return NULL;
+  return pMem;
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_calloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap and initialize with
+  the zeroes.  The region should be freed using \c glink_os_free
+  when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_calloc( size_t size )
+{
+  void *pMem;
+  pMem = malloc(size);
+  if( pMem == NULL )
+  {
+    return NULL;
+  }
+  else
+  {
+    memset( pMem, 0, size );
+    return pMem;
+  }
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_free
+===========================================================================*/
+/**
+  Free a region of memory that was allocated by \c glink_os_malloc.
+
+  @param[in] pMem    The reference to the region of memory to be freed.
+
+  @return    NA
+*/
+/*=========================================================================*/
+void glink_os_free( void *pMem )
+{
+  free( pMem );
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_string_copy
+===========================================================================*/
+/**
+  Copies the source string into the destination buffer until
+  size is reached, or until a '\0' is encountered.  If valid,
+  the destination string will always be NULL deliminated.
+
+  @param[in] dst    The destination string, contents will be updated.
+  @param[in] src    The source string
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+char *glink_os_string_copy( char *dst, const char *src, uint32 size )
+{
+  ( void )strlcpy( dst, src, size );
+
+  return dst;
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_string_compare
+===========================================================================*/
+/**
+  Compares two strings delimited by size or NULL character.
+
+  @param[in] s1     String 1
+  @param[in] s2     String 2
+  @param[in] size   The maximum number of characters to compare
+
+  @return
+  0 if strings are identical (up to size characters), non-zero otherwise
+*/
+/*==========================================================================*/
+long glink_os_string_compare( const char *s1, const char *s2, uint32 size )
+{
+  return strncmp( s1, s2, size );
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_copy_mem
+===========================================================================*/
+/**
+  Copies the source buffer into the destination buffer.
+
+  @param[in] dst    The destination, contents will be updated.
+  @param[in] src    The source
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+void glink_os_copy_mem( void *dst, const void *src, uint32 size )
+{
+  memcpy( dst, src, size );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_register_isr
+===========================================================================*/
+/**
+  Registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to register for
+  @param[in]  isr       Callback to be invoked when interrupt fires
+  @param[in]  cb_data   Data to be provided to the callback
+
+  @return     TRUE if registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_register_isr( uint32 irq_in, os_isr_cb_fn isr, void* cb_data )
+{
+  boolean return_value = TRUE;
+
+  /* Register the interrupt */
+  dprintf(SPEW, "Register interrupt: %u\n", irq_in);
+  register_int_handler(irq_in, (int_handler)(isr), cb_data);
+
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_deregister_isr
+===========================================================================*/
+/**
+  De-registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to deregister for
+
+  @return     TRUE if de-registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_deregister_isr( uint32 irq_in )
+{
+  boolean return_value = TRUE;
+  mask_interrupt(irq_in);
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_enable_interrupt
+===========================================================================*/
+/**
+  Enables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to enable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_enable_interrupt( uint32 irq_in )
+{
+  boolean return_value = TRUE;
+  unmask_interrupt(irq_in);
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_disable_interrupt
+===========================================================================*/
+/**
+  Disables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to disable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_disable_interrupt( uint32 irq_in )
+{
+  boolean return_value = TRUE;
+  dprintf(INFO, "Disable IPC Interrupt\n");
+  mask_interrupt(irq_in);
+  return ( return_value );
+}
diff --git a/platform/msm_shared/glink/glink_rpmcore_setup.c b/platform/msm_shared/glink/glink_rpmcore_setup.c
new file mode 100644
index 0000000..a206afa
--- /dev/null
+++ b/platform/msm_shared/glink/glink_rpmcore_setup.c
@@ -0,0 +1,65 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*===========================================================================
+INCLUDE FILES
+===========================================================================*/
+
+#include "glink.h"
+#include "glink_internal.h"
+
+
+/*===========================================================================
+EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glink_core_setup
+===========================================================================*/
+/**
+
+  Initializes internal core functions based on the transport capabilities.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup(glink_transport_if_type *if_ptr)
+{
+  if (if_ptr->glink_core_priv->xport_capabilities & GLINK_CAPABILITY_INTENTLESS)
+  {
+    glink_core_setup_intentless_xport(if_ptr);
+  }
+  else
+  {
+    ASSERT(0);
+  }
+}
diff --git a/platform/msm_shared/glink/glink_vector.c b/platform/msm_shared/glink/glink_vector.c
new file mode 100644
index 0000000..31f0883
--- /dev/null
+++ b/platform/msm_shared/glink/glink_vector.c
@@ -0,0 +1,196 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include "glink.h"
+#include "glink_core_if.h"
+#include "glink_transport_if.h"
+#include "glink_vector.h"
+#include "glink_os_utils.h"
+
+/*===========================================================================
+                       LOCAL DATA DECLARATIONS
+===========================================================================*/
+
+
+/*===========================================================================
+                       PRIVATE FUNCTIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glink_dummy_tx_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a non-vectored buffer.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_dummy_tx_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  glink_core_tx_pkt_type* pkt = (glink_core_tx_pkt_type*)iovec;
+
+  if (pkt == NULL || size == NULL || pkt->size <= offset)
+  {
+    return NULL;
+  }
+
+  *size = pkt->size - offset;
+
+  return (char*)(pkt->data) + offset;
+}
+
+/*===========================================================================
+FUNCTION      glink_iovec_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  glink_iovector_type* iovec_l = (glink_iovector_type*)iovec;
+
+  if (iovec_l == NULL || size == NULL)
+  {
+    return NULL;
+  }
+
+  if (!iovec_l->vlist)
+  {
+    // create vlist and map virtual from physical addresses
+    ASSERT(0);
+  }
+
+  if (!iovec_l->vlast || iovec_l->vlast->start_offset > offset)
+  {
+       iovec_l->vlast = iovec_l->vlist;
+  }
+
+  while (iovec_l->vlast &&
+         iovec_l->vlast->start_offset + iovec_l->vlast->size <= offset)
+  {
+    iovec_l->vlast = iovec_l->vlast->next;
+  }
+
+  if (iovec_l->vlast == NULL)
+  {
+    return NULL;
+  }
+
+  offset -= iovec_l->vlast->start_offset;
+  *size = iovec_l->vlast->size - offset;
+
+  return (char*)(iovec_l->vlast->data) + offset;
+}
+
+/*===========================================================================
+FUNCTION      glink_iovec_pprovider
+===========================================================================*/
+/**
+
+  Buffer provider for physical space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     physical address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_pprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  glink_iovector_type* iovec_l = (glink_iovector_type*)iovec;
+
+  if (iovec_l == NULL || size == NULL)
+  {
+    return NULL;
+  }
+
+  if (!iovec_l->plist)
+  {
+    // create plist and get physical addresses from virtual
+    ASSERT(0); // not implemented
+  }
+
+  if (!iovec_l->plast || iovec_l->plast->start_offset > offset)
+  {
+       iovec_l->plast = iovec_l->plist;
+  }
+
+  while (iovec_l->plast &&
+         iovec_l->plast->start_offset + iovec_l->plast->size <= offset)
+  {
+    iovec_l->plast = iovec_l->plast->next;
+  }
+
+  if (iovec_l->plast == NULL)
+  {
+    return NULL;
+  }
+
+  offset -= iovec_l->plast->start_offset;
+  *size = iovec_l->plast->size - offset;
+
+  return (char*)(iovec_l->plast->data) + offset;
+}
diff --git a/platform/msm_shared/glink/xport_rpm.c b/platform/msm_shared/glink/xport_rpm.c
new file mode 100644
index 0000000..05329f9
--- /dev/null
+++ b/platform/msm_shared/glink/xport_rpm.c
@@ -0,0 +1,1150 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+#include "glink.h"
+#include "glink_core_if.h"
+#include "glink_transport_if.h"
+#include "glink_os_utils.h"
+#include "glink_internal.h"
+#include "glink_vector.h"
+#include "xport_rpm_config.h"
+#include "xport_rpm.h"
+#include <reg.h>
+#include <bits.h>
+#include <platform/iomap.h>
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+#define XPORT_RPM_NAME "RPM"
+
+#define XPORT_RPM_LOG(msg, remote_host, param) \
+          GLINK_LOG_EVENT(GLINK_EVENT_XPORT_INTERNAL, msg, XPORT_RPM_NAME, \
+            remote_host, (uint32)param)
+
+#define MSGRAM_READ32(ctx, ind) (*(volatile uint32*)&(ctx)->rx_fifo[ind])
+#define CHECK_INDEX_WRAP_AROUND(ind, size) \
+          {if ((ind) >= (size)) ind = 0;}
+
+#define ROUNDUP64(d) (((d) + 7) & (~7))
+#define ROUNDUP32(d) (((d) + 3) & (~3))
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+extern const uint32 xport_rpm_config_num;
+extern const char* xport_rpm_msg_ram;
+extern const void* xport_rpm_msg_ram_toc;
+
+xport_rpm_config_type* xport_rpm_get_config(uint32 ind);
+
+/* RPM channel descriptor */
+typedef struct _xport_rpm_ind_type
+{
+  uint32 read_ind;
+  uint32 write_ind;
+} xport_rpm_ind_type;
+
+/* RPM transport context */
+typedef struct _xport_rpm_ctx_type
+{
+  /* context structure should start from trasport interface */
+  glink_transport_if_type xport_if;
+  const xport_rpm_config_type *pcfg;
+  volatile xport_rpm_ind_type* tx_desc;
+  volatile xport_rpm_ind_type* rx_desc;
+  char* tx_fifo;
+  char* rx_fifo;
+  uint32 tx_fifo_size;
+  uint32 rx_fifo_size;
+  os_cs_type *tx_link_lock;
+  os_cs_type *rx_link_lock;
+  uint32 pkt_start_ind;
+  uint32 pkt_size;
+  boolean reset;
+  boolean irq_mask;
+} xport_rpm_ctx_type;
+
+xport_rpm_ctx_type *xport_rpm_ctx = NULL;
+glink_core_version_type xport_rpm_version;
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      xport_rpm_plain_pkt_provider
+===========================================================================*/
+/**
+
+  Packet provider for virtual space that operates on MSG RAM FIFO.
+
+  @param[in]  iovec   Pointer to the vector.
+  @param[in]  offset  Offset within the vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+static void* xport_rpm_pkt_provider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  xport_rpm_ctx_type* ctx_ptr = (xport_rpm_ctx_type*)iovec;
+  uint32 last;
+
+  if (ctx_ptr == NULL || size == NULL || ctx_ptr->pkt_size <= offset)
+  {
+    return NULL;
+  }
+
+  last = ctx_ptr->rx_fifo_size - ctx_ptr->pkt_start_ind;
+
+  if (offset >= last)
+  {
+    *size = ctx_ptr->pkt_size - offset;
+
+    return &ctx_ptr->rx_fifo[offset - last];
+  }
+
+  *size = ctx_ptr->pkt_size <= last ?
+          ctx_ptr->pkt_size - offset :
+          last - offset;
+
+  return &ctx_ptr->rx_fifo[offset + ctx_ptr->pkt_start_ind];
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_send_event
+===========================================================================*/
+/**
+
+  Updates shared write index and sends interrupt.
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+
+  @return     None.
+
+  @sideeffects  None.
+
+  @dependencies It should be invoked within tx_link_lock protection.
+*/
+/*=========================================================================*/
+static void xport_rpm_send_event
+(
+  xport_rpm_ctx_type *ctx_ptr
+)
+{
+  /* read out the write index to initiate a bus transaction from MSG RAM */
+  volatile uint32 write_ind = ctx_ptr->tx_desc->write_ind;
+
+  XPORT_RPM_LOG("Send event write ind", ctx_ptr->pcfg->remote_ss, write_ind);
+
+  // notify rpm
+  dprintf(SPEW, "%s:%d: Notify RPM with IPC interrupt\n", __func__, __LINE__);
+  /* Set BIT 0 to notify RPM via IPC interrupt*/
+  writel(BIT(0), APCS_HLOS_IPC_INTERRUPT_0);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_write_msgram
+===========================================================================*/
+/**
+
+  Copies data from local buffer into Tx FIFO located at MSG RAM
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+  @param[in]  write_ind Index to start wrting from.
+  @param[in]  buffer    Buffer to copy from.
+  @param[in]  size      Size of the data in the buffer.
+
+  @return     New write index.
+
+  @sideeffects  None.
+
+  @dependencies It should be invoked within tx_link_lock protection.
+*/
+/*=========================================================================*/
+static uint32 xport_rpm_write_msgram
+(
+  xport_rpm_ctx_type *ctx_ptr,
+  uint32 write_ind,
+  uint32 *buffer,
+  uint32 size
+)
+{
+  uint32 remaining = ctx_ptr->tx_fifo_size - write_ind;
+  uint32 *buffer_end;
+  volatile uint32* write_ptr = (volatile uint32*)&ctx_ptr->tx_fifo[write_ind];
+
+  if (remaining <= size)
+  {
+    buffer_end = (uint32*)((char*)buffer + remaining);
+
+    /* write in 32bit increments due to MSG RAM access requirement */
+    while (buffer < buffer_end)
+    {
+      *write_ptr++ = *buffer++;
+    }
+
+    size -= remaining;
+    write_ptr = (volatile uint32*)&ctx_ptr->tx_fifo[0];
+  }
+
+  buffer_end = (uint32*)((char*)buffer + size);
+
+  /* write in 32bit increments due to MSG RAM access requirement */
+  while (buffer < buffer_end)
+  {
+    *write_ptr++ = *buffer++;
+  }
+
+  return (char*)write_ptr - &ctx_ptr->tx_fifo[0];
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_send_cmd
+===========================================================================*/
+/**
+
+  Helper to send a single command.
+
+  @param[in]  ctx_ptr           Pointer to transport context.
+  @param[in]  cmd               buffer containing the command
+  @param[in]  cmd_size          Size of command buffer.
+  @param[in]  data              buffer containing the data
+  @param[in]  data_size         Size of data buffer.
+
+  @return     None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+static glink_err_type xport_rpm_send_cmd
+(
+  xport_rpm_ctx_type  *ctx_ptr,
+  uint32              *cmd,
+  uint32               cmd_size,
+  uint32              *data,
+  uint32               data_size
+)
+{
+  uint32 total_size = cmd_size + data_size;
+  uint32 reserve_size = ROUNDUP64(total_size);
+  uint32 write_ind, read_ind, avail_size;
+
+  glink_os_cs_acquire(ctx_ptr->tx_link_lock);
+
+  write_ind = ctx_ptr->tx_desc->write_ind;
+  read_ind = ctx_ptr->tx_desc->read_ind;
+  avail_size = write_ind < read_ind ? read_ind - write_ind :
+               ctx_ptr->tx_fifo_size - write_ind + read_ind;
+
+  if (reserve_size + sizeof(uint64_t) > avail_size)
+  {
+    glink_os_cs_release(ctx_ptr->tx_link_lock);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  XPORT_RPM_LOG("send cmd", ctx_ptr->pcfg->remote_ss, cmd[0]);
+
+  write_ind
+    = xport_rpm_write_msgram( ctx_ptr, write_ind,
+                              cmd, ROUNDUP32( cmd_size ) );
+
+  if (data != NULL)
+  {
+    write_ind
+      = xport_rpm_write_msgram( ctx_ptr, write_ind,
+                                data, ROUNDUP32( data_size ) );
+  }
+
+  /* add alignment bytes to Tx FIFO */
+  write_ind += (reserve_size - total_size) & (~3);
+
+  if (write_ind >= ctx_ptr->tx_fifo_size)
+  {
+    write_ind -= ctx_ptr->tx_fifo_size;
+  }
+
+  ctx_ptr->tx_desc->write_ind = write_ind;
+
+  xport_rpm_send_event(ctx_ptr);
+
+  glink_os_cs_release(ctx_ptr->tx_link_lock);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_version
+===========================================================================*/
+/**
+
+  Transmit a version command for local negotiation -
+  expected response is to be delivered via glink_rx_cmd_version_ack().
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  version   Version to be sent.
+  @param[in]  feature   Features to be sent.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32 version,
+  uint32 features
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_VERSION_REQ);
+  cmd[0] |= XPORT_RPM_SET_VERSION(version);
+  cmd[1] = features;
+
+  if(xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    dprintf(CRITICAL, "%s:%d: Send Version Failed\n", __func__, __LINE__);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_version_ack
+===========================================================================*/
+/**
+
+  Transmit a version ack for remote negotiation.
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  version   Version to be sent.
+  @param[in]  feature   Features to be sent.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_version_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32 version,
+  uint32 features
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_VERSION_ACK);
+  cmd[0] |= XPORT_RPM_SET_VERSION(version);
+  cmd[1] = features;
+
+  if (xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    dprintf(CRITICAL, "%s:%d: Send Version ACK Failed", __func__, __LINE__);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_set_version
+===========================================================================*/
+/**
+
+  Signals that negotiation is complete and the transport can now
+  do version-specific initialization.
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  version   Version to be used.
+  @param[in]  feature   Features to be used.
+
+  @return     Capabilities.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+uint32 xport_rpm_set_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32 version,
+  uint32 features
+)
+{
+  return GLINK_CAPABILITY_SIG_SUPPORT | GLINK_CAPABILITY_INTENTLESS;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_open
+===========================================================================*/
+/**
+
+  Sends the open command - expected response is to be delivered
+  via glink_rx_cmd_ch_open_ack().
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  lcid     Local channel ID.
+  @param[in]  name     Channel name.
+  @param[in]  prio     Requested xport priority by channel.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_ch_open
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid,
+  const char *name,
+  glink_xport_priority prio
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_OPEN_CHANNEL);
+  cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+  cmd[1] =  strlen(name) + 1;
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), (void*)name, cmd[1]);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_close
+===========================================================================*/
+/**
+
+  Sends the close command - expected response is to be delivered
+  via glink_rx_cmd_ch_close_ack().
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  lcid     Local channel ID.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_ch_close
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd;
+
+  cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_CLOSE_CHANNEL);
+  cmd |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_remote_open_ack
+===========================================================================*/
+/**
+
+  Sends the remote open ACK command.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  rcid     Remote channel ID.
+  @param[in]  prio     send negotiated xport priority to remote side.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_ch_remote_open_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32 rcid,
+  glink_xport_priority prio
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd;
+
+  cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_OPEN_CHANNEL_ACK);
+  cmd |= XPORT_RPM_SET_CHANNEL_ID(rcid);
+
+  if (xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    //ERR_FATAL("send Open Ack failed", 0, 0, 0);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_remote_close_ack
+===========================================================================*/
+/**
+
+  Sends the remote close ACK command.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  rcid     Remote channel ID.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_ch_remote_close_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32 rcid
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd;
+
+  cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_CLOSE_CHANNEL_ACK);
+  cmd |= XPORT_RPM_SET_CHANNEL_ID(rcid);
+
+  if (xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    dprintf(CRITICAL, "%s:%d: Send Clock ACK failed\n", __func__, __LINE__);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx
+===========================================================================*/
+/**
+
+  Send a data packet or a fragment of it.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  lcid     Local channel ID.
+  @param[in]  pctx     Packet TX context.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid,
+  glink_core_tx_pkt_type *pctx
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[4];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_TX_DATA);
+  cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+  cmd[1] = 0;
+  cmd[2] = pctx->size;
+  cmd[3] = 0;
+
+  pctx->size_remaining = 0;
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), (void*)pctx->data, pctx->size);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_set_sigs
+===========================================================================*/
+/**
+
+  Sends the local channel signals as per the specified 32-bit mask.
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  lcid      Local channel ID.
+  @param[in]  sigs      Signal mask.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_set_sigs
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid,
+  uint32 sigs
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_TX_SIGNALS);
+  cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+  cmd[1] = sigs;
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_negotiate_features
+===========================================================================*/
+/**
+
+  Callback to verify feature set.
+
+  @param[in]  if_ptr        Pointer to transport interface.
+  @param[in]  version_ptr   Pointer to version descriptor.
+  @param[in]  features      Proposed feature set.
+
+  @return     0.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+uint32 xport_rpm_negotiate_features(
+  glink_transport_if_type *if_ptr,
+  const glink_core_version_type *version_ptr,
+  uint32 features)
+{
+  return 0;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_poll
+===========================================================================*/
+/**
+
+  Poll of RPM transport.
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_poll( xport_rpm_ctx_type *ctx_ptr )
+{
+  uint32 write_ind, read_ind;
+  boolean stop_processing = FALSE;
+
+  if (ctx_ptr->reset == TRUE)
+  {
+    /* reset flag has been set after SSR, notify link up */
+    ctx_ptr->reset = FALSE;
+    ctx_ptr->xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)ctx_ptr);
+  }
+
+  glink_os_cs_acquire(ctx_ptr->rx_link_lock);
+
+  /* Process pending commands and data */
+  write_ind = ctx_ptr->rx_desc->write_ind;
+  read_ind = ctx_ptr->rx_desc->read_ind;
+
+  XPORT_RPM_LOG("RPM ISR write ind", ctx_ptr->pcfg->remote_ss, write_ind);
+  XPORT_RPM_LOG("RPM ISR read ind", ctx_ptr->pcfg->remote_ss, read_ind);
+
+  /* Ensure the index is 64-bit aligned */
+  if ((write_ind & 0x7) != 0)
+  {
+    dprintf(CRITICAL,"%s:%d: Write Index is not aligned: %u\n",__func__, __LINE__, write_ind);
+    ASSERT(0);
+  }
+
+  while (write_ind != read_ind && !stop_processing)
+  {
+    uint32 cmd = MSGRAM_READ32(ctx_ptr, read_ind);
+    uint32 cid = XPORT_RPM_GET_CHANNEL_ID(cmd); // most commands have channel ID
+    uint32 cmd_arg;
+
+    /* it can't wrap aroud here so just inceremt the index */
+    read_ind += sizeof(cmd);
+
+    XPORT_RPM_LOG("Cmd Rx", ctx_ptr->pcfg->remote_ss, cmd);
+
+    switch (XPORT_RPM_GET_CMD_ID(cmd))
+    {
+      case XPORT_RPM_CMD_VERSION_REQ:
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* no need to incerment read_ind here since it will be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version(
+          (glink_transport_if_type *)ctx_ptr,
+          XPORT_RPM_GET_VERSION(cmd), cmd_arg);
+        break;
+
+      case XPORT_RPM_CMD_VERSION_ACK:
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* no need to increment read_ind here since it will be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version_ack(
+          (glink_transport_if_type *)ctx_ptr,
+          XPORT_RPM_GET_VERSION(cmd), cmd_arg);
+        break;
+
+      case XPORT_RPM_CMD_OPEN_CHANNEL:
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+        cmd_arg = ROUNDUP64(cmd_arg);
+
+        read_ind += sizeof(cmd_arg);
+
+        /* channel name should fit into the FIFO */
+        if (cmd_arg == 0 || cmd_arg >= ctx_ptr->rx_fifo_size)
+        {
+          dprintf(CRITICAL, "%s:%d: Invalid name length: %u", __func__, __LINE__, cmd_arg);
+          ASSERT(0);
+        }
+        else
+        {
+          char    tmpstr[ROUNDUP64(GLINK_CH_NAME_LEN)] = {0};
+          uint32  curr = 0;
+          uint32* string_ptr;
+          string_ptr = (uint32 *)&tmpstr[0];
+          while (curr < cmd_arg && curr < sizeof(tmpstr))
+          {
+            CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+            *(string_ptr++) = MSGRAM_READ32(ctx_ptr, read_ind);
+            curr += sizeof(uint32);
+            read_ind += sizeof(uint32);
+          }
+
+          /* add all the unread stuff */
+          read_ind += cmd_arg - curr;
+
+          /* make sure the last character is NULL */
+          tmpstr[sizeof(tmpstr) - 1] = 0;
+
+          ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
+            (glink_transport_if_type *)ctx_ptr, cid, tmpstr, GLINK_XPORT_RPM);
+        }
+
+        break;
+
+      case XPORT_RPM_CMD_CLOSE_CHANNEL:
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_close(
+          //(glink_transport_if_type *)ctx_ptr, XPORT_RPM_GET_CHANNEL_ID(cmd));
+          (glink_transport_if_type *)ctx_ptr, cid);
+
+        /* no need to increment read_ind here since it would be rounded up */
+
+        break;
+
+      case XPORT_RPM_CMD_OPEN_CHANNEL_ACK:
+
+        /* no need to increment read_ind here since it would be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
+            (glink_transport_if_type *)ctx_ptr, cid, GLINK_XPORT_RPM);
+
+        break;
+
+      case XPORT_RPM_CMD_CLOSE_CHANNEL_ACK:
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
+          (glink_transport_if_type *)ctx_ptr, cid);
+
+        /* no need to increment read_ind here since it would be rounded up */
+
+        break;
+
+      case XPORT_RPM_CMD_TX_DATA:
+      {
+        glink_rx_intent_type desc;
+        memset( &desc, sizeof( glink_rx_intent_type), 0 );
+
+        read_ind += sizeof(cmd_arg);
+
+        CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* packet data should fit into the FIFO */
+        if (cmd_arg >= ctx_ptr->rx_fifo_size)
+        {
+          dprintf(CRITICAL, "%s:%d: Invalid packet length: %u",__func__, __LINE__, cmd_arg);
+          ASSERT(0);
+        }
+
+        read_ind += 2*sizeof(cmd_arg);
+
+        CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+        ctx_ptr->pkt_start_ind = read_ind;
+        ctx_ptr->pkt_size = cmd_arg;
+
+        desc.size = cmd_arg;
+        desc.used = cmd_arg;
+        desc.pkt_sz = cmd_arg;
+        desc.iovec = ctx_ptr;
+        desc.vprovider = xport_rpm_pkt_provider;
+
+        read_ind += cmd_arg;
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_put_pkt_ctx(
+          (glink_transport_if_type *)ctx_ptr, cid,
+          &desc, TRUE);
+
+        /* If interrupt was disabled then stop delivering messages */
+        stop_processing = ctx_ptr->irq_mask;
+
+        break;
+      }
+
+      case XPORT_RPM_CMD_TX_SIGNALS:
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* no need to incerement read_ind here since it will be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_remote_sigs(
+          (glink_transport_if_type *)ctx_ptr,
+          cid, cmd_arg);
+        break;
+
+      default:
+      	dprintf(CRITICAL, "%s:%d: Invalid Command: %u\n",__func__, __LINE__, cmd);
+      	ASSERT(0);
+        break;
+    }
+
+    read_ind = ROUNDUP64(read_ind);
+
+    if (read_ind >= ctx_ptr->rx_fifo_size)
+    {
+      read_ind -= ctx_ptr->rx_fifo_size;
+    }
+
+    /* Update the shared read index */
+    ctx_ptr->rx_desc->read_ind = read_ind;
+  }
+
+  glink_os_cs_release(ctx_ptr->rx_link_lock);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+#ifdef GLINK_RPM_PROC
+/*===========================================================================
+FUNCTION      xport_rpm_isr
+===========================================================================*/
+/**
+
+  ISR of RPM transport.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_isr( void )
+{
+  xport_rpm_ctx_type *ctx_ptr  = xport_rpm_get_context();
+
+  return xport_rpm_poll( ctx_ptr );
+}
+#else
+/*===========================================================================
+FUNCTION      xport_rpm_isr
+===========================================================================*/
+/**
+
+  ISR of RPM transport.
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_isr( xport_rpm_ctx_type *ctx_ptr )
+{
+  return xport_rpm_poll( ctx_ptr );
+}
+#endif
+
+
+/*===========================================================================
+FUNCTION      xport_rpm_ssr
+===========================================================================*/
+/**
+
+  Processes SSR event.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_ssr(glink_transport_if_type *if_ptr)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+  ctx_ptr->tx_desc->write_ind = 0;
+  ctx_ptr->rx_desc->read_ind = 0;
+  ctx_ptr->reset = TRUE;
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_wait_link_down
+===========================================================================*/
+/**
+
+  Waits for read/write indicies to be set to 0 by the remote host.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+
+  @return     TRUE if link is down, FALSE otherwise.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+boolean xport_rpm_wait_link_down(glink_transport_if_type *if_ptr)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+  return (ctx_ptr->tx_desc->write_ind == 0 &&
+          ctx_ptr->tx_desc->read_ind == 0  &&
+          ctx_ptr->rx_desc->write_ind == 0 &&
+          ctx_ptr->rx_desc->read_ind == 0);
+}
+
+
+/*===========================================================================
+FUNCTION      xport_rpm_mask_interrupt
+===========================================================================*/
+/**
+
+  Enables or disables interrupts.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  mask     TRUE=mask, FALSE=unmask
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_mask_interrupt(glink_transport_if_type *if_ptr, boolean mask)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+  if (ctx_ptr->irq_mask != mask)
+  {
+    if (mask)
+    {
+      glink_os_disable_interrupt(ctx_ptr->pcfg->irq_in);
+    }
+    else
+    {
+      glink_os_enable_interrupt(ctx_ptr->pcfg->irq_in);
+    }
+
+    ctx_ptr->irq_mask = mask;
+  }
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_init
+===========================================================================*/
+/**
+
+  Initializes RPM transport.
+  Must be called before any other operations are done.
+
+  @param[in]  arg   The argument.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_init(void *arg)
+{
+  uint32 ind;
+  glink_core_transport_cfg_type xport_rpm_cfg = { 0 };
+  uint32 *msg_ram_toc = (uint32*)xport_rpm_msg_ram_toc;
+  xport_rpm_toc_entry_type *entry;
+  uint32 msg_ram_toc_num;
+  char* msg_ram_toc_entry_start = (char*)&msg_ram_toc[XPORT_RPM_TOC_ENTRIES_IDX];
+  dprintf(SPEW, "%s:%d: RPM Transport INIT\n", __func__, __LINE__);
+
+  if (xport_rpm_config_num == 0)
+  {
+    return GLINK_STATUS_SUCCESS;
+  }
+
+  if (msg_ram_toc[XPORT_RPM_TOC_MAGIC_IDX] != XPORT_RPM_TOC_MAGIC)
+  {
+    dprintf(CRITICAL, "%s:%d: RPM Transport Failure: Invalid ToC cookie\n", __func__, __LINE__);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  msg_ram_toc_num = msg_ram_toc[XPORT_RPM_TOC_LENGTH_IDX];
+
+  if (msg_ram_toc_num == 0)
+  {
+    dprintf(SPEW, "%s:%d RPM Transport Success\n", __func__, __LINE__);
+    return GLINK_STATUS_SUCCESS;
+  }
+
+  xport_rpm_ctx = glink_os_calloc(sizeof(*xport_rpm_ctx)*xport_rpm_config_num);
+
+  if (xport_rpm_ctx == NULL)
+  {
+    dprintf(INFO, "%s:%d RPM Transport Failed to allocate context\n", __func__, __LINE__);
+    ASSERT(0);
+  }
+
+  /* Initialize supported version and features */
+  xport_rpm_version.version = 1;
+  xport_rpm_version.features = 0;
+  xport_rpm_version.negotiate_features = &xport_rpm_negotiate_features;
+
+  /* Initialize edges */
+  dprintf(SPEW, "%s:%d: Initialize Edges\n", __func__, __LINE__);
+
+  for (ind = 0; ind < xport_rpm_config_num; ind++)
+  {
+    xport_rpm_ctx[ind].pcfg = xport_rpm_get_config(ind);
+
+    /* Find FIFOs in MSG RAM ToC */
+    for (entry = (xport_rpm_toc_entry_type*)msg_ram_toc_entry_start;
+         (char*)entry < msg_ram_toc_num*sizeof(*entry) + msg_ram_toc_entry_start &&
+           (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL);
+         entry++)
+    {
+      if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->tx_fifo_id)
+      {
+        xport_rpm_ctx[ind].tx_desc = (xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
+        xport_rpm_ctx[ind].tx_desc->write_ind = 0;
+        xport_rpm_ctx[ind].tx_fifo = (char*)(xport_rpm_ctx[ind].tx_desc + 1);
+        xport_rpm_ctx[ind].tx_fifo_size = entry->fifo_size;
+      }
+      else if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->rx_fifo_id)
+      {
+        xport_rpm_ctx[ind].rx_desc =(xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
+        xport_rpm_ctx[ind].rx_desc->read_ind = 0;
+        xport_rpm_ctx[ind].rx_fifo = (char*)(xport_rpm_ctx[ind].rx_desc + 1);
+        xport_rpm_ctx[ind].rx_fifo_size = entry->fifo_size;
+      }
+    }
+
+    if (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL)
+    {
+      /* FIFOs not found in MSG RAM ToC. */
+      xport_rpm_ctx[ind].pcfg = NULL;
+      continue;
+    }
+
+    /* Initialize context */
+    xport_rpm_ctx[ind].tx_link_lock = NULL;
+    xport_rpm_ctx[ind].rx_link_lock = NULL;
+
+    /* Initialize GLink transport interface */
+    xport_rpm_ctx[ind].xport_if.tx_cmd_version = &xport_rpm_tx_cmd_version;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_version_ack = &xport_rpm_tx_cmd_version_ack;
+    xport_rpm_ctx[ind].xport_if.set_version = &xport_rpm_set_version;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_open = &xport_rpm_tx_cmd_ch_open;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_close = &xport_rpm_tx_cmd_ch_close;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_open_ack = &xport_rpm_tx_cmd_ch_remote_open_ack;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_close_ack = &xport_rpm_tx_cmd_ch_remote_close_ack;
+    xport_rpm_ctx[ind].xport_if.tx = &xport_rpm_tx;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_set_sigs = &xport_rpm_tx_cmd_set_sigs;
+    xport_rpm_ctx[ind].xport_if.ssr = &xport_rpm_ssr;
+    xport_rpm_ctx[ind].xport_if.mask_rx_irq = &xport_rpm_mask_interrupt;
+    xport_rpm_ctx[ind].xport_if.poll = (poll_fn)&xport_rpm_poll;
+    xport_rpm_ctx[ind].xport_if.wait_link_down = &xport_rpm_wait_link_down;
+
+    /* TODO: glink transport priority */
+    xport_rpm_ctx[ind].xport_if.glink_priority = GLINK_XPORT_RPM;
+
+    /* Setup GLink configuration */
+    xport_rpm_cfg.name = XPORT_RPM_NAME;
+    xport_rpm_cfg.remote_ss = xport_rpm_ctx[ind].pcfg->remote_ss;
+    xport_rpm_cfg.version = &xport_rpm_version;
+    xport_rpm_cfg.version_count = 1;
+    xport_rpm_cfg.max_cid = 0xFF;
+    xport_rpm_cfg.max_iid = 0;
+    if (glink_core_register_transport(&xport_rpm_ctx[ind].xport_if, &xport_rpm_cfg) !=
+        GLINK_STATUS_SUCCESS)
+    {
+      /* Registration failed, set index to invalid. */
+      xport_rpm_ctx[ind].pcfg = NULL;
+      continue;
+    }
+
+    if ( !glink_os_register_isr( xport_rpm_ctx[ind].pcfg->irq_in,
+                                (os_isr_cb_fn)xport_rpm_isr,
+                                &xport_rpm_ctx[ind]) )
+    {
+       /* ISR registration failed, set index to invalid. */
+      xport_rpm_ctx[ind].pcfg = NULL;
+      continue;
+    }
+
+    /* send link up notification */
+    xport_rpm_ctx[ind].xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)&xport_rpm_ctx[ind].xport_if);
+  }
+
+  return GLINK_STATUS_SUCCESS;
+}
diff --git a/platform/msm_shared/glink/xport_rpm_config.c b/platform/msm_shared/glink/xport_rpm_config.c
new file mode 100644
index 0000000..1fff513
--- /dev/null
+++ b/platform/msm_shared/glink/xport_rpm_config.c
@@ -0,0 +1,92 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include "xport_rpm_config.h"
+#include "smem_type.h"
+#include "glink_os_utils.h"
+#include <platform/iomap.h>
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+
+#define XPORT_RPM_MSG_RAM_BASE        RPM_SS_MSG_RAM_START_ADDRESS_BASE_PHYS
+#define XPORT_RPM_MSG_RAM_SIZE        RPM_SS_MSG_RAM_START_ADDRESS_BASE_SIZE
+
+/** Size of Glink RPM transport ToC in MSG RAM */
+#define XPORT_RPM_MSG_TOC_SIZE        0x100
+
+/*===========================================================================
+                        DATA DECLARATIONS
+===========================================================================*/
+const xport_rpm_config_type xport_rpm_config[] =
+{
+  /* LK->Rpm */
+  {
+    "rpm",                /* Remote host name        */
+    XPORT_RPM_AP2R_ID,    /* Tx FIFO ID in RPM ToC   */
+    XPORT_RPM_R2AP_ID,    /* Rx FIFO ID in RPM ToC   */
+    {                     /* Outgoing interrupt      */
+      8, //DALIPCINT_PROC_RPM,
+      0, //DALIPCINT_GP_0
+    },
+    200                   /* Incoming interrupt      */
+  }
+};
+
+const uint32 xport_rpm_config_num = ARRAY_LENGTH(xport_rpm_config);
+const char* xport_rpm_msg_ram = (char*)XPORT_RPM_MSG_RAM_BASE;
+const uint32* xport_rpm_msg_ram_toc = (uint32*)(XPORT_RPM_MSG_RAM_BASE + XPORT_RPM_MSG_RAM_SIZE - XPORT_RPM_MSG_TOC_SIZE);
+
+/*===========================================================================
+FUNCTION      xport_rpm_get_config
+===========================================================================*/
+/**
+
+  Provides a pointer to transport config strucutre.
+
+  @param[in]  ind    Index of the config
+
+  @return     Pointer to transport config strucutre.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+const xport_rpm_config_type* xport_rpm_get_config(uint32 ind)
+{
+  if (ind >= xport_rpm_config_num)
+  {
+    return NULL;
+  }
+
+  return &xport_rpm_config[ind];
+}
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 04ce64d..1d2bd44 100755
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -142,5 +142,5 @@
 int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info);
 int update_device_tree(void *fdt, const char *, void *, unsigned);
 int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint64_t size, uint64_t addr);
-void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags);
+void *dev_tree_appended(void *kernel, uint32_t kernel_size, uint32_t dtb_offset, void *tags);
 #endif
diff --git a/platform/msm_shared/include/glink.h b/platform/msm_shared/include/glink.h
new file mode 100644
index 0000000..fe5b823
--- /dev/null
+++ b/platform/msm_shared/include/glink.h
@@ -0,0 +1,580 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_H
+#define GLINK_H
+
+/**
+ * @file glink.h
+ *
+ * Public API for the GLink
+ */
+
+/** \defgroup glink GLink
+ * \ingroup SMD
+ *
+ * GLink reliable, in-order, datagram-based interprocessor communication
+ * over a set of supported transport (Shared Memory, UART, BAM, HSIC)
+ *
+ * All ports preserve message boundaries across the interprocessor channel; one
+ * write into the port exactly matches one read from the port.
+ */
+/*@{*/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include <stdlib.h>
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+/** GLink status/return codes */
+typedef enum {
+  GLINK_STATUS_SUCCESS = 0,
+  GLINK_STATUS_FAILURE,
+  GLINK_STATUS_INVALID_PARAM,
+  GLINK_STATUS_NOT_INIT,
+  GLINK_STATUS_OUT_OF_RESOURCES,
+  GLINK_STATUS_NO_TRANSPORT
+}glink_err_type;
+
+/** List of possible suvsystems */
+/**
+  "apss"   Application Processor Subsystem
+  "mpss"   Modem subsystem
+  "lpass"  Low Power Audio Subsystem
+  "dsps"   Sensors Processor
+  "wcnss"  Wireless Connectivity Subsystem
+  "rpm"    Resource Power Manager processor
+*/
+
+/** Max allowed channel name length */
+#define GLINK_CH_NAME_LEN 32
+
+/* Bit position of DTR/CTS/CD/RI bits in control sigs 32 bit signal map */
+#define SMD_DTR_SIG_SHFT 31
+#define SMD_CTS_SIG_SHFT 30
+#define SMD_CD_SIG_SHFT  29
+#define SMD_RI_SIG_SHFT  28
+
+/** Version number for the glink_link_id_type structure */
+#define GLINK_LINK_ID_VER  0x00000001
+
+/** Macro to initialize the link identifier structure with default values.
+ * It memsets the header to 0 and initializes the header field */
+#define GLINK_LINK_ID_STRUCT_INIT(link_id) \
+                          (link_id).xport = 0; \
+                          (link_id).remote_ss = 0; \
+                          (link_id).link_notifier = 0; \
+                          (link_id).handle = 0; \
+                          (link_id).version = GLINK_LINK_ID_VER;
+
+/* GLink tx options */
+/* Whether to block and request for remote rx intent in
+ * case it is not available for this pkt tx */
+#define GLINK_TX_REQ_INTENT      0x00000001
+
+/* If the tx call is being made from single threaded context. GLink tries to
+ * flush data into the transport in glink_tx() context, or returns error if
+ * it is not able to do so */
+#define GLINK_TX_SINGLE_THREADED 0x00000002
+
+/* ======================= glink open cfg options ==================*/
+
+/* Specified transport is just the initial transport and migration is possible
+ * to higher-priority transports.  Without this flag, the open will fail if
+ * the transport does not exist. */
+#define GLINK_OPT_INITIAL_XPORT   0x00000001
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+/** Enums to identify link state */
+typedef enum {
+ GLINK_LINK_STATE_UP,  /* Called after specified link is online */
+ GLINK_LINK_STATE_DOWN /* Called after SSR (before REMOTE_DISCONNECT) */
+} glink_link_state_type;
+
+/** Data structure holding the link state information */
+typedef struct          glink_link_info_t {
+  const char*           xport;      /* Transport name */
+  const char*           remote_ss;  /* Remote subsystem name */
+  glink_link_state_type link_state; /* Link state */
+}glink_link_info_type;
+
+/* Callback function invoked when link goes up/down */
+typedef void (*glink_link_state_notif_cb)
+(
+  glink_link_info_type *link_info, /* Ptr to link information strcuture */
+  void* priv                       /* Client private data */
+);
+
+/**
+ * Opaque handle returned by glink_register_link_state_cb. Client uses this
+ * handle to call glink_deregister_link_state_cb() to deregister their
+ * callback
+ *
+ * Client must not modify or try to interpret this value
+ */
+typedef struct glink_link_notif_data_type * glink_link_handle_type;
+
+/** Data structure to provide link information for the link to monitor */
+typedef struct glink_link_id_t {
+  unsigned int              version; /* This fields identifies the verion of
+                                        the structure. Initialized by
+                                        GLINK_LINK_ID_STRUCT_INIT macro */
+
+  const char*               xport;         /* NULL = any transport */
+  const char*               remote_ss;     /* NULL = any subsystem */
+  glink_link_state_notif_cb link_notifier; /* Notification callback */
+  glink_link_handle_type    handle;  /* Set by glink_register_link_state_cb */
+}glink_link_id_type;
+
+/**
+ * Opaque handle returned by glink_open. Client uses this handle to call into
+ * GLink API for any further activity related to the channel,
+ *
+ * Client must to modify or try to interpret this value
+ */
+typedef struct glink_channel_ctx* glink_handle_type;
+
+/** GLink logical link state notifications */
+typedef enum {
+  /** Channel is fully opened. Both local and remote end have
+      opened channel from their respective ends, and data communication
+      can now take place */
+  GLINK_CONNECTED = 0,
+
+  /** Local side has called glink_close() and remote side has acknowledged
+      this end's close. Client may call glink_open() after this point */
+  GLINK_LOCAL_DISCONNECTED,
+
+  /** Remote side has called glink_close() to close the channel */
+  GLINK_REMOTE_DISCONNECTED
+}glink_channel_event_type;
+
+/** Vector buffer provider type*/
+typedef void* (*glink_buffer_provider_fn)
+(
+  void*  iovec,   /* vector buffer */
+  size_t offset,  /* offset from the beginning of the vector */
+  size_t *size    /* size of the returned contiguous buffer */
+);
+
+/** Data receive notification callback type*/
+typedef void (*glink_rx_notification_cb)
+(
+  glink_handle_type handle,     /* handle for the glink channel */
+  const void        *priv,      /* priv client data passed in glink_open */
+  const void        *pkt_priv,  /* private client data assiciated with the
+                                   rx intent that client queued earlier */
+  const void        *ptr,       /* pointer to the received buffer */
+  size_t            size,       /* size of the packet */
+  size_t            intent_used /* size of the intent used for this packet */
+);
+
+/** Vector receive notification callback type*/
+typedef void (*glink_rxv_notification_cb)
+(
+  glink_handle_type        handle,    /* handle for the glink channel */
+  const void               *priv,     /* priv client data passed in glink_open */
+  const void               *pkt_priv, /* private client data assiciated with the
+                                         rx intent that client queued earlier */
+  void                     *iovec,    /* pointer to the received vector */
+  size_t                   size,      /* size of the packet */
+  size_t                   intent_used, /* size of the intent used for this packet */
+  glink_buffer_provider_fn vprovider, /* Buffer provider for virtual space */
+  glink_buffer_provider_fn pprovider  /* Buffer provider for physical space */
+);
+
+/** Data transmit notification callback type*/
+typedef void (*glink_tx_notification_cb)
+(
+  glink_handle_type handle,    /* handle for the glink channel */
+  const void        *priv,     /* priv client data passed in glink_open */
+  const void        *pkt_priv, /* private client data assiciated with the
+                                  tx pkt that client queued earlier */
+  const void        *ptr,      /* pointer to the transmitted buffer */
+  size_t            size       /* size of the packet */
+);
+
+/** GLink channel state change notification callback type*/
+typedef void (*glink_state_notification_cb)
+(
+  glink_handle_type         handle, /* handle for the glink channel */
+  const void                *priv,  /* priv client data passed in glink_open */
+  glink_channel_event_type  event   /* Notification event */
+);
+
+/** Request for a receive intent of size req_size is queued. The request
+ * originates from the remote side GLink client. Return true if intent will
+ * be queued or false if intent request will be denied. */
+typedef bool (*glink_notify_rx_intent_req_cb)
+(
+  glink_handle_type         handle,   /* handle for the glink channel */
+  const void                *priv,    /* priv client data passed in glink_open */
+  size_t                    req_size  /* Requested size */
+);
+
+/** New intent arrival notification callback type*/
+typedef void (*glink_notify_rx_intent_cb)
+(
+  glink_handle_type         handle,   /* handle for the glink channel */
+  const void                *priv,    /* priv client data passed in glink_open */
+  size_t                    size      /* Intent size */
+);
+
+/** Control signal change notification - Invoked when remote side
+ *  alters its control signals */
+typedef void (*glink_notify_rx_sigs_cb)
+(
+  glink_handle_type  handle,   /* handle for the glink channel */
+  const void         *priv,    /* priv client data passed in glink_open  */
+  uint32_t             prev,     /* Previous remote state */
+  uint32_t             curr      /* Current remote state */
+);
+
+/** rx_intent abort notification. This callback would be invoked for
+ *  every rx_intent that is queued with GLink core at the time the
+ *  remote side or local side decides to close the port */
+typedef void(*glink_notify_rx_abort_cb)
+(
+glink_handle_type  handle,   /* handle for the glink channel */
+const void         *priv,    /* priv client data passed in glink_open  */
+const void         *pkt_priv /* pkt specific private data */
+);
+
+/** tx abort notification. This callback would be invoked if client
+ *   had queued a tx buffer with glink and it had not been transmitted i.e.
+ *   tx_done callback has not been called for this buffer and remote side
+ *   or local side closed the port*/
+typedef void(*glink_notify_tx_abort_cb)
+(
+glink_handle_type  handle,   /* handle for the glink channel */
+const void         *priv,    /* priv client data passed in glink_open  */
+const void         *pkt_priv /* pkt specific private data */
+);
+
+/**
+ * Data Structure for GLink logical channel open configuration
+ *
+ * This structure is used by the clients to open a GLink logical channel
+ * when calling glink_open()
+ */
+typedef struct {
+  /** string name for the transport to use (Optional)*/
+  const char                    *transport;
+
+  /** string name for the remote subsystem to which the user wants to
+      connect */
+  const char                    *remote_ss;
+
+  /** string name for the channel */
+  const char                    *name;
+
+  /** bitfield for specifying various options */
+  unsigned                      options;
+
+  /** Private data for client to maintain context. This data is passed back
+      to client in the notification callbacks */
+  const void                    *priv;
+
+  /** Data receive notification callback. Optional if notify_rxv is provided */
+  glink_rx_notification_cb      notify_rx;
+
+  /** Vector receive notification callback. Optional if notify_rx is provided */
+  glink_rxv_notification_cb     notify_rxv;
+
+  /** Data transmit notification callback */
+  glink_tx_notification_cb      notify_tx_done;
+
+  /** GLink channel state notification callback */
+  glink_state_notification_cb   notify_state;
+
+  /** Intent request from the remote side. Optional */
+  glink_notify_rx_intent_req_cb notify_rx_intent_req;
+
+  /** New intent arrival from the remote side */
+  glink_notify_rx_intent_cb     notify_rx_intent;
+
+  /** Control signal change notification - Invoked when remote side
+   *  alters its control signals. Optional */
+  glink_notify_rx_sigs_cb       notify_rx_sigs;
+
+  /** rx_intent abort notification. This callback would be invoked for
+   *  every rx_intent that is queued with GLink core at the time the
+   *  remote side or local side decides to close the port. Optional */
+  glink_notify_rx_abort_cb      notify_rx_abort;
+
+  /** tx abort notification. This callback would be invoked if client
+  *   had queued a tx buffer with glink and it had not been transmitted i.e.
+  *   tx_done callback has not been called for this buffer and remote side
+  *   or local side closed the port. Optional */
+  glink_notify_tx_abort_cb      notify_tx_abort;
+
+}glink_open_config_type;
+
+/*===========================================================================
+                      GLINK PUBLIC API
+===========================================================================*/
+/**
+ * Regsiters a client specified callback to be invoked when the specified
+ * transport (link) is up/down.
+ *
+ * @param[in]    link_id  Pointer to the configuration structure for the
+ *                        xport(link) to be monitored. See glink.h
+ * @param[in]    priv     Callback data returned to client when callback
+ *                        is invoked.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Puts the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_register_link_state_cb
+(
+  glink_link_id_type *link_id,
+  void* priv
+);
+
+/**
+ * Degsiter the link UP/DOWN notification callback associated with the
+ * provided handle.
+ *
+ * @param[in]    handle  Callback handler returned by
+ *                       glink_register_link_state_cb
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Removes the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_deregister_link_state_cb
+(
+  glink_link_handle_type handle
+);
+
+/**
+ * Opens a logical GLink based on the specified config params
+ *
+ * @param[in]    cfg_ptr  Pointer to the configuration structure for the
+ *                        GLink. See glink.h
+ * @param[out]   handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Allocates channel resources and informs remote host about
+ *               channel open.
+ */
+glink_err_type glink_open
+(
+  glink_open_config_type *cfg_ptr,
+  glink_handle_type      *handle
+);
+
+/**
+ * Closes the GLink logical channel specified by the handle.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Closes local end of the channel and informs remote host
+ */
+glink_err_type glink_close
+(
+  glink_handle_type handle
+);
+
+/**
+ * Transmit the provided buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *data      Pointer to the data buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   options    Flags specifying how transmission for this buffer
+ *                         would be handled. See GLINK_TX_* flag definitions.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_tx
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  const void        *data,
+  size_t            size,
+  uint32_t            options
+);
+
+/**
+ * Transmit the provided vector buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *iovec     Pointer to the vector buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   vprovider  Buffer provider for virtual space
+ *
+ * @param[in]   pprovider  Buffer provider for physical space
+ *
+ * @param[in]   options    Flags specifying how transmission for this buffer
+ *                         would be handled. See GLINK_TX_* flag definitions.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_txv
+(
+  glink_handle_type        handle,
+  const void               *pkt_priv,
+  void                     *iovec,
+  size_t                   size,
+  glink_buffer_provider_fn vprovider,
+  glink_buffer_provider_fn pprovider,
+  uint32_t                   options
+);
+
+/**
+ * Queue one or more Rx intent for the logical GPIC Link channel.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv Per packet private data
+ *
+ * @param[in]   size      Size of buffer
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL allocates rx buffers for receiving packets
+ */
+glink_err_type glink_queue_rx_intent
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  size_t            size
+);
+
+/**
+ * Client uses this to signal to GLink layer that it is done with the received
+ * data buffer. This API should be called to free up the receive buffer, which,
+ * in zero-copy mode is actually remote-side's transmit buffer.
+ *
+ * @param[in]   handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *ptr     Pointer to the received buffer
+ *
+ * @param[in]   reuse    Reuse intent
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL frees the Rx buffer
+ */
+glink_err_type glink_rx_done
+(
+  glink_handle_type handle,
+  const void        *ptr,
+  bool           reuse
+);
+
+/**
+ * Set the 32 bit control signal field. Depending on the transport, it may
+ * take appropriate actions on the set bit-mask, or transmit the entire
+ * 32-bit value to the remote host.
+ *
+ * @param[in]   handle     GLink handle associated with the logical channel
+ *
+ * @param[in]   sig_value  32 bit signal word
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_set
+(
+  glink_handle_type handle,
+  uint32_t            sig_value
+);
+
+/**
+ * Get the local 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_local_get
+(
+  glink_handle_type handle,
+  uint32_t            *sig_value
+);
+
+/**
+ * Get the remote 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_remote_get
+(
+  glink_handle_type handle,
+  uint32_t            *sig_value
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //GLINK_H
diff --git a/platform/msm_shared/include/glink_channel_migration.h b/platform/msm_shared/include/glink_channel_migration.h
new file mode 100644
index 0000000..3693660
--- /dev/null
+++ b/platform/msm_shared/include/glink_channel_migration.h
@@ -0,0 +1,141 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_CH_MGR__H
+#define GLINK_CH_MGR__H
+
+/*===========================================================================
+
+                    GLink channel migration Header File
+
+===========================================================================*/
+
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        FEATURE DEFINITIONS
+===========================================================================*/
+
+/**
+ * This function returns glink_transport_if pointer based on
+ *  XPORT priority
+ *
+ * @param[in]    prio       glink xport prio
+ * @param[in]   remote_ss   remote subsytem name
+ *
+ * @return       pointer to glink_transport_if_type struct
+ *
+ * @sideeffects  NONE
+ */
+glink_transport_if_type *glinki_get_xport_from_prio
+(
+  glink_xport_priority prio,
+  const char *remote_ss
+);
+
+/**
+ * This function negotiated xport priorities and gives best
+ *  available priority
+ *
+ * @param[in]    requested_best_prio priority requested by remote subsytem
+ * @param[in]    current_best_prio   priority requested by channel on local
+                                     side
+ *
+ * @return       Negotiated xport priority
+ *
+ * @sideeffects  NONE
+ */
+glink_xport_priority glinki_negotiate_ch_migration
+(
+  glink_xport_priority requested_prio,
+  glink_xport_priority current_prio
+);
+
+/**
+ * This function searches channel with given name on all available
+ * xports and returns channel context and xport on which channel is
+ * present. These return values are used to negotiate xport priorities
+ * and to decide if channel needs to be migrated from given xport
+ * to negotiated xport
+ *
+ * @param[in]    if_ptr              transport on which channel is opened
+ * @param[in]    name                name of the channel
+ * @param[in]    is_local_channel    flag to notify this function if channel to
+ *	                                 be searched will have state REMOTE_OPEN
+ *                                   or LOCAL_OPEN
+ * @param[out]   present_ch_ctx      channel context to be returned
+ * @param[out]   present_if_ptr      xport pointer on which channel is open
+ *
+ * @return       TRUE  -  if channel found
+ *               FALSE -  if channel is not found
+ *
+ * @sideeffects  NONE
+ */
+boolean glinki_local_channel_exists
+(
+  glink_transport_if_type *if_ptr,
+  glink_transport_if_type **present_if_ptr,
+  const char               *name,
+  glink_channel_ctx_type  **present_ch_ctx,
+  boolean                    is_local_channel
+);
+
+/**
+ * This function sets flag for channel context to represent
+ * that channel is tagged for deletion. This is to cover corner
+ * case where local side might close the channel but channel
+ * context still sticks around and might be found again for
+ * xport negotiation.
+ *
+ * @param[in]    if_ptr  transport on which channel is opened
+ * @param[in]    name    name of the channel
+ * @param[in]    prio    priority of negotiated xport. all channels on
+ *	                     xports other than xport with this prio will be
+ *		                 tagged for deletion
+ *
+ * @return       NONE
+ *
+ * @sideeffects  NONE
+ */
+void glinki_tag_ch_for_deletion
+(
+  glink_transport_if_type *if_ptr,
+  const char              *name,
+  glink_xport_priority    prio
+);
+
+#endif /* GLINK_CHANNEL_MIGRATION_H */
diff --git a/platform/msm_shared/include/glink_core_if.h b/platform/msm_shared/include/glink_core_if.h
new file mode 100644
index 0000000..040bf31
--- /dev/null
+++ b/platform/msm_shared/include/glink_core_if.h
@@ -0,0 +1,512 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_CORE_IF_H
+#define GLINK_CORE_IF_H
+
+/**
+ * @file glink_core_if.h
+ *
+ * Public API for the transport abstraction layer to call into GLINK Core
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+#include "smem_list.h"
+#include "glink.h"
+#include "glink_transport_if.h"
+#include "glink_os_utils.h"
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+typedef struct glink_core_version glink_core_version_type;
+
+struct glink_channel_ctx;
+typedef struct glink_channel_ctx glink_channel_ctx_type;
+
+/**
+ * Transport status
+ */
+typedef enum {
+  GLINK_XPORT_REGISTERED = 0,
+  GLINK_XPORT_NEGOTIATING,
+  GLINK_XPORT_LINK_UP,
+
+}glink_transport_status_type;
+
+struct glink_rx_intent {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type    link;
+
+  void       *data;      /* Pointer to the data buffer to be transmitted */
+  const void *pkt_priv;  /* Per packet private data */
+  size_t     size;       /* Size of data buffer */
+  size_t     used;       /* Actual valid data in *data field */
+  size_t     pkt_sz;     /* Size of the packet */
+  uint32     iid;        /* Intent ID */
+  void       *iovec;     /* Pointer to the data buffer to be transmitted */
+  glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
+  glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
+};
+/** GLink channel states*/
+typedef enum {
+  /** GLink channel state during initialization. No resources have been
+   *  allocated for this channel as neither GLink end has actually opened
+   *  the channel */
+  GLINK_CH_STATE_CLOSED,
+
+  /** GLink channel state when the local side has opened the channel. GLink
+   *  core is waiting for the other end of the channel to open */
+  GLINK_CH_STATE_LOCAL_OPEN,
+
+  /** GLink channel state when it is fully open. This implies that both ends
+   *  of the GLink channel are now open. Data transfer can now take place */
+  GLINK_CH_STATE_OPEN,
+
+  /** GLink channel state when remote side has initiated a OPEN operation. */
+  GLINK_CH_STATE_REMOTE_OPEN,
+
+  /** GLink channel state when remote side has initiated a CLOSE operation.
+   *  Data cannot be transmitted/received any further on this channel */
+  GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE,
+
+  /** GLink channel state when the local side has initiated a CLOSE. This
+   *  would be followed by a GLINK_STATE_CLOSE state transition after
+   *  the remote side has acknowledged the CLOSE request */
+   GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE,
+
+  /** GLink channel state would transition to SLEEP if the underlying
+   *  transport supports low power mode and decides to go into sleep
+   *  due to inactivity for some time or any other reason. */
+  GLINK_CH_STATE_SLEEP,
+
+  /** GLink channel state would transition to AWAKE state when underlying
+   *  transport layer has powered up the hardware */
+  GLINK_CH_STATE_AWAKE
+}glink_ch_state_type;
+
+/** Indicates that transport is now ready to start negotiation using the
+ *  v0 configuration. */
+typedef void (*link_up_fn)
+(
+  glink_transport_if_type *if_ptr    /* Pointer to the interface instance */
+);
+
+/** Receive transport version for remote-initiated version negotiation */
+typedef void (*rx_cmd_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Receive ACK to previous glink_transport_if_type::tx_cmd_version command */
+typedef void (*rx_cmd_version_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Sets the core version used by the transport; called after completing
+ *  negotiation.*/
+typedef void (*set_core_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version  /* Version */
+);
+
+/** Receive remote channel open request; expected response is
+ *  glink_transport_if_type:: tx_cmd_ch_remote_open_ack */
+typedef void (*rx_cmd_ch_remote_open_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  const char              *name,   /* String name for the logical channel */
+  glink_xport_priority    prio     /* priority of xport */
+);
+
+/** This function is invoked by the transport in response to
+ *  glink_transport_if_type:: tx_cmd_ch_open */
+typedef void (*rx_cmd_ch_open_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  glink_xport_priority    prio
+);
+
+/** This function is invoked by the transport in response to
+ *  glink_transport_if_type:: tx_cmd_ch_close */
+typedef void (*rx_cmd_ch_close_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid     /* Local channel ID */
+);
+
+/** Remote channel close request; will result in sending
+ *  glink_transport_if_type:: tx_cmd_ch_remote_close_ack */
+typedef void (*rx_cmd_ch_remote_close_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+);
+
+/** Process local state transition */
+typedef void (*ch_state_local_trans_fn)
+(
+  glink_transport_if_type  *if_ptr,  /* Pointer to the interface instance */
+  uint32                   lcid,     /* Local channel ID */
+  glink_ch_state_type      new_state /* New local channel state */
+);
+
+/** Transport invokes this call on receiving remote RX intent */
+typedef void (*rx_cmd_remote_rx_intent_put_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  uint32                  riid,    /* Remote intent ID */
+  size_t                  size     /* Size of receive intent */
+);
+
+/** Get receive packet context (if successful, should be followed by call to
+    rx_put_pkt_ctx) */
+typedef glink_rx_intent_type* (*rx_get_pkt_ctx_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  uint32                  liid     /* Local intent ID */
+);
+
+/** Receive a packet fragment (must have previously received an rx_cmd_rx_data
+    packet). */
+typedef void (*rx_put_pkt_ctx_fn)
+(
+  glink_transport_if_type *if_ptr,     /* Pointer to the interface instance */
+  uint32                  rcid,        /* Remote channel ID */
+  glink_rx_intent_type    *intent_ptr, /* Fragment ptr */
+  boolean                 complete     /* True if pkt is complete */
+);
+
+/** Transport invokes this call to inform GLink that remote side is
+ *  done with previous transmitted packet. */
+typedef void (*rx_cmd_tx_done_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  uint32                  riid,    /* Remote intent ID */
+  boolean                 reuse    /* Reuse intent */
+);
+
+/** Remote side is requesting an RX intent */
+typedef void (*rx_cmd_remote_rx_intent_req_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  size_t                  size     /* Size of the requested intent */
+);
+
+/** ACK to RX Intent Request */
+typedef void (*rx_cmd_rx_intent_req_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  boolean                 granted  /* True if RX Intent will be queued, FALSE
+                                      if request will not be granted. */
+);
+
+/** If transport was full and could not continue a transmit operation,
+ *  then it will call this function to notify the core that it is ready to
+ *  resume transmission. */
+typedef void (*tx_resume_fn)
+(
+  glink_transport_if_type *if_ptr  /* Pointer to the interface instance */
+);
+
+/** Received 32-bit signals value from remote side. It is passed on to
+ *  the client */
+typedef void (*rx_cmd_remote_sigs_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  rcid,       /* Remote channel ID */
+  uint32                  remote_sigs /* Remote control signals */
+);
+
+/** Channel open config verification */
+typedef boolean(*verify_open_cfg_fn)
+(
+  glink_channel_ctx_type   *ch_ctx    /* Pointer to the channel context */
+);
+
+/** Channel initialization */
+typedef glink_err_type (*channel_init_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel cleanup */
+typedef void (*channel_cleanup_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel receive pkt */
+typedef void(*channel_receive_pkt_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx,  /* Pointer to the channel context */
+  glink_rx_intent_type *intent_ptr      /* Pointer to the intent context */
+);
+
+/** Use remote intent */
+typedef glink_err_type(*use_rm_intent_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx,  /* Pointer to the channel context */
+  glink_core_tx_pkt_type *pctx,         /* Pointer to the packet context */
+  boolean req_intent                    /* Request intent flag */
+);
+
+
+/** Transport specific data pointer that transport may choose fill in
+ * with some data */
+struct glink_core_xport_ctx
+{
+  /* Transport name */
+  char                          xport[32];
+
+  /* Remote subsystem name */
+  char                          remote_ss[32];
+
+  /** Keep track of version array index in use */
+  const glink_core_version_type *version_array;
+
+  /** Keep track of version array index in use */
+  uint32                        version_indx;
+
+  /* Keeps track of the current status of the transport */
+  glink_transport_status_type   status;
+
+  /* Transport's capabilities */
+  uint32                        xport_capabilities;
+
+  /* Free lcid */
+  uint32                        free_lcid;
+
+  /* Keeps track of the open channels for this transport/edge combination */
+  smem_list_type                open_list;
+
+  /* Critical section to protect access to open_list */
+  os_cs_type                    channel_q_cs;
+
+  /* Local channel intents queued so far. This also helps determining liid
+   * when client queues new rx intents locally */
+  uint32                        liid;
+
+  /* Critical section to protect access to liid allocation */
+  os_cs_type                    liid_cs;
+
+  /* channel open config verification */
+  verify_open_cfg_fn            verify_open_cfg;
+
+  /* channel init function */
+  channel_init_fn               channel_init;
+
+  /* channel cleanup function */
+  channel_cleanup_fn            channel_cleanup;
+
+  /* channel receive pkt */
+  channel_receive_pkt_fn        channel_receive_pkt;
+
+  /** Use remote intent */
+  use_rm_intent_fn              use_rm_intent;
+};
+
+/**
+ * Data Structure for Transport abstraction layer to call into GLink Core
+ * for logical channel control state update and data Tx/Rx notifications.
+ */
+struct glink_core_if
+{
+  /** Indicates that transport is now ready to start negotiation using the
+   *  v0 configuration. */
+  link_up_fn                     link_up;
+
+
+  /** Receive transport version for remote-initiated version negotiation */
+  rx_cmd_version_fn              rx_cmd_version;
+
+
+  /** Receive ACK to previous glink_transport_if_type::tx_cmd_version command */
+  rx_cmd_version_ack_fn          rx_cmd_version_ack;
+
+  /** Sets the core version used by the transport; called after completing
+   *  negotiation.*/
+  set_core_version_fn            set_core_version;
+
+  /** Receive remote channel open request; expected response is
+   *  glink_transport_if_type:: tx_cmd_ch_remote_open_ack */
+  rx_cmd_ch_remote_open_fn       rx_cmd_ch_remote_open;
+
+
+  /** This function is invoked by the transport in response to
+   *  glink_transport_if_type:: tx_cmd_ch_open */
+  rx_cmd_ch_open_ack_fn          rx_cmd_ch_open_ack;
+
+
+  /** This function is invoked by the transport in response to
+   *  glink_transport_if_type:: tx_cmd_ch_close */
+  rx_cmd_ch_close_ack_fn         rx_cmd_ch_close_ack;
+
+
+  /** Remote channel close request; will result in sending
+   *  glink_transport_if_type:: tx_cmd_ch_remote_close_ack */
+  rx_cmd_ch_remote_close_fn      rx_cmd_ch_remote_close;
+
+
+  /** Process local state transition */
+  ch_state_local_trans_fn        ch_state_local_trans;
+
+
+  /** Transport invokes this call on receiving remote RX intent */
+  rx_cmd_remote_rx_intent_put_fn rx_cmd_remote_rx_intent_put;
+
+  /** Get receive packet context (if successful, should be followed by call to
+      rx_put_pkt_ctx) */
+  rx_get_pkt_ctx_fn              rx_get_pkt_ctx;
+
+  /** Receive a packet fragment (must have previously received an rx_cmd_rx_data
+      packet). */
+  rx_put_pkt_ctx_fn              rx_put_pkt_ctx;
+
+  /** Transport invokes this call to inform GLink that remote side is
+   *   done with previous transmitted packet. */
+  rx_cmd_tx_done_fn              rx_cmd_tx_done;
+
+  /** Remote side is requesting an RX intent */
+  rx_cmd_remote_rx_intent_req_fn rx_cmd_remote_rx_intent_req;
+
+  /** ACK to RX Intent Request */
+  rx_cmd_rx_intent_req_ack_fn    rx_cmd_rx_intent_req_ack;
+
+  /** Received 32-bit signals value from remote side. It is passed on to
+   *  the client */
+  rx_cmd_remote_sigs_fn          rx_cmd_remote_sigs;
+
+  /** If transport was full and could not continue a transmit operation,
+   *  then it will call this function to notify the core that it is ready to
+   *  resume transmission. */
+  tx_resume_fn                   tx_resume;
+};
+
+/** Feature negotiation function.  The version negotiation starts out using
+ *  the full feature set from the features element and then calls this
+ *  function with a subset passed into the features argument.  This
+ *  function should filter passed in features with the supported feature
+ *  set.  For simple cases, a bitwise AND can be used, but for more
+ *  complicated cases (such as when features are mutually exclusive),
+ *  this function enables a more complex negotiation sequence.
+ */
+typedef uint32 (*negotiate_features_fn)
+(
+  glink_transport_if_type       *if_ptr,      /* Pointer to the interface
+                                                 instance */
+  const glink_core_version_type *version_ptr, /* Version structure */
+  uint32                        features      /* Subset of features based on
+                                                 negotiation */
+);
+
+/**
+ * Version structure
+ */
+struct glink_core_version {
+  uint32                   version;      /* Version number */
+  uint32                   features;     /* Set of features supported in
+                                            this version */
+
+  /** Feature negotiation function.  The version negotiation starts out using
+   *  the full feature set from the features element and then calls this
+   *  function with a subset passed into the features argument.  This
+   *  function should filter passed in features with the supported feature
+   *  set.  For simple cases, a bitwise AND can be used, but for more
+   *  complicated cases (such as when features are mutually exclusive),
+   *  this function enables a more complex negotiation sequence.
+   */
+  negotiate_features_fn    negotiate_features;
+};
+
+/**
+ * Data Structure for Transport abstraction layer to call into GLink Core
+ * while registering with GLink
+ */
+typedef struct {
+  const char                    *name;      /* Name of the transport */
+  const char                    *remote_ss; /* Remote host name */
+  const glink_core_version_type *version;   /* Array of supported versions */
+  size_t                        version_count; /* Number of elements in version[] */
+  uint32                        max_cid;    /* Max channel ID supported by
+                                               transport */
+  uint32                        max_iid;    /* Max Rx intent ID supported by
+                                               transport */
+}glink_core_transport_cfg_type;
+
+/*===========================================================================
+                      PUBLIC FUNCTION DECLARATIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_core_register_transport
+
+DESCRIPTION   Transport calls this API to register its interface with GLINK
+              Core
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            *cfg      Pointer to transport configuration structure.
+
+RETURN VALUE  Standard GLINK error codes.
+
+SIDE EFFECTS  None
+===========================================================================*/
+
+glink_err_type glink_core_register_transport
+(
+  glink_transport_if_type       *if_ptr,
+  glink_core_transport_cfg_type *cfg
+);
+
+#endif //GLINK_CORE_IF_H
+
diff --git a/platform/msm_shared/include/glink_internal.h b/platform/msm_shared/include/glink_internal.h
new file mode 100644
index 0000000..96b0a59
--- /dev/null
+++ b/platform/msm_shared/include/glink_internal.h
@@ -0,0 +1,845 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_INTERNAL_H
+#define GLINK_INTERNAL_H
+
+/*===========================================================================
+
+                    GLink Core Internal Header File
+
+===========================================================================*/
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include "smem_list.h"
+#include "glink.h"
+#include "glink_os_utils.h"
+#include "glink_core_if.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        FEATURE DEFINITIONS
+===========================================================================*/
+#define GLINK_VERSION 0
+#define GLINK_FEATURE_FLAGS 0
+#define GLINK_NUM_HOSTS     7
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+#define GLINK_LOG_EVENT(type, ch_name, xport, remote_ss, param) \
+  glink_mem_log(__FUNCTION__, __LINE__, type, ch_name, xport, remote_ss, param);
+
+#define GLINK_MEM_LOG_SIZE 128
+
+/*===========================================================================
+                           TYPE DEFINITIONS
+===========================================================================*/
+typedef enum {
+  GLINK_EVENT_INIT,
+  GLINK_EVENT_REGISTER_XPORT,
+  GLINK_EVENT_CH_OPEN,
+  GLINK_EVENT_CH_CLOSE,
+  GLINK_EVENT_CH_TX,
+  GLINK_EVENT_CH_Q_RX_INTENT,
+  GLINK_EVENT_CH_RX_DONE,
+  GLINK_EVENT_LINK_UP,
+  GLINK_EVENT_RX_CMD_VER,
+  GLINK_EVENT_RM_CH_OPEN,
+  GLINK_EVENT_CH_OPEN_ACK,
+  GLINK_EVENT_CH_CLOSE_ACK,
+  GLINK_EVENT_CH_REMOTE_CLOSE,
+  GLINK_EVENT_CH_STATE_TRANS,
+  GLINK_EVENT_CH_INTENT_PUT,
+  GLINK_EVENT_CH_RX_DATA,
+  GLINK_EVENT_CH_RX_DATA_FRAG,
+  GLINK_EVENT_CH_GET_PKT_CTX,
+  GLINK_EVENT_CH_PUT_PKT_CTX,
+  GLINK_EVENT_CH_TX_DONE,
+  GLINK_EVENT_CH_SIG_SET,
+  GLINK_EVENT_CH_SIG_L_GET,
+  GLINK_EVENT_CH_SIG_R_GET,
+  GLINK_EVENT_XPORT_INTERNAL,
+}glink_log_event_type;
+
+typedef struct _glink_channel_intents_type {
+  /* Critical section to protest access to intent queues */
+  os_cs_type                    intent_q_cs;
+
+  /* Event that glink_tx waits on and blocks until remote rx_intents
+  * are available */
+  os_event_type                 rm_intent_avail_evt;
+
+  /* Size of requested intent that this channel wait on */
+  size_t                        rm_intent_req_size;
+
+  /* Linked list of remote Rx intents. Data can be transmitted only when
+  * remote intents are available */
+  smem_list_type                remote_intent_q;
+
+  /* Linked list of remote Rx intents which local GLink core has used to
+  * transmit data, and are pending Tx complete */
+  smem_list_type                remote_intent_pending_tx_q;
+
+  /* Linked list of local Rx intents. Data can be received only when
+  * local intents are available */
+  smem_list_type                local_intent_q;
+
+  /* Linked list of remote Rx intents held by the clients */
+  smem_list_type                local_intent_client_q;
+
+  /* Read intent being gathered */
+  glink_rx_intent_type          *cur_read_intent;
+
+} glink_channel_intents_type;
+
+struct glink_channel_ctx {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type           link;
+
+  /* Channel name */
+  char                          name[GLINK_CH_NAME_LEN];
+
+  /* Local channel ID */
+  uint32                        lcid;
+
+  /* Remote Channel ID */
+  uint32                        rcid;
+
+  /* Channel state */
+  glink_ch_state_type           state;
+
+  /* Channel local control signal state */
+  uint32                        local_sigs;
+
+  /* Channel remote control signal state */
+  uint32                        remote_sigs;
+
+  /* Critical section to protect tx operations */
+  os_cs_type                    tx_cs;
+
+  /* channel intent collection */
+  glink_channel_intents_type    *pintents;
+
+  /* Interface pointer with with this channel is registered */
+  glink_transport_if_type       *if_ptr;
+
+  /** Private data for client to maintain context. This data is passed back
+   * to client in the notification callbacks */
+  const void                    *priv;
+
+  /** Data receive notification callback */
+  glink_rx_notification_cb      notify_rx;
+
+  /** Vector receive notification callback */
+  glink_rxv_notification_cb      notify_rxv;
+
+  /** Data transmit notification callback */
+  glink_tx_notification_cb      notify_tx_done;
+
+  /** GLink channel state notification callback */
+  glink_state_notification_cb   notify_state;
+
+  /** Intent request from the remote side */
+  glink_notify_rx_intent_req_cb notify_rx_intent_req;
+
+  /** New intent arrival from the remote side */
+  glink_notify_rx_intent_cb     notify_rx_intent;
+
+  /** Control signal change notification - Invoked when remote side
+   *  alters its control signals */
+  glink_notify_rx_sigs_cb       notify_rx_sigs;
+
+  /** rx_intent abort notification. This callback would be invoked for
+  *  every rx_intent that is queued with GLink core at the time the
+  *  remote side or local side decides to close the port. Optional */
+  glink_notify_rx_abort_cb      notify_rx_abort;
+
+  /** tx abort notification. This callback would be invoked if client
+  *   had queued a tx buffer with glink and it had not been transmitted i.e.
+  *   tx_done callback has not been called for this buffer and remote side
+  *   or local side closed the port. Optional */
+  glink_notify_tx_abort_cb      notify_tx_abort;
+
+  /* glink transport if pointer for preferred channel */
+  glink_transport_if_type       *req_if_ptr;
+
+  /* reference count for no of times channel open/close has been called */
+  uint32                        ref_count;
+
+  /* flag to check if channel is marked for deletion
+   * This is workaround to prevent channel migration algorithm from finding channel
+   * which should be closed but has not been closed yet. This case occurs when glink_close
+   * is called for closing channel on initial xport and it is being opened on other xport.
+   * This may lead to remote side opening channel on neogitated xport from which local side
+   * will get remote open again. In this case channel to be closed will be found for negotiation
+   * on initial xport again and channel migration algorithm will be triggered(again)  */
+  boolean                       tag_ch_for_close;
+
+  /* save glink open config options */
+  uint32 ch_open_options;
+};
+
+
+typedef struct _glink_mem_log_entry_type {
+  const char *func;
+  uint32 line;
+  glink_log_event_type type;
+  const char *msg;
+  const char *xport;
+  const char *remote_ss;
+  uint32 param;
+} glink_mem_log_entry_type;
+
+/* Structure to store link notification callbacks */
+typedef struct {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type       link;
+
+  const char*               xport;         /* NULL = any transport */
+  const char*               remote_ss;     /* NULL = any subsystem */
+  glink_link_state_notif_cb link_notifier; /* Notification callback */
+  void                      *priv;         /* Notification priv ptr */
+} glink_link_notif_data_type;
+
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+extern os_cs_type *glink_transport_q_cs;
+extern const char *glink_hosts_supported[GLINK_NUM_HOSTS];
+extern smem_list_type glink_registered_transports[];
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_link_up
+
+DESCRIPTION   Indicates that transport is now ready to start negotiation
+              using the v0 configuration
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_link_up
+(
+  glink_transport_if_type *if_ptr
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version
+
+DESCRIPTION   Receive transport version for remote-initiated version
+              negotiation
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version   Remote Version
+
+            features  Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version_ack
+
+DESCRIPTION   Receive ACK to previous glink_transport_if::tx_cmd_version
+              command
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version   Remote Version
+
+            features  Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_open
+
+DESCRIPTION   Receive remote channel open request; Calls
+              glink_transport_if:: tx_cmd_ch_remote_open_ack as a result
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+            *name     String name for logical channel
+
+            prio      requested xport priority from remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_open
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  rcid,
+  const char              *name,
+  glink_xport_priority    prio
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_open_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if:: tx_cmd_ch_open
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid      Local Channel ID
+
+            prio      Negotiated xport priority obtained from remote side
+                      after negotiation happened on remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_open_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  lcid,
+  glink_xport_priority    prio
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_close_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if_type:: tx_cmd_ch_close
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid      Local Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_close_ack
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid     /* Local channel ID */
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_close
+
+DESCRIPTION   Remote channel close request; will result in sending
+              glink_transport_if_type:: tx_cmd_ch_remote_close_ack
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_close
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+);
+
+/*===========================================================================
+FUNCTION      glink_ch_state_local_trans
+
+DESCRIPTION   Process local state transition
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_ch_state_local_trans
+(
+  glink_transport_if_type  *if_ptr,  /* Pointer to the interface instance */
+  uint32                   lcid,     /* Local channel ID */
+  glink_ch_state_type      new_state /* New local channel state */
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_put_pkt_ctx
+
+DESCRIPTION   Transport invokes this call to receive a packet fragment (must
+              have previously received an rx_cmd_rx_data packet)
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            *intent_ptr  Pointer to the intent fragment
+
+            complete     True if pkt is complete
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_put_pkt_ctx
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  glink_rx_intent_type    *intent_ptr, /* Fragment ptr */
+  boolean                 complete     /* True if pkt is complete */
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_remote_sigs
+
+DESCRIPTION   Transport invokes this call to inform GLink of remote side
+              changing its control signals
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            remote_sigs  Remote signal state.
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_remote_sigs
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  rcid,       /* Remote channel ID */
+  uint32                  remote_sigs /* Remote control signals */
+);
+
+/*===========================================================================
+FUNCTION      glink_tx_resume
+
+DESCRIPTION   If transport was full and could not continue a transmit
+              operation, then it will call this function to notify the core
+              that it is ready to resume transmission.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_tx_resume
+(
+  glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/*===========================================================================
+FUNCTION      glink_set_core_version
+
+DESCRIPTION   Sets the core version used by the transport; called after
+              completing negotiation.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+             version   Negotiated transport version
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_set_core_version
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version  /* Version */
+);
+
+/*===========================================================================
+                           CHANNEL CONTEXT APIS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glinki_ch_is_fully_opened
+
+DESCRIPTION   Determine if both the local and remote channel state is fully
+              open
+
+ARGUMENTS     *cfg_ptr   - Pointer to channel context
+
+RETURN VALUE  True if fully opened, FALSE otherwise.
+
+SIDE EFFECTS  None
+===========================================================================*/
+boolean glinki_ch_is_fully_opened
+(
+  glink_channel_ctx_type *ctx
+);
+
+
+/*===========================================================================
+FUNCTION      glinki_ch_push_local_rx_intent
+
+DESCRIPTION   Create and push a local receive intent to internal list
+
+ARGUMENTS     *cfg_ptr   - Pointer to channel context
+
+              *pkt_priv  - Client-provided opaque data
+
+              size       - Size of Receive Intent
+
+RETURN VALUE  Pointer to the new intent
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_push_local_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  const void             *pkt_priv,
+  size_t                 size
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_get_local_rx_intent
+
+DESCRIPTION   Lookup a local receive intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              liid        - Local Receive Intent ID
+
+RETURN VALUE  Pointer to the intent or NULL if not match is found.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_get_local_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  uint32                 liid
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_remove_local_rx_intent
+
+DESCRIPTION   Removes Local Receive Intent ID
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              liid        - Local Receive Intent ID
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_remove_local_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  uint32                 liid
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_set_local_rx_intent_notified
+
+DESCRIPTION   Sets the state of the intent as client-notified
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *intent_ptr - Pointer to the receive intent
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_set_local_rx_intent_notified
+(
+  glink_channel_ctx_type *ctx,
+  glink_rx_intent_type   *intent_ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_get_local_rx_intent_notified
+
+DESCRIPTION   Lookup a Local Receive Intent ID that is in the client-notified
+              state
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *ptr        - Data pointer of receive buffer from client
+                            (passed in through glink_rx_done)
+
+RETURN VALUE  Pointer to the intent or NULL if not match is found.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_get_local_rx_intent_notified
+(
+  glink_channel_ctx_type *ctx,
+  void                   *ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_remove_local_rx_intent_notified
+
+DESCRIPTION   Removes the Local Receive Intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *intent_ptr - Pointer to the receive intent
+
+RETURN VALUE  New channel context or NULL
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_channel_ctx_type* glinki_ch_remove_local_rx_intent_notified
+(
+  glink_channel_ctx_type *ctx,
+  glink_rx_intent_type   *intent_ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_push_remote_rx_intent
+
+DESCRIPTION   Adds a new Remote Receive Intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              size        - Size of the Remote Receive Intent
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_push_remote_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  size_t                 size
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_pop_remote_rx_intent
+
+DESCRIPTION   Removes a Remote Receive Intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              size        - Size of the Remote Receive Intent
+
+              *riid_ptr   - Pointer to the Remote Receive Intent
+
+RETURN VALUE  Standard GLink Err code.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_err_type glinki_ch_pop_remote_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  size_t                size,
+  uint32                *riid_ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_get_tx_pending_remote_done
+
+DESCRIPTION   Lookup packet transmit context for a packet that is waiting for
+              the remote-done notification.
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              riid        - Remote Receive Intent ID
+
+RETURN VALUE  Pointer to the transmit packet context or NULL if not match is
+              found.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_core_tx_pkt_type* glinki_ch_get_tx_pending_remote_done
+(
+  glink_channel_ctx_type *ctx,
+  uint32                 riid
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_remove_tx_pending_remote_done
+
+DESCRIPTION   Removes a packet transmit context for a packet that is waiting
+              for the remote-done notification.
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *tx_pkt     - Pointer to the packet context to remove
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_remove_tx_pending_remote_done
+(
+  glink_channel_ctx_type       *ctx,
+  glink_core_tx_pkt_type       *tx_pkt
+);
+
+/*===========================================================================
+FUNCTION      glinki_add_ch_to_xport
+
+DESCRIPTION   Add remote/local channel context to xport open channel queue
+
+ARGUMENTS     *if_ptr            - Pointer to xport if on which channel is to
+                                   be opened
+              *req_if_ptr        - Pointer to xport if on which channel
+			                       actually wants to open
+              *ch_ctx            - channel context
+              **allocated_ch_ctx - Pointer to channel context pointer
+              local_open         - flag to determine if channel is opened
+			                       locally or remotely
+              migration state    - flag to identify whether channel migration
+			                       negotiation is done
+                                   TRUE - negotiation is not complete
+                                   FALSE - negotiation is complete.
+								   channel is being opened on same xport as negotiated
+              prio               - negotiated xport priority
+			                       (used to send priority via remote_open_ack to
+								    remote side)
+              *tx_pkt            - Pointer to the packet context to remove
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_err_type glinki_add_ch_to_xport
+(
+  glink_transport_if_type  *if_ptr,
+  glink_transport_if_type  *req_if_ptr,
+  glink_channel_ctx_type   *ch_ctx,
+  glink_channel_ctx_type   **allocated_ch_ctx,
+  unsigned int              local_open,
+  boolean                  migration_state,
+  glink_xport_priority     prio
+);
+
+void glink_mem_log
+(
+  const char *func,
+  uint32 line,
+  glink_log_event_type type,
+  const char *msg,
+  const char *xport,
+  const char *remote_ss,
+  uint32 param
+);
+
+/*===========================================================================
+FUNCTION      glink_core_setup
+===========================================================================*/
+/**
+
+  Initializes internal core functions based on the transport capabilities.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup(glink_transport_if_type *if_ptr);
+
+/*===========================================================================
+FUNCTION      glink_core_setup_full_xport
+===========================================================================*/
+/**
+
+  Initializes internal core functions for the full-featured transport.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup_full_xport(glink_transport_if_type *if_ptr);
+
+/*===========================================================================
+FUNCTION      glink_core_setup_intentless_xport
+===========================================================================*/
+/**
+
+  Initializes internal core functions for the intentless transport.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr);
+
+#endif /* GLINK_INTERNAL_H */
diff --git a/platform/msm_shared/include/glink_os_type.h b/platform/msm_shared/include/glink_os_type.h
new file mode 100644
index 0000000..091ad05
--- /dev/null
+++ b/platform/msm_shared/include/glink_os_type.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OS_TYPE_H
+#define OS_TYPE_H
+
+/*===========================================================================
+
+                      G-Link OS Specific types/functions
+
+===========================================================================*/
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include <string.h>
+#include <assert.h>
+
+/*===========================================================================
+                        MACRO DEFINITIONS
+===========================================================================*/
+
+#define OS_LOG_INIT( ) glink_os_log_init()
+
+/*===========================================================================
+                        TYPE DEFINITIONS
+===========================================================================*/
+#define DALSYS_SYNC_OBJ_SIZE_BYTES           40
+#define DALSYS_EVENT_OBJ_SIZE_BYTES          80
+
+typedef bool boolean;
+typedef uint64_t uint64;
+typedef uint32_t uint32;
+typedef long int32;
+#define TRUE 1
+#define FALSE 0
+
+typedef struct DALSYSEventObj  DALSYSEventObj;
+
+struct DALSYSEventObj
+{
+  unsigned long long _bSpace[DALSYS_EVENT_OBJ_SIZE_BYTES/sizeof(unsigned long long)];
+};
+
+
+typedef struct DALSYSSyncObj  DALSYSSyncObj;
+struct DALSYSSyncObj
+{
+  unsigned long long _bSpace[DALSYS_SYNC_OBJ_SIZE_BYTES/sizeof(unsigned long long)];
+};
+
+typedef DALSYSSyncObj os_cs_type;
+
+typedef void ( *os_timer_cb_fn )( void *cb_data );
+
+typedef struct
+{
+  void * dal_event;
+  DALSYSEventObj    dal_obj_memory;
+}os_event_type;
+
+typedef void ( *os_isr_cb_fn )( void *cb_data );
+
+typedef struct os_ipc_intr_struct
+{
+  uint32_t processor;
+  uint32_t irq_out;
+} os_ipc_intr_type;
+
+#endif /* OS_TYPE_H */
diff --git a/platform/msm_shared/include/glink_os_utils.h b/platform/msm_shared/include/glink_os_utils.h
new file mode 100644
index 0000000..e0a1613
--- /dev/null
+++ b/platform/msm_shared/include/glink_os_utils.h
@@ -0,0 +1,258 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OS_UTILS_H
+#define OS_UTILS_H
+
+/*===========================================================================
+
+                      G-Link OS Specific types/functions
+
+===========================================================================*/
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include <glink_os_type.h>
+
+/*===========================================================================
+                        MACRO DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                        TYPE DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glink_os_cs_init
+===========================================================================*/
+/**
+  Initializes a Critical Section
+
+  @param[in]  cs   pointer to critical section object allocated by caller.
+
+  @return
+  TRUE if critical section was initialized, FALSE otherwise
+*/
+/*=========================================================================*/
+bool glink_os_cs_init( os_cs_type *cs );
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_acquire
+===========================================================================*/
+/**
+  Lock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_acquire( os_cs_type *cs );
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_release
+===========================================================================*/
+/**
+  Unlock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_release( os_cs_type *cs );
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_create
+===========================================================================*/
+/**
+  Create and initializesa Critical Section
+
+  @return     The critical section.
+*/
+/*=========================================================================*/
+os_cs_type *glink_os_cs_create( void );
+
+/*===========================================================================
+  FUNCTION  glink_os_malloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap.  The region should be
+  freed using \c glink_os_free when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_malloc( size_t size );
+
+/*===========================================================================
+  FUNCTION  glink_os_calloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap and initialize with
+  the zeroes.  The region should be freed using \c glink_os_free
+  when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_calloc( size_t size );
+
+/*===========================================================================
+  FUNCTION  glink_os_free
+===========================================================================*/
+/**
+  Free a region of memory that was allocated by \c glink_os_malloc.
+
+  @param[in] pMem    The reference to the region of memory to be freed.
+
+  @return    NA
+*/
+/*=========================================================================*/
+void glink_os_free( void *pMem );
+
+/*===========================================================================
+  FUNCTION  glink_os_string_copy
+===========================================================================*/
+/**
+  Copies the source string into the destination buffer until
+  size is reached, or until a '\0' is encountered.  If valid,
+  the destination string will always be NULL deliminated.
+
+  @param[in] dst    The destination string, contents will be updated.
+  @param[in] src    The source string
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+char *glink_os_string_copy(char *dst, const char *src, uint32_t size);
+
+/*===========================================================================
+  FUNCTION  glink_os_string_compare
+===========================================================================*/
+/**
+  Compares two strings delimited by size or NULL character.
+
+  @param[in] s1     String 1
+  @param[in] s2     String 2
+  @param[in] size   The maximum number of characters to compare
+
+  @return
+  0 if strings are identical (up to size characters), non-zero otherwise
+*/
+/*==========================================================================*/
+long glink_os_string_compare( const char *s1, const char *s2, uint32_t size );
+
+/*===========================================================================
+  FUNCTION  glink_os_copy_mem
+===========================================================================*/
+/**
+  Copies the source buffer into the destination buffer.
+
+  @param[in] dst    The destination, contents will be updated.
+  @param[in] src    The source
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+void glink_os_copy_mem(void *dst, const void *src, uint32_t size);
+
+/*===========================================================================
+  FUNCTION      glink_os_register_isr
+===========================================================================*/
+/**
+  Registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to register for
+  @param[in]  isr       Callback to be invoked when interrupt fires
+  @param[in]  cb_data   Data to be provided to the callback
+
+  @return     true if registration was successful, false otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_register_isr( uint32_t irq_in, os_isr_cb_fn isr, void *cb_data );
+
+/*===========================================================================
+  FUNCTION      glink_os_deregister_isr
+===========================================================================*/
+/**
+  De-registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to deregister for
+
+  @return     TRUE if de-registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_deregister_isr( uint32_t irq_in );
+
+/*===========================================================================
+  FUNCTION      glink_os_enable_interrupt
+===========================================================================*/
+/**
+  Enables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to enable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_enable_interrupt( uint32_t irq_in );
+
+/*===========================================================================
+  FUNCTION      glink_os_disable_interrupt
+===========================================================================*/
+/**
+  Disables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to disable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_disable_interrupt( uint32_t irq_in );
+
+bool glink_os_log_init( void );
+
+#endif /* OS_UTILS_H */
diff --git a/platform/msm_shared/include/glink_rpm.h b/platform/msm_shared/include/glink_rpm.h
new file mode 100644
index 0000000..c7cfdeb
--- /dev/null
+++ b/platform/msm_shared/include/glink_rpm.h
@@ -0,0 +1,108 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_RPM_H
+#define GLINK_RPM_H
+
+/**
+ * @file glink_rpm.h
+ *
+ * Public API for the GLink-RPM
+ */
+
+/** \defgroup glink GLink
+ * \ingroup SMD
+ *
+ * GLink reliable, in-order, datagram-based interprocessor communication
+ * over a set of supported transport (Shared Memory, UART, BAM, HSIC)
+ *
+ * All ports preserve message boundaries across the interprocessor channel; one
+ * write into the port exactly matches one read from the port.
+ */
+/*@{*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "glink_os_utils.h"
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+/*================= RESTRICTED API ==========================*/
+/** Note that these API are only supported for RPM client. No other
+ * client may use these as a generic API as the underlying implementation
+ * works only for RPM ports */
+
+
+/**
+ * This API allows the RPM client to poll the transport for any new data
+ * that might have come in. It would *usually* be used when incoming interrupts
+ * are disabled.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_rx_poll
+(
+  glink_handle_type handle
+);
+
+/**
+ * This API allows the RPM client to mask/unmask rx interrupts
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[in]   mask        Whether to mask or un-mask the incoming interrupt
+ *
+ * @param[in]   platform_struct Any platform specific into that transport may
+                                require
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_mask_rx_interrupt
+(
+  glink_handle_type handle,
+  boolean           mask,
+  void              *platform_struct
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //GLINK_RPM_H
+
diff --git a/platform/msm_shared/include/glink_transport_if.h b/platform/msm_shared/include/glink_transport_if.h
new file mode 100644
index 0000000..da9e2bd
--- /dev/null
+++ b/platform/msm_shared/include/glink_transport_if.h
@@ -0,0 +1,353 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_TRANSPORT_IF_H
+#define GLINK_TRANSPORT_IF_H
+
+/**
+ * @file glink_transport_if.h
+ *
+ * Public API for the GLink Core to transport interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include <smem_list.h>
+#include <glink_os_utils.h>
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+/* GLink transport capability bit definitions */
+/* Whether transport supports signalling */
+#define GLINK_CAPABILITY_SIG_SUPPORT 0x00000001
+/* Intentless mode of operation */
+#define GLINK_CAPABILITY_INTENTLESS  0x00000002
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+/* forward declaration */
+struct glink_transport_if;
+typedef struct glink_transport_if   glink_transport_if_type;
+
+struct glink_core_xport_ctx;
+typedef struct glink_core_xport_ctx glink_core_xport_ctx_type;
+
+struct glink_core_if;
+typedef struct glink_core_if        glink_core_if_type;
+
+struct glink_rx_intent;
+typedef struct glink_rx_intent      glink_rx_intent_type;
+
+/* Priority of transports registered with glink */
+typedef enum {
+  GLINK_XPORT_SMEM = 100,
+  GLINK_XPORT_RPM = 100,
+  GLINK_XPORT_SMD = 200,
+  GLINK_XPORT_CP_ENGINE = 300,
+  GLINK_MIN_PRIORITY = GLINK_XPORT_CP_ENGINE,
+  GLINK_INVALID_PRIORITY
+} glink_xport_priority;
+
+/** Glink core -> Xport pkt type definition */
+typedef struct {
+  void       *data;      /* Pointer to the data buffer to be transmitted */
+  const void *pkt_priv;  /* Per packet private data */
+  uint32     iid;        /* Remote intent ID being used to transmit data */
+  size_t     size;       /* Size of data buffer */
+  size_t     size_remaining; /* Size left to transmit */
+  void       *iovec;      /* Pointer to the data buffer to be transmitted */
+  glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
+  glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
+}glink_core_tx_pkt_type;
+
+/** Transmit a version command for local negotiation. The transport would call
+ *  glink_transport_if_type::rx_cmd_version_ack callback as a result */
+typedef void (*tx_cmd_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Transmit a version ack for remote nogotiation */
+typedef void (*tx_cmd_version_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Signals the negotiation is complete and transport can now do version
+ *  specific initialization. Return uint32 transport capabilities bit field */
+typedef uint32 (*set_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Sends OPEN command to transport for transport to do whatever it deems
+ *  necessary to open a GLink logical channel.
+ *  GLink Core expects glink_transport_if_type::rx_cmd_ch_open_ack to be called
+ *  as a result of channel opening. */
+typedef glink_err_type (*tx_cmd_ch_open_fn)
+(
+  glink_transport_if_type *if_ptr,/* Pointer to the interface instance */
+  uint32                  lcid,   /* Local channel ID */
+  const char              *name,  /* String name for the logical channel */
+  glink_xport_priority    prio
+);
+
+/** Sends CLOSE command to transport for transport to do whatever it deems
+ *  necessary to close the specified GLink logical channel.
+ *  GLink Core expects glink_transport_if_type::rx_cmd_ch_close_ack to be
+ *  called as a result of channel closing. */
+typedef glink_err_type (*tx_cmd_ch_close_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                     lcid  /* Local channel ID */
+);
+
+/** Sends the remote open ACK command in response to receiving
+ *  glink_core_if_type::rx_cmd_ch_remote_open */
+typedef void (*tx_cmd_ch_remote_open_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  glink_xport_priority    prio
+);
+
+/** Sends the remote close ACK command in response to receiving
+ *  glink_core_if_type::rx_cmd_ch_remote_close */
+typedef void (*tx_cmd_ch_remote_close_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+);
+
+/** Allocates a receive buffer for the local rx intent */
+typedef glink_err_type (*allocate_rx_intent_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  size_t                  size,       /* Size of Rx intent */
+  glink_rx_intent_type    *intent_ptr /* Intent ptr */
+);
+
+/** Deallocates a receive buffer for the local rx intent */
+typedef glink_err_type (*deallocate_rx_intent_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  glink_rx_intent_type    *intent_ptr /* Intent ptr */
+);
+
+/** Send receive intent ID for a given channel */
+typedef glink_err_type (*tx_cmd_local_rx_intent_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  size_t                  size,    /* Size of Rx intent */
+  uint32                  liid     /* Local indent ID */
+);
+
+/** Send receive done command for an intent for the specified channel */
+typedef void(*tx_cmd_local_rx_done_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  uint32                  liid,    /* Local indent ID */
+  boolean                 reuse    /* Reuse indent */
+);
+
+/** Send a data packet to the transport to be transmitted over the specified
+ *  channel */
+typedef glink_err_type (*tx_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  glink_core_tx_pkt_type  *pctx    /* Packet to be transmitted */
+);
+
+/** Send a intent request to the remote side to have it queue more rx intents
+ *  to unblock this end's tx operation */
+typedef glink_err_type (*tx_cmd_rx_intent_req_fn)
+(
+  glink_transport_if_type *if_ptr,   /* Pointer to the interface instance */
+  uint32                  lcid,      /* Local channel ID */
+  size_t                  size       /* Size of the requested intent */
+);
+
+/** Send the ACK back for the rx intent request send by the other side,
+ *  specifynig whether the request was granted ot not */
+typedef glink_err_type (*tx_cmd_remote_rx_intent_req_ack_fn)
+(
+  glink_transport_if_type *if_ptr,   /* Pointer to the interface instance */
+  uint32                  lcid,      /* Local channel ID */
+  boolean                 granted    /* Whether of not the intent request was
+                                        granted */
+);
+
+/** Sets the local channel signals as per the specified 32-bit mask.
+ *  Transport may also send the 32-bit value as-is to the remote side. */
+typedef glink_err_type (*tx_cmd_set_sigs_fn)
+(
+  glink_transport_if_type *if_ptr,   /* Pointer to the interface instance */
+  uint32                  lcid,      /* Local channel ID */
+  uint32                  sigs       /* Whether of not the intent request was
+                                        granted */
+);
+
+/** Lets the XAL know of SSR on that edge. */
+typedef glink_err_type (*ssr_fn)
+(
+  glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
+);
+
+/** Trigger a poll for any rx data / signals on transport. */
+typedef glink_err_type (*poll_fn)
+(
+  glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
+);
+
+/** Mask/Unmask rx interrupt associated with transport. */
+typedef glink_err_type (*mask_rx_irq_fn)
+(
+  glink_transport_if_type *if_ptr,  /* Pointer to the interface instance */
+  boolean                 mask      /* TRUE-mask, FALSE=unmask */
+);
+
+/** Wait for the link to go down. */
+typedef boolean (*wait_link_down_fn)
+(
+  glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
+);
+
+
+/**
+ * Data Structure for GLink Core to call into transport API
+ *
+ * This structure is used by the GLink core to operate transport
+ * This set of function pointers to to be filled in by the transport
+ * abstraction layer.
+ */
+struct glink_transport_if {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type                link;
+
+  /** Transmit a version command for local negotiation. The transport would
+   * call glink_transport_if_type::rx_cmd_version_ack callback as a result */
+  tx_cmd_version_fn                  tx_cmd_version;
+
+  /** Transmit a version ack for remote nogotiation */
+  tx_cmd_version_ack_fn              tx_cmd_version_ack;
+
+  /** Signals the negotiation is complete and transport can now do version
+   *  specific initialization */
+  set_version_fn                     set_version;
+
+
+  /** Sends OPEN command to transport for transport to do whatever it deems
+   *  necessary to open a GLink logical channel.
+   *  GLink Core expects glink_transport_if_type::rx_cmd_ch_open_ack to be
+   *  called as a result of channel opening. */
+  tx_cmd_ch_open_fn                  tx_cmd_ch_open;
+
+
+  /** Sends CLOSE command to transport for transport to do whatever it deems
+   *  necessary to close the specified GLink logical channel.
+   *  GLink Core expects glink_transport_if_type::rx_cmd_ch_close_ack to be
+   *  called as a result of channel closing. */
+  tx_cmd_ch_close_fn                 tx_cmd_ch_close;
+
+
+  /** Sends the remote open ACK command in response to receiving
+   *  glink_core_if_type::rx_cmd_ch_remote_open */
+  tx_cmd_ch_remote_open_ack_fn       tx_cmd_ch_remote_open_ack;
+
+  /** Sends the remote close ACK command in response to receiving
+   *  glink_core_if_type::rx_cmd_ch_remote_close */
+  tx_cmd_ch_remote_close_ack_fn      tx_cmd_ch_remote_close_ack;
+
+  /** Allocates a receive vector buffer for the local rx intent */
+  allocate_rx_intent_fn               allocate_rx_intent;
+
+  /** Deallocates a receive vector buffer for the local rx intent */
+  deallocate_rx_intent_fn             deallocate_rx_intent;
+
+  /** Send receive intent ID for a given channel */
+  tx_cmd_local_rx_intent_fn          tx_cmd_local_rx_intent;
+
+
+  /** Send receive done command for an intent for the specified channel */
+  tx_cmd_local_rx_done_fn            tx_cmd_local_rx_done;
+
+
+  /** Send a data packet to the transport to be transmitted over the specified
+   *  channel */
+  tx_fn                              tx;
+
+   /** Send request to the remote to queue more rx intents */
+  tx_cmd_rx_intent_req_fn            tx_cmd_rx_intent_req;
+
+  /** Send ACK to the remote side's request to queue more rx intents */
+  tx_cmd_remote_rx_intent_req_ack_fn tx_cmd_remote_rx_intent_req_ack;
+
+  /** Sets the local channel signals as per the specified 32-bit mask.
+   *  Transport may also send the 32-bit value as-is to the remote side. */
+  tx_cmd_set_sigs_fn                 tx_cmd_set_sigs;
+
+  /** Lets the XAL know of SSR on that edge. */
+  ssr_fn                             ssr;
+
+  /** Trigger a poll for any rx data / signals on transport. */
+  poll_fn                            poll;
+
+  /** Mask/Unmask rx interrupt associated with transport */
+  mask_rx_irq_fn                     mask_rx_irq;
+
+  /** Wait for the link to go down. */
+  wait_link_down_fn                  wait_link_down;
+
+  /** Transport specific data pointer that transport may choose fill in
+   * with some data */
+  glink_core_xport_ctx_type          *glink_core_priv;
+
+  /** GLINK core interface pointer associated with this transport interface */
+  glink_core_if_type                 *glink_core_if_ptr;
+
+  /* glink transport priority */
+  glink_xport_priority                glink_priority;
+};
+
+#endif //GLINK_TRANSPORT_IF_H
diff --git a/platform/msm_shared/include/glink_vector.h b/platform/msm_shared/include/glink_vector.h
new file mode 100644
index 0000000..863c19a
--- /dev/null
+++ b/platform/msm_shared/include/glink_vector.h
@@ -0,0 +1,155 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GLINK_VECTOR_H
+#define GLINK_VECTOR_H
+
+/*===========================================================================
+
+                    GLink Vector Header File
+
+===========================================================================*/
+
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include "glink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        FEATURE DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                           TYPE DEFINITIONS
+===========================================================================*/
+typedef struct _glink_iovector_element_type {
+  struct _glink_iovector_element_type *next;
+  void* data;
+  size_t start_offset;
+  size_t size;
+} glink_iovector_element_type;
+
+typedef struct _glink_iovector_type {
+  glink_iovector_element_type *vlist; /* virtual buffers list */
+  glink_iovector_element_type *vlast; /* last accessed element in vlist */
+  glink_iovector_element_type *plist; /* physical buffers list */
+  glink_iovector_element_type *plast; /* last accessed element in plist */
+} glink_iovector_type;
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_dummy_tx_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a non-vectored buffer.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_dummy_tx_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+);
+
+/*===========================================================================
+FUNCTION      glink_dummy_rx_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+);
+
+/*===========================================================================
+FUNCTION      glink_dummy_rx_pprovider
+===========================================================================*/
+/**
+
+  Buffer provider for physical space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     physical address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_pprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+);
+
+#endif /* GLINK_VECTOR_H */
diff --git a/platform/msm_shared/include/rpm-glink.h b/platform/msm_shared/include/rpm-glink.h
new file mode 100644
index 0000000..1d8060a
--- /dev/null
+++ b/platform/msm_shared/include/rpm-glink.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Fundation, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __RPM_GLINK_H
+#define __RPM_GLINK_H
+
+#include <arch/defines.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <rpm-ipc.h>
+#include <glink.h>
+
+typedef struct
+{
+	uint32_t version;
+	uint32_t cmd;
+	uint32_t seqnumber;
+	uint32_t namelength;
+	char name[32];
+} rpm_ssr_req;
+
+typedef rpm_cmd rpm_ack_msg;
+glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type);
+uint32_t rpm_glink_recv_data(char *rx_buffer, uint32_t *len);
+void rpm_glink_clk_enable(uint32_t *data, uint32_t len);
+void rpm_glink_clk_disable(uint32_t *data, uint32_t len);
+void rpm_glink_init();
+void rpm_glink_uninit();
+void rpm_scalar_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv, void *buffer, size_t size, size_t intent_used);
+void rpm_vector_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv, void *buffer, size_t size, size_t intent_used, glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider);
+void rpm_glink_tx_done_isr(void);
+
+void rpm_glink_notify_state_isr(glink_handle_type handle, void *data, glink_channel_event_type event);
+#endif
diff --git a/platform/msm_shared/include/rpm-ipc.h b/platform/msm_shared/include/rpm-ipc.h
new file mode 100644
index 0000000..f02e8b0
--- /dev/null
+++ b/platform/msm_shared/include/rpm-ipc.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Fundation, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __RPM_IPC_H
+#define __RPM_IPC_H
+
+#include <arch/defines.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#define RPM_REQ_MAGIC 0x00716572
+#define RPM_CMD_MAGIC 0x00646d63
+#define REQ_MSG_LENGTH 0x14
+#define CMD_MSG_LENGTH 0x08
+#define ACK_MSG_LENGTH 0x0C
+
+typedef enum
+{
+	RPM_REQUEST_TYPE,
+	RPM_CMD_TYPE,
+	RPM_SUCCESS_REQ_ACK,
+	RPM_SUCCESS_CMD_ACK,
+	RPM_ERROR_ACK,
+}msg_type;
+
+enum
+{
+	RESOURCETYPE,
+	RESOURCEID,
+	KVP_KEY,
+	KVP_LENGTH,
+	KVP_VALUE,
+};
+
+typedef struct
+{
+	uint32_t type;
+	uint32_t len;
+} rpm_gen_hdr;
+
+typedef struct
+{
+	uint32_t key;
+	uint32_t len;
+	uint32_t val;
+} kvp_data;
+
+typedef struct
+{
+	uint32_t id;
+	uint32_t set;
+	uint32_t resourceType;
+	uint32_t resourceId;
+	uint32_t dataLength;
+}rpm_req_hdr;
+
+typedef struct
+{
+	rpm_gen_hdr hdr;
+	rpm_req_hdr req_hdr;
+	kvp_data *data;
+} rpm_req;
+
+typedef struct
+{
+	rpm_gen_hdr hdr;
+	kvp_data *data;
+} rpm_cmd;
+
+typedef rpm_cmd rpm_ack_msg;
+int rpm_send_data(uint32_t *data, uint32_t len, msg_type type);
+void rpm_clk_enable(uint32_t *data, uint32_t len);
+
+void fill_kvp_object(kvp_data **kdata, uint32_t *data, uint32_t len);
+void free_kvp_object(kvp_data **kdata);
+#endif
diff --git a/platform/msm_shared/include/rpm-smd.h b/platform/msm_shared/include/rpm-smd.h
index 5ac8a1b..a1eb4a2 100644
--- a/platform/msm_shared/include/rpm-smd.h
+++ b/platform/msm_shared/include/rpm-smd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -33,65 +33,10 @@
 #include <arch/defines.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <rpm-ipc.h>
 
-typedef enum
-{
-	RPM_REQUEST_TYPE,
-	RPM_CMD_TYPE,
-	RPM_SUCCESS_REQ_ACK,
-	RPM_SUCCESS_CMD_ACK,
-	RPM_ERROR_ACK,
-}msg_type;
-
-enum
-{
-	RESOURCETYPE,
-	RESOURCEID,
-	KVP_KEY,
-	KVP_LENGTH,
-	KVP_VALUE,
-};
-
-typedef struct
-{
-	uint32_t type;
-	uint32_t len;
-} rpm_gen_hdr;
-
-typedef struct
-{
-	uint32_t key;
-	uint32_t len;
-	uint32_t val;
-} kvp_data;
-
-typedef struct
-{
-	uint32_t id;
-	uint32_t set;
-	uint32_t resourceType;
-	uint32_t resourceId;
-	uint32_t dataLength;
-}rpm_req_hdr;
-
-typedef struct
-{
-	rpm_gen_hdr hdr;
-	rpm_req_hdr req_hdr;
-	kvp_data *data;
-} rpm_req;
-
-typedef struct
-{
-	rpm_gen_hdr hdr;
-	kvp_data *data;
-} rpm_cmd;
-
-typedef rpm_cmd rpm_ack_msg;
-int rpm_send_data(uint32_t *data, uint32_t len, msg_type type);
-uint32_t rpm_recv_data(uint32_t *len);
-void rpm_clk_enable(uint32_t *data, uint32_t len);
-void rpm_clk_disable(uint32_t *data, uint32_t len);
+int rpm_smd_send_data(uint32_t *data, uint32_t len, msg_type type);
+uint32_t rpm_smd_recv_data(uint32_t *len);
 void rpm_smd_init();
 void rpm_smd_uninit();
 #endif
diff --git a/platform/msm_shared/include/smem_list.h b/platform/msm_shared/include/smem_list.h
new file mode 100644
index 0000000..22148cb
--- /dev/null
+++ b/platform/msm_shared/include/smem_list.h
@@ -0,0 +1,214 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SMEM_LIST_H
+#define SMEM_LIST_H
+
+/**
+ * @file smem_list.h
+ *
+ * Public data types and functions to implement a generic
+ * list.
+ */
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup smem
+@{ */
+
+
+/*===========================================================================
+
+                        TYPE DEFINITIONS
+
+===========================================================================*/
+
+/** Defines the structure to link to the SMEM list */
+typedef struct smem_list_link
+{
+  struct smem_list_link *next;
+} smem_list_link_type;
+
+
+/** Defines the generic SMEM list type */
+typedef struct smem_list
+{
+  smem_list_link_type *next;
+  long count;
+} smem_list_type;
+
+/*===========================================================================
+
+                      PUBLIC FUNCTION DECLARATIONS
+
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      smem_list_init
+===========================================================================*/
+/**
+  Creates a generic list.
+
+  @param[in/out] list   Pointer to the user list.
+
+  @return
+  N/A.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_init( smem_list_type *list );
+
+/*===========================================================================
+FUNCTION      smem_list_append
+===========================================================================*/
+/**
+  Appends an element to the end of a generic list.
+
+  The element must contain a smem_list_link_type at its base address.
+  The element should not be already present in any list.
+
+  @param[in/out] list   Pointer to the user list.
+  @param[in] item       Element to be inserted.
+
+  @return
+  N/A.
+
+  @dependencies
+  The element must contain a smem_list_link_type at its base address.
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_append( smem_list_type *list, void *item );
+
+/*===========================================================================
+FUNCTION      smem_list_delete
+===========================================================================*/
+/**
+  Removes the specified element from a generic list.
+
+  The element may be present at any point in the list.
+
+  @param[in] list       Pointer to the user list.
+  @param[in] item       Element to be removed.
+
+  @return
+  0 if the element is deleted, or a negative error code if the element
+  is not found.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_delete( smem_list_type *list, void *item );
+
+/*===========================================================================
+FUNCTION      smem_list_first
+===========================================================================*/
+/**
+  Retrieves the first element in the list without removing it.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the first element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_first( smem_list_type *list );
+
+/*===========================================================================
+FUNCTION      smem_list_next
+===========================================================================*/
+/**
+  Retrieves the next element in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the next element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_next( void * item );
+
+/*===========================================================================
+FUNCTION      smem_list_count
+===========================================================================*/
+/**
+  Gets the number of elements in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Count of elements in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_count( smem_list_type *list );
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */ /* end_addtogroup smem */
+
+#endif /* SMEM_LIST_H */
diff --git a/platform/msm_shared/include/smem_type.h b/platform/msm_shared/include/smem_type.h
new file mode 100644
index 0000000..17a2bb0
--- /dev/null
+++ b/platform/msm_shared/include/smem_type.h
@@ -0,0 +1,237 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SMEM_TYPE_H
+#define SMEM_TYPE_H
+
+/**
+ * @file smem_type.h
+ *
+ * Public data types used by SMEM
+ */
+
+/** @addtogroup smem
+@{ */
+
+/*===========================================================================
+                               TYPE DEFINITIONS
+===========================================================================*/
+/******************************************************************************
+   The most significant two bytes of this number are the smem major version and
+ the least significant two bytes are the smem minor version.  The major version
+ number should be updated whenever a change which causes an incompatibility is
+ introduced.
+   The minor version number can track API changes and deprecations that will
+ not affect remote processors.  This may include changes to the smem_mem_type
+ enum, if dependencies have already been satisfied on the relevant processors.
+   Inconsistencies in minor version, between processors, will not prevent smem
+ from booting, but major version inconsistencies will.
+   0x2XXX in the minor version indicates that it is the SMEM minor version, and
+ unrelated to proc comm, which no longer exists.
+******************************************************************************/
+#define SMEM_VERSION_ID                     0x000B2002
+
+#define SMEM_MAJOR_VERSION_MASK             0xFFFF0000
+#define SMEM_MINOR_VERSION_MASK             0x0000FFFF
+#define SMEM_FULL_VERSION_MASK              0xFFFFFFFF
+
+#define SMEM_NUM_SMD_CHANNELS               64
+#define SMEM_NUM_SMP2P_EDGES                8
+
+/** Types of memory that can be requested via smem_alloc.
+
+  All of these types of memory have corresponding buffers allocated in
+  smem_data_decl. If a buffer is added to smem_data_decl, add a corresponding
+  entry to this list.
+
+  SMEM_VERSION_FIRST and SMEM_VERSION_LAST are the first and last
+  boundaries for external version checking via the smem_version_set routine.
+  To set up versioning for a shared item, add an entry between
+  SMEM_VERSION_FIRST and SMEM_VERSION_LAST and update the SMEM version in
+  smem_version.h.
+
+  SMEM_VERSION_LAST need not be the last item in the enum.
+*/
+typedef enum
+{
+  SMEM_MEM_FIRST,
+  SMEM_RESERVED_PROC_COMM = SMEM_MEM_FIRST,
+  SMEM_FIRST_FIXED_BUFFER = SMEM_RESERVED_PROC_COMM,
+  SMEM_HEAP_INFO,
+  SMEM_ALLOCATION_TABLE,
+  SMEM_VERSION_INFO,
+  SMEM_HW_RESET_DETECT,
+  SMEM_RESERVED_AARM_WARM_BOOT,
+  SMEM_DIAG_ERR_MESSAGE,
+  SMEM_SPINLOCK_ARRAY,
+  SMEM_MEMORY_BARRIER_LOCATION,
+  SMEM_LAST_FIXED_BUFFER = SMEM_MEMORY_BARRIER_LOCATION,
+  SMEM_AARM_PARTITION_TABLE,
+  SMEM_AARM_BAD_BLOCK_TABLE,
+  SMEM_RESERVE_BAD_BLOCKS,
+  SMEM_RESERVED_WM_UUID,
+  SMEM_CHANNEL_ALLOC_TBL,
+  SMEM_SMD_BASE_ID,
+  SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_CHANNELS,
+  SMEM_SMEM_LOG_EVENTS,
+  SMEM_RESERVED_SMEM_STATIC_LOG_IDX,
+  SMEM_RESERVED_SMEM_STATIC_LOG_EVENTS,
+  SMEM_RESERVED_SMEM_SLOW_CLOCK_SYNC,
+  SMEM_RESERVED_SMEM_SLOW_CLOCK_VALUE,
+  SMEM_RESERVED_BIO_LED_BUF,
+  SMEM_SMSM_SHARED_STATE,
+  SMEM_RESERVED_SMSM_INT_INFO,
+  SMEM_RESERVED_SMSM_SLEEP_DELAY,
+  SMEM_RESERVED_SMSM_LIMIT_SLEEP,
+  SMEM_RESERVED_SLEEP_POWER_COLLAPSE_DISABLED,
+  SMEM_APPS_POWER_STATUS = SMEM_RESERVED_SLEEP_POWER_COLLAPSE_DISABLED, /*APSS power status*/
+  SMEM_RESERVED_KEYPAD_KEYS_PRESSED,
+  SMEM_RESERVED_KEYPAD_STATE_UPDATED,
+  SMEM_RESERVED_KEYPAD_STATE_IDX,
+  SMEM_RESERVED_GPIO_INT,
+  SMEM_RESERVED_MDDI_LCD_IDX,
+  SMEM_RESERVED_MDDI_HOST_DRIVER_STATE,
+  SMEM_RESERVED_MDDI_LCD_DISP_STATE,
+  SMEM_RESERVED_LCD_CUR_PANEL,
+  SMEM_RESERVED_MARM_BOOT_SEGMENT_INFO,
+  SMEM_RESERVED_AARM_BOOT_SEGMENT_INFO,
+  SMEM_RESERVED_SLEEP_STATIC,
+  SMEM_RESERVED_SCORPION_FREQUENCY,
+  SMEM_RESERVED_SMD_PROFILES,
+  SMEM_RESERVED_TSSC_BUSY,
+  SMEM_RESERVED_HS_SUSPEND_FILTER_INFO,
+  SMEM_RESERVED_BATT_INFO,
+  SMEM_RESERVED_APPS_BOOT_MODE,
+  SMEM_VERSION_FIRST,
+  SMEM_VERSION_SMD = SMEM_VERSION_FIRST,
+  SMEM_VERSION_SMD_BRIDGE,
+  SMEM_VERSION_SMSM,
+  SMEM_VERSION_SMD_NWAY_LOOP,
+  SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
+  SMEM_RESERVED_OSS_RRCASN1_BUF1,
+  SMEM_RESERVED_OSS_RRCASN1_BUF2,
+  SMEM_ID_VENDOR0,
+  SMEM_ID_VENDOR1,
+  SMEM_ID_VENDOR2,
+  SMEM_HW_SW_BUILD_ID,
+  SMEM_RESERVED_SMD_BLOCK_PORT_BASE_ID,
+  SMEM_RESERVED_SMD_BLOCK_PORT_PROC0_HEAP =
+                   SMEM_RESERVED_SMD_BLOCK_PORT_BASE_ID +
+                   SMEM_NUM_SMD_CHANNELS,
+  SMEM_RESERVED_SMD_BLOCK_PORT_PROC1_HEAP =
+                   SMEM_RESERVED_SMD_BLOCK_PORT_PROC0_HEAP +
+                   SMEM_NUM_SMD_CHANNELS,
+  SMEM_I2C_MUTEX = SMEM_RESERVED_SMD_BLOCK_PORT_PROC1_HEAP +
+                   SMEM_NUM_SMD_CHANNELS,
+  SMEM_SCLK_CONVERSION,
+  SMEM_RESERVED_SMD_SMSM_INTR_MUX,
+  SMEM_SMSM_CPU_INTR_MASK,
+  SMEM_RESERVED_APPS_DEM_SLAVE_DATA,
+  SMEM_RESERVED_QDSP6_DEM_SLAVE_DATA,
+  SMEM_RESERVED_CLKREGIM_BSP,
+  SMEM_RESERVED_CLKREGIM_SOURCES,
+  SMEM_SMD_FIFO_BASE_ID,
+  SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID +
+                                    SMEM_NUM_SMD_CHANNELS,
+  SMEM_POWER_ON_STATUS_INFO,
+  SMEM_DAL_AREA,
+  SMEM_SMEM_LOG_POWER_IDX,
+  SMEM_SMEM_LOG_POWER_WRAP,
+  SMEM_SMEM_LOG_POWER_EVENTS,
+  SMEM_ERR_CRASH_LOG,
+  SMEM_ERR_F3_TRACE_LOG,
+  SMEM_SMD_BRIDGE_ALLOC_TABLE,
+  SMEM_SMD_FEATURE_SET,
+  SMEM_RESERVED_SD_IMG_UPGRADE_STATUS,
+  SMEM_SEFS_INFO,
+  SMEM_RESERVED_RESET_LOG,
+  SMEM_RESERVED_RESET_LOG_SYMBOLS,
+  SMEM_MODEM_SW_BUILD_ID,
+  SMEM_SMEM_LOG_MPROC_WRAP,
+  SMEM_RESERVED_BOOT_INFO_FOR_APPS,
+  SMEM_SMSM_SIZE_INFO,
+  SMEM_SMD_LOOPBACK_REGISTER,
+  SMEM_SSR_REASON_MSS0,
+  SMEM_SSR_REASON_WCNSS0,
+  SMEM_SSR_REASON_LPASS0,
+  SMEM_SSR_REASON_DSPS0,
+  SMEM_SSR_REASON_VCODEC0,
+  SMEM_VOICE,
+  SMEM_ID_SMP2P_BASE_APPS, /* = 427 */
+  SMEM_ID_SMP2P_BASE_MODEM = SMEM_ID_SMP2P_BASE_APPS +
+                              SMEM_NUM_SMP2P_EDGES, /* = 435 */
+  SMEM_ID_SMP2P_BASE_ADSP = SMEM_ID_SMP2P_BASE_MODEM +
+                              SMEM_NUM_SMP2P_EDGES, /* = 443 */
+  SMEM_ID_SMP2P_BASE_WCN = SMEM_ID_SMP2P_BASE_ADSP +
+                              SMEM_NUM_SMP2P_EDGES, /* = 451 */
+  SMEM_ID_SMP2P_BASE_RPM = SMEM_ID_SMP2P_BASE_WCN +
+                              SMEM_NUM_SMP2P_EDGES, /* = 459 */
+  SMEM_FLASH_DEVICE_INFO = SMEM_ID_SMP2P_BASE_RPM +
+                              SMEM_NUM_SMP2P_EDGES, /* = 467 */
+  SMEM_BAM_PIPE_MEMORY, /* = 468 */
+  SMEM_IMAGE_VERSION_TABLE, /* = 469 */
+  SMEM_LC_DEBUGGER, /* = 470 */
+  SMEM_FLASH_NAND_DEV_INFO, /* =471 */
+  SMEM_A2_BAM_DESCRIPTOR_FIFO,          /* = 472 */
+  SMEM_CPR_CONFIG,                      /* = 473 */
+  SMEM_CLOCK_INFO,                      /* = 474 */
+  SMEM_IPC_INFO,                        /* = 475 */
+  SMEM_RF_EEPROM_DATA,                  /* = 476 */
+  SMEM_COEX_MDM_WCN,                    /* = 477 */
+  SMEM_GLINK_NATIVE_XPORT_DESCRIPTOR,   /* = 478 */
+  SMEM_GLINK_NATIVE_XPORT_FIFO_0,       /* = 479 */
+  SMEM_GLINK_NATIVE_XPORT_FIFO_1,       /* = 480 */
+
+  SMEM_MEM_LAST = SMEM_GLINK_NATIVE_XPORT_FIFO_1,
+  SMEM_INVALID
+} smem_mem_type;
+
+/**
+ * A list of hosts supported in SMEM
+*/
+typedef enum
+{
+  SMEM_APPS      = 0,                     /**< Apps Processor */
+  SMEM_MODEM     = 1,                     /**< Modem processor */
+  SMEM_ADSP      = 2,                     /**< ADSP processor */
+  SMEM_RSVD3     = 3,                     /**< Reserved */
+  SMEM_WCN       = 4,                     /**< WCN processor */
+  SMEM_RSVD5     = 5,                     /**< Reserved */
+  SMEM_RPM       = 6,                     /**< RPM processor */
+  SMEM_NUM_HOSTS = 7,                     /**< Max number of host in target */
+  SMEM_INVALID_HOST,                      /**< Invalid processor */
+
+  SMEM_Q6        = SMEM_ADSP,             /**< Kept for legacy purposes.
+                                           **  New code should use SMEM_ADSP */
+  SMEM_RIVA      = SMEM_WCN,              /**< Kept for legacy purposes.
+                                           **  New code should use SMEM_WCN */
+}smem_host_type;
+
+/** @} */ /* end_addtogroup smem */
+
+#endif /* SMEM_TYPE_H */
diff --git a/platform/msm_shared/include/xport_rpm.h b/platform/msm_shared/include/xport_rpm.h
new file mode 100644
index 0000000..2566172
--- /dev/null
+++ b/platform/msm_shared/include/xport_rpm.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef XPORT_RPM_H
+#define XPORT_RPM_H
+
+/**
+ * @file xport_rpm.h
+ *
+ * Internal definitions for RPM Glink transport
+ */
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include "glink_transport_if.h"
+#include <glink.h>
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+
+/* Version request command */
+#define XPORT_RPM_CMD_VERSION_REQ       0x0
+/* Version ACK command */
+#define XPORT_RPM_CMD_VERSION_ACK       0x1
+/* Open channel command */
+#define XPORT_RPM_CMD_OPEN_CHANNEL      0x2
+/* Close channel command */
+#define XPORT_RPM_CMD_CLOSE_CHANNEL     0x3
+/* Open channel ACK command */
+#define XPORT_RPM_CMD_OPEN_CHANNEL_ACK  0x4
+/* Tx data command */
+#define XPORT_RPM_CMD_TX_DATA           0x9
+/* Close channel ACK command */
+#define XPORT_RPM_CMD_CLOSE_CHANNEL_ACK 0xB
+/* Tx signals command */
+#define XPORT_RPM_CMD_TX_SIGNALS        0xF
+
+
+#define XPORT_RPM_GET_CMD_ID(c)      ((c) & 0xFFFF)
+#define XPORT_RPM_SET_CMD_ID(cmd_id) ((cmd_id) & 0xFFFF)
+
+#define XPORT_RPM_GET_CHANNEL_ID(c)   (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_CHANNEL_ID(cid) (((cid) << 16) & 0xFFFF0000)
+#define XPORT_RPM_GET_STR_LEN(c)      (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_STR_LEN(c)      (((c) << 16) & 0xFFFF0000)
+#define XPORT_RPM_GET_PRIO(c)         ((c) & 0xFFFF)
+#define XPORT_RPM_SET_PRIO(c)         ((c) & 0xFFFF)
+
+#define XPORT_RPM_GET_VERSION(c) (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_VERSION(v) (((v) << 16) & 0xFFFF0000)
+
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+
+glink_err_type xport_rpm_init(void *arg);
+#endif //XPORT_RPM_H
+
diff --git a/platform/msm_shared/include/xport_rpm_config.h b/platform/msm_shared/include/xport_rpm_config.h
new file mode 100644
index 0000000..e0e24dd
--- /dev/null
+++ b/platform/msm_shared/include/xport_rpm_config.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef XPORT_RPM_CONFIG_H
+#define XPORT_RPM_CONFIG_H
+
+/**
+ * @file xport_rpm_config.h
+ *
+ * Internal definitions for RPM Glink transport configurations
+ */
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include "glink.h"
+#include "glink_os_utils.h"
+#include "smem_type.h"
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+#define XPORT_RPM_TOC_MAGIC 0x67727430
+
+#define XPORT_RPM_AP2R_ID   0x61703272
+#define XPORT_RPM_R2AP_ID   0x72326170
+#define XPORT_RPM_MP2R_ID   0x6D703272
+#define XPORT_RPM_R2MP_ID   0x72326D70
+#define XPORT_RPM_AD2R_ID   0x61643272
+#define XPORT_RPM_R2AD_ID   0x72326164
+#define XPORT_RPM_SC2R_ID   0x73633272
+#define XPORT_RPM_R2SC_ID   0x72327363
+#define XPORT_RPM_WC2R_ID   0x77633272
+#define XPORT_RPM_R2WC_ID   0x72327763
+#define XPORT_RPM_TZ2R_ID   0x747A3272
+#define XPORT_RPM_R2TZ_ID   0x7232747A
+
+#define XPORT_RPM_TOC_MAGIC_IDX    0
+#define XPORT_RPM_TOC_LENGTH_IDX   1
+#define XPORT_RPM_TOC_ENTRIES_IDX  2
+
+#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+typedef struct _xport_rpm_toc_entry_type
+{
+  uint32 fifo_id;                   /* FIFO ID                */
+  uint32 fifo_offset;               /* FIFO offset in MSG RAM */
+  uint32 fifo_size;                 /* FIFO size              */
+} xport_rpm_toc_entry_type;
+
+typedef struct _xport_rpm_toc_config_type
+{
+  uint32 fifo_id;                    /* FIFO ID                        */
+  smem_host_type host;               /* Host ID for MSG RAM allocation */
+  uint32 fifo_size;                  /* FIFO size                      */
+} xport_rpm_toc_config_type;
+
+
+typedef struct _xport_rpm_config_type
+{
+  const char* remote_ss;            /* Remote host name        */
+  uint32 tx_fifo_id;                /* Tx FIFO ID in RPM ToC   */
+  uint32 rx_fifo_id;                /* Rx FIFO ID in RPM ToC   */
+  os_ipc_intr_type irq_out;         /* Outgoing interrupt      */
+  uint32 irq_in;                    /* Incoming interrupt      */
+} xport_rpm_config_type;
+
+#endif //XPORT_RPM_CONFIG_H
+
diff --git a/platform/msm_shared/rpm-glink.c b/platform/msm_shared/rpm-glink.c
new file mode 100644
index 0000000..01cae61
--- /dev/null
+++ b/platform/msm_shared/rpm-glink.c
@@ -0,0 +1,379 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Fundation, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <rpm-glink.h>
+#include <smd.h>
+#include <glink.h>
+#include <glink_rpm.h>
+#include <xport_rpm.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <arch/defines.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <platform/timer.h>
+#include <platform/interrupts.h>
+#include <platform/clock.h>
+#include <platform/iomap.h>
+#include <platform/irqs.h>
+#include <pm8x41.h>
+#include <kernel/event.h>
+
+#define RPM_REQ_MAGIC 0x00716572
+#define RPM_CMD_MAGIC 0x00646d63
+#define REQ_MSG_LENGTH 0x14
+#define CMD_MSG_LENGTH 0x08
+#define ACK_MSG_LENGTH 0x0C
+
+glink_handle_type rpm_glink_port, ssr_glink_port;
+static uint32_t msg_id;
+static event_t wait_for_data;
+
+extern glink_err_type glink_wait_link_down(glink_handle_type handle);
+
+glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type)
+{
+	rpm_req req;
+	rpm_cmd cmd;
+	glink_err_type send_err = 0;
+	uint32_t len_to_rpm = 0;
+	void *rpm_data = NULL;
+	event_init(&wait_for_data, false, EVENT_FLAG_AUTOUNSIGNAL);
+
+	switch(type)
+	{
+		case RPM_REQUEST_TYPE:
+			req.hdr.type = RPM_REQ_MAGIC;
+			req.hdr.len = len + REQ_MSG_LENGTH;//20
+			req.req_hdr.id = ++msg_id;
+			req.req_hdr.set = 0;
+			req.req_hdr.resourceType = data[RESOURCETYPE];
+			req.req_hdr.resourceId = data[RESOURCEID];
+			req.req_hdr.dataLength = len;
+
+			fill_kvp_object(&req.data, data, len);
+			len_to_rpm = req.req_hdr.dataLength + 0x28;
+
+			rpm_data = (void*) malloc(len_to_rpm);
+			ASSERT(rpm_data);
+			memset(rpm_data, 0, len_to_rpm);
+			memcpy(rpm_data, &req.hdr, sizeof(rpm_gen_hdr));
+			memcpy(rpm_data + sizeof(rpm_gen_hdr), &req.req_hdr, sizeof(rpm_req_hdr));
+			memcpy(rpm_data + sizeof(rpm_gen_hdr)+ sizeof(rpm_req_hdr), req.data, len);
+
+			// Send Data Request to RPM
+			send_err = glink_tx(rpm_glink_port, NULL, (const void *)rpm_data, len_to_rpm, 0);
+			if (send_err)
+			{
+				dprintf(CRITICAL, "%s:%d, Glink tx error\n", __func__, __LINE__);
+				free(rpm_data);
+				free_kvp_object(&req.data);
+				break;
+			}
+#ifdef DEBUG_GLINK
+			dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
+#endif
+			event_wait(&wait_for_data);
+			free(rpm_data);
+			free_kvp_object(&req.data);
+			break;
+		case RPM_CMD_TYPE:
+			cmd.hdr.type = RPM_CMD_MAGIC;
+			cmd.hdr.len = CMD_MSG_LENGTH;//0x8;
+			len_to_rpm  = sizeof(rpm_cmd);
+
+			fill_kvp_object(&cmd.data, data, len);
+			send_err = glink_tx(rpm_glink_port, NULL, (const void *)&cmd, len_to_rpm, 0);
+			if (send_err)
+				dprintf(CRITICAL, "%s:%d, Glink tx error\n", __func__, __LINE__);
+			free_kvp_object(&cmd.data);
+			break;
+		default:
+			dprintf(CRITICAL, "Invalid RPM Request\n");
+			break;
+	}
+
+	return send_err;
+}
+
+uint32_t rpm_glink_recv_data(char *rx_buffer, uint32_t* len)
+{
+	rpm_ack_msg *resp;
+	msg_type type = 0;
+	uint32_t ret = 0;
+	/* As per the current design rpm response does not exceed 20 bytes */
+	if (rx_buffer == NULL)
+	{
+		dprintf(CRITICAL, "Invalid pointer to data received from RPM\n");
+		return 99;
+	}
+	resp = (rpm_ack_msg *)rx_buffer;
+
+	arch_invalidate_cache_range((addr_t)resp, sizeof(rpm_gen_hdr));
+
+	if(resp->hdr.type == RPM_CMD_MAGIC)
+	{
+		type = RPM_CMD_TYPE;
+	}
+	else if(resp->hdr.type == RPM_REQ_MAGIC)
+	{
+		type = RPM_REQUEST_TYPE;
+	}
+
+	if (type == RPM_CMD_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
+	{
+		dprintf(SPEW, "Received SUCCESS CMD ACK\n");
+	}
+	else if (type == RPM_REQUEST_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
+	{
+		dprintf(SPEW, "Received SUCCESS REQ ACK \n");
+	}
+	else
+	{
+		ret = 1;
+		dprintf(CRITICAL, "Received ERROR ACK \n");
+	}
+
+	if(!ret)
+	{
+		ret = sizeof(rpm_gen_hdr) + sizeof(kvp_data);
+	}
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "%s:%d Return value %u\n", __func__, __LINE__, ret);
+#endif
+	return ret;
+}
+
+void rpm_vector_glink_ssr_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
+							void *buffer, size_t size, size_t intent_used,
+							glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
+{
+	char rx_buffer[12];
+	char *return_buffer = NULL;
+	uint32_t ret = 0;
+	uint32_t offset = 0;
+	size_t return_size = 0;
+
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "RPM Vector GLINK SSR ISR\n");
+#endif
+	if (size == 0)
+	{
+		dprintf(CRITICAL, "Invalid size of RPM response\n");
+		ASSERT(0);
+	}
+	if (size > sizeof(rx_buffer))
+	{
+		dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
+		ASSERT(0);
+	}
+	do
+	{
+		return_buffer = vprovider(buffer, offset, &return_size);
+		if(return_buffer)
+		{
+			memcpy(rx_buffer+offset,return_buffer, return_size);
+			offset += return_size;
+		}
+	} while(return_buffer);
+	ret = rpm_glink_recv_data(rx_buffer,(uint32_t *)&size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
+	}
+	// Release the mutex
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "Received Data from RPM\n");
+#endif
+	event_signal(&wait_for_data, false);
+}
+
+void rpm_vector_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
+							void *buffer, size_t size, size_t intent_used,
+							glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
+{
+	char rx_buffer[64];
+	char *return_buffer = NULL;
+	uint32_t ret = 0;
+	uint32_t offset = 0;
+	size_t return_size = 0;
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "RPM Vector GLINK ISR\n");
+#endif
+	if (size == 0)
+	{
+		dprintf(CRITICAL, "Invalid size of RPM response\n");
+		ASSERT(0);
+	}
+	if (size > sizeof(rx_buffer))
+	{
+		dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
+		ASSERT(0);
+	}
+	do
+	{
+		return_buffer = vprovider(buffer, offset, &return_size);
+		if(return_buffer)
+		{
+			memcpy(rx_buffer+offset,return_buffer, return_size);
+			offset += return_size;
+		}
+	} while(return_buffer);
+	ret = rpm_glink_recv_data(rx_buffer, (uint32_t *)&size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
+	}
+	// Release the mutex
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "Received Data from RPM\n");
+#endif
+	event_signal(&wait_for_data, false);
+}
+
+void rpm_glink_notify_state_isr(glink_handle_type handle, void *data, glink_channel_event_type event)
+{
+	if(event == GLINK_CONNECTED)
+	{
+		dprintf(INFO, "Glink Connection between APPS and RPM established\n");
+		return;
+	}
+}
+
+void rpm_glink_tx_done_isr(void)
+{
+	//empty function for tx_done cb. Nothing required here for now since we are always in
+	//"single-threaded" operation of sending GLink requests
+	return;
+}
+
+void rpm_glink_open(glink_link_info_type *link_info, void* priv)
+{
+	glink_err_type ret;
+	glink_open_config_type glink_open_cfg = {0}, glink_ssr_open_cfg = {0};
+
+	// Open channel for tx
+	glink_open_cfg.name = "rpm_requests";
+	glink_open_cfg.remote_ss = link_info->remote_ss;
+	glink_open_cfg.notify_rx = NULL;
+	glink_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_isr;
+	glink_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
+	glink_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_isr;
+	glink_open_cfg.priv = NULL;
+	ret = glink_open(&glink_open_cfg, &rpm_glink_port);
+	if (ret == GLINK_STATUS_SUCCESS)
+		dprintf(INFO, "Opening RPM Glink Port success\n");
+	else
+	{
+		dprintf(CRITICAL, "Opening RPM Glink Port failure %d\n", ret);
+		ASSERT(0);
+	}
+
+	// Open Channel for tear down
+	glink_ssr_open_cfg.name = "glink_ssr";
+	glink_ssr_open_cfg.remote_ss = link_info->remote_ss;
+	glink_ssr_open_cfg.notify_rx = NULL;
+	glink_ssr_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_ssr_isr;
+	glink_ssr_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
+	glink_ssr_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_isr;
+	glink_ssr_open_cfg.priv = NULL;
+
+	ret = glink_open(&glink_ssr_open_cfg, &ssr_glink_port);
+	if (ret == GLINK_STATUS_SUCCESS)
+		dprintf(INFO, "Opening SSR Glink Port success\n");
+	else
+	{
+		dprintf(CRITICAL, "Opening SSR Glink Port failure %d\n", ret);
+		ASSERT(0);
+	}
+
+}
+
+void rpm_glink_init()
+{
+	glink_err_type ret;
+	glink_link_id_type link_id;
+
+	dprintf(INFO, "RPM GLink Init\n");
+	// Initialize RPM transport
+	ret = xport_rpm_init(NULL);
+	if (ret == GLINK_STATUS_SUCCESS)
+	{
+		unmask_interrupt(GLINK_IPC_IRQ);
+		GLINK_LINK_ID_STRUCT_INIT(link_id);
+		link_id.remote_ss = "rpm";
+		link_id.link_notifier = (glink_link_state_notif_cb)rpm_glink_open;
+		glink_register_link_state_cb(&link_id, NULL);
+	}
+	else
+	{
+		dprintf(CRITICAL, "RPM Glink Init Failure\n");
+		ASSERT(0);
+	}
+}
+
+void rpm_glink_uninit()
+{
+	rpm_ssr_req req;
+	glink_err_type ret;
+	uint32_t len_to_rpm, loop = 100000;
+
+	// update ssr request
+	req.version = 0;
+	req.cmd = 0;
+	req.seqnumber = 0;
+	memset(req.name, 0, sizeof(req.name));
+	strncpy(req.name, "apss", 4);
+	req.namelength = strlen(req.name);
+	len_to_rpm = sizeof(rpm_ssr_req);
+	dprintf(INFO, "RPM GLINK UnInit\n");
+	ret = glink_tx(ssr_glink_port, NULL, (const void *)&req, len_to_rpm, 0);
+
+	if (ret)
+	{
+		dprintf(CRITICAL, "Glink SSR Channel: Tx for link tear down request failure\n");
+		ASSERT(0);
+	}
+
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
+#endif
+	// loop till the FIFO indices are cleared
+	while((ret = glink_wait_link_down(ssr_glink_port)) && loop)
+	{
+		loop--;
+		mdelay(1);
+		continue;
+	}
+	if (!loop)
+	{
+		dprintf(INFO, "%s:%d, Tearing down Glink SSR Channel Timed out\n", __func__, __LINE__);
+		ASSERT(0);
+	}
+}
diff --git a/platform/msm_shared/rpm-ipc.c b/platform/msm_shared/rpm-ipc.c
new file mode 100644
index 0000000..2bd3c51
--- /dev/null
+++ b/platform/msm_shared/rpm-ipc.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Fundation, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <arch/defines.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <rpm-ipc.h>
+#include <rpm-glink.h>
+#include <rpm-smd.h>
+#include <string.h>
+
+void fill_kvp_object(kvp_data **kdata, uint32_t *data, uint32_t len)
+{
+	*kdata = (kvp_data *) memalign(CACHE_LINE, ROUNDUP(len, CACHE_LINE));
+	ASSERT(*kdata);
+
+	memcpy(*kdata, data+2, len);
+}
+
+void free_kvp_object(kvp_data **kdata)
+{
+	if(*kdata)
+		free(*kdata);
+}
+
+int rpm_send_data(uint32_t *data, uint32_t len, msg_type type)
+{
+	int ret = 0;
+#ifdef GLINK_SUPPORT
+	ret = rpm_glink_send_data(data, len, type);
+#else
+	ret = rpm_smd_send_data(data, len, type);
+#endif
+	return ret;
+}
+
+void rpm_clk_enable(uint32_t *data, uint32_t len)
+{
+	if(rpm_send_data(data, len, RPM_REQUEST_TYPE))
+	{
+		dprintf(CRITICAL, "Clock enable failure\n");
+		ASSERT(0);
+	}
+}
diff --git a/platform/msm_shared/rpm-smd.c b/platform/msm_shared/rpm-smd.c
index 693d369..d6869ee 100644
--- a/platform/msm_shared/rpm-smd.c
+++ b/platform/msm_shared/rpm-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,12 +36,6 @@
 #include <stdlib.h>
 #include <platform/timer.h>
 
-#define RPM_REQ_MAGIC 0x00716572
-#define RPM_CMD_MAGIC 0x00646d63
-#define REQ_MSG_LENGTH 0x14
-#define CMD_MSG_LENGTH 0x08
-#define ACK_MSG_LENGTH 0x0C
-
 static uint32_t msg_id;
 smd_channel_info_t ch;
 
@@ -55,21 +49,7 @@
 	smd_uninit(&ch);
 }
 
-static void fill_kvp_object(kvp_data **kdata, uint32_t *data, uint32_t len)
-{
-	*kdata = (kvp_data *) memalign(CACHE_LINE, ROUNDUP(len, CACHE_LINE));
-	ASSERT(*kdata);
-
-	memcpy(*kdata, data+2, len);
-}
-
-static void free_kvp_object(kvp_data **kdata)
-{
-	if(*kdata)
-		free(*kdata);
-}
-
-int rpm_send_data(uint32_t *data, uint32_t len, msg_type type)
+int rpm_smd_send_data(uint32_t *data, uint32_t len, msg_type type)
 {
 	rpm_req req;
 	rpm_cmd cmd;
@@ -103,7 +83,7 @@
 			ret = smd_write(&ch, smd_data, len_to_smd, SMD_APPS_RPM);
 
 			/* Read the response */
-			ack_msg_len = rpm_recv_data(&rlen);
+			ack_msg_len = rpm_smd_recv_data(&rlen);
 
 			smd_signal_read_complete(&ch, ack_msg_len);
 
@@ -127,7 +107,7 @@
 	return ret;
 }
 
-uint32_t rpm_recv_data(uint32_t* len)
+uint32_t rpm_smd_recv_data(uint32_t* len)
 {
 	rpm_ack_msg *resp;
 	msg_type type;
@@ -171,15 +151,3 @@
 
 	return ret;
 }
-
-void rpm_clk_enable(uint32_t *data, uint32_t len)
-{
-	/* Send the request to SMD */
-	rpm_send_data(data, len, RPM_REQUEST_TYPE);
-}
-
-void rpm_clk_disable(uint32_t *data, uint32_t len)
-{
-	dprintf(CRITICAL,"Clock disable\n");
-}
-
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 846dc6e..cf372ea 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -23,6 +23,7 @@
 
 ifeq ($(ENABLE_SMD_SUPPORT),1)
 OBJS += \
+	$(LOCAL_DIR)/rpm-ipc.o \
 	$(LOCAL_DIR)/rpm-smd.o \
 	$(LOCAL_DIR)/smd.o
 endif
@@ -43,6 +44,21 @@
 	$(LOCAL_DIR)/boot_verifier.o
 endif
 
+ifeq ($(ENABLE_GLINK_SUPPORT),1)
+OBJS += \
+		$(LOCAL_DIR)/rpm-ipc.o \
+		$(LOCAL_DIR)/glink/glink_api.o \
+		$(LOCAL_DIR)/glink/glink_core_if.o \
+		$(LOCAL_DIR)/glink/glink_rpmcore_setup.o \
+		$(LOCAL_DIR)/glink/glink_core_intentless_xport.o \
+		$(LOCAL_DIR)/glink/glink_os_utils_dal.o \
+		$(LOCAL_DIR)/glink/glink_vector.o \
+		$(LOCAL_DIR)/glink/xport_rpm.o \
+		$(LOCAL_DIR)/glink/xport_rpm_config.o \
+		$(LOCAL_DIR)/smem_list.o \
+		$(LOCAL_DIR)/rpm-glink.o
+endif
+
 ifeq ($(PLATFORM),msm8x60)
 	OBJS += $(LOCAL_DIR)/mipi_dsi.o \
 			$(LOCAL_DIR)/i2c_qup.o \
diff --git a/platform/msm_shared/smem_list.c b/platform/msm_shared/smem_list.c
new file mode 100644
index 0000000..fc89671
--- /dev/null
+++ b/platform/msm_shared/smem_list.c
@@ -0,0 +1,242 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*===========================================================================
+
+                         S H A R E D   M E M O R Y
+
+===========================================================================*/
+
+
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include "smem_list.h"
+#include <sys/types.h>
+
+/*=============================================================================
+
+            GLOBAL DEFINITIONS AND DECLARATIONS FOR MODULE
+
+=============================================================================*/
+
+
+/*===========================================================================
+
+                      PRIVATE FUNCTION DECLARATIONS
+
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      smem_list_init
+===========================================================================*/
+/**
+  Creates a generic list.
+
+  @param[in/out] list   Pointer to the user list.
+
+  @return
+  N/A.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_init( smem_list_type *list )
+{
+  list->next  = NULL;
+  list->count = 0;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_append
+===========================================================================*/
+/**
+  Appends an element to the end of a generic list.
+
+  The element must contain a smem_list_link_type at its base address.
+  The element should not be already present in any list.
+
+  @param[in/out] list   Pointer to the user list.
+  @param[in] item       Element to be inserted.
+
+  @return
+  N/A.
+
+  @dependencies
+  The element must contain a smem_list_link_type at its base address.
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_append( smem_list_type *list, void *item )
+{
+  smem_list_link_type *link = ( smem_list_link_type * )list;
+
+  /* get next item until link->next points to null */
+  while( link->next )
+  {
+    link = link->next;
+  }
+
+  /* link->next points to null here, but we can point it to the new item */
+  link->next = item;
+
+  /* point link to the head of the new item */
+  link = item;
+
+  /* terminate the list */
+  link->next = NULL;
+
+  list->count++;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_delete
+===========================================================================*/
+/**
+  Removes the specified element from a generic list.
+
+  The element may be present at any point in the list.
+
+  @param[in] list       Pointer to the user list.
+  @param[in] item       Element to be removed.
+
+  @return
+  0 if the element is deleted, or a negative error code if the element
+  is not found.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_delete( smem_list_type *list, void *item )
+{
+  smem_list_link_type *link = ( smem_list_link_type * )list;
+
+  /* get next item until link points to item in question */
+  while( link->next != item )
+  {
+    if( NULL == link->next )
+    {
+      return -1;
+    }
+
+    link = link->next;
+  }
+
+  link->next = ( ( smem_list_link_type * )item )->next;
+
+  list->count--;
+
+  return 0;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_first
+===========================================================================*/
+/**
+  Retrieves the first element in the list without removing it.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the first element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_first( smem_list_type *list )
+{
+  /* return the first item in the list */
+  return list->next;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_next
+===========================================================================*/
+/**
+  Retrieves the next element in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the next element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_next( void * item )
+{
+  /* just return the item that this item points to
+   * (base address contains a pointer) */
+  return ( ( smem_list_link_type * )item )->next;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_count
+===========================================================================*/
+/**
+  Gets the number of elements in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Count of elements in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_count( smem_list_type *list )
+{
+  return list->count;
+}
+
diff --git a/target/msm8916/oem_panel.c b/target/msm8916/oem_panel.c
index 9e4349d..4c51fcb 100644
--- a/target/msm8916/oem_panel.c
+++ b/target/msm8916/oem_panel.c
@@ -64,6 +64,8 @@
 #define NT35590_720P_CMD_PANEL_ON_DELAY 40
 #define SAMSUNG_WXGA_VIDEO_PANEL_ON_DELAY 100
 
+#define BOARD_SOC_VERSION3	0x30000
+
 /*---------------------------------------------------------------------------*/
 /* static panel selection variable                                           */
 /*---------------------------------------------------------------------------*/
@@ -711,7 +713,9 @@
 	 * Update all data structures after 'panel_init' label. Only panel
 	 * selection is supposed to happen before that.
 	 */
-	if (platform_is_msm8939() || platform_is_msm8929() || (hw_id == HW_PLATFORM_QRD)) {
+	if ((platform_is_msm8939() && (board_soc_version() !=
+		BOARD_SOC_VERSION3)) || platform_is_msm8929() ||
+		(hw_id == HW_PLATFORM_QRD)) {
 		phy_db->regulator_mode = DSI_PHY_REGULATOR_LDO_MODE;
 		memcpy(panel_regulator_settings,
 				ldo_regulator_settings, REGULATOR_SIZE);
diff --git a/target/msm8994/regulator.c b/target/msm8994/regulator.c
index c28afa2..51bd966 100644
--- a/target/msm8994/regulator.c
+++ b/target/msm8994/regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -28,7 +28,7 @@
  */
 
 #include <regulator.h>
-#include <rpm-smd.h>
+#include <rpm-ipc.h>
 
 static uint32_t ldo2[][11]=
 {