Merge "mmc: msm_sdcc: data timeout errors are expected during HS200 tuning"
diff --git a/Documentation/arm/msm/adsprpc-drv.txt b/Documentation/arm/msm/adsprpc-drv.txt
new file mode 100644
index 0000000..f468ddb
--- /dev/null
+++ b/Documentation/arm/msm/adsprpc-drv.txt
@@ -0,0 +1,198 @@
+Introduction
+============
+
+The MSM ADSPRPC driver implements an IPC (Inter-Processor Communication)
+mechanism that allows for clients to transparently make remote method
+invocations across processor boundaries.
+
+The below diagram depicts invocation of a single method where the client
+and objects reside on different processors. An object could expose
+multiple methods which can be grouped together and referred to as an
+interface.
+
+: ,--------,        ,------,  ,-----------,  ,------,        ,--------,
+: |        | method |      |  |           |  |      | method |        |
+: | Client |------->| Stub |->| Transport |->| Skel |------->| Object |
+: |        |        |      |  |           |  |      |        |        |
+: `--------`        `------`  `-----------`  `------`        `--------`
+
+Client:    Linux user mode process that initiates the remote invocation
+Stub:      Auto generated code linked in with the user mode process that
+           takes care of marshaling parameters
+Transport: Involved in carrying an invocation from a client to an
+           object. This involves two portions: 1) MSM ADSPRPC Linux
+           kernel driver that receives the remote invocation, queues
+           them up and then waits for the response after signaling the
+           remote side. 2) Service running on the remote side that
+           dequeues the messages from the queue and dispatches them for
+           processing.
+Skel:      Auto generated code that takes care of un-marshaling
+           parameters
+Object:    Method implementation
+
+Hardware description
+====================
+
+The driver interfaces with the components in the DSP subsystem and does
+not drive or manage any hardware resources.
+
+Software description
+====================
+
+The MSM ADSPRPC driver uses SMD (Shared Memory Driver) to send and
+receive messages with the remote processor. The SMD channel used for
+communication is opened during initialization of the driver and is
+closed when the driver module is unloaded. The driver does not expose
+HLOS memory to the remote processor but rather communication of
+invocation parameters happen over ION allocated buffers.
+
+The driver receives remote call invocations via an ioctl call. When a
+remote call invocation is received, the driver does the following:
+- Retrieves the invocation parameters
+- Copies input buffers in HLOS memory to ION allocated buffers
+- Allocates ION buffers for output buffers in HLOS memory as required
+- Scatter-gathers list of pages for ION allocated input and output
+  buffers
+- Coalesces information about the contiguous page buffers
+- Builds up a message with the received information
+- Sends the message to a remote processor through an SMD channel
+- Waits for a response from the remote processor through the SMD channel
+- Reads the message available from the shared memory SMD channel
+- Copies back from ION buffers to HLOS memory for output buffers
+- Returns the response of the remote invocation
+
+Design
+======
+
+The design goals of this transport mechanism are:
+- Fast and efficient ways to transfer huge buffers across
+  inter-processor boundaries
+- Zero copy of ION allocated buffers passed during invocations
+
+To achieve the zero copy approach of ION allocated user space buffers,
+the driver scatter-gathers the list of pages of the buffers being passed
+in. This information is then sent over to the remote processor for it
+to map into its address space.
+
+The invocation requests sent over the SMD channel carry context
+information as to whom the request is originating from. The responses
+received over the SMD channel have context information in the message
+which is then used to wake the thread waiting for a response.
+
+If the remote processor goes down and gets restarted, the SMD channel
+is re-initialized when the remote processor comes back up. An
+error code would be returned to the client for all invocations that
+happen before the SMD channel could get completely re-initialized.
+
+Power Management
+================
+
+None
+
+SMP/multi-core
+==============
+
+The driver uses semaphores to wake up clients waiting for a remote
+invocation response.
+
+Security
+========
+
+Use of the zero copy approach results in a page-size granularity of
+all buffers being passed to the remote processor. The objects that will
+be manipulating these buffers on the remote processor will be signed
+and trusted entities, thereby alleviating any fear of intentional
+scribbling of these buffers.
+
+Performance
+===========
+
+In order to minimize latencies across remote invocations:
+- messages exchanged between the remote processors are kept short
+- zero copy approach for ION allocated user space buffers
+
+Interface
+=========
+
+The driver exposes a user space interface through /dev/adsprpc-smd and
+the user space clients send commands to the driver by using the
+following ioctl command:
+
+- FASTRPC_IOCTL_INVOKE: Parameters passed in includes the buffers and
+  data related to remote invocation.
+
+  /*
+   * Information about the input/output buffer or an handle to the
+   * object being passed in the remote invocation
+   *
+   * @pv:     Pointer to input/output buffer
+   * @len:    Length of the input/output buffer
+   * @handle: Handle to the remote object
+   */
+  typedef union {
+	struct remote_buf {
+		void *pv;
+		int len;
+	} buf;
+	unsigned int handle;
+  } remote_arg;
+
+  /*
+   * Invocation parameters passed via ioctl call by the client
+   *
+   * @handle: Handle to the object on which the method is to be
+   *          invoked
+   * @sc:     Scalars detailing the parameters being passed in
+   *          bits 0-3: Number of output handles
+   *          bits 4-7: Number of input handles
+   *          bits 8-15: Number of output buffers
+   *          bits 16-23: Number of input buffers
+   *          bits 24-28: Method to be invoked
+   *          bits 29-31: Method attributes
+   * @pra:    Remote arguments to be passed for method invocation
+   */
+  struct fastrpc_ioctl_invoke {
+	unsigned int handle;
+	unsigned int sc;
+	remote_arg *pra;
+  };
+
+Driver parameters
+=================
+
+None
+
+Config options
+==============
+
+None
+
+Dependencies
+============
+
+The ADSPRPC driver requires that the ADSP RPC SMD channel be created and
+the SMD subsystem be initialized. During initialization, the driver
+opens an existing SMD edge channel between ADSP and Apps processor. On
+success, the driver waits for the "channel opened" event from SMD,
+acknowledging the channel availability from the remote SMD driver for
+communication to begin.
+
+User space utilities
+====================
+
+None
+
+Other
+=====
+
+None
+
+Known issues
+============
+
+None
+
+To do
+=====
+
+None
diff --git a/Documentation/devicetree/bindings/cache/msm_cache_dump.txt b/Documentation/devicetree/bindings/cache/msm_cache_dump.txt
new file mode 100644
index 0000000..b7a68b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/cache/msm_cache_dump.txt
@@ -0,0 +1,24 @@
+* Qualcomm Krait L1 / L2 cache dumping device
+This is a virtual device that dumps the contents of L1 and L2 caches in the
+event of a kernel panic or a watchdog trigger.
+
+Required properties:
+- compatible:			Should be "qcom,cache_dump"
+- qcom,l1-dump-size:		Amount of memory needed for L1 dump(s), in bytes
+- qcom,l2-dump-size:		Amount of memory needed for L2 dump, in bytes
+- qcom,memory-reservation-size: Combined reserved memory for the dump buffers
+- qcom,memory-reservation-type: Type of memory to be reserved
+
+Optional properties:
+- qcom,use-imem-dump-offset: If specified, store cache dump buffer addresses
+  in IMEM rather than using the memory dump reservation table.
+
+Example:
+	qcom,cache_dump {
+		compatible = "qcom,cache_dump";
+		qcom,l1-dump-size = <0x100000>;
+		qcom,l2-dump-size = <0x400000>;
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x500000>;
+	};
+
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
index e7c742c..dac87a3 100644
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpio.dtsi
@@ -109,6 +109,13 @@
 
 			gpio@d200 {
 				status = "ok";
+				qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+				qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+				qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+				qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+				qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+				qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+				qcom,master-en = <1>;
 			};
 
 			gpio@d300 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index fe60c83..ffd4518 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -860,6 +860,14 @@
 		interrupt-names = "l1_irq", "l2_irq";
 	};
 
+	qcom,cache_dump {
+		compatible = "qcom,cache_dump";
+		qcom,l1-dump-size = <0x100000>;
+		qcom,l2-dump-size = <0x500000>;
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
+	};
+
 	tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index db184cd..afe528d 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -391,6 +391,7 @@
 CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
 CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_HDMI_MHL_8334=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 5415425..4c9383d 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -394,6 +394,7 @@
 CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
 CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_HDMI_MHL_8334=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 471ecd9..10d2f4d 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -20,14 +20,18 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
 CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_EFI_PARTITION=y
 CONFIG_ARCH_MSM=y
@@ -35,39 +39,41 @@
 CONFIG_ARCH_MSM8226=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
 # CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_KERNEL_PMEM_EBI_REGION=y
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_BAM_DMUX=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_HW3D is not set
+CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_MSM_PIL_MBA=y
 CONFIG_MSM_PIL_VENUS=y
 CONFIG_MSM_PIL_PRONTO=y
-CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_MODEM_SSR_8974=y
 CONFIG_MSM_ADSP_SSR_8974=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
-CONFIG_MSM_QDSS=y
+CONFIG_MSM_BUS_SCALING=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ADSP_LOADER=m
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
 CONFIG_MSM_OCMEM_DEBUG=y
 CONFIG_MSM_OCMEM_NONSECURE=y
-CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_MSM_WATCHDOG_V2=y
-CONFIG_MSM_DLOAD_MODE=y
-CONFIG_PANIC_TIMEOUT=5
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L1_ERR_PANIC=y
+CONFIG_MSM_L1_ERR_LOG=y
 CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
+CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
-CONFIG_MSM_ADSP_LOADER=m
+CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -77,6 +83,8 @@
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -113,10 +121,100 @@
 CONFIG_IPV6_MIP6=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_HTB=y
 CONFIG_NET_SCH_PRIO=y
 CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCISMD=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=m
+CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_BLK_DEV_LOOP=y
@@ -136,15 +234,20 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_KS8851=m
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=n
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
@@ -156,14 +259,12 @@
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
-CONFIG_MSM_BUS_SCALING=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
-CONFIG_SLIMBUS=y
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -171,11 +272,11 @@
 CONFIG_GPIO_QPNP_PIN_DEBUG=y
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
-CONFIG_HWMON=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
+CONFIG_WCD9320_CODEC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_REGULATOR_QPNP=y
@@ -186,9 +287,10 @@
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_OV2720=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
-CONFIG_MSM_CAM_IRQ_ROUTER=n
+CONFIG_MSM_JPEG=y
 CONFIG_MSM_CCI=y
 CONFIG_MSM_CSI30_HEADER=y
 CONFIG_MSM_CSIPHY=y
@@ -196,11 +298,8 @@
 CONFIG_MSM_CSI2_REGISTER=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
-CONFIG_OV2720=y
-CONFIG_MSM_JPEG=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
-CONFIG_RADIO_ADAPTERS=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
@@ -218,7 +317,6 @@
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_MSM8974=y
-CONFIG_WCD9320_CODEC=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_STORAGE=y
@@ -248,8 +346,6 @@
 CONFIG_MMC_TEST=m
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
@@ -273,6 +369,7 @@
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
+CONFIG_MSM_QDSS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
@@ -286,48 +383,34 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
 # CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
+CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
-CONFIG_LIBCRC32C=y
-
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-
-CONFIG_BT_HCISMD=y
-CONFIG_MSM_BT_POWER=y
-
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
-CONFIG_MSM_BAM_DMUX=y
-CONFIG_WCNSS_CORE=y
-CONFIG_WCNSS_CORE_PRONTO=y
-CONFIG_CFG80211=m
-CONFIG_RFKILL=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_MEDIA=y
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 63d402f..1e9504b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -37,6 +37,8 @@
 
 #include "signal.h"
 
+#include <trace/events/exception.h>
+
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
 void *vectors_page;
@@ -410,6 +412,8 @@
 	if (call_undef_hook(regs, instr) == 0)
 		return;
 
+	trace_undef_instr(regs, (void *)pc);
+
 #ifdef CONFIG_DEBUG_USER
 	if (user_debug & UDBG_UNDEFINED) {
 		printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 3f19b2a..2beb990 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -474,10 +474,10 @@
 	if (branch->has_sibling == 1)
 		return -ENXIO;
 
-	if (branch->parent)
-		return rcg_clk_list_rate(branch->parent, n);
+	if (branch->parent && branch->parent->ops->list_rate)
+		return branch->parent->ops->list_rate(branch->parent, n);
 	else
-		return 0;
+		return -ENXIO;
 }
 
 static enum handoff branch_clk_handoff(struct clk *c)
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index b65bd1f..acf577e 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -365,25 +365,25 @@
 static struct msm_iommu_dev gfx3d_iommu = {
 	.name = "gfx3d",
 	.ncb = 3,
-	.ttbr_split = 2,
+	.ttbr_split = 1,
 };
 
 static struct msm_iommu_dev gfx3d1_iommu = {
 	.name = "gfx3d1",
 	.ncb = 3,
-	.ttbr_split = 2,
+	.ttbr_split = 1,
 };
 
 static struct msm_iommu_dev gfx2d0_iommu = {
 	.name = "gfx2d0",
 	.ncb = 2,
-	.ttbr_split = 2,
+	.ttbr_split = 1,
 };
 
 static struct msm_iommu_dev gfx2d1_iommu = {
 	.name = "gfx2d1",
 	.ncb = 2,
-	.ttbr_split = 2,
+	.ttbr_split = 1,
 };
 
 static struct msm_iommu_dev vcap_iommu = {
diff --git a/arch/arm/mach-msm/include/mach/msm_memory_dump.h b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
index 5e686bf..729a077 100644
--- a/arch/arm/mach-msm/include/mach/msm_memory_dump.h
+++ b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
@@ -17,7 +17,8 @@
 
 enum dump_client_type {
 	MSM_CPU_CTXT = 0,
-	MSM_CACHE,
+	MSM_L1_CACHE,
+	MSM_L2_CACHE,
 	MSM_OCMEM,
 	MSM_TMC_ETFETB,
 	MSM_ETM0_REG,
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
index 9759d5a..8b4978f 100644
--- a/arch/arm/mach-msm/msm_cache_dump.c
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -21,10 +21,13 @@
 #include <linux/pm.h>
 #include <linux/memory_alloc.h>
 #include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <mach/scm.h>
 #include <mach/msm_cache_dump.h>
 #include <mach/memory.h>
 #include <mach/msm_iomap.h>
+#include <mach/msm_memory_dump.h>
 
 #define L2_DUMP_OFFSET 0x14
 
@@ -37,6 +40,7 @@
  */
 static struct l1_cache_dump *l1_dump;
 static struct l2_cache_dump *l2_dump;
+static int use_imem_dump_offset;
 
 static int msm_cache_dump_panic(struct notifier_block *this,
 				unsigned long event, void *ptr)
@@ -45,7 +49,8 @@
 	/*
 	 * Clear the bootloader magic so the dumps aren't overwritten
 	 */
-	__raw_writel(0, MSM_IMEM_BASE + L2_DUMP_OFFSET);
+	if (use_imem_dump_offset)
+		__raw_writel(0, MSM_IMEM_BASE + L2_DUMP_OFFSET);
 
 	scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 2);
 	scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 1);
@@ -65,14 +70,38 @@
 static int msm_cache_dump_probe(struct platform_device *pdev)
 {
 	struct msm_cache_dump_platform_data *d = pdev->dev.platform_data;
+	struct msm_client_dump l1_dump_entry, l2_dump_entry;
 	int ret;
 	struct {
 		unsigned long buf;
 		unsigned long size;
 	} l1_cache_data;
 	void *temp;
-	unsigned long total_size = d->l1_size + d->l2_size;
+	u32 l1_size, l2_size;
+	unsigned long total_size;
 
+	if (pdev->dev.of_node) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   "qcom,l1-dump-size", &l1_size);
+		if (ret)
+			return ret;
+
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   "qcom,l2-dump-size", &l2_size);
+		if (ret)
+			return ret;
+
+		use_imem_dump_offset = of_property_read_bool(pdev->dev.of_node,
+						   "qcom,use-imem-dump-offset");
+	} else {
+		l1_size = d->l1_size;
+		l2_size = d->l2_size;
+
+		/* Non-DT targets assume the IMEM dump offset shall be used */
+		use_imem_dump_offset = 1;
+	};
+
+	total_size = l1_size + l2_size;
 	msm_cache_dump_addr = allocate_contiguous_ebi_nomap(total_size, SZ_4K);
 
 	if (!msm_cache_dump_addr) {
@@ -86,7 +115,7 @@
 	iounmap(temp);
 
 	l1_cache_data.buf = msm_cache_dump_addr;
-	l1_cache_data.size = d->l1_size;
+	l1_cache_data.size = l1_size;
 
 	ret = scm_call(L1C_SERVICE_ID, L1C_BUFFER_SET_COMMAND_ID,
 			&l1_cache_data, sizeof(l1_cache_data), NULL, 0);
@@ -96,10 +125,11 @@
 			__func__, ret);
 
 	l1_dump = (struct l1_cache_dump *)msm_cache_dump_addr;
+	l2_dump = (struct l2_cache_dump *)(msm_cache_dump_addr + l1_size);
 
 #if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
-	l1_cache_data.buf = msm_cache_dump_addr + d->l1_size;
-	l1_cache_data.size = d->l2_size;
+	l1_cache_data.buf = msm_cache_dump_addr + l1_size;
+	l1_cache_data.size = l2_size;
 
 	ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_SET_COMMAND_ID,
 			&l1_cache_data, sizeof(l1_cache_data), NULL, 0);
@@ -108,11 +138,27 @@
 		pr_err("%s: could not register L2 buffer ret = %d.\n",
 			__func__, ret);
 #endif
-	__raw_writel(msm_cache_dump_addr + d->l1_size,
+
+	if (use_imem_dump_offset)
+		__raw_writel(msm_cache_dump_addr + l1_size,
 			MSM_IMEM_BASE + L2_DUMP_OFFSET);
+	else {
+		l1_dump_entry.id = MSM_L1_CACHE;
+		l1_dump_entry.start_addr = msm_cache_dump_addr;
+		l1_dump_entry.end_addr = l1_dump_entry.start_addr + l1_size - 1;
 
+		l2_dump_entry.id = MSM_L2_CACHE;
+		l2_dump_entry.start_addr = msm_cache_dump_addr + l1_size;
+		l2_dump_entry.end_addr = l2_dump_entry.start_addr + l2_size - 1;
 
-	l2_dump = (struct l2_cache_dump *)(msm_cache_dump_addr + d->l1_size);
+		ret = msm_dump_table_register(&l1_dump_entry);
+		if (ret)
+			pr_err("Could not register L1 dump area: %d\n", ret);
+
+		ret = msm_dump_table_register(&l2_dump_entry);
+		if (ret)
+			pr_err("Could not register L2 dump area: %d\n", ret);
+	}
 
 	atomic_notifier_chain_register(&panic_notifier_list,
 						&msm_cache_dump_blk);
@@ -126,11 +172,18 @@
 	return 0;
 }
 
+static struct of_device_id cache_dump_match_table[] = {
+	{	.compatible = "qcom,cache_dump",	},
+	{}
+};
+EXPORT_COMPAT("qcom,cache_dump");
+
 static struct platform_driver msm_cache_dump_driver = {
 	.remove		= __devexit_p(msm_cache_dump_remove),
 	.driver         = {
 		.name = "msm_cache_dump",
-		.owner = THIS_MODULE
+		.owner = THIS_MODULE,
+		.of_match_table = cache_dump_match_table,
 	},
 };
 
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index ba0e242..3040a31 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -21,7 +21,6 @@
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
 
-#include <asm/mach-types.h>
 #include <mach/msm_iomap.h>
 
 #include "peripheral-loader.h"
@@ -359,18 +358,12 @@
 
 static int __init pil_riva_init(void)
 {
-	if (machine_is_mpq8064_hrd()) {
-		pr_err("pil_riva not supported on this target\n");
-		return 0;
-	}
 	return platform_driver_register(&pil_riva_driver);
 }
 module_init(pil_riva_init);
 
 static void __exit pil_riva_exit(void)
 {
-	if (machine_is_mpq8064_hrd())
-		return;
 	platform_driver_unregister(&pil_riva_driver);
 }
 module_exit(pil_riva_exit);
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 0c75f66..ed8cb345 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -26,3 +26,4 @@
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
+obj-m += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
new file mode 100644
index 0000000..6e6f8e8
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "adsprpc.h"
+
+struct smq_invoke_ctx {
+	struct completion work;
+	int retval;
+	atomic_t free;
+};
+
+struct smq_context_list {
+	struct smq_invoke_ctx *ls;
+	int size;
+	int last;
+};
+
+struct fastrpc_apps {
+	smd_channel_t *chan;
+	struct smq_context_list clst;
+	struct completion work;
+	struct ion_client *iclient;
+	struct cdev cdev;
+	dev_t dev_no;
+	spinlock_t wrlock;
+	spinlock_t hlock;
+	struct hlist_head htbl[RPC_HASH_SZ];
+};
+
+struct fastrpc_buf {
+	struct ion_handle *handle;
+	void *virt;
+	ion_phys_addr_t phys;
+	int size;
+	int used;
+};
+
+struct fastrpc_device {
+	uint32_t tgid;
+	struct hlist_node hn;
+	struct fastrpc_buf buf;
+};
+
+static struct fastrpc_apps gfa;
+
+static void free_mem(struct fastrpc_buf *buf)
+{
+	struct fastrpc_apps *me = &gfa;
+
+	if (buf->handle) {
+		if (buf->virt) {
+			ion_unmap_kernel(me->iclient, buf->handle);
+			buf->virt = 0;
+		}
+		ion_free(me->iclient, buf->handle);
+		buf->handle = 0;
+	}
+}
+
+static int alloc_mem(struct fastrpc_buf *buf)
+{
+	struct ion_client *clnt = gfa.iclient;
+	int err = 0;
+
+	buf->handle = ion_alloc(clnt, buf->size, SZ_4K,
+				ION_HEAP(ION_AUDIO_HEAP_ID));
+	VERIFY(0 == IS_ERR_OR_NULL(buf->handle));
+	buf->virt = 0;
+	VERIFY(0 != (buf->virt = ion_map_kernel(clnt, buf->handle,
+						ION_SET_CACHE(CACHED))));
+	VERIFY(0 == ion_phys(clnt, buf->handle, &buf->phys, &buf->size));
+ bail:
+	if (err && !IS_ERR_OR_NULL(buf->handle))
+		free_mem(buf);
+	return err;
+}
+
+static int context_list_ctor(struct smq_context_list *me, int size)
+{
+	int err = 0;
+	VERIFY(0 != (me->ls = kzalloc(size, GFP_KERNEL)));
+	me->size = size / sizeof(*me->ls);
+	me->last = 0;
+ bail:
+	return err;
+}
+
+static void context_list_dtor(struct smq_context_list *me)
+{
+	kfree(me->ls);
+	me->ls = 0;
+}
+
+static void context_list_alloc_ctx(struct smq_context_list *me,
+					struct smq_invoke_ctx **po)
+{
+	int ii = me->last;
+	struct smq_invoke_ctx *ctx;
+
+	for (;;) {
+		ii = ii % me->size;
+		ctx = &me->ls[ii];
+		if (atomic_read(&ctx->free) == 0)
+			if (0 == atomic_cmpxchg(&ctx->free, 0, 1))
+				break;
+		ii++;
+	}
+	me->last = ii;
+	ctx->retval = -1;
+	init_completion(&ctx->work);
+	*po = ctx;
+}
+
+static void context_free(struct smq_invoke_ctx *me)
+{
+	if (me)
+		atomic_set(&me->free, 0);
+}
+
+static void context_notify_user(struct smq_invoke_ctx *me, int retval)
+{
+	me->retval = retval;
+	complete(&me->work);
+}
+
+static void context_notify_all_users(struct smq_context_list *me)
+{
+	int ii;
+
+	if (!me->ls)
+		return;
+	for (ii = 0; ii < me->size; ++ii) {
+		if (atomic_read(&me->ls[ii].free) != 0)
+			complete(&me->ls[ii].work);
+	}
+}
+
+static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
+			struct fastrpc_buf *ibuf, struct fastrpc_buf *obuf)
+{
+	struct smq_phy_page *pgstart, *pages;
+	struct smq_invoke_buf *list;
+	int ii, rlen, err = 0;
+	int inbufs = REMOTE_SCALARS_INBUFS(sc);
+	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+
+	VERIFY(0 != try_module_get(THIS_MODULE));
+	LOCK_MMAP(kernel);
+	*obuf = *ibuf;
+ retry:
+	list = smq_invoke_buf_start((remote_arg_t *)obuf->virt, sc);
+	pgstart = smq_phy_page_start(sc, list);
+	pages = pgstart + 1;
+	rlen = obuf->size - ((uint32_t)pages - (uint32_t)obuf->virt);
+	if (rlen < 0) {
+		rlen = ((uint32_t)pages - (uint32_t)obuf->virt) - obuf->size;
+		obuf->size += buf_page_size(rlen);
+		obuf->handle = 0;
+		VERIFY(0 == alloc_mem(obuf));
+		goto retry;
+	}
+	pgstart->addr = obuf->phys;
+	pgstart->size = obuf->size;
+	for (ii = 0; ii < inbufs + outbufs; ++ii) {
+		void *buf;
+		int len, num;
+
+		len = pra[ii].buf.len;
+		if (!len)
+			continue;
+		buf = pra[ii].buf.pv;
+		num = buf_num_pages(buf, len);
+		if (!kernel)
+			list[ii].num = buf_get_pages(buf, len, num,
+				ii >= inbufs, pages, rlen / sizeof(*pages));
+		else
+			list[ii].num = 0;
+		VERIFY(list[ii].num >= 0);
+		if (list[ii].num) {
+			list[ii].pgidx = pages - pgstart;
+			pages = pages + list[ii].num;
+		} else if (rlen > sizeof(*pages)) {
+			list[ii].pgidx = pages - pgstart;
+			pages = pages + 1;
+		} else {
+			if (obuf->handle != ibuf->handle)
+				free_mem(obuf);
+			obuf->size += buf_page_size(sizeof(*pages));
+			obuf->handle = 0;
+			VERIFY(0 == alloc_mem(obuf));
+			goto retry;
+		}
+		rlen = obuf->size - ((uint32_t) pages - (uint32_t) obuf->virt);
+	}
+	obuf->used = obuf->size - rlen;
+ bail:
+	if (err && (obuf->handle != ibuf->handle))
+		free_mem(obuf);
+	UNLOCK_MMAP(kernel);
+	module_put(THIS_MODULE);
+	return err;
+}
+
+static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
+			remote_arg_t *rpra, remote_arg_t *upra,
+			struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs,
+			int *nbufs)
+{
+	struct smq_invoke_buf *list;
+	struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
+	struct smq_phy_page *pages;
+	void *args;
+	int ii, rlen, size, used, inh, bufs = 0, err = 0;
+	int inbufs = REMOTE_SCALARS_INBUFS(sc);
+	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+
+	list = smq_invoke_buf_start(rpra, sc);
+	pages = smq_phy_page_start(sc, list);
+	used = ALIGN_8(pbuf->used);
+	args = (void *)((char *)pbuf->virt + used);
+	rlen = pbuf->size - used;
+	for (ii = 0; ii < inbufs + outbufs; ++ii) {
+		int num;
+
+		rpra[ii].buf.len = pra[ii].buf.len;
+		if (list[ii].num) {
+			rpra[ii].buf.pv = pra[ii].buf.pv;
+			continue;
+		}
+		if (rlen < pra[ii].buf.len) {
+			struct fastrpc_buf *b;
+			pbuf->used = pbuf->size - rlen;
+			VERIFY(0 != (b = krealloc(obufs,
+				 (bufs + 1) * sizeof(*obufs), GFP_KERNEL)));
+			obufs = b;
+			pbuf = obufs + bufs;
+			pbuf->size = buf_num_pages(0, pra[ii].buf.len) *
+								PAGE_SIZE;
+			VERIFY(0 == alloc_mem(pbuf));
+			bufs++;
+			args = pbuf->virt;
+			rlen = pbuf->size;
+		}
+		num = buf_num_pages(args, pra[ii].buf.len);
+		if (pbuf == ibuf) {
+			list[ii].num = num;
+			list[ii].pgidx = 0;
+		} else {
+			list[ii].num = 1;
+			pages[list[ii].pgidx].addr =
+				buf_page_start((void *)(pbuf->phys +
+							 (pbuf->size - rlen)));
+			pages[list[ii].pgidx].size =
+				buf_page_size(pra[ii].buf.len);
+		}
+		if (ii < inbufs) {
+			if (!kernel)
+				VERIFY(0 == copy_from_user(args, pra[ii].buf.pv,
+							pra[ii].buf.len));
+			else
+				memmove(args, pra[ii].buf.pv, pra[ii].buf.len);
+		}
+		rpra[ii].buf.pv = args;
+		args = (void *)((char *)args + ALIGN_8(pra[ii].buf.len));
+		rlen -= ALIGN_8(pra[ii].buf.len);
+	}
+	for (ii = 0; ii < inbufs; ++ii) {
+		if (rpra[ii].buf.len)
+			dmac_flush_range(rpra[ii].buf.pv,
+				  (char *)rpra[ii].buf.pv + rpra[ii].buf.len);
+	}
+	pbuf->used = pbuf->size - rlen;
+	size = sizeof(*rpra) * REMOTE_SCALARS_INHANDLES(sc);
+	if (size) {
+		inh = inbufs + outbufs;
+		if (!kernel)
+			VERIFY(0 == copy_from_user(&rpra[inh], &upra[inh],
+							size));
+		else
+			memmove(&rpra[inh], &upra[inh], size);
+	}
+	dmac_flush_range(rpra, (char *)rpra + used);
+ bail:
+	*abufs = obufs;
+	*nbufs = bufs;
+	return err;
+}
+
+static int put_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
+			remote_arg_t *rpra, remote_arg_t *upra)
+{
+	int ii, inbufs, outbufs, outh, size;
+	int err = 0;
+
+	inbufs = REMOTE_SCALARS_INBUFS(sc);
+	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+	for (ii = inbufs; ii < inbufs + outbufs; ++ii) {
+		if (rpra[ii].buf.pv != pra[ii].buf.pv)
+			VERIFY(0 == copy_to_user(pra[ii].buf.pv,
+					rpra[ii].buf.pv, rpra[ii].buf.len));
+	}
+	size = sizeof(*rpra) * REMOTE_SCALARS_OUTHANDLES(sc);
+	if (size) {
+		outh = inbufs + outbufs + REMOTE_SCALARS_INHANDLES(sc);
+		if (!kernel)
+			VERIFY(0 == copy_to_user(&upra[outh], &rpra[outh],
+						size));
+		else
+			memmove(&upra[outh], &rpra[outh], size);
+	}
+ bail:
+	return err;
+}
+
+static void inv_args(uint32_t sc, remote_arg_t *rpra, int used)
+{
+	int ii, inbufs, outbufs;
+	int inv = 0;
+
+	inbufs = REMOTE_SCALARS_INBUFS(sc);
+	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+	for (ii = inbufs; ii < inbufs + outbufs; ++ii) {
+		if (buf_page_start(rpra) == buf_page_start(rpra[ii].buf.pv))
+			inv = 1;
+		else
+			dmac_inv_range(rpra[ii].buf.pv,
+				(char *)rpra[ii].buf.pv + rpra[ii].buf.len);
+	}
+
+	if (inv || REMOTE_SCALARS_OUTHANDLES(sc))
+		dmac_inv_range(rpra, (char *)rpra + used);
+}
+
+static int fastrpc_invoke_send(struct fastrpc_apps *me, remote_handle_t handle,
+				 uint32_t sc, struct smq_invoke_ctx *ctx,
+				 struct fastrpc_buf *buf)
+{
+	struct smq_msg msg;
+	int err = 0, len;
+
+	msg.pid = current->tgid;
+	msg.tid = current->pid;
+	msg.invoke.header.ctx = ctx;
+	msg.invoke.header.handle = handle;
+	msg.invoke.header.sc = sc;
+	msg.invoke.page.addr = buf->phys;
+	msg.invoke.page.size = buf_page_size(buf->used);
+	spin_lock(&me->wrlock);
+	len = smd_write(me->chan, &msg, sizeof(msg));
+	spin_unlock(&me->wrlock);
+	VERIFY(len == sizeof(msg));
+ bail:
+	return err;
+}
+
+static void fastrpc_deinit(void)
+{
+	struct fastrpc_apps *me = &gfa;
+
+	if (me->chan)
+		(void)smd_close(me->chan);
+	context_list_dtor(&me->clst);
+	ion_client_destroy(me->iclient);
+	me->iclient = 0;
+	me->chan = 0;
+}
+
+static void fastrpc_read_handler(void)
+{
+	struct fastrpc_apps *me = &gfa;
+	struct smq_invoke_rsp rsp;
+	int err = 0;
+
+	do {
+		VERIFY(sizeof(rsp) ==
+				 smd_read_from_cb(me->chan, &rsp, sizeof(rsp)));
+		context_notify_user(rsp.ctx, rsp.retval);
+	} while (!err);
+ bail:
+	return;
+}
+
+static void smd_event_handler(void *priv, unsigned event)
+{
+	struct fastrpc_apps *me = (struct fastrpc_apps *)priv;
+
+	switch (event) {
+	case SMD_EVENT_OPEN:
+		complete(&(me->work));
+		break;
+	case SMD_EVENT_CLOSE:
+		context_notify_all_users(&me->clst);
+		break;
+	case SMD_EVENT_DATA:
+		fastrpc_read_handler();
+		break;
+	}
+}
+
+static int fastrpc_init(void)
+{
+	int err = 0;
+	struct fastrpc_apps *me = &gfa;
+
+	if (me->chan == 0) {
+		int ii;
+		spin_lock_init(&me->hlock);
+		spin_lock_init(&me->wrlock);
+		init_completion(&me->work);
+		for (ii = 0; ii < RPC_HASH_SZ; ++ii)
+			INIT_HLIST_HEAD(&me->htbl[ii]);
+		VERIFY(0 == context_list_ctor(&me->clst, SZ_4K));
+		me->iclient = msm_ion_client_create(ION_HEAP_CARVEOUT_MASK,
+							DEVICE_NAME);
+		VERIFY(0 == IS_ERR_OR_NULL(me->iclient));
+		VERIFY(0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
+						SMD_APPS_QDSP, &me->chan,
+						me, smd_event_handler));
+		VERIFY(0 != wait_for_completion_timeout(&me->work,
+							RPC_TIMEOUT));
+	}
+ bail:
+	if (err)
+		fastrpc_deinit();
+	return err;
+}
+
+static void free_dev(struct fastrpc_device *dev)
+{
+	if (dev) {
+		module_put(THIS_MODULE);
+		free_mem(&dev->buf);
+		kfree(dev);
+	}
+}
+
+static int alloc_dev(struct fastrpc_device **dev)
+{
+	int err = 0;
+	struct fastrpc_device *fd = 0;
+
+	VERIFY(0 != try_module_get(THIS_MODULE));
+	VERIFY(0 != (fd = kzalloc(sizeof(*fd), GFP_KERNEL)));
+	fd->buf.size = PAGE_SIZE;
+	VERIFY(0 == alloc_mem(&fd->buf));
+	fd->tgid = current->tgid;
+	INIT_HLIST_NODE(&fd->hn);
+	*dev = fd;
+ bail:
+	if (err)
+		free_dev(fd);
+	return err;
+}
+
+static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev)
+{
+	struct hlist_head *head;
+	struct fastrpc_device *dev = 0;
+	struct hlist_node *n;
+	uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
+	int err = 0;
+
+	spin_lock(&me->hlock);
+	head = &me->htbl[h];
+	hlist_for_each_entry(dev, n, head, hn) {
+		if (dev->tgid == current->tgid) {
+			hlist_del(&dev->hn);
+			break;
+		}
+	}
+	spin_unlock(&me->hlock);
+	VERIFY(dev != 0);
+	*rdev = dev;
+ bail:
+	if (err) {
+		free_dev(dev);
+		err = alloc_dev(rdev);
+	}
+	return err;
+}
+
+static void add_dev(struct fastrpc_apps *me, struct fastrpc_device *dev)
+{
+	struct hlist_head *head;
+	uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
+
+	spin_lock(&me->hlock);
+	head = &me->htbl[h];
+	hlist_add_head(&dev->hn, head);
+	spin_unlock(&me->hlock);
+	return;
+}
+
+static int fastrpc_release_current_dsp_process(void);
+
+static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t kernel,
+			struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra)
+{
+	remote_arg_t *rpra = 0;
+	struct fastrpc_device *dev = 0;
+	struct smq_invoke_ctx *ctx = 0;
+	struct fastrpc_buf obuf, *abufs = 0, *b;
+	int interrupted = 0;
+	uint32_t sc;
+	int ii, nbufs = 0, err = 0;
+
+	sc = invoke->sc;
+	obuf.handle = 0;
+	if (REMOTE_SCALARS_LENGTH(sc)) {
+		VERIFY(0 == get_dev(me, &dev));
+		VERIFY(0 == get_page_list(kernel, sc, pra, &dev->buf, &obuf));
+		rpra = (remote_arg_t *)obuf.virt;
+		VERIFY(0 == get_args(kernel, sc, pra, rpra, invoke->pra, &obuf,
+					&abufs, &nbufs));
+	}
+
+	context_list_alloc_ctx(&me->clst, &ctx);
+	VERIFY(0 == fastrpc_invoke_send(me, invoke->handle, sc, ctx, &obuf));
+	inv_args(sc, rpra, obuf.used);
+	VERIFY(0 == (interrupted =
+			wait_for_completion_interruptible(&ctx->work)));
+	VERIFY(0 == (err = ctx->retval));
+	VERIFY(0 == put_args(kernel, sc, pra, rpra, invoke->pra));
+ bail:
+	if (interrupted) {
+		init_completion(&ctx->work);
+		if (!kernel)
+			(void)fastrpc_release_current_dsp_process();
+		wait_for_completion(&ctx->work);
+	}
+	context_free(ctx);
+	for (ii = 0, b = abufs; ii < nbufs; ++ii, ++b)
+		free_mem(b);
+	kfree(abufs);
+	if (dev) {
+		add_dev(me, dev);
+		if (obuf.handle != dev->buf.handle)
+			free_mem(&obuf);
+	}
+	return err;
+}
+
+static int fastrpc_create_current_dsp_process(void)
+{
+	int err = 0;
+	struct fastrpc_ioctl_invoke ioctl;
+	struct fastrpc_apps *me = &gfa;
+	remote_arg_t ra[1];
+	int tgid = 0;
+
+	tgid = current->tgid;
+	ra[0].buf.pv = &tgid;
+	ra[0].buf.len = sizeof(tgid);
+	ioctl.handle = 1;
+	ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
+	ioctl.pra = ra;
+	VERIFY(0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
+ bail:
+	return err;
+}
+
+static int fastrpc_release_current_dsp_process(void)
+{
+	int err = 0;
+	struct fastrpc_apps *me = &gfa;
+	struct fastrpc_ioctl_invoke ioctl;
+	remote_arg_t ra[1];
+	int tgid = 0;
+
+	tgid = current->tgid;
+	ra[0].buf.pv = &tgid;
+	ra[0].buf.len = sizeof(tgid);
+	ioctl.handle = 1;
+	ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
+	ioctl.pra = ra;
+	VERIFY(0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
+ bail:
+	return err;
+}
+
+static void cleanup_current_dev(void)
+{
+	struct fastrpc_apps *me = &gfa;
+	uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
+	struct hlist_head *head;
+	struct hlist_node *pos;
+	struct fastrpc_device *dev;
+
+ rnext:
+	dev = 0;
+	spin_lock(&me->hlock);
+	head = &me->htbl[h];
+	hlist_for_each_entry(dev, pos, head, hn) {
+		if (dev->tgid == current->tgid) {
+			hlist_del(&dev->hn);
+			break;
+		}
+	}
+	spin_unlock(&me->hlock);
+	if (dev) {
+		free_dev(dev);
+		goto rnext;
+	}
+	return;
+}
+
+static int fastrpc_device_release(struct inode *inode, struct file *file)
+{
+	(void)fastrpc_release_current_dsp_process();
+	cleanup_current_dev();
+	return 0;
+}
+
+static int fastrpc_device_open(struct inode *inode, struct file *filp)
+{
+	int err = 0;
+
+	if (0 != try_module_get(THIS_MODULE)) {
+		/* This call will cause a dev to be created
+		 * which will addref this module
+		 */
+		VERIFY(0 == fastrpc_create_current_dsp_process());
+ bail:
+		if (err)
+			cleanup_current_dev();
+		module_put(THIS_MODULE);
+	}
+	return err;
+}
+
+
+static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
+				 unsigned long ioctl_param)
+{
+	struct fastrpc_apps *me = &gfa;
+	struct fastrpc_ioctl_invoke invoke;
+	remote_arg_t *pra = 0;
+	void *param = (char *)ioctl_param;
+	int bufs, err = 0;
+
+	switch (ioctl_num) {
+	case FASTRPC_IOCTL_INVOKE:
+		VERIFY(0 == copy_from_user(&invoke, param, sizeof(invoke)));
+		bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
+			REMOTE_SCALARS_OUTBUFS(invoke.sc);
+		if (bufs) {
+			bufs = bufs * sizeof(*pra);
+			VERIFY(0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+		}
+		VERIFY(0 == copy_from_user(pra, invoke.pra, bufs));
+		VERIFY(0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
+								pra)));
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+ bail:
+	kfree(pra);
+	return err;
+}
+
+static const struct file_operations fops = {
+	.open = fastrpc_device_open,
+	.release = fastrpc_device_release,
+	.unlocked_ioctl = fastrpc_device_ioctl,
+};
+
+static int __init fastrpc_device_init(void)
+{
+	struct fastrpc_apps *me = &gfa;
+	int err = 0;
+
+	VERIFY(0 == fastrpc_init());
+	VERIFY(0 == alloc_chrdev_region(&me->dev_no, 0, 1, DEVICE_NAME));
+	cdev_init(&me->cdev, &fops);
+	me->cdev.owner = THIS_MODULE;
+	VERIFY(0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1));
+	pr_info("'mknod /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no));
+ bail:
+	return err;
+}
+
+static void __exit fastrpc_device_exit(void)
+{
+	struct fastrpc_apps *me = &gfa;
+
+	fastrpc_deinit();
+	cdev_del(&me->cdev);
+	unregister_chrdev_region(me->dev_no, 1);
+}
+
+module_init(fastrpc_device_init);
+module_exit(fastrpc_device_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/arch/arm/mach-msm/qdsp6v2/adsprpc.h
new file mode 100644
index 0000000..368b8e6
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef ADSPRPC_H
+#define ADSPRPC_H
+
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/hash.h>
+#include <linux/ion.h>
+#include <mach/msm_smd.h>
+#include <mach/ion.h>
+#include "adsprpc_shared.h"
+
+#ifndef ION_ADSPRPC_HEAP_ID
+#define ION_ADSPRPC_HEAP_ID ION_AUDIO_HEAP_ID
+#endif
+
+#define RPC_TIMEOUT	(5 * HZ)
+#define RPC_HASH_BITS	5
+#define RPC_HASH_SZ	(1 << RPC_HASH_BITS)
+
+#define ALIGN_8(a)	ALIGN(a, 8)
+
+#define LOCK_MMAP(kernel)\
+		do {\
+			if (!kernel)\
+				down_read(&current->mm->mmap_sem);\
+		} while (0)
+
+#define UNLOCK_MMAP(kernel)\
+		do {\
+			if (!kernel)\
+				up_read(&current->mm->mmap_sem);\
+		} while (0)
+
+
+static inline uint32_t buf_page_start(void *buf)
+{
+	uint32_t start = (uint32_t) buf & PAGE_MASK;
+	return start;
+}
+
+static inline uint32_t buf_page_offset(void *buf)
+{
+	uint32_t offset = (uint32_t) buf & (PAGE_SIZE - 1);
+	return offset;
+}
+
+static inline int buf_num_pages(void *buf, int len)
+{
+	uint32_t start = buf_page_start(buf) >> PAGE_SHIFT;
+	uint32_t end = (((uint32_t) buf + len - 1) & PAGE_MASK) >> PAGE_SHIFT;
+	int nPages = end - start + 1;
+	return nPages;
+}
+
+static inline uint32_t buf_page_size(uint32_t size)
+{
+	uint32_t sz = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+	return sz > PAGE_SIZE ? sz : PAGE_SIZE;
+}
+
+static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access,
+				  struct smq_phy_page *pages, int nr_elems)
+{
+	struct vm_area_struct *vma;
+	uint32_t start = buf_page_start(addr);
+	uint32_t len = nr_pages << PAGE_SHIFT;
+	uint32_t pfn;
+	int n = -1, err = 0;
+
+	VERIFY(0 != access_ok(access ? VERIFY_WRITE : VERIFY_READ,
+			      (void __user *)start, len));
+	VERIFY(0 != (vma = find_vma(current->mm, start)));
+	VERIFY(((uint32_t)addr + sz) <= vma->vm_end);
+	n = 0;
+	VERIFY(0 != (vma->vm_flags & VM_PFNMAP));
+	VERIFY(0 != (vma->vm_flags & VM_PFN_AT_MMAP));
+	VERIFY(nr_elems > 0);
+	pfn = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+	pages->addr = __pfn_to_phys(pfn);
+	pages->size = len;
+	n++;
+ bail:
+	return n;
+}
+
+#endif
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
new file mode 100644
index 0000000..04b1d4a
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef ADSPRPC_SHARED_H
+#define ADSPRPC_SHARED_H
+
+#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
+#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
+#define DEVICE_NAME      "adsprpc-smd"
+
+/* Retrives number of input buffers from the scalars parameter */
+#define REMOTE_SCALARS_INBUFS(sc)        (((sc) >> 16) & 0x0ff)
+
+/* Retrives number of output buffers from the scalars parameter */
+#define REMOTE_SCALARS_OUTBUFS(sc)       (((sc) >> 8) & 0x0ff)
+
+/* Retrives number of input handles from the scalars parameter */
+#define REMOTE_SCALARS_INHANDLES(sc)     (((sc) >> 4) & 0x0f)
+
+/* Retrives number of output handles from the scalars parameter */
+#define REMOTE_SCALARS_OUTHANDLES(sc)    ((sc) & 0x0f)
+
+#define REMOTE_SCALARS_LENGTH(sc)	(REMOTE_SCALARS_INBUFS(sc) +\
+					REMOTE_SCALARS_OUTBUFS(sc) +\
+					REMOTE_SCALARS_INHANDLES(sc) +\
+					REMOTE_SCALARS_OUTHANDLES(sc))
+
+#define REMOTE_SCALARS_MAKEX(attr, method, in, out, oin, oout) \
+		((((uint32_t)   (attr) & 0x7) << 29) | \
+		(((uint32_t) (method) & 0x1f) << 24) | \
+		(((uint32_t)     (in) & 0xff) << 16) | \
+		(((uint32_t)    (out) & 0xff) <<  8) | \
+		(((uint32_t)    (oin) & 0x0f) <<  4) | \
+		((uint32_t)   (oout) & 0x0f))
+
+#define REMOTE_SCALARS_MAKE(method, in, out) \
+		REMOTE_SCALARS_MAKEX(0, method, in, out, 0, 0)
+
+
+#ifndef VERIFY_PRINT_ERROR
+#define VERIFY_EPRINTF(format, args) (void)0
+#endif
+
+#ifndef VERIFY_PRINT_INFO
+#define VERIFY_IPRINTF(args) (void)0
+#endif
+
+#ifndef VERIFY
+#define __STR__(x) #x ":"
+#define __TOSTR__(x) __STR__(x)
+#define __FILE_LINE__ __FILE__ ":" __TOSTR__(__LINE__)
+
+#define VERIFY(val) \
+do {\
+	VERIFY_IPRINTF(__FILE_LINE__"info: calling: " #val "\n");\
+	if (0 == (val)) {\
+		err = err == 0 ? -1 : err;\
+		VERIFY_EPRINTF(__FILE_LINE__"error: %d: " #val "\n", err);\
+		goto bail;\
+	} else {\
+		VERIFY_IPRINTF(__FILE_LINE__"info: passed: " #val "\n");\
+	} \
+} while (0)
+#endif
+
+#define remote_handle_t uint32_t
+#define remote_arg_t    union remote_arg
+
+struct remote_buf {
+	void *pv;		/* buffer pointer */
+	int len;		/* length of buffer */
+};
+
+union remote_arg {
+	struct remote_buf buf;	/* buffer info */
+	remote_handle_t h;	/* remote handle */
+};
+
+struct fastrpc_ioctl_invoke {
+	remote_handle_t handle;	/* remote handle */
+	uint32_t sc;		/* scalars describing the data */
+	remote_arg_t *pra;	/* remote arguments list */
+};
+
+struct smq_null_invoke {
+	struct smq_invoke_ctx *ctx; /* invoke caller context */
+	remote_handle_t handle;	    /* handle to invoke */
+	uint32_t sc;		    /* scalars structure describing the data */
+};
+
+struct smq_phy_page {
+	uint32_t addr;		/* physical address */
+	uint32_t size;		/* size of contiguous region */
+};
+
+struct smq_invoke_buf {
+	int num;		/* number of contiguous regions */
+	int pgidx;		/* index to start of contiguous region */
+};
+
+struct smq_invoke {
+	struct smq_null_invoke header;
+	struct smq_phy_page page;   /* remote arg and list of pages address */
+};
+
+struct smq_msg {
+	uint32_t pid;           /* process group id */
+	uint32_t tid;           /* thread id */
+	struct smq_invoke invoke;
+};
+
+struct smq_invoke_rsp {
+	struct smq_invoke_ctx *ctx;  /* invoke caller context */
+	int retval;	             /* invoke return value */
+};
+
+static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg_t *pra,
+							uint32_t sc)
+{
+	int len = REMOTE_SCALARS_LENGTH(sc);
+	return (struct smq_invoke_buf *)(&pra[len]);
+}
+
+static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc,
+						struct smq_invoke_buf *buf)
+{
+	int nTotal = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
+	return (struct smq_phy_page *)(&buf[nTotal]);
+}
+
+static inline int smq_invoke_buf_size(uint32_t sc, int nPages)
+{
+	struct smq_phy_page *start = smq_phy_page_start(sc, 0);
+	return (int)(&(start[nPages]));
+}
+
+#endif
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 30acebf..928e59b 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -35,6 +35,7 @@
 
 #include <mach/msm_smd.h>
 #include <mach/peripheral-loader.h>
+#include <mach/msm_ipc_logging.h>
 
 #include "smd_private.h"
 #ifdef CONFIG_ARCH_FSM9XXX
@@ -89,6 +90,9 @@
 static void check_and_wakeup_writer(struct smd_pkt_dev *smd_pkt_devp);
 static uint32_t is_modem_smsm_inited(void);
 
+#define SMD_PKT_IPC_LOG_PAGE_CNT 2
+static void *smd_pkt_ilctxt;
+
 static int msm_smd_pkt_debug_mask;
 module_param_named(debug_mask, msm_smd_pkt_debug_mask,
 		int, S_IRUGO | S_IWUSR | S_IWGRP);
@@ -105,22 +109,44 @@
 #define DEBUG
 
 #ifdef DEBUG
+
+#define SMD_PKT_LOG_STRING(x...) \
+do { \
+	if (smd_pkt_ilctxt) \
+		ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: "x); \
+} while (0)
+
+#define SMD_PKT_LOG_BUF(buf, cnt) \
+do { \
+	char log_buf[128]; \
+	int i; \
+	if (smd_pkt_ilctxt) { \
+		i = cnt < 16 ? cnt : 16; \
+		hex_dump_to_buffer(buf, i, 16, 1, log_buf, \
+				   sizeof(log_buf), false); \
+		ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: %s", log_buf); \
+	} \
+} while (0)
+
 #define D_STATUS(x...) \
 do { \
 	if (msm_smd_pkt_debug_mask & SMD_PKT_STATUS) \
 		pr_info("Status: "x); \
+	SMD_PKT_LOG_STRING(x); \
 } while (0)
 
 #define D_READ(x...) \
 do { \
 	if (msm_smd_pkt_debug_mask & SMD_PKT_READ) \
 		pr_info("Read: "x); \
+	SMD_PKT_LOG_STRING(x); \
 } while (0)
 
 #define D_WRITE(x...) \
 do { \
 	if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE) \
 		pr_info("Write: "x); \
+	SMD_PKT_LOG_STRING(x); \
 } while (0)
 
 #define D_READ_DUMP_BUFFER(prestr, cnt, buf) \
@@ -129,6 +155,7 @@
 		print_hex_dump(KERN_INFO, prestr, \
 			       DUMP_PREFIX_NONE, 16, 1, \
 			       buf, cnt, 1); \
+	SMD_PKT_LOG_BUF(buf, cnt); \
 } while (0)
 
 #define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) \
@@ -137,12 +164,14 @@
 		print_hex_dump(KERN_INFO, prestr, \
 			       DUMP_PREFIX_NONE, 16, 1, \
 			       buf, cnt, 1); \
+	SMD_PKT_LOG_BUF(buf, cnt); \
 } while (0)
 
 #define D_POLL(x...) \
 do { \
 	if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
 		pr_info("Poll: "x); \
+	SMD_PKT_LOG_STRING(x); \
 } while (0)
 
 #define E_SMD_PKT_SSR(x) \
@@ -1032,6 +1061,9 @@
 
 	INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
 
+	smd_pkt_ilctxt = ipc_log_context_create(SMD_PKT_IPC_LOG_PAGE_CNT,
+						"smd_pkt");
+
 	D_STATUS("SMD Packet Port Driver Initialized.\n");
 	return 0;
 
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index ed03b33..19ef5a6 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -37,6 +37,9 @@
 
 #include "fault.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/exception.h>
+
 #ifdef CONFIG_MMU
 
 #ifdef CONFIG_KPROBES
@@ -173,6 +176,8 @@
 {
 	struct siginfo si;
 
+	trace_user_fault(tsk, addr, fsr);
+
 #ifdef CONFIG_DEBUG_USER
 	if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
 	    ((user_debug & UDBG_BUS)  && (sig == SIGBUS))) {
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c827ec7..a669b45 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1124,6 +1124,7 @@
 			driver->apps_rsp_buf[2] = 0x0;
 			driver->apps_rsp_buf[3] = 0x0;
 			*(int *)(driver->apps_rsp_buf + 4) = 0x0;
+			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
 			if (driver->ch_cntl)
 				diag_send_log_mask_update(driver->ch_cntl,
 								 ALL_EQUIP_ID);
@@ -1133,7 +1134,7 @@
 			if (driver->ch_wcnss_cntl)
 				diag_send_log_mask_update(driver->ch_wcnss_cntl,
 								 ALL_EQUIP_ID);
-			ENCODE_RSP_AND_SEND(7);
+			ENCODE_RSP_AND_SEND(11);
 			return 0;
 		}
 #endif
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 1219af1..a23fff0 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -30,3 +30,12 @@
 
 	  For production builds, you should probably say 'N' here to avoid
 	  potential power, performance and memory penalty.
+
+config CONTROL_TRACE
+	tristate "Turn on to control tracing"
+	help
+	  Builds module to abort tracing on a user space data, instruction
+	  or prefetch abort.
+
+	  For production builds, you should probably say 'N' here to avoid
+	  potential power, performance and memory penalty.
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 4ee93cf..a2815de 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,3 +1,3 @@
-
+obj-$(CONFIG_CONTROL_TRACE) += control_trace.o
 obj-$(CONFIG_OF) += of_coresight.o
 obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-csr.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o
diff --git a/drivers/coresight/control_trace.c b/drivers/coresight/control_trace.c
new file mode 100644
index 0000000..aa8bfc5
--- /dev/null
+++ b/drivers/coresight/control_trace.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * DLKM to register a callback with a ftrace event
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
+#include <linux/coresight.h>
+
+#include <trace/events/exception.h>
+
+static void abort_coresight_tracing(void *ignore, struct task_struct *task,\
+					unsigned long addr, unsigned int fsr)
+{
+	coresight_abort();
+	pr_debug("control_trace: task_name: %s, addr: %lu, fsr:%u",\
+		(char *)task->comm, addr, fsr);
+}
+
+static void abort_tracing_undef_instr(void *ignore, struct pt_regs *regs,\
+					void *pc)
+{
+	if (user_mode(regs)) {
+		coresight_abort();
+		pr_debug("control_trace: pc: %p", pc);
+	}
+}
+
+static int __init control_trace_init(void)
+{
+	int ret_user_fault, ret_undef_instr;
+	ret_user_fault = register_trace_user_fault(abort_coresight_tracing,\
+							NULL);
+	ret_undef_instr = register_trace_undef_instr(abort_tracing_undef_instr,\
+							NULL);
+	if (ret_user_fault != 0 || ret_undef_instr != 0) {
+		pr_info("control_trace: Module Not Registered\n");
+		return (ret_user_fault < 0 ?\
+			ret_user_fault : ret_undef_instr);
+	}
+	pr_info("control_trace: Module Registered\n");
+	return 0;
+}
+
+module_init(control_trace_init);
+
+static void __exit control_trace_exit(void)
+{
+	unregister_trace_user_fault(abort_coresight_tracing, NULL);
+	unregister_trace_undef_instr(abort_tracing_undef_instr, NULL);
+	pr_info("control_trace: Module Removed\n");
+}
+
+module_exit(control_trace_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Kernel Module to abort tracing");
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index b8fca38..7bf928f 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2706,62 +2706,100 @@
 	return val;
 }
 
+struct a3xx_vbif_data {
+	unsigned int reg;
+	unsigned int val;
+};
+
+/* VBIF registers start after 0x3000 so use 0x0 as end of list marker */
+static struct a3xx_vbif_data a305_vbif[] = {
+	/* Set up 16 deep read/write request queues */
+	{ A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010 },
+	{ A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 },
+	{ A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010 },
+	/* Enable WR-REQ */
+	{ A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000FF },
+	/* Set up round robin arbitration between both AXI ports */
+	{ A3XX_VBIF_ARB_CTL, 0x00000030 },
+	/* Set up AOOO */
+	{ A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003C },
+	{ A3XX_VBIF_OUT_AXI_AOOO, 0x003C003C },
+	{0, 0},
+};
+
+static struct a3xx_vbif_data a320_vbif[] = {
+	/* Set up 16 deep read/write request queues */
+	{ A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010 },
+	{ A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 },
+	{ A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010 },
+	{ A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010 },
+	/* Enable WR-REQ */
+	{ A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000FF },
+	/* Set up round robin arbitration between both AXI ports */
+	{ A3XX_VBIF_ARB_CTL, 0x00000030 },
+	/* Set up AOOO */
+	{ A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003C },
+	{ A3XX_VBIF_OUT_AXI_AOOO, 0x003C003C },
+	/* Enable 1K sort */
+	{ A3XX_VBIF_ABIT_SORT, 0x000000FF },
+	{ A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4 },
+	{0, 0},
+};
+
+static struct a3xx_vbif_data a330_vbif[] = {
+	/* Set up 16 deep read/write request queues */
+	{ A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818 },
+	{ A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818 },
+	{ A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818 },
+	{ A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818 },
+	{ A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 },
+	{ A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818 },
+	{ A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818 },
+	/* Enable WR-REQ */
+	{ A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003F },
+	/* Set up round robin arbitration between both AXI ports */
+	{ A3XX_VBIF_ARB_CTL, 0x00000030 },
+	/* Set up VBIF_ROUND_ROBIN_QOS_ARB */
+	{ A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001 },
+	/* Set up AOOO */
+	{ A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000FFFF },
+	{ A3XX_VBIF_OUT_AXI_AOOO, 0xFFFFFFFF },
+	/* Enable 1K sort */
+	{ A3XX_VBIF_ABIT_SORT, 0x1FFFF },
+	{ A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4 },
+	/* Disable VBIF clock gating. This is to enable AXI running
+	 * higher frequency than GPU.
+	 */
+	{ A3XX_VBIF_CLKON, 1 },
+	{0, 0},
+};
+
 static void a3xx_start(struct adreno_device *adreno_dev)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
+	struct a3xx_vbif_data *vbif = NULL;
 
-	/* Set up 16 deep read/write request queues */
-	if (adreno_is_a330(adreno_dev)) {
-		adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
-		adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
-		adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
-		adreno_regwrite(device, A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
-		adreno_regwrite(device, A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
-		adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
-		adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
-		/* Enable WR-REQ */
-		adreno_regwrite(device, A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003F);
+	if (adreno_is_a305(adreno_dev))
+		vbif = a305_vbif;
+	else if (adreno_is_a320(adreno_dev))
+		vbif = a320_vbif;
+	else if (adreno_is_a330(adreno_dev))
+		vbif = a330_vbif;
 
-		/* Set up round robin arbitration between both AXI ports */
-		adreno_regwrite(device, A3XX_VBIF_ARB_CTL, 0x00000030);
-		/* Set up VBIF_ROUND_ROBIN_QOS_ARB */
-		adreno_regwrite(device, A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
+	BUG_ON(vbif == NULL);
 
-		/* Set up AOOO */
-		adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000FFFF);
-		adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO, 0xFFFFFFFF);
-
-		/* Enable 1K sort */
-		adreno_regwrite(device, A3XX_VBIF_ABIT_SORT, 0x1FFFF);
-		adreno_regwrite(device, A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
-
-		/* Diable VBIF clock gating. This is to enable AXI running
-		 * higher frequency than GPU.
-		 */
-		adreno_regwrite(device, A3XX_VBIF_CLKON, 1);
-	} else {
-		adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
-		adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
-		adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
-		adreno_regwrite(device, A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
-		adreno_regwrite(device, A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
-		adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
-		adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
-		/* Enable WR-REQ */
-		adreno_regwrite(device, A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000FF);
-
-		/* Set up round robin arbitration between both AXI ports */
-		adreno_regwrite(device, A3XX_VBIF_ARB_CTL, 0x00000030);
-		/* Set up AOOO */
-		adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003C);
-		adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO, 0x003C003C);
+	while (vbif->reg != 0) {
+		adreno_regwrite(device, vbif->reg, vbif->val);
+		vbif++;
 	}
 
-	if (cpu_is_apq8064()) {
-		/* Enable 1K sort */
-		adreno_regwrite(device, A3XX_VBIF_ABIT_SORT, 0x000000FF);
-		adreno_regwrite(device, A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
-	}
 	/* Make all blocks contribute to the GPU BUSY perf counter */
 	adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
 
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index dee889d..0e1e100 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -320,7 +320,7 @@
 	if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
 		return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
 	else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
-		return SZ_2G;
+		return SZ_2G - KGSL_PAGETABLE_BASE;
 	else
 		return 0;
 }
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 8e35252..181a97e 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -31,6 +31,7 @@
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
+#include <mach/msm_xo.h>
 
 /* User Bank register set */
 #define PM8XXX_ADC_ARB_USRP_CNTRL1			0x197
@@ -141,6 +142,7 @@
 	struct work_struct			cool_work;
 	uint32_t				mpp_base;
 	struct device				*hwmon;
+	struct msm_xo_voter			*adc_voter;
 	int					msm_suspend_check;
 	struct pm8xxx_adc_amux_properties	*conv;
 	struct pm8xxx_adc_arb_btm_param		batt;
@@ -290,14 +292,34 @@
 	return rc;
 }
 
+static int32_t pm8xxx_adc_xo_vote(bool on)
+{
+	struct pm8xxx_adc *adc_pmic = pmic_adc;
+
+	if (on)
+		msm_xo_mode_vote(adc_pmic->adc_voter, MSM_XO_MODE_ON);
+	else
+		msm_xo_mode_vote(adc_pmic->adc_voter, MSM_XO_MODE_OFF);
+
+	return 0;
+}
+
 static int32_t pm8xxx_adc_channel_power_enable(uint32_t channel,
 							bool power_cntrl)
 {
 	int rc = 0;
 
-	switch (channel)
+	switch (channel) {
 	case ADC_MPP_1_AMUX8:
 		rc = pm8xxx_adc_patherm_power(power_cntrl);
+		break;
+	case CHANNEL_DIE_TEMP:
+	case CHANNEL_MUXOFF:
+		rc = pm8xxx_adc_xo_vote(power_cntrl);
+		break;
+	default:
+		break;
+	}
 
 	return rc;
 }
@@ -1147,6 +1169,7 @@
 	struct pm8xxx_adc *adc_pmic = pmic_adc;
 	int i;
 
+	msm_xo_put(adc_pmic->adc_voter);
 	platform_set_drvdata(pdev, NULL);
 	pmic_adc = NULL;
 	if (!pa_therm) {
@@ -1265,6 +1288,14 @@
 	}
 	adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
 
+	if (adc_pmic->adc_voter == NULL) {
+		adc_pmic->adc_voter = msm_xo_get(MSM_XO_TCXO_D0, "pmic_xoadc");
+		if (IS_ERR(adc_pmic->adc_voter)) {
+			dev_err(&pdev->dev, "Failed to get XO vote\n");
+			return PTR_ERR(adc_pmic->adc_voter);
+		}
+	}
+
 	pa_therm = regulator_get(adc_pmic->dev, "pa_therm");
 	if (IS_ERR(pa_therm)) {
 		rc = PTR_ERR(pa_therm);
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 6cddf2d..e2f37cc 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -699,7 +699,8 @@
 			for (i = 0; i < 6; i++)
 				e_addr[i] = buf[7-i];
 
-			ret = slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
+			ret = slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr,
+						false);
 			/* Is this Qualcomm ported generic device? */
 			if (!ret && e_addr[5] == QC_MFGID_LSB &&
 				e_addr[4] == QC_MFGID_MSB &&
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 6d96d3b..bd25875 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -681,13 +681,13 @@
 }
 
 static int ctrl_getlogical_addr(struct slim_controller *ctrl, const u8 *eaddr,
-				u8 e_len, u8 *laddr)
+				u8 e_len, u8 *entry)
 {
 	u8 i;
 	for (i = 0; i < ctrl->num_dev; i++) {
 		if (ctrl->addrt[i].valid &&
 			memcmp(ctrl->addrt[i].eaddr, eaddr, e_len) == 0) {
-			*laddr = i;
+			*entry = i;
 			return 0;
 		}
 	}
@@ -699,23 +699,28 @@
  * @ctrl: Controller with which device is enumerated.
  * @e_addr: 6-byte elemental address of the device.
  * @e_len: buffer length for e_addr
- * @laddr: Return logical address.
+  * @laddr: Return logical address (if valid flag is false)
+  * @valid: true if laddr holds a valid address that controller wants to
+  *	set for this enumeration address. Otherwise framework sets index into
+  *	address table as logical address.
  * Called by controller in response to REPORT_PRESENT. Framework will assign
  * a logical address to this enumeration address.
  * Function returns -EXFULL to indicate that all logical addresses are already
  * taken.
  */
 int slim_assign_laddr(struct slim_controller *ctrl, const u8 *e_addr,
-				u8 e_len, u8 *laddr)
+				u8 e_len, u8 *laddr, bool valid)
 {
 	int ret;
 	u8 i = 0;
+	bool exists = false;
 	struct slim_device *sbdev;
 	mutex_lock(&ctrl->m_ctrl);
 	/* already assigned */
-	if (ctrl_getlogical_addr(ctrl, e_addr, e_len, laddr) == 0)
-		i = *laddr;
-	else {
+	if (ctrl_getlogical_addr(ctrl, e_addr, e_len, &i) == 0) {
+		*laddr = ctrl->addrt[i].laddr;
+		exists = true;
+	} else {
 		if (ctrl->num_dev >= 254) {
 			ret = -EXFULL;
 			goto ret_assigned_laddr;
@@ -737,22 +742,26 @@
 		}
 		memcpy(ctrl->addrt[i].eaddr, e_addr, e_len);
 		ctrl->addrt[i].valid = true;
+		/* Preferred address is index into table */
+		if (!valid)
+			*laddr = i;
 	}
 
-	ret = ctrl->set_laddr(ctrl, ctrl->addrt[i].eaddr, 6, i);
+	ret = ctrl->set_laddr(ctrl, (const u8 *)&ctrl->addrt[i].eaddr, 6,
+				*laddr);
 	if (ret) {
 		ctrl->addrt[i].valid = false;
 		goto ret_assigned_laddr;
 	}
-	*laddr = i;
+	ctrl->addrt[i].laddr = *laddr;
 
-	dev_dbg(&ctrl->dev, "setting slimbus l-addr:%x\n", i);
+	dev_dbg(&ctrl->dev, "setting slimbus l-addr:%x\n", *laddr);
 ret_assigned_laddr:
 	mutex_unlock(&ctrl->m_ctrl);
-	if (ret)
+	if (exists || ret)
 		return ret;
 
-	pr_info("slimbus laddr:0x%x, EAPC:0x%x:0x%x", i,
+	pr_info("slimbus:%d laddr:0x%x, EAPC:0x%x:0x%x", ctrl->nr, *laddr,
 				e_addr[1], e_addr[2]);
 	mutex_lock(&ctrl->m_ctrl);
 	list_for_each_entry(sbdev, &ctrl->devs, dev_list) {
@@ -785,12 +794,21 @@
 				u8 e_len, u8 *laddr)
 {
 	int ret = 0;
+	u8 entry;
 	struct slim_controller *ctrl = sb->ctrl;
 	if (!ctrl || !laddr || !e_addr || e_len != 6)
 		return -EINVAL;
 	mutex_lock(&ctrl->m_ctrl);
-	ret = ctrl_getlogical_addr(ctrl, e_addr, e_len, laddr);
+	ret = ctrl_getlogical_addr(ctrl, e_addr, e_len, &entry);
+	if (!ret)
+		*laddr = ctrl->addrt[entry].laddr;
 	mutex_unlock(&ctrl->m_ctrl);
+	if (ret == -ENXIO && ctrl->get_laddr) {
+		ret = ctrl->get_laddr(ctrl, e_addr, e_len, laddr);
+		if (!ret)
+			ret = slim_assign_laddr(ctrl, e_addr, e_len, laddr,
+						true);
+	}
 	return ret;
 }
 EXPORT_SYMBOL_GPL(slim_get_logical_addr);
@@ -943,8 +961,6 @@
 	u16 ec;
 	u8 tid, mlen = 6;
 
-	if (sbdev->laddr != SLIM_LA_MANAGER && sbdev->laddr >= ctrl->num_dev)
-		return -ENXIO;
 	ret = slim_ele_access_sanity(msg, mc, rbuf, wbuf, len);
 	if (ret)
 		goto xfer_err;
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index 8753c0d..87f43e1c 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -262,6 +262,8 @@
 			return;
 		}
 
+		usb_free_urb(urb);
+
 		spin_lock_irqsave(&ksb->lock, flags);
 	}
 	spin_unlock_irqrestore(&ksb->lock, flags);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 6e3567f..f6d9eb7 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -606,7 +606,7 @@
 
 static int mdp_hist_init_mgmt(struct mdp_hist_mgmt *mgmt, uint32_t block)
 {
-	uint32_t bins, extra, index, term = 0;
+	uint32_t bins, extra, index, intr = 0, term = 0;
 	init_completion(&mgmt->mdp_hist_comp);
 	mutex_init(&mgmt->mdp_hist_mutex);
 	mutex_init(&mgmt->mdp_do_hist_mutex);
@@ -622,6 +622,8 @@
 	switch (block) {
 	case MDP_BLOCK_DMA_P:
 		term = MDP_HISTOGRAM_TERM_DMA_P;
+		intr = (mdp_rev >= MDP_REV_40) ? INTR_DMA_P_HISTOGRAM :
+								MDP_HIST_DONE;
 		bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
 			MDP_REV41_HIST_MAX_BIN;
 		extra = 2;
@@ -630,6 +632,7 @@
 		break;
 	case MDP_BLOCK_DMA_S:
 		term = MDP_HISTOGRAM_TERM_DMA_S;
+		intr = INTR_DMA_S_HISTOGRAM;
 		bins = MDP_REV42_HIST_MAX_BIN;
 		extra = 2;
 		mgmt->base += 0x5000;
@@ -637,6 +640,7 @@
 		break;
 	case MDP_BLOCK_VG_1:
 		term = MDP_HISTOGRAM_TERM_VG_1;
+		intr = INTR_VG1_HISTOGRAM;
 		bins = MDP_REV42_HIST_MAX_BIN;
 		extra = 1;
 		mgmt->base += 0x6000;
@@ -644,6 +648,7 @@
 		break;
 	case MDP_BLOCK_VG_2:
 		term = MDP_HISTOGRAM_TERM_VG_2;
+		intr = INTR_VG2_HISTOGRAM;
 		bins = MDP_REV42_HIST_MAX_BIN;
 		extra = 1;
 		mgmt->base += 0x6000;
@@ -651,6 +656,8 @@
 		break;
 	default:
 		term = MDP_HISTOGRAM_TERM_DMA_P;
+		intr = (mdp_rev >= MDP_REV_40) ? INTR_DMA_P_HISTOGRAM :
+								MDP_HIST_DONE;
 		bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
 			MDP_REV41_HIST_MAX_BIN;
 		extra = 2;
@@ -658,6 +665,7 @@
 		index = MDP_HIST_MGMT_DMA_P;
 	}
 	mgmt->irq_term = term;
+	mgmt->intr = intr;
 
 	mgmt->c0 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
 	if (mgmt->c0 == NULL)
@@ -802,20 +810,45 @@
 static int mdp_histogram_enable(struct mdp_hist_mgmt *mgmt)
 {
 	uint32_t base;
+	unsigned long flag;
 	if (mgmt->mdp_is_hist_data == TRUE) {
 		pr_err("%s histogram already started\n", __func__);
 		return -EINVAL;
 	}
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	mdp_enable_irq(mgmt->irq_term);
+	base = (uint32_t) (MDP_BASE + mgmt->base);
+	/*First make sure that device is not collecting histogram*/
+	mgmt->mdp_is_hist_data = FALSE;
+	mgmt->mdp_is_hist_valid = FALSE;
+	mgmt->mdp_is_hist_init = FALSE;
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	outp32(MDP_INTR_CLEAR, mgmt->intr);
+	mdp_intr_mask &= ~mgmt->intr;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	MDP_OUTP(base + 0x001C, 0);
+	MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+	MDP_OUTP(base + 0x0024, 0);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+	cancel_work_sync(&mgmt->mdp_histogram_worker);
+	mutex_lock(&mgmt->mdp_hist_mutex);
+
+	/*Then initialize histogram*/
 	INIT_COMPLETION(mgmt->mdp_hist_comp);
 
-	base = (uint32_t) (MDP_BASE + mgmt->base);
+	spin_lock_irqsave(&mdp_spin_lock, flag);
 	MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
 	MDP_OUTP(base + 0x0010, 1);
 	MDP_OUTP(base + 0x001C, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
 
+	outp32(MDP_INTR_CLEAR, mgmt->intr);
+	mdp_intr_mask |= mgmt->intr;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	mdp_enable_irq(mgmt->irq_term);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
 	MDP_OUTP(base + 0x0004, mgmt->frame_cnt);
 	if (mgmt->block != MDP_BLOCK_VG_1 && mgmt->block != MDP_BLOCK_VG_2)
 		MDP_OUTP(base + 0x0008, mgmt->bit_mask);
@@ -830,6 +863,7 @@
 static int mdp_histogram_disable(struct mdp_hist_mgmt *mgmt)
 {
 	uint32_t base, status;
+	unsigned long flag;
 	if (mgmt->mdp_is_hist_data == FALSE) {
 		pr_err("%s histogram already stopped\n", __func__);
 		return -EINVAL;
@@ -842,6 +876,13 @@
 	base = (uint32_t) (MDP_BASE + mgmt->base);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	outp32(MDP_INTR_CLEAR, mgmt->intr);
+	mdp_intr_mask &= ~mgmt->intr;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	mdp_disable_irq(mgmt->irq_term);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
 	if (mdp_rev >= MDP_REV_42)
 		MDP_OUTP(base + 0x0020, 1);
 	status = inpdw(base + 0x001C);
@@ -856,7 +897,6 @@
 		complete(&mgmt->mdp_hist_comp);
 	}
 
-	mdp_disable_irq(mgmt->irq_term);
 	return 0;
 }
 
@@ -1102,6 +1142,7 @@
 	struct mdp_hist_mgmt *mgmt = container_of(data, struct mdp_hist_mgmt,
 							mdp_histogram_worker);
 	int ret = 0;
+	bool hist_ready;
 	mutex_lock(&mgmt->mdp_hist_mutex);
 	if (mgmt->mdp_is_hist_data == FALSE) {
 		pr_debug("%s, Histogram disabled before read.\n", __func__);
@@ -1116,8 +1157,9 @@
 			pr_err("mgmt->hist invalid NULL\n");
 		ret = -EINVAL;
 	}
+	hist_ready = (mgmt->mdp_is_hist_init && mgmt->mdp_is_hist_valid);
 
-	if (!ret) {
+	if (!ret && hist_ready) {
 		switch (mgmt->block) {
 		case MDP_BLOCK_DMA_P:
 		case MDP_BLOCK_DMA_S:
@@ -1138,7 +1180,7 @@
 	 * if read was triggered by an underrun or failed copying,
 	 * don't wake up readers
 	 */
-	if (!ret && mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
+	if (!ret && hist_ready) {
 		mgmt->hist = NULL;
 		if (waitqueue_active(&mgmt->mdp_hist_comp.wait))
 			complete(&mgmt->mdp_hist_comp);
@@ -1150,7 +1192,7 @@
 			mgmt->mdp_is_hist_init = TRUE;
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	if (!ret)
+	if (!ret && hist_ready)
 		__mdp_histogram_kickoff(mgmt);
 	else
 		__mdp_histogram_reset(mgmt);
@@ -1728,10 +1770,8 @@
 	isr &= mask;
 	if (isr & INTR_HIST_RESET_SEQ_DONE)
 		__mdp_histogram_kickoff(mgmt);
-
-	if (isr & INTR_HIST_DONE) {
+	else if (isr & INTR_HIST_DONE)
 		queue_work(mdp_hist_wq, &mgmt->mdp_histogram_worker);
-	}
 }
 
 #ifndef CONFIG_FB_MSM_MDP40
@@ -1741,7 +1781,6 @@
 	struct mdp_dma_data *dma;
 	unsigned long flag;
 	struct mdp_hist_mgmt *mgmt = NULL;
-	char *base_addr;
 	int i, ret;
 	int vsync_isr;
 	/* Ensure all the register write are complete */
@@ -1813,13 +1852,7 @@
 				mgmt = mdp_hist_mgmt_array[i];
 				if (!mgmt)
 					continue;
-
-				base_addr = MDP_BASE + mgmt->base;
-				outpdw(base_addr + 0x010, 1);
-				outpdw(base_addr + 0x01C, INTR_HIST_DONE |
-						INTR_HIST_RESET_SEQ_DONE);
 				mgmt->mdp_is_hist_valid = FALSE;
-				__mdp_histogram_reset(mgmt);
 			}
 		}
 
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 1397507..371174c 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -256,6 +256,7 @@
 struct mdp_hist_mgmt {
 	uint32_t block;
 	uint32_t irq_term;
+	uint32_t intr;
 	uint32_t base;
 	struct completion mdp_hist_comp;
 	struct mutex mdp_hist_mutex;
@@ -323,6 +324,14 @@
 #define TV_OUT_DMA3_START   BIT(13)
 #define MDP_HIST_DONE       BIT(20)
 
+/*MDP4 MDP histogram interrupts*/
+/*note: these are only applicable on MDP4+ targets*/
+#define INTR_VG1_HISTOGRAM		BIT(5)
+#define INTR_VG2_HISTOGRAM		BIT(6)
+#define INTR_DMA_P_HISTOGRAM		BIT(17)
+#define INTR_DMA_S_HISTOGRAM		BIT(26)
+/*end MDP4 MDP histogram interrupts*/
+
 /* histogram interrupts */
 #define INTR_HIST_DONE			BIT(1)
 #define INTR_HIST_RESET_SEQ_DONE	BIT(0)
@@ -337,7 +346,6 @@
 			MDP_DMA_S_DONE| \
 			MDP_DMA_E_DONE| \
 			LCDC_UNDERFLOW| \
-			MDP_HIST_DONE| \
 			TV_ENC_UNDERRUN)
 #endif
 
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 6fc83df..005e87c 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -111,33 +111,23 @@
 };
 
 /* system interrupts */
+/*note histogram interrupts defined in mdp.h*/
 #define INTR_OVERLAY0_DONE		BIT(0)
 #define INTR_OVERLAY1_DONE		BIT(1)
 #define INTR_DMA_S_DONE			BIT(2)
 #define INTR_DMA_E_DONE			BIT(3)
 #define INTR_DMA_P_DONE			BIT(4)
-#define INTR_VG1_HISTOGRAM		BIT(5)
-#define INTR_VG2_HISTOGRAM		BIT(6)
 #define INTR_PRIMARY_VSYNC		BIT(7)
 #define INTR_PRIMARY_INTF_UDERRUN	BIT(8)
 #define INTR_EXTERNAL_VSYNC		BIT(9)
 #define INTR_EXTERNAL_INTF_UDERRUN	BIT(10)
 #define INTR_PRIMARY_RDPTR		BIT(11)	/* read pointer */
-#define INTR_DMA_P_HISTOGRAM		BIT(17)
-#define INTR_DMA_S_HISTOGRAM		BIT(26)
 #define INTR_OVERLAY2_DONE		BIT(30)
 
 #ifdef CONFIG_FB_MSM_OVERLAY
-#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_HISTOGRAM | \
-				INTR_DMA_S_HISTOGRAM | \
-				INTR_VG1_HISTOGRAM | \
-				INTR_VG2_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK	(0)
 #else
-#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_DONE| \
-				INTR_DMA_P_HISTOGRAM | \
-				INTR_DMA_S_HISTOGRAM | \
-				INTR_VG1_HISTOGRAM | \
-				INTR_VG2_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_DONE)
 #endif
 
 enum {
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 63f0aa1..18cf817 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3092,6 +3092,7 @@
 int mdp4_overlay_unset_mixer(int mixer)
 {
 	struct mdp4_overlay_pipe *pipe;
+	struct mdp4_overlay_pipe *orgpipe;
 	int i, cnt = 0;
 
 	/* free pipe besides base layer pipe */
@@ -3103,6 +3104,10 @@
 		mdp4_overlay_reg_flush(pipe, 1);
 		mdp4_mixer_stage_down(pipe, 1);
 		mdp4_overlay_pipe_free(pipe);
+		/*Clear real pipe attributes as well */
+		orgpipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+		if (orgpipe != NULL)
+			orgpipe->pipe_used = 0;
 		cnt++;
 	}
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index fcdccca..2d21929 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -677,6 +677,11 @@
 			/* adb stop */
 			if (pipe->pipe_type == OVERLAY_TYPE_BF)
 				mdp4_overlay_borderfill_stage_down(pipe);
+
+			/* base pipe may change after borderfill_stage_down */
+			pipe = vctrl->base_pipe;
+			mdp4_mixer_stage_down(pipe, 1);
+			mdp4_overlay_pipe_free(pipe);
 			vctrl->base_pipe = NULL;
 		} else {
 			/* system suspending */
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index f3bd775..f01543b 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -579,6 +579,10 @@
 			if (pipe->pipe_type == OVERLAY_TYPE_BF)
 				mdp4_overlay_borderfill_stage_down(pipe);
 
+			/* base pipe may change after borderfill_stage_down */
+			pipe = vctrl->base_pipe;
+			mdp4_mixer_stage_down(pipe, 1);
+			mdp4_overlay_pipe_free(pipe);
 			/* pipe == rgb2 */
 			vctrl->base_pipe = NULL;
 		} else {
@@ -1009,6 +1013,8 @@
 	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
+	mdp4_overlay_mdp_perf_upd(mfd, 1);
 	mdp4_dtv_pipe_commit();
+	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 323a8fe..bc8ded5 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -664,6 +664,11 @@
 			/* adb stop */
 			if (pipe->pipe_type == OVERLAY_TYPE_BF)
 				mdp4_overlay_borderfill_stage_down(pipe);
+
+			/* base pipe may change after borderfill_stage_down */
+			pipe = vctrl->base_pipe;
+			mdp4_mixer_stage_down(pipe, 1);
+			mdp4_overlay_pipe_free(pipe);
 			vctrl->base_pipe = NULL;
 		} else {
 			/* system suspending */
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 359f37e..b35acfb 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -500,7 +500,6 @@
 	uint32 isr, mask, panel;
 	struct mdp_dma_data *dma;
 	struct mdp_hist_mgmt *mgmt = NULL;
-	char *base_addr;
 	int i, ret;
 
 	mdp_is_in_isr = TRUE;
@@ -528,12 +527,7 @@
 			mgmt = mdp_hist_mgmt_array[i];
 			if (!mgmt)
 				continue;
-			base_addr = MDP_BASE + mgmt->base;
-			MDP_OUTP(base_addr + 0x010, 1);
-			outpdw(base_addr + 0x01c, INTR_HIST_DONE |
-						INTR_HIST_RESET_SEQ_DONE);
 			mgmt->mdp_is_hist_valid = FALSE;
-			__mdp_histogram_reset(mgmt);
 		}
 	}
 
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index e92201f..e333235 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -143,10 +143,15 @@
  * struct slim_addrt: slimbus address used internally by the slimbus framework.
  * @valid: If the device is still there or if the address can be reused.
  * @eaddr: 6-bytes-long elemental address
+ * @laddr: It is possible that controller will set a predefined logical address
+ *	rather than the one assigned by framework. (i.e. logical address may
+ *	not be same as index into this table). This entry will store the
+ *	logical address value for this enumeration address.
  */
 struct slim_addrt {
 	bool	valid;
 	u8	eaddr[6];
+	u8	laddr;
 };
 
 /*
@@ -500,6 +505,9 @@
  *	send unicast message to this device with its logical address.
  * @allocbw: Controller can override default reconfiguration and channel
  *	scheduling algorithm.
+ * @get_laddr: It is possible that controller needs to set fixed logical
+ *	address table and get_laddr can be used in that case so that controller
+ *	can do this assignment.
  * @wakeup: This function pointer implements controller-specific procedure
  *	to wake it up from clock-pause. Framework will call this to bring
  *	the controller out of clock pause.
@@ -546,6 +554,8 @@
 				const u8 *ea, u8 elen, u8 laddr);
 	int			(*allocbw)(struct slim_device *sb,
 				int *subfrmc, int *clkgear);
+	int			(*get_laddr)(struct slim_controller *ctrl,
+				const u8 *ea, u8 elen, u8 *laddr);
 	int			(*wakeup)(struct slim_controller *ctrl);
 	int			(*config_port)(struct slim_controller *ctrl,
 				u8 port);
@@ -983,14 +993,17 @@
  * @ctrl: Controller with which device is enumerated.
  * @e_addr: 6-byte elemental address of the device.
  * @e_len: buffer length for e_addr
- * @laddr: Return logical address.
+ * @laddr: Return logical address (if valid flag is false)
+ * @valid: true if laddr holds a valid address that controller wants to
+ *	set for this enumeration address. Otherwise framework sets index into
+ *	address table as logical address.
  * Called by controller in response to REPORT_PRESENT. Framework will assign
  * a logical address to this enumeration address.
  * Function returns -EXFULL to indicate that all logical addresses are already
  * taken.
  */
 extern int slim_assign_laddr(struct slim_controller *ctrl, const u8 *e_addr,
-				u8 e_len, u8 *laddr);
+				u8 e_len, u8 *laddr, bool valid);
 
 /*
  * slim_msg_response: Deliver Message response received from a device to the
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index ac4ec09..1da6aa2 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -242,18 +242,18 @@
  */
 struct adm_cmd_set_pp_params_v5 {
 	struct apr_hdr hdr;
-		u32                  data_payload_addr_lsw;
+	u32		payload_addr_lsw;
 	/* LSW of parameter data payload address.*/
-	u32                  data_payload_addr_msw;
+	u32		payload_addr_msw;
 	/* MSW of parameter data payload address.*/
 
-		u32                  mem_map_handle;
+	u32		mem_map_handle;
 /* Memory map handle returned by ADM_CMD_SHARED_MEM_MAP_REGIONS
  * command */
 /* If mem_map_handle is zero implies the message is in
  * the payload */
 
-	u32                  data_payload_size;
+	u32		payload_size;
 /* Size in bytes of the variable payload accompanying this
  * message or
  * in shared memory. This is used for parsing the parameter
diff --git a/include/trace/events/exception.h b/include/trace/events/exception.h
new file mode 100644
index 0000000..110e920
--- /dev/null
+++ b/include/trace/events/exception.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM exception
+
+#if !defined(_TRACE_EXCEPTION_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EXCEPTION_H
+
+#include <linux/tracepoint.h>
+
+struct task_struct;
+
+TRACE_EVENT(user_fault,
+
+	TP_PROTO(struct task_struct *tsk, unsigned long addr, unsigned int fsr),
+
+	TP_ARGS(tsk, addr, fsr),
+
+	TP_STRUCT__entry(
+		__string(task_name, tsk->comm)
+		__field(unsigned long, addr)
+		__field(unsigned int, fsr)
+	),
+
+	TP_fast_assign(
+	__assign_str(task_name, tsk->comm)
+		__entry->addr	= addr;
+		__entry->fsr	= fsr;
+	),
+
+	TP_printk("task_name:%s addr:%lu, fsr:%u", __get_str(task_name),\
+		__entry->addr, __entry->fsr)
+);
+
+struct pt_regs;
+
+TRACE_EVENT(undef_instr,
+
+	TP_PROTO(struct pt_regs *regs, void *prog_cnt),
+
+	TP_ARGS(regs, prog_cnt),
+
+	TP_STRUCT__entry(
+		__field(void *, prog_cnt)
+		__field(struct pt_regs *, regs)
+	),
+
+	TP_fast_assign(
+		__entry->regs		= regs;
+		__entry->prog_cnt	= prog_cnt;
+	),
+
+	TP_printk("pc:%p", __entry->prog_cnt)
+);
+
+#endif
+
+#include <trace/define_trace.h>
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ac11f1a..a47e446 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -8379,8 +8379,9 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct tabla_priv *tabla = platform_get_drvdata(pdev);
-	dev_dbg(dev, "%s: system resume\n", __func__);
-	tabla->mbhc_last_resume = jiffies;
+	dev_dbg(dev, "%s: system resume tabla %p\n", __func__, tabla);
+	if (tabla)
+		tabla->mbhc_last_resume = jiffies;
 	return 0;
 }
 
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 9bc565e..80d6e5d 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1310,6 +1310,24 @@
 	return 0;
 }
 
+static int msm_slim_4_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 1;
+
+	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+			channels->min, channels->max);
+	return 0;
+}
+
+
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
@@ -2002,7 +2020,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_slim_4_rx_be_hw_params_fixup,
 		.ops = &msm_slimbus_4_be_ops,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index e5837b2..62257b4 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -41,6 +41,14 @@
 	wait_queue_head_t wait[Q6_AFE_MAX_PORTS];
 };
 
+static struct acdb_cal_block mem_addr_audproc[MAX_AUDPROC_TYPES];
+static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
+
+/* 0 - (MAX_AUDPROC_TYPES -1):				audproc handles */
+/* (MAX_AUDPROC_TYPES -1) - (2 * MAX_AUDPROC_TYPES -1):	audvol handles */
+atomic_t mem_map_handles[(2 * MAX_AUDPROC_TYPES)];
+atomic_t mem_map_index;
+
 static struct adm_ctl			this_adm;
 
 static int32_t adm_callback(struct apr_client_data *data, void *priv)
@@ -63,6 +71,18 @@
 			}
 			this_adm.apr = NULL;
 		}
+		pr_debug("Resetting calibration blocks");
+		for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
+			/* Device calibration */
+			mem_addr_audproc[i].cal_size = 0;
+			mem_addr_audproc[i].cal_kvaddr = 0;
+			mem_addr_audproc[i].cal_paddr = 0;
+
+			/* Volume calibration */
+			mem_addr_audvol[i].cal_size = 0;
+			mem_addr_audvol[i].cal_kvaddr = 0;
+			mem_addr_audvol[i].cal_paddr = 0;
+		}
 		return 0;
 	}
 
@@ -82,18 +102,23 @@
 			switch (payload[0]) {
 			case ADM_CMD_SET_PP_PARAMS_V5:
 				if (rtac_make_adm_callback(
-					payload, data->payload_size))
+					payload, data->payload_size)) {
 					pr_debug("%s: payload[0]: 0x%x\n",
 						__func__, payload[0]);
 					break;
+				}
 			case ADM_CMD_DEVICE_CLOSE_V5:
 			case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
-			case ADM_CMD_SHARED_MEM_MAP_REGIONS:
 			case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
-				pr_debug("ADM_CMD_MATRIX_MAP_ROUTINGS\n");
+				pr_debug("%s: Basic callback received, wake up.\n",
+					__func__);
 				atomic_set(&this_adm.copp_stat[index], 1);
 				wake_up(&this_adm.wait[index]);
 				break;
+			case ADM_CMD_SHARED_MEM_MAP_REGIONS:
+				/* Block until memory handle comes back */
+				/* via ADM_CMDRSP_SHARED_MEM_MAP_REGIONS */
+				break;
 			default:
 				pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
 								payload[0]);
@@ -125,6 +150,14 @@
 			rtac_make_adm_callback(payload,
 				data->payload_size);
 			break;
+		case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
+			pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
+				__func__);
+			atomic_set(&mem_map_handles[
+				atomic_read(&mem_map_index)], *payload);
+			atomic_set(&this_adm.copp_stat[0], 1);
+			wake_up(&this_adm.wait[index]);
+			break;
 		default:
 			pr_err("%s: Unknown cmd:0x%x\n", __func__,
 							data->opcode);
@@ -134,12 +167,143 @@
 	return 0;
 }
 
-/* TODO: send_adm_cal_block function to be defined
-	when calibration available for 8974 */
+static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
+{
+	s32				result = 0;
+	struct adm_cmd_set_pp_params_v5	adm_params;
+	int index = afe_get_port_index(port_id);
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d portid %d\n",
+				__func__, index, port_id);
+		return 0;
+	}
+
+	pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
+
+	if (!aud_cal || aud_cal->cal_size == 0) {
+		pr_debug("%s: No ADM cal to send for port_id = %d!\n",
+			__func__, port_id);
+		result = -EINVAL;
+		goto done;
+	}
+
+	adm_params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+		APR_HDR_LEN(20), APR_PKT_VER);
+	adm_params.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+		sizeof(adm_params));
+	adm_params.hdr.src_svc = APR_SVC_ADM;
+	adm_params.hdr.src_domain = APR_DOMAIN_APPS;
+	adm_params.hdr.src_port = port_id;
+	adm_params.hdr.dest_svc = APR_SVC_ADM;
+	adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
+	adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+	adm_params.hdr.token = port_id;
+	adm_params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
+	adm_params.payload_addr_lsw = aud_cal->cal_paddr;
+	adm_params.payload_addr_msw = 0;
+	adm_params.mem_map_handle = atomic_read(&mem_map_handles[
+					atomic_read(&mem_map_index)]);
+	adm_params.payload_size = aud_cal->cal_size;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	pr_debug("%s: Sending SET_PARAMS payload = 0x%x, size = %d\n",
+		__func__, adm_params.payload_addr_lsw,
+		adm_params.payload_size);
+	result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params);
+	if (result < 0) {
+		pr_err("%s: Set params failed port = %d payload = 0x%x\n",
+			__func__, port_id, aud_cal->cal_paddr);
+		result = -EINVAL;
+		goto done;
+	}
+	/* Wait for the callback */
+	result = wait_event_timeout(this_adm.wait[index],
+		atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!result) {
+		pr_err("%s: Set params timed out port = %d, payload = 0x%x\n",
+			__func__, port_id, aud_cal->cal_paddr);
+		result = -EINVAL;
+		goto done;
+	}
+
+	result = 0;
+done:
+	return result;
+}
+
 static void send_adm_cal(int port_id, int path)
 {
-	/* function to be defined when calibration available for 8974 */
+	int			result = 0;
+	s32			acdb_path;
+	struct acdb_cal_block	aud_cal;
+	int			size = 4096;
 	pr_debug("%s\n", __func__);
+
+	/* Maps audio_dev_ctrl path definition to ACDB definition */
+	acdb_path = path - 1;
+
+	pr_debug("%s: Sending audproc cal\n", __func__);
+	get_audproc_cal(acdb_path, &aud_cal);
+
+	/* map & cache buffers used */
+	if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr)  &&
+		(aud_cal.cal_size > 0)) ||
+		(aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
+
+		atomic_set(&mem_map_index, acdb_path);
+		if (mem_addr_audproc[acdb_path].cal_paddr != 0)
+			adm_memory_unmap_regions(port_id,
+				&mem_addr_audproc[acdb_path].cal_paddr,
+				&size, 1);
+
+		result = adm_memory_map_regions(port_id, &aud_cal.cal_paddr,
+						0, &aud_cal.cal_size, 1);
+		if (result < 0)
+			pr_err("ADM audproc mmap did not work! path = %d, addr = 0x%x, size = %d\n",
+				acdb_path, aud_cal.cal_paddr,
+				aud_cal.cal_size);
+		else
+			mem_addr_audproc[acdb_path] = aud_cal;
+	}
+
+	if (!send_adm_cal_block(port_id, &aud_cal))
+		pr_debug("%s: Audproc cal sent for port id: %d, path %d\n",
+			__func__, port_id, acdb_path);
+	else
+		pr_debug("%s: Audproc cal not sent for port id: %d, path %d\n",
+			__func__, port_id, acdb_path);
+
+	pr_debug("%s: Sending audvol cal\n", __func__);
+	get_audvol_cal(acdb_path, &aud_cal);
+
+	/* map & cache buffers used */
+	if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr)  &&
+		(aud_cal.cal_size > 0))  ||
+		(aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
+
+		atomic_set(&mem_map_index, (acdb_path + MAX_AUDPROC_TYPES));
+		if (mem_addr_audvol[acdb_path].cal_paddr != 0)
+			adm_memory_unmap_regions(port_id,
+				&mem_addr_audvol[acdb_path].cal_paddr,
+				&size, 1);
+
+		result = adm_memory_map_regions(port_id, &aud_cal.cal_paddr,
+						0, &aud_cal.cal_size, 1);
+		if (result < 0)
+			pr_err("ADM audvol mmap did not work! path = %d, addr = 0x%x, size = %d\n",
+				acdb_path, aud_cal.cal_paddr,
+				aud_cal.cal_size);
+		else
+			mem_addr_audvol[acdb_path] = aud_cal;
+	}
+
+	if (!send_adm_cal_block(port_id, &aud_cal))
+		pr_debug("%s: Audvol cal sent for port id: %d, path %d\n",
+			__func__, port_id, acdb_path);
+	else
+		pr_debug("%s: Audvol cal not sent for port id: %d, path %d\n",
+			__func__, port_id, acdb_path);
 }
 
 int adm_connect_afe_port(int mode, int session_id, int port_id)
@@ -572,7 +736,8 @@
 	unmap_regions.hdr.dest_port = 0;
 	unmap_regions.hdr.token = 0;
 	unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
-	unmap_regions.mem_map_handle = this_adm.mem_map_handle[index];
+	unmap_regions.mem_map_handle = atomic_read(&mem_map_handles[
+						atomic_read(&mem_map_index)]);
 	atomic_set(&this_adm.copp_stat[0], 0);
 	ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
 	if (ret < 0) {