Merge "msm: kgsl: Fix the address translation ranges for GPU IOMMU"
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/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index 46b39ec..21d376a 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -13,7 +13,7 @@
 - interrupts:	Specifies the interrupt associated with PON.
 
 Optional properties:
-- qcom,pon-dbc-delay:		The debouce delay for the power-key interrupt
+- qcom,pon-dbc-delay		The debouce delay for the power-key interrupt
 				specifed in us. The value ranges from 2 seconds
 				to 1/64 of a second. Possible values are -
 				- 2, 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64
@@ -24,11 +24,15 @@
 				reset source. All the child nodes are optional,
 				if none of them are specified the driver fails
 				to register.
+- qcom,system-reset		Specifies that this PON peripheral can be used
+				to reset the system. This property can only be
+				used by one device on the system. It is an error
+				to include it more than once.
 
 All the below properties are in the sub-node section (properties of the child
 node).
 
-- qcom,pull-up:			The initial state of the reset pin under
+- qcom,pull-up			The initial state of the reset pin under
 				consideration.
 				0 = No pull-up
 				1 = pull-up enabled
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 0f5fd1c..facb1a8 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -30,6 +30,7 @@
 				     <0x0 0x8 0x4>;
 			interrupt-names = "kpdpwr", "resin", "resin-bark";
 			qcom,pon-dbc-delay = <15625>;
+			qcom,system-reset;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
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/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index f3efbb8..8e3f4b8 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -309,8 +309,9 @@
 		qcom,ipc-bit-offset = <1>;
 
 		qcom,gic-parent = <&intc>;
-		qcom,gic-map = <47 180>, /* usb2_hsic_async_wakeup_irq */
+		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
+			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
 			<0xff 59>,  /* mss_to_apps_irq(2) */
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 1b792d9..7f10641 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -283,6 +283,7 @@
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index aeb59af..0e0653f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -285,6 +285,7 @@
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 2c8f71e..afe528d 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -69,6 +69,7 @@
 CONFIG_MSM_DSPS=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_AVS_HW=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_PIL_QDSP6V4=y
 CONFIG_MSM_PIL_RIVA=y
@@ -96,6 +97,7 @@
 CONFIG_MSM_L1_ERR_PANIC=y
 CONFIG_MSM_L1_ERR_LOG=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_DCVS=y
 CONFIG_MSM_HSIC_SYSMON=y
 CONFIG_STRICT_MEMORY_RWX=y
@@ -389,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 a2deab2..4c9383d 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -68,6 +68,7 @@
 CONFIG_MSM_DSPS=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_AVS_HW=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_PIL_QDSP6V4=y
 CONFIG_MSM_PIL_RIVA=y
@@ -87,6 +88,7 @@
 CONFIG_MSM_RPM_RBCPR_STATS_LOG=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
+CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_RTB=y
@@ -392,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/Kconfig b/arch/arm/mach-msm/Kconfig
index badee85..c9b786c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2142,6 +2142,14 @@
 	depends on PM
 	bool
 
+config MSM_EVENT_TIMER
+	bool "Event timer"
+	help
+		This option enables a modules that manages a list of event timers that
+		need to be monitored by the PM. The enables the PM code to monitor
+		events that require the core to be awake and ready to handle the
+		event.
+
 config MSM_NOPM
 	default y if !PM
 	bool
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 70234bf..d8e625a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -343,6 +343,7 @@
 obj-$(CONFIG_MSM_BUSPM_DEV) += msm-buspm-dev.o
 
 obj-$(CONFIG_MSM_IOMMU)		+= devices-iommu.o iommu_domains.o
+obj-$(CONFIG_MSM_EVENT_TIMER)		+= event_timer.o
 
 ifdef CONFIG_VCM
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 7be3667..1a2ae48 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -739,7 +739,8 @@
 			}
 		}
 
-		if (!(plls_enabled & (1 << tgt_s->pll))) {
+		if ((tgt_s->pll != ACPU_PLL_TCXO) &&
+				!(plls_enabled & (1 << tgt_s->pll))) {
 			rc = clk_enable(pll_clk[tgt_s->pll].clk);
 			if (rc < 0) {
 				pr_err("PLL%d enable failed (%d)\n",
@@ -827,7 +828,8 @@
 		goto out;
 
 	/* Change the AXI bus frequency if we can. */
-	if (strt_s->axiclk_khz != tgt_s->axiclk_khz) {
+	if (reason != SETRATE_PC &&
+		strt_s->axiclk_khz != tgt_s->axiclk_khz) {
 		res = clk_set_rate(drv_state.ebi1_clk,
 				tgt_s->axiclk_khz * 1000);
 		if (res < 0)
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index 3c80875..06c2579 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -219,7 +219,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0x00700000,
+	.pte_efuse_phys = 0x007000C0,
 	.stby_khz = 384000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 07a7f8f..9e6662d 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -138,7 +138,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0x00700000,
+	.pte_efuse_phys = 0x007000C0,
 	.stby_khz = 384000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 77876ee..b8ca865 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -221,7 +221,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0x00700000,
+	.pte_efuse_phys = 0x007000C0,
 	.stby_khz = 384000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index dbc3e32..d589f1a 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -200,7 +200,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0x00700000,
+	.pte_efuse_phys = 0x007000C0,
 	.stby_khz = 384000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 631bd7e..e16c6b6 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -112,8 +112,10 @@
 	{ }
 };
 
+#define AVS(x) .avsdscr_setting = (x)
+
 static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   950000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   950000, AVS(0x40001F) },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   975000 },
 	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   975000 },
 	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),  1000000 },
@@ -126,20 +128,20 @@
 	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(6),  1100000 },
 	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(6),  1125000 },
 	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(6),  1125000 },
-	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1175000 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1175000 },
-	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1200000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1200000 },
-	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1225000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1225000 },
-	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1237500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1237500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1250000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1175000, AVS(0x400015) },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1175000, AVS(0x400015) },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1200000, AVS(0x400015) },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1200000, AVS(0x400015) },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1225000, AVS(0x400015) },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1225000, AVS(0x400015) },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1237500, AVS(0x400015) },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1237500, AVS(0x100018) },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1250000, AVS(0x400012) },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   900000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   900000, AVS(0x40007F) },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
 	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
 	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   950000 },
@@ -152,20 +154,20 @@
 	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(6),  1050000 },
 	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(6),  1075000 },
 	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(6),  1075000 },
-	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1125000 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1125000 },
-	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1150000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1150000 },
-	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1175000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1175000 },
-	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1187500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1187500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1200000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1125000, AVS(0x400015) },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1125000, AVS(0x400015) },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1150000, AVS(0x400015) },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1150000, AVS(0x400015) },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1175000, AVS(0x400015) },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1175000, AVS(0x400015) },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1187500, AVS(0x400015) },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1187500, AVS(0x100018) },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1200000, AVS(0x400012) },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   850000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   850000, AVS(0x4000FF) },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   875000 },
 	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   875000 },
 	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
@@ -178,15 +180,15 @@
 	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(6),  1000000 },
 	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(6),  1025000 },
 	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(6),  1025000 },
-	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1075000 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1075000 },
-	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1100000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1100000 },
-	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1125000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1125000 },
-	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1137500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1137500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1150000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1075000, AVS(0x10001B) },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1075000, AVS(0x10001B) },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1100000, AVS(0x10001B) },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1100000, AVS(0x10001B) },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1125000, AVS(0x10001B) },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1125000, AVS(0x400012) },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1137500, AVS(0x400012) },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1137500, AVS(0x400012) },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1150000, AVS(0x400012) },
 	{ 0, { 0 } }
 };
 
@@ -204,7 +206,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0x00700000,
+	.pte_efuse_phys = 0x007000C0,
 	.stby_khz = 384000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 63bff55..628e1ba 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -146,7 +146,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0x00700000,
+	.pte_efuse_phys = 0x007000C0,
 	.stby_khz = 384000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 16f77ba..ee2ca45 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -179,7 +179,7 @@
 	.l2_freq_tbl = l2_freq_tbl,
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
-	.qfprom_phys_base = 0xFC4A8000,
+	.pte_efuse_phys = 0xFC4B80B0,
 	.stby_khz = 300000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 9afa7c0..2951c1a 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -36,6 +36,7 @@
 
 #include "acpuclock.h"
 #include "acpuclock-krait.h"
+#include "avs.h"
 
 /* MUX source selects. */
 #define PRI_SRC_SEL_SEC_SRC	0
@@ -44,9 +45,6 @@
 #define SEC_SRC_SEL_L2PLL	1
 #define SEC_SRC_SEL_AUX		2
 
-/* PTE EFUSE register offset. */
-#define PTE_EFUSE		0xC0
-
 static DEFINE_MUTEX(driver_lock);
 static DEFINE_SPINLOCK(l2_lock);
 
@@ -472,6 +470,12 @@
 	vdd_data.vdd_core = calculate_vdd_core(tgt);
 	vdd_data.ua_core = tgt->ua_core;
 
+	/* Disable AVS before voltage switch */
+	if (reason == SETRATE_CPUFREQ && drv.scalable[cpu].avs_enabled) {
+		AVS_DISABLE(cpu);
+		drv.scalable[cpu].avs_enabled = false;
+	}
+
 	/* Increase VDD levels if needed. */
 	if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG) {
 		rc = increase_vdd(cpu, &vdd_data, reason);
@@ -507,6 +511,12 @@
 	/* Drop VDD levels if we can. */
 	decrease_vdd(cpu, &vdd_data, reason);
 
+	/* Re-enable AVS */
+	if (reason == SETRATE_CPUFREQ && tgt->avsdscr_setting) {
+		AVS_ENABLE(cpu, tgt->avsdscr_setting);
+		drv.scalable[cpu].avs_enabled = true;
+	}
+
 	dev_dbg(drv.dev, "ACPU%d speed change complete\n", cpu);
 
 out:
@@ -926,25 +936,27 @@
 
 static void krait_apply_vmin(struct acpu_level *tbl)
 {
-	for (; tbl->speed.khz != 0; tbl++)
+	for (; tbl->speed.khz != 0; tbl++) {
 		if (tbl->vdd_core < 1150000)
 			tbl->vdd_core = 1150000;
+		tbl->avsdscr_setting = 0;
+	}
 }
 
-static int __init select_freq_plan(u32 qfprom_phys)
+static int __init select_freq_plan(u32 pte_efuse_phys)
 {
-	void __iomem *qfprom_base;
-	u32 pte_efuse, pvs, tbl_idx;
+	void __iomem *pte_efuse;
+	u32 pte_efuse_val, pvs, tbl_idx;
 	char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
 
-	qfprom_base = ioremap(qfprom_phys, SZ_256);
+	pte_efuse = ioremap(pte_efuse_phys, 4);
 	/* Select frequency tables. */
-	if (qfprom_base) {
-		pte_efuse = readl_relaxed(qfprom_base + PTE_EFUSE);
-		pvs = (pte_efuse >> 10) & 0x7;
-		iounmap(qfprom_base);
+	if (pte_efuse) {
+		pte_efuse_val = readl_relaxed(pte_efuse);
+		pvs = (pte_efuse_val >> 10) & 0x7;
+		iounmap(pte_efuse);
 		if (pvs == 0x7)
-			pvs = (pte_efuse >> 13) & 0x7;
+			pvs = (pte_efuse_val >> 13) & 0x7;
 
 		switch (pvs) {
 		case 0x0:
@@ -1005,7 +1017,7 @@
 		GFP_KERNEL);
 	BUG_ON(!drv.bus_scale->usecase);
 
-	tbl_idx = select_freq_plan(params->qfprom_phys_base);
+	tbl_idx = select_freq_plan(params->pte_efuse_phys);
 	drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
 				    params->pvs_tables[tbl_idx].size,
 				    GFP_KERNEL);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 1b891b1..d615b85 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -143,6 +143,7 @@
  * @l2_level: L2 configuration to use.
  * @vdd_core: CPU core voltage in uV.
  * @ua_core: CPU core current consumption in uA.
+ * @avsdscr_setting: AVS DSCR configuration.
  */
 struct acpu_level {
 	const int use_for_scaling;
@@ -150,6 +151,7 @@
 	const unsigned int l2_level;
 	int vdd_core;
 	int ua_core;
+	unsigned int avsdscr_setting;
 };
 
 /**
@@ -203,6 +205,7 @@
  * @l2_vote: L2 performance level vote associate with the current CPU speed.
  * @vreg: Array of voltage regulators needed by the scalable.
  * @initialized: Flag set to true when per_cpu_init() has been called.
+ * @avs_enabled: True if avs is enabled for the scalabale. False otherwise.
  */
 struct scalable {
 	const phys_addr_t hfpll_phys_base;
@@ -214,6 +217,7 @@
 	unsigned int l2_vote;
 	struct vreg vreg[NUM_VREG];
 	bool initialized;
+	bool avs_enabled;
 };
 
 /**
@@ -236,7 +240,7 @@
  * @pvs_tables: CPU frequency tables.
  * @l2_freq_tbl: L2 frequency table.
  * @l2_freq_tbl_size: Size of @l2_freq_tbl.
- * @qfprom_phys_base: Physical base address of QFPROM.
+ * @pte_efuse_phys: Physical address of PTE EFUSE.
  * @bus_scale: MSM bus driver parameters.
  * @stby_khz: KHz value corresponding to an always-on clock source.
  */
@@ -247,7 +251,7 @@
 	struct pvs_table *pvs_tables;
 	struct l2_level *l2_freq_tbl;
 	size_t l2_freq_tbl_size;
-	phys_addr_t qfprom_phys_base;
+	phys_addr_t pte_efuse_phys;
 	struct msm_bus_scale_pdata *bus_scale;
 	unsigned long stby_khz;
 };
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index bbb9a81..6cdafbc 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -189,6 +189,7 @@
 	REGULATOR_SUPPLY("vcc_i2c",		"3-0024"),
 	REGULATOR_SUPPLY("vddp",		"0-0048"),
 	REGULATOR_SUPPLY("hdmi_lvl_tsl",	"hdmi_msm.0"),
+	REGULATOR_SUPPLY("vdd-io",		"spi0.2"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
@@ -252,7 +253,7 @@
 };
 VREG_CONSUMERS(EXT_3P3V) = {
 	REGULATOR_SUPPLY("ext_3p3v",		NULL),
-	REGULATOR_SUPPLY("vdd_io",		"spi0.2"),
+	REGULATOR_SUPPLY("vdd-phy",		"spi0.2"),
 	REGULATOR_SUPPLY("mhl_usb_hs_switch",	"msm_otg"),
 	REGULATOR_SUPPLY("lvds_vccs_3p3v",      "lvds.0"),
 	REGULATOR_SUPPLY("dsi1_vccs_3p3v",      "mipi_dsi.1"),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 3a82b07..06efc03 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1688,8 +1688,8 @@
 		.reg_base_addr = MSM_SAW0_BASE,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
 #if defined(CONFIG_MSM_AVS_HW)
-		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
-		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x50589464,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00020000,
 #endif
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x03020004,
@@ -1703,8 +1703,8 @@
 		.reg_base_addr = MSM_SAW1_BASE,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
 #if defined(CONFIG_MSM_AVS_HW)
-		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
-		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x50589464,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00020000,
 #endif
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
@@ -2822,19 +2822,24 @@
 		msm_kgsl_3d0.dev.platform_data;
 	uint32_t soc_platform_version = socinfo_get_version();
 
+	/* Fixup data that needs to change based on GPU ID */
 	if (cpu_is_msm8960ab()) {
 		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
 		/* 8960PRO nominal clock rate is 325Mhz instead of 320Mhz */
 		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 325000000;
-	} else if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
-		kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
-		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
-	} else if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
-		/* 8960v3 GPU registers returns 5 for patch release
-		 * but it should be 6, so dummy up the chipid here
-		 * based the platform type
-		 */
-		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+	} else {
+		kgsl_3d0_pdata->iommu_count = 1;
+		if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+			kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+			kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+		}
+		if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
+			/* 8960v3 GPU registers returns 5 for patch release
+			 * but it should be 6, so dummy up the chipid here
+			 * based the platform type
+			 */
+			kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+		}
 	}
 
 	/* Register the 3D core */
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 01bc9dd..6ddb462 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -6430,16 +6430,16 @@
 		is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
 		if (!is_pll_enabled)
 			/* Ref clk = 27MHz and program pll14 to 480MHz */
-			configure_pll(&pll14_config, &pll14_regs, 1);
+			configure_sr_pll(&pll14_config, &pll14_regs, 1);
 
 		/* Program PLL15 to 975MHz with ref clk = 27MHz */
-		configure_pll(&pll15_config, &pll15_regs, 0);
+		configure_sr_pll(&pll15_config, &pll15_regs, 0);
 
 		/* Check if PLL4 is active */
 		is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
 		if (!is_pll_enabled)
 			/* Ref clk = 27MHz and program pll4 to 393.2160MHz */
-			configure_pll(&pll4_config_393, &pll4_regs, 1);
+			configure_sr_pll(&pll4_config_393, &pll4_regs, 1);
 
 		/* Enable PLL4 source on the LPASS Primary PLL Mux */
 		writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
@@ -6457,7 +6457,7 @@
 		pll15_config.l = 0x21 | BVAL(31, 7, 0x600);
 		pll15_config.m = 0x1;
 		pll15_config.n = 0x3;
-		configure_pll(&pll15_config, &pll15_regs, 0);
+		configure_sr_pll(&pll15_config, &pll15_regs, 0);
 		/* Disable AUX and BIST outputs */
 		writel_relaxed(0, MM_PLL3_TEST_CTL_REG);
 	}
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index b054e08..62e8f0f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5594,16 +5594,16 @@
 
 	if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
 			& gpll0_clk_src.status_mask))
-		configure_pll(&gpll0_config, &gpll0_regs, 1);
+		configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
 
 	if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
 			& gpll1_clk_src.status_mask))
-		configure_pll(&gpll1_config, &gpll1_regs, 1);
+		configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
 
-	configure_pll(&mmpll0_config, &mmpll0_regs, 1);
-	configure_pll(&mmpll1_config, &mmpll1_regs, 1);
-	configure_pll(&mmpll3_config, &mmpll3_regs, 0);
-	configure_pll(&lpapll0_config, &lpapll0_regs, 1);
+	configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
+	configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
+	configure_sr_hpm_lp_pll(&mmpll3_config, &mmpll3_regs, 0);
+	configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
 
 	/* Enable GPLL0's aux outputs. */
 	regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
@@ -5769,7 +5769,7 @@
 	if (!virt_bases[APCS_BASE])
 		panic("clock-8974: Unable to ioremap APCS_GCC_CC memory!");
 
-	clk_ops_local_pll.enable = msm8974_pll_clk_enable;
+	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
 
 	vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
 	if (IS_ERR(vdd_dig_reg))
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 648a8d4..15eaa4b 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1807,14 +1807,14 @@
 		regval |= BIT(12);
 		writel_relaxed(regval, BB_PLL0_TEST_CTL_REG);
 
-		configure_pll(&pll0_config, &pll0_regs, 1);
+		configure_sr_pll(&pll0_config, &pll0_regs, 1);
 	}
 
 	/* Check if PLL14 is enabled in FSM mode */
 	is_pll_enabled  = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
 
 	if (!is_pll_enabled)
-		configure_pll(&pll14_config, &pll14_regs, 1);
+		configure_sr_pll(&pll14_config, &pll14_regs, 1);
 	else if (!(readl_relaxed(BB_PLL14_MODE_REG) & BIT(20)))
 		WARN(1, "PLL14 enabled in non-FSM mode!\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/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index d5831e2..23941d7 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -247,7 +247,7 @@
 
 #define PLL_LOCKED_BIT BIT(16)
 
-int msm8974_pll_clk_enable(struct clk *c)
+int sr_hpm_lp_pll_clk_enable(struct clk *c)
 {
 	unsigned long flags;
 	struct pll_clk *pll = to_pll_clk(c);
@@ -255,23 +255,12 @@
 	int ret = 0;
 
 	spin_lock_irqsave(&pll_reg_lock, flags);
-	mode = readl_relaxed(PLL_MODE_REG(pll));
-	/* Disable PLL bypass mode. */
-	mode |= PLL_BYPASSNL;
+
+	/* Disable PLL bypass mode and de-assert reset. */
+	mode = PLL_BYPASSNL | PLL_RESET_N;
 	writel_relaxed(mode, PLL_MODE_REG(pll));
 
-	/*
-	 * H/W requires a 5us delay between disabling the bypass and
-	 * de-asserting the reset. Delay 10us just to be safe.
-	 */
-	mb();
-	udelay(10);
-
-	/* De-assert active-low PLL reset. */
-	mode |= PLL_RESET_N;
-	writel_relaxed(mode, PLL_MODE_REG(pll));
-
-	/* Wait for pll to enable. */
+	/* Wait for pll to lock. */
 	for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
 		if (readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT)
 			break;
@@ -453,7 +442,8 @@
 	.is_enabled = pll_clk_is_enabled,
 };
 
-static void __init __set_fsm_mode(void __iomem *mode_reg)
+static void __init __set_fsm_mode(void __iomem *mode_reg,
+					u32 bias_count, u32 lock_count)
 {
 	u32 regval = readl_relaxed(mode_reg);
 
@@ -463,12 +453,12 @@
 
 	/* Program bias count */
 	regval &= ~BM(19, 14);
-	regval |= BVAL(19, 14, 0x1);
+	regval |= BVAL(19, 14, bias_count);
 	writel_relaxed(regval, mode_reg);
 
 	/* Program lock count */
 	regval &= ~BM(13, 8);
-	regval |= BVAL(13, 8, 0x8);
+	regval |= BVAL(13, 8, lock_count);
 	writel_relaxed(regval, mode_reg);
 
 	/* Enable PLL FSM voting */
@@ -476,7 +466,7 @@
 	writel_relaxed(regval, mode_reg);
 }
 
-void __init configure_pll(struct pll_config *config,
+void __init __configure_pll(struct pll_config *config,
 		struct pll_config_regs *regs, u32 ena_fsm_mode)
 {
 	u32 regval;
@@ -509,8 +499,21 @@
 	regval &= ~config->vco_mask;
 	regval |= config->vco_val;
 	writel_relaxed(regval, PLL_CONFIG_REG(regs));
-
-	/* Configure in FSM mode if necessary */
-	if (ena_fsm_mode)
-		__set_fsm_mode(PLL_MODE_REG(regs));
 }
+
+void __init configure_sr_pll(struct pll_config *config,
+		struct pll_config_regs *regs, u32 ena_fsm_mode)
+{
+	__configure_pll(config, regs, ena_fsm_mode);
+	if (ena_fsm_mode)
+		__set_fsm_mode(PLL_MODE_REG(regs), 0x1, 0x8);
+}
+
+void __init configure_sr_hpm_lp_pll(struct pll_config *config,
+		struct pll_config_regs *regs, u32 ena_fsm_mode)
+{
+	__configure_pll(config, regs, ena_fsm_mode);
+	if (ena_fsm_mode)
+		__set_fsm_mode(PLL_MODE_REG(regs), 0x1, 0x0);
+}
+
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index 90f8a95..30f595b 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -111,7 +111,7 @@
 }
 
 int sr_pll_clk_enable(struct clk *c);
-int msm8974_pll_clk_enable(struct clk *c);
+int sr_hpm_lp_pll_clk_enable(struct clk *c);
 
 /*
  * PLL vote clock APIs
@@ -146,6 +146,8 @@
 	void *const __iomem *base;
 };
 
-void __init configure_pll(struct pll_config *, struct pll_config_regs *, u32);
-
+void configure_sr_pll(struct pll_config *config, struct pll_config_regs *regs,
+				u32 ena_fsm_mode);
+void configure_sr_hpm_lp_pll(struct pll_config *config,
+				struct pll_config_regs *, u32 ena_fsm_mode);
 #endif
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 05bd56ef..6c9b413 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,19 +32,6 @@
 
 #include "acpuclock.h"
 
-#ifdef CONFIG_SMP
-struct cpufreq_work_struct {
-	struct work_struct work;
-	struct cpufreq_policy *policy;
-	struct completion complete;
-	int frequency;
-	int status;
-};
-
-static DEFINE_PER_CPU(struct cpufreq_work_struct, cpufreq_work);
-static struct workqueue_struct *msm_cpufreq_wq;
-#endif
-
 struct cpufreq_suspend_t {
 	struct mutex suspend_mutex;
 	int device_suspended;
@@ -91,45 +78,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_SMP
-static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
-					unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
-		break;
-	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
-		mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
-		per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
-		mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
-		break;
-	case CPU_DOWN_FAILED:
-	case CPU_DOWN_FAILED_FROZEN:
-		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
-	.notifier_call = msm_cpufreq_cpu_callback,
-};
-
-static void set_cpu_work(struct work_struct *work)
-{
-	struct cpufreq_work_struct *cpu_work =
-		container_of(work, struct cpufreq_work_struct, work);
-
-	cpu_work->status = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
-	complete(&cpu_work->complete);
-}
-#endif
-
 static int msm_cpufreq_target(struct cpufreq_policy *policy,
 				unsigned int target_freq,
 				unsigned int relation)
@@ -137,19 +85,12 @@
 	int ret = -EFAULT;
 	int index;
 	struct cpufreq_frequency_table *table;
-#ifdef CONFIG_SMP
-	struct cpufreq_work_struct *cpu_work = NULL;
-	cpumask_var_t mask;
 
 	if (!cpu_active(policy->cpu)) {
 		pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
 		return -ENODEV;
 	}
 
-	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
-		return -ENOMEM;
-#endif
-
 	mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 
 	if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {
@@ -167,39 +108,13 @@
 		goto done;
 	}
 
-#ifdef CONFIG_CPU_FREQ_DEBUG
 	pr_debug("CPU[%d] target %d relation %d (%d-%d) selected %d\n",
 		policy->cpu, target_freq, relation,
 		policy->min, policy->max, table[index].frequency);
-#endif
 
-#ifdef CONFIG_SMP
-	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
-	cpu_work->policy = policy;
-	cpu_work->frequency = table[index].frequency;
-	cpu_work->status = -ENODEV;
-
-	cpumask_clear(mask);
-	cpumask_set_cpu(policy->cpu, mask);
-	if (cpumask_equal(mask, &current->cpus_allowed)) {
-		ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
-		goto done;
-	} else {
-		cancel_work_sync(&cpu_work->work);
-		INIT_COMPLETION(cpu_work->complete);
-		queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
-		wait_for_completion(&cpu_work->complete);
-	}
-
-	ret = cpu_work->status;
-#else
 	ret = set_cpu_freq(policy, table[index].frequency);
-#endif
 
 done:
-#ifdef CONFIG_SMP
-	free_cpumask_var(mask);
-#endif
 	mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 	return ret;
 }
@@ -282,10 +197,6 @@
 	int cur_freq;
 	int index;
 	struct cpufreq_frequency_table *table;
-#ifdef CONFIG_SMP
-	struct cpufreq_work_struct *cpu_work = NULL;
-#endif
-
 
 	table = cpufreq_frequency_get_table(policy->cpu);
 	if (table == NULL)
@@ -314,7 +225,7 @@
 	    CPUFREQ_RELATION_H, &index) &&
 	    cpufreq_frequency_table_target(policy, table, cur_freq,
 	    CPUFREQ_RELATION_L, &index)) {
-		pr_info("cpufreq: cpu%d at invalid freq: %d\n",
+		pr_info("%s: cpu%d at invalid freq: %d\n", __func__,
 				policy->cpu, cur_freq);
 		return -EINVAL;
 	}
@@ -334,15 +245,39 @@
 
 	policy->cpuinfo.transition_latency =
 		acpuclk_get_switch_time() * NSEC_PER_USEC;
-#ifdef CONFIG_SMP
-	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
-	INIT_WORK(&cpu_work->work, set_cpu_work);
-	init_completion(&cpu_work->complete);
-#endif
 
 	return 0;
 }
 
+static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
+		unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+		break;
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+		mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+		per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
+		mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+		break;
+	case CPU_DOWN_FAILED:
+	case CPU_DOWN_FAILED_FROZEN:
+		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
+	.notifier_call = msm_cpufreq_cpu_callback,
+};
+
 static int msm_cpufreq_suspend(void)
 {
 	int cpu;
@@ -382,6 +317,10 @@
 	}
 }
 
+static struct notifier_block msm_cpufreq_pm_notifier = {
+	.notifier_call = msm_cpufreq_pm_event,
+};
+
 static struct freq_attr *msm_freq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
@@ -398,10 +337,6 @@
 	.attr		= msm_freq_attr,
 };
 
-static struct notifier_block msm_cpufreq_pm_notifier = {
-	.notifier_call = msm_cpufreq_pm_event,
-};
-
 static int __init msm_cpufreq_register(void)
 {
 	int cpu;
@@ -411,10 +346,7 @@
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
 	}
 
-#ifdef CONFIG_SMP
-	msm_cpufreq_wq = create_workqueue("msm-cpufreq");
 	register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
-#endif
 
 	register_pm_notifier(&msm_cpufreq_pm_notifier);
 	return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index d22690c..33782ab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -3145,18 +3145,29 @@
 	},
 };
 
-static const struct kgsl_iommu_ctx kgsl_3d0_iommu_ctxs[] = {
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu0_ctxs[] = {
 	{ "gfx3d_user", 0 },
 	{ "gfx3d_priv", 1 },
 };
 
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu1_ctxs[] = {
+	{ "gfx3d1_user", 0 },
+	{ "gfx3d1_priv", 1 },
+};
+
 static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
 	{
-		.iommu_ctxs = kgsl_3d0_iommu_ctxs,
-		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu_ctxs),
+		.iommu_ctxs = kgsl_3d0_iommu0_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctxs),
 		.physstart = 0x07C00000,
 		.physend = 0x07C00000 + SZ_1M - 1,
 	},
+	{
+		.iommu_ctxs = kgsl_3d0_iommu1_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu1_ctxs),
+		.physstart = 0x07D00000,
+		.physend = 0x07D00000 + SZ_1M - 1,
+	},
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index cd5b2e5..c877ba9 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1728,7 +1728,7 @@
 	uint32_t quot;
 
 	/* This formula is as per chip characterization data */
-	quot = max_quot - ((max_freq / 10 - new_freq / 10) * 5);
+	quot = max_quot - (((max_freq - new_freq) * 5) / 10);
 
 	return quot;
 }
diff --git a/arch/arm/mach-msm/event_timer.c b/arch/arm/mach-msm/event_timer.c
new file mode 100644
index 0000000..e06dad4
--- /dev/null
+++ b/arch/arm/mach-msm/event_timer.c
@@ -0,0 +1,318 @@
+/* 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 <linux/module.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <mach/event_timer.h>
+
+#define __INIT_HEAD(x)	{ .head = RB_ROOT,\
+			.next = NULL, }
+
+#define DEFINE_TIME_HEAD(x) struct timerqueue_head x = __INIT_HEAD(x)
+
+/**
+ * struct event_timer_info - basic event timer structure
+ * @node: timerqueue node to track time ordered data structure
+ *        of event timers
+ * @timer: hrtimer created for this event.
+ * @function : callback function for event timer.
+ * @data : callback data for event timer.
+ */
+struct event_timer_info {
+	struct timerqueue_node node;
+	void (*function)(void *);
+	void *data;
+};
+
+
+static DEFINE_TIME_HEAD(timer_head);
+static DEFINE_SPINLOCK(event_timer_lock);
+static struct hrtimer event_hrtimer;
+static enum hrtimer_restart event_hrtimer_cb(struct hrtimer *hrtimer);
+
+static int msm_event_debug_mask;
+module_param_named(
+	debug_mask, msm_event_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
+);
+
+enum {
+	MSM_EVENT_TIMER_DEBUG = 1U << 0,
+};
+
+
+/**
+ * add_event_timer() : Add a wakeup event. Intended to be called
+ *                     by clients once. Returns a handle to be used
+ *                     for future transactions.
+ * @function : The callback function will be called when event
+ *             timer expires.
+ * @data: callback data provided by client.
+ */
+struct event_timer_info *add_event_timer(void (*function)(void *), void *data)
+{
+	struct event_timer_info *event_info =
+			kzalloc(sizeof(struct event_timer_info), GFP_KERNEL);
+
+	if (!event_info)
+		return NULL;
+
+	event_info->function = function;
+	event_info->data = data;
+	/* Init rb node and hr timer */
+	timerqueue_init(&event_info->node);
+
+	return event_info;
+}
+
+/**
+ * is_event_next(): Helper function to check if the event is the next
+ *                   next expiring event
+ * @event : handle to the event to be checked.
+ */
+static bool is_event_next(struct event_timer_info *event)
+{
+	struct event_timer_info *next_event;
+	struct timerqueue_node *next;
+	bool ret = false;
+
+	next = timerqueue_getnext(&timer_head);
+	if (!next)
+		goto exit_is_next_event;
+
+	next_event = container_of(next, struct event_timer_info, node);
+	if (!next_event)
+		goto exit_is_next_event;
+
+	if (next_event == event)
+		ret = true;
+
+exit_is_next_event:
+	return ret;
+}
+
+/**
+ * is_event_active(): Helper function to check if the timer for a given event
+ *                    has been started.
+ * @event : handle to the event to be checked.
+ */
+static bool is_event_active(struct event_timer_info *event)
+{
+	struct timerqueue_node *next;
+	struct event_timer_info *next_event;
+	bool ret = false;
+
+	for (next = timerqueue_getnext(&timer_head); next;
+			next = timerqueue_iterate_next(next)) {
+		next_event = container_of(next, struct event_timer_info, node);
+
+		if (event == next_event) {
+			ret = true;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
+ * create_httimer(): Helper function to setup hrtimer.
+ */
+static void create_hrtimer(ktime_t expires)
+{
+	static bool timer_initialized;
+
+	if (!timer_initialized) {
+		hrtimer_init(&event_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+		timer_initialized = true;
+	}
+
+	event_hrtimer.function = event_hrtimer_cb;
+	hrtimer_start(&event_hrtimer, expires, HRTIMER_MODE_ABS);
+
+	if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+		pr_info("%s: Setting timer for %lu", __func__,
+			(unsigned long)ktime_to_ns(expires));
+}
+
+/**
+ * event_hrtimer_cb() : Callback function for hr timer.
+ *                      Make the client CB from here and remove the event
+ *                      from the time ordered queue.
+ */
+static enum hrtimer_restart event_hrtimer_cb(struct hrtimer *hrtimer)
+{
+	struct event_timer_info *event;
+	struct timerqueue_node *next;
+
+	next = timerqueue_getnext(&timer_head);
+
+	while (next && (ktime_to_ns(next->expires)
+		<= ktime_to_ns(hrtimer->node.expires))) {
+		if (!next)
+			goto hrtimer_cb_exit;
+
+		event = container_of(next, struct event_timer_info, node);
+		if (!event)
+			goto hrtimer_cb_exit;
+
+		if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+			pr_info("%s: Deleting event @ %lu", __func__,
+			(unsigned long)ktime_to_ns(next->expires));
+
+		timerqueue_del(&timer_head, &event->node);
+
+		if (event->function)
+			event->function(event->data);
+		next = timerqueue_getnext(&timer_head);
+	}
+
+	if (next)
+		create_hrtimer(next->expires);
+
+hrtimer_cb_exit:
+	return HRTIMER_NORESTART;
+}
+
+/**
+ * create_timer_smp(): Helper function used setting up timer on core 0.
+ */
+static void create_timer_smp(void *data)
+{
+	unsigned long flags;
+	struct event_timer_info *event =
+		(struct event_timer_info *)data;
+
+	local_irq_save(flags);
+	create_hrtimer(event->node.expires);
+	local_irq_restore(flags);
+}
+
+/**
+ *  setup_timer() : Helper function to setup timer on primary
+ *                  core during hrtimer callback.
+ *  @event: event handle causing the wakeup.
+ */
+static void setup_event_hrtimer(struct event_timer_info *event)
+{
+	struct timerqueue_node *next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&event_timer_lock, flags);
+	if (is_event_active(event))
+		timerqueue_del(&timer_head, &event->node);
+
+	next = timerqueue_getnext(&timer_head);
+	timerqueue_add(&timer_head, &event->node);
+	spin_unlock_irqrestore(&event_timer_lock, flags);
+
+	if (!next ||
+		(next && (ktime_to_ns(event->node.expires) <
+				ktime_to_ns(next->expires)))) {
+		if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+			pr_info("%s: Setting timer for %lu", __func__,
+			(unsigned long)ktime_to_ns(event->node.expires));
+
+		smp_call_function_single(0, create_timer_smp, event, 1);
+		}
+}
+
+/**
+ * activate_event_timer() : Set the expiration time for an event in absolute
+ *                           ktime. This is a oneshot event timer, clients
+ *                           should call this again to set another expiration.
+ *  @event : event handle.
+ *  @event_time : event time in absolute ktime.
+ */
+void activate_event_timer(struct event_timer_info *event, ktime_t event_time)
+{
+	if (!event)
+		return;
+
+	if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+		pr_info("%s: Adding event timer @ %lu", __func__,
+				(unsigned long)ktime_to_us(event_time));
+
+	event->node.expires = event_time;
+	/* Start hr timer and add event to rb tree */
+	setup_event_hrtimer(event);
+}
+
+
+/**
+ * deactivate_event_timer() : Deactivate an event timer, this removes the event from
+ *                            the time ordered queue of event timers.
+ * @event: event handle.
+ */
+void deactivate_event_timer(struct event_timer_info *event)
+{
+	unsigned long flags;
+
+	if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+		pr_info("%s: Deactivate timer", __func__);
+
+	spin_lock_irqsave(&event_timer_lock, flags);
+	if (is_event_active(event)) {
+		if (is_event_next(event))
+			hrtimer_try_to_cancel(&event_hrtimer);
+
+		timerqueue_del(&timer_head, &event->node);
+	}
+	spin_unlock_irqrestore(&event_timer_lock, flags);
+}
+
+/**
+ * destroy_event_timer() : Free the event info data structure allocated during
+ *                         add_event_timer().
+ * @event: event handle.
+ */
+void destroy_event_timer(struct event_timer_info *event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&event_timer_lock, flags);
+	if (is_event_active(event)) {
+		if (is_event_next(event))
+			hrtimer_try_to_cancel(&event_hrtimer);
+
+		timerqueue_del(&timer_head, &event->node);
+	}
+	spin_unlock_irqrestore(&event_timer_lock, flags);
+	kfree(event);
+}
+
+/**
+ * get_next_event_timer() - Get the next wakeup event. Returns
+ *                          a ktime value of the next expiring event.
+ */
+ktime_t get_next_event_time(void)
+{
+	unsigned long flags;
+	struct timerqueue_node *next;
+	ktime_t next_event = ns_to_ktime(0);
+
+	spin_lock_irqsave(&event_timer_lock, flags);
+	next = timerqueue_getnext(&timer_head);
+	spin_unlock_irqrestore(&event_timer_lock, flags);
+
+	if (!next)
+		return next_event;
+
+	next_event = hrtimer_get_remaining(&event_hrtimer);
+	if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+		pr_info("%s: Next Event %lu", __func__,
+			(unsigned long)ktime_to_us(next_event));
+
+	return next_event;
+}
diff --git a/arch/arm/mach-msm/include/mach/event_timer.h b/arch/arm/mach-msm/include/mach/event_timer.h
new file mode 100644
index 0000000..7a00b23
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/event_timer.h
@@ -0,0 +1,77 @@
+/* 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 __ARCH_ARM_MACH_MSM_EVENT_TIMER_H
+#define __ARCH_ARM_MACH_MSM_EVENT_TIMER_H
+
+#include <linux/hrtimer.h>
+
+struct event_timer_info;
+
+#ifdef CONFIG_MSM_EVENT_TIMER
+/**
+ * add_event_timer() : Add a wakeup event. Intended to be called
+ *                     by clients once. Returns a handle to be used
+ *                     for future transactions.
+ * @function : The callback function will be called when event
+ *             timer expires.
+ * @data : Callback data provided by client.
+ */
+struct event_timer_info *add_event_timer(void (*function)(void *), void *data);
+
+/** activate_event_timer() : Set the expiration time for an event in absolute
+ *                           ktime. This is a oneshot event timer, clients
+ *                           should call this again to set another expiration.
+ *  @event : Event handle.
+ *  @event_time : Event time in absolute ktime.
+ */
+void activate_event_timer(struct event_timer_info *event, ktime_t event_time);
+
+/**
+ * deactivate_event_timer() : Deactivate an event timer.
+ * @event: event handle.
+ */
+void deactivate_event_timer(struct event_timer_info *event);
+
+/**
+ * destroy_event_timer() : Free the event info data structure allocated during
+ * add_event_timer().
+ * @event: event handle.
+ */
+void destroy_event_timer(struct event_timer_info *event);
+
+/**
+ * get_next_event_timer() : Get the next wakeup event.
+ *                          returns a ktime value of the next
+ *                          expiring event.
+ */
+ktime_t get_next_event_time(void);
+#else
+static inline void *add_event_timer(void (*function)(void *), void *data)
+{
+	return NULL;
+}
+
+static inline void activate_event_timer(void *event, ktime_t event_time) {}
+
+static inline void deactivate_event_timer(void *event) {}
+
+static inline void destroy_event_timer(void *event) {}
+
+static inline ktime_t get_next_event_time(void)
+{
+	return ns_to_ktime(0);
+}
+
+#endif /* CONFIG_MSM_EVENT_TIMER_MANAGER */
+#endif /* __ARCH_ARM_MACH_MSM_EVENT_TIMER_H */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 493cf36..eecdd67 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -23,7 +23,7 @@
  *
  */
 
-#define MSM9625_SHARED_RAM_PHYS	0x18D00000
+#define MSM9625_SHARED_RAM_PHYS	0x00000000
 
 #define MSM9625_APCS_GCC_PHYS	0xF9011000
 #define MSM9625_APCS_GCC_SIZE	SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 21bea4f..6f925d4 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -105,7 +105,7 @@
 
 
 #if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
-	|| defined(CONFIG_ARCH_MSM7X30)
+	|| defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
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/io.c b/arch/arm/mach-msm/io.c
index 5430f99..e0fec65 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -497,7 +497,7 @@
 
 void __init msm_map_mpq8092_io(void)
 {
-	msm_shared_ram_phys = MSM8974_MSM_SHARED_RAM_PHYS;
+	msm_shared_ram_phys = MSM8092_MSM_SHARED_RAM_PHYS;
 	msm_map_io(mpq8092_io_desc, ARRAY_SIZE(mpq8092_io_desc));
 }
 #endif /* CONFIG_ARCH_MPQ8092 */
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 7dc8d0f..c82eac1 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2096,7 +2096,7 @@
 			mutex_lock(&rt_entry->lock);
 			i += scnprintf(buf + i, max - i,
 				       "Node Id: 0x%08x\n", rt_entry->node_id);
-			if (j == IPC_ROUTER_NID_LOCAL) {
+			if (rt_entry->node_id == IPC_ROUTER_NID_LOCAL) {
 				i += scnprintf(buf + i, max - i,
 				       "XPRT Name: Loopback\n");
 				i += scnprintf(buf + i, max - i,
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index f7456ef..8218a42 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -92,8 +92,8 @@
 }
 
 static void *msm_lpm_lowest_limits(bool from_idle,
-		enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
-		uint32_t sleep_us, uint32_t *power)
+		enum msm_pm_sleep_mode sleep_mode,
+		struct msm_pm_time_params *time_param, uint32_t *power)
 {
 	unsigned int cpu = smp_processor_id();
 	struct msm_rpmrs_level *best_level = NULL;
@@ -114,20 +114,22 @@
 		if (sleep_mode != level->sleep_mode)
 			continue;
 
-		if (latency_us < level->latency_us)
+		if (time_param->latency_us < level->latency_us)
 			continue;
 
-		if (sleep_us <= 1) {
+		if (time_param->sleep_us <= 1) {
 			pwr = level->energy_overhead;
-		} else if (sleep_us <= level->time_overhead_us) {
-			pwr = level->energy_overhead / sleep_us;
-		} else if ((sleep_us >> 10) > level->time_overhead_us) {
+		} else if (time_param->sleep_us <= level->time_overhead_us) {
+			pwr = level->energy_overhead / time_param->sleep_us;
+		} else if ((time_param->sleep_us >> 10)
+				> level->time_overhead_us) {
 			pwr = level->steady_state_power;
 		} else {
 			pwr = level->steady_state_power;
 			pwr -= (level->time_overhead_us *
-					level->steady_state_power)/sleep_us;
-			pwr += level->energy_overhead / sleep_us;
+				level->steady_state_power) /
+						time_param->sleep_us;
+			pwr += level->energy_overhead / time_param->sleep_us;
 		}
 
 		if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
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/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index e2640a2..12f7d96 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -44,6 +44,8 @@
  */
 #define TIMER_COUNT(freq, delay) ((freq * delay) / 1000)
 #define ALL_CPR_IRQ 0x3F
+#define STEP_QUOT_MAX 25
+#define STEP_QUOT_MIN 12
 
 /* Need platform device handle for suspend and resume APIs */
 static struct platform_device *cpr_pdev;
@@ -269,8 +271,19 @@
 		goto err_poll_result;
 	}
 	quot2 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
-	chip_data->step_quot = (quot1 - quot2) / 4;
-	pr_info("%s: Calculated Step Quot is %d\n",
+	/*
+	 * Based on chip characterization data, it is good to add some
+	 * margin on top of calculated step quot to help reduce the
+	 * number of CPR interrupts. The present value suggested is 3.
+	 * Further, if the step quot is outside range, clamp it to the
+	 * maximum permitted value.
+	 */
+	chip_data->step_quot = ((quot1 - quot2) / 4) + 3;
+	if (chip_data->step_quot < STEP_QUOT_MIN ||
+			chip_data->step_quot > STEP_QUOT_MAX)
+		chip_data->step_quot = STEP_QUOT_MAX;
+
+	pr_info("%s: Step Quot is %d\n",
 			__func__, chip_data->step_quot);
 	/* Disable the cpr */
 	cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
@@ -626,6 +639,8 @@
 					RBCPR_GCNT_TARGET(cpr->curr_osc)));
 		pr_debug("%s: new_freq: %d, set_freq: %d, quot: %d\n", __func__,
 			freqs->new, new_freq, quot);
+		pr_info("%s: PVS Voltage setting is: %d\n", __func__,
+			regulator_get_voltage(cpr->vreg_cx));
 
 		enable_irq(cpr->irq);
 		/**
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
index 85dc85d..4aba69c 100644
--- a/arch/arm/mach-msm/ocmem_rdm.c
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -93,8 +93,8 @@
 static void *br_base;
 static void *dm_base;
 
-static atomic_t dm_pending;
-static wait_queue_head_t dm_wq;
+struct completion dm_clear_event;
+struct completion dm_transfer_event;
 /* Shadow tables for debug purposes */
 struct ocmem_br_table {
 	unsigned int offset;
@@ -136,22 +136,22 @@
 		pr_debug("Data mover completed\n");
 		irq_status &= ~BIT(0);
 		ocmem_write(irq_status, dm_base + DM_INTR_CLR);
+		complete(&dm_transfer_event);
 	} else if (irq_status & BIT(1)) {
 		pr_debug("Data clear engine completed\n");
 		irq_status &= ~BIT(1);
 		ocmem_write(irq_status, dm_base + DM_INTR_CLR);
+		complete(&dm_clear_event);
 	} else {
 		BUG_ON(1);
 	}
-	atomic_set(&dm_pending, 0);
-	wake_up_interruptible(&dm_wq);
 	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_MSM_OCMEM_NONSECURE
 int ocmem_clear(unsigned long start, unsigned long size)
 {
-	atomic_set(&dm_pending, 1);
+	INIT_COMPLETION(dm_clear_event);
 	/* Clear DM Mask */
 	ocmem_write(DM_MASK_RESET, dm_base + DM_INTR_MASK);
 	/* Clear DM Interrupts */
@@ -169,8 +169,8 @@
 	/* Trigger Data Clear */
 	ocmem_write(DM_CLR_ENABLE, dm_base + DM_CLR_TRIGGER);
 
-	wait_event_interruptible(dm_wq,
-		atomic_read(&dm_pending) == 0);
+	wait_for_completion(&dm_clear_event);
+
 	return 0;
 }
 #else
@@ -249,7 +249,7 @@
 
 	status = ocmem_read(dm_base + DM_GEN_STATUS);
 	pr_debug("Transfer status before %x\n", status);
-	atomic_set(&dm_pending, 1);
+	INIT_COMPLETION(dm_transfer_event);
 	/* The DM and BR tables must be programmed before triggering the
 	 * Data Mover else the coherent transfer would be corrupted
 	 */
@@ -258,9 +258,7 @@
 	ocmem_write(dm_ctrl, dm_base + DM_CTRL);
 	pr_debug("ocmem: rdm: dm_ctrl %x br_ctrl %x\n", dm_ctrl, br_ctrl);
 
-	wait_event_interruptible(dm_wq,
-		atomic_read(&dm_pending) == 0);
-
+	wait_for_completion(&dm_transfer_event);
 	ocmem_disable_core_clock();
 	return 0;
 }
@@ -291,7 +289,8 @@
 		return rc;
 	}
 
-	init_waitqueue_head(&dm_wq);
+	init_completion(&dm_clear_event);
+	init_completion(&dm_transfer_event);
 	/* Clear DM Mask */
 	ocmem_write(DM_MASK_RESET, dm_base + DM_INTR_MASK);
 	/* enable dm interrupts */
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/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index dbb23d5..60ee8f0 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -49,6 +49,7 @@
 #include "spm.h"
 #include "timer.h"
 #include "pm-boot.h"
+#include <mach/event_timer.h>
 
 /******************************************************************************
  * Debug Definitions
@@ -112,6 +113,7 @@
 		"standalone_power_collapse",
 };
 
+static struct hrtimer pm_hrtimer;
 static struct msm_pm_sleep_ops pm_sleep_ops;
 /*
  * Write out the attribute.
@@ -645,6 +647,28 @@
 	return time;
 }
 
+/**
+ * pm_hrtimer_cb() : Callback function for hrtimer created if the
+ *                   core needs to be awake to handle an event.
+ * @hrtimer : Pointer to hrtimer
+ */
+static enum hrtimer_restart pm_hrtimer_cb(struct hrtimer *hrtimer)
+{
+	return HRTIMER_NORESTART;
+}
+
+/**
+ * msm_pm_set_timer() : Set an hrtimer to wakeup the core in time
+ *                      to handle an event.
+ */
+static void msm_pm_set_timer(uint32_t modified_time_us)
+{
+	u64 modified_time_ns = modified_time_us * NSEC_PER_USEC;
+	ktime_t modified_ktime = ns_to_ktime(modified_time_ns);
+	pm_hrtimer.function = pm_hrtimer_cb;
+	hrtimer_start(&pm_hrtimer, modified_ktime, HRTIMER_MODE_ABS);
+}
+
 /******************************************************************************
  * External Idle/Suspend Functions
  *****************************************************************************/
@@ -657,15 +681,25 @@
 int msm_pm_idle_prepare(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
-	uint32_t latency_us;
-	uint32_t sleep_us;
 	int i;
 	unsigned int power_usage = -1;
 	int ret = 0;
+	uint32_t modified_time_us = 0;
+	struct msm_pm_time_params time_param;
 
-	latency_us = (uint32_t) pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
-	sleep_us = (uint32_t) ktime_to_ns(tick_nohz_get_sleep_length());
-	sleep_us = DIV_ROUND_UP(sleep_us, 1000);
+	time_param.latency_us =
+		(uint32_t) pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
+	time_param.sleep_us =
+		(uint32_t) (ktime_to_us(tick_nohz_get_sleep_length())
+								& UINT_MAX);
+	time_param.modified_time_us = 0;
+
+	if (!dev->cpu)
+		time_param.next_event_us =
+			(uint32_t) (ktime_to_us(get_next_event_time())
+								& UINT_MAX);
+	else
+		time_param.next_event_us = 0;
 
 	for (i = 0; i < dev->state_count; i++) {
 		struct cpuidle_state *state = &drv->states[i];
@@ -702,17 +736,18 @@
 		case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
 			if (!allow)
 				break;
+			/* fall through */
 
 			if (pm_sleep_ops.lowest_limits)
 				rs_limits = pm_sleep_ops.lowest_limits(true,
-						mode, latency_us, sleep_us,
-						&power);
+						mode, &time_param, &power);
 
 			if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
 				pr_info("CPU%u: %s: %s, latency %uus, "
 					"sleep %uus, limit %p\n",
 					dev->cpu, __func__, state->desc,
-					latency_us, sleep_us, rs_limits);
+					time_param.latency_us,
+					time_param.sleep_us, rs_limits);
 
 			if (!rs_limits)
 				allow = false;
@@ -730,6 +765,7 @@
 		if (allow) {
 			if (power < power_usage) {
 				power_usage = power;
+				modified_time_us = time_param.modified_time_us;
 				ret = mode;
 			}
 
@@ -738,6 +774,8 @@
 		}
 	}
 
+	if (modified_time_us && !dev->cpu)
+		msm_pm_set_timer(modified_time_us);
 	return ret;
 }
 
@@ -850,6 +888,11 @@
 	int i;
 	int64_t period = 0;
 	int64_t time = msm_pm_timer_enter_suspend(&period);
+	struct msm_pm_time_params time_param;
+
+	time_param.latency_us = -1;
+	time_param.sleep_us = -1;
+	time_param.next_event_us = 0;
 
 	if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
 		pr_info("%s\n", __func__);
@@ -887,8 +930,7 @@
 #endif /* CONFIG_MSM_SLEEP_TIME_OVERRIDE */
 		if (pm_sleep_ops.lowest_limits)
 			rs_limits = pm_sleep_ops.lowest_limits(false,
-					MSM_PM_SLEEP_MODE_POWER_COLLAPSE, -1,
-					-1, &power);
+			MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power);
 
 		if (rs_limits) {
 			if (pm_sleep_ops.enter_sleep)
@@ -1046,6 +1088,7 @@
 
 	suspend_set_ops(&msm_pm_ops);
 	msm_pm_qtimer_available();
+	hrtimer_init(&pm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 	msm_cpuidle_init();
 	platform_driver_register(&msm_pc_counter_driver);
 
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index e2553e2..51256ca 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -57,6 +57,13 @@
 
 #define MSM_PM_MODE(cpu, mode_nr)  ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))
 
+struct msm_pm_time_params {
+	uint32_t latency_us;
+	uint32_t sleep_us;
+	uint32_t next_event_us;
+	uint32_t modified_time_us;
+};
+
 struct msm_pm_platform_data {
 	u8 idle_supported;   /* Allow device to enter mode during idle */
 	u8 suspend_supported; /* Allow device to enter mode during suspend */
@@ -72,8 +79,8 @@
 
 struct msm_pm_sleep_ops {
 	void *(*lowest_limits)(bool from_idle,
-			enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
-			uint32_t sleep_us, uint32_t *power);
+			enum msm_pm_sleep_mode sleep_mode,
+			struct msm_pm_time_params *time_param, uint32_t *power);
 	int (*enter_sleep)(uint32_t sclk_count, void *limits,
 			bool from_idle, bool notify_rpm);
 	void (*exit_sleep)(void *limits, bool from_idle,
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/restart.c b/arch/arm/mach-msm/restart.c
index 53736ac..5883b0c 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -24,6 +24,7 @@
 #include <linux/mfd/pmic8058.h>
 #include <linux/mfd/pmic8901.h>
 #include <linux/mfd/pm8xxx/misc.h>
+#include <linux/qpnp/power-on.h>
 
 #include <asm/mach-types.h>
 #include <asm/cacheflush.h>
@@ -128,6 +129,7 @@
 	set_dload_mode(0);
 #endif
 	pm8xxx_reset_pwr_off(0);
+	qpnp_pon_system_pwr_off(0);
 
 	if (lower_pshold) {
 		if (!use_restart_v2())
@@ -208,6 +210,7 @@
 #endif
 
 	pm8xxx_reset_pwr_off(1);
+	qpnp_pon_system_pwr_off(1);
 
 	if (cmd != NULL) {
 		if (!strncmp(cmd, "bootloader", 10)) {
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 9d794e7..2a835f7 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -20,6 +20,7 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
+#include <linux/hrtimer.h>
 #include <mach/rpm.h>
 #include <mach/msm_iomap.h>
 #include <asm/mach-types.h>
@@ -37,6 +38,7 @@
 enum {
 	MSM_RPMRS_DEBUG_OUTPUT = BIT(0),
 	MSM_RPMRS_DEBUG_BUFFER = BIT(1),
+	MSM_RPMRS_DEBUG_EVENT_TIMER = BIT(2),
 };
 
 static int msm_rpmrs_debug_mask;
@@ -891,8 +893,8 @@
 }
 
 static void *msm_rpmrs_lowest_limits(bool from_idle,
-		enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
-		uint32_t sleep_us, uint32_t *power)
+		enum msm_pm_sleep_mode sleep_mode,
+		struct msm_pm_time_params *time_param, uint32_t *power)
 {
 	unsigned int cpu = smp_processor_id();
 	struct msm_rpmrs_level *best_level = NULL;
@@ -900,6 +902,8 @@
 	bool gpio_detectable = false;
 	int i;
 	uint32_t pwr;
+	uint32_t next_wakeup_us = time_param->sleep_us;
+	bool modify_event_timer;
 
 	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
 		irqs_detectable = msm_mpm_irqs_detectable(from_idle);
@@ -909,16 +913,32 @@
 	for (i = 0; i < msm_rpmrs_level_count; i++) {
 		struct msm_rpmrs_level *level = &msm_rpmrs_levels[i];
 
+		modify_event_timer = false;
+
 		if (!level->available)
 			continue;
 
 		if (sleep_mode != level->sleep_mode)
 			continue;
 
-		if (latency_us < level->latency_us)
+		if (time_param->latency_us < level->latency_us)
 			continue;
 
-		if (sleep_us <= level->time_overhead_us)
+		if (time_param->next_event_us &&
+				time_param->next_event_us < level->latency_us)
+			continue;
+
+		if (time_param->next_event_us) {
+			if ((time_param->next_event_us < time_param->sleep_us)
+			|| ((time_param->next_event_us - level->latency_us) <
+				time_param->sleep_us)) {
+				modify_event_timer = true;
+				next_wakeup_us = time_param->next_event_us -
+						level->latency_us;
+			}
+		}
+
+		if (next_wakeup_us <= level->time_overhead_us)
 			continue;
 
 		if (!msm_rpmrs_irqs_detectable(&level->rs_limits,
@@ -929,18 +949,17 @@
 			if (!cpu && msm_rpm_local_request_is_outstanding())
 					break;
 
-
-		if (sleep_us <= 1) {
+		if (next_wakeup_us <= 1) {
 			pwr = level->energy_overhead;
-		} else if (sleep_us <= level->time_overhead_us) {
-			pwr = level->energy_overhead / sleep_us;
-		} else if ((sleep_us >> 10) > level->time_overhead_us) {
+		} else if (next_wakeup_us <= level->time_overhead_us) {
+			pwr = level->energy_overhead / next_wakeup_us;
+		} else if ((next_wakeup_us >> 10) > level->time_overhead_us) {
 			pwr = level->steady_state_power;
 		} else {
 			pwr = level->steady_state_power;
 			pwr -= (level->time_overhead_us *
-					level->steady_state_power)/sleep_us;
-			pwr += level->energy_overhead / sleep_us;
+				level->steady_state_power)/next_wakeup_us;
+			pwr += level->energy_overhead / next_wakeup_us;
 		}
 
 		if (!best_level ||
@@ -950,6 +969,12 @@
 			best_level = level;
 			if (power)
 				*power = pwr;
+			if (modify_event_timer && best_level->latency_us > 1)
+				time_param->modified_time_us =
+					time_param->next_event_us -
+							best_level->latency_us;
+			else
+				time_param->modified_time_us = 0;
 		}
 	}
 
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 5962d71..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
@@ -65,6 +66,7 @@
 	wait_queue_head_t ch_opened_wait_queue;
 
 	int i;
+	int ref_cnt;
 
 	int blocking_write;
 	int is_open;
@@ -88,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);
@@ -104,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) \
@@ -128,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) \
@@ -136,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) \
@@ -270,6 +300,7 @@
 	if (!smd_pkt_devp)
 		return -EINVAL;
 
+	mutex_lock(&smd_pkt_devp->ch_lock);
 	switch (cmd) {
 	case TIOCMGET:
 		D_STATUS("%s TIOCMGET command on smd_pkt_dev id:%d\n",
@@ -288,6 +319,7 @@
 		pr_err("%s: Unrecognized ioctl command %d\n", __func__, cmd);
 		ret = -1;
 	}
+	mutex_unlock(&smd_pkt_devp->ch_lock);
 
 	return ret;
 }
@@ -867,9 +899,12 @@
 			smd_pkt_devp->ch_size =
 				smd_write_avail(smd_pkt_devp->ch);
 			r = 0;
+			smd_pkt_devp->ref_cnt++;
 			D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
 				 __func__, smd_pkt_devp->i);
 		}
+	} else {
+		smd_pkt_devp->ref_cnt++;
 	}
 release_pil:
 	if (peripheral && (r < 0))
@@ -902,12 +937,14 @@
 	D_STATUS("Begin %s on smd_pkt_dev id:%d\n",
 		 __func__, smd_pkt_devp->i);
 
-	clean_and_signal(smd_pkt_devp);
-
 	mutex_lock(&smd_pkt_devp->ch_lock);
 	mutex_lock(&smd_pkt_devp->rx_lock);
 	mutex_lock(&smd_pkt_devp->tx_lock);
-	if (smd_pkt_devp->ch != 0) {
+	if (smd_pkt_devp->ref_cnt > 0)
+		smd_pkt_devp->ref_cnt--;
+
+	if (smd_pkt_devp->ch != 0 && smd_pkt_devp->ref_cnt == 0) {
+		clean_and_signal(smd_pkt_devp);
 		r = smd_close(smd_pkt_devp->ch);
 		smd_pkt_devp->ch = 0;
 		smd_pkt_devp->blocking_write = 0;
@@ -916,15 +953,15 @@
 		smd_pkt_devp->driver.probe = NULL;
 		if (smd_pkt_devp->pil)
 			pil_put(smd_pkt_devp->pil);
+		smd_pkt_devp->has_reset = 0;
+		smd_pkt_devp->do_reset_notification = 0;
+		smd_pkt_devp->wakelock_locked = 0;
+		wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
 	}
 	mutex_unlock(&smd_pkt_devp->tx_lock);
 	mutex_unlock(&smd_pkt_devp->rx_lock);
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 
-	smd_pkt_devp->has_reset = 0;
-	smd_pkt_devp->do_reset_notification = 0;
-	smd_pkt_devp->wakelock_locked = 0;
-	wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
 	D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
 		 __func__, smd_pkt_devp->i);
 
@@ -1024,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/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 26dfdff..1eab9bf 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -310,9 +310,43 @@
 	return 0;
 }
 
+#ifdef CONFIG_MSM_AVS_HW
+static void msm_spm_drv_disable_avs(struct msm_spm_driver_data *dev)
+{
+	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+	dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] &= ~BIT(27);
+	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+}
+
+static void msm_spm_drv_enable_avs(struct msm_spm_driver_data *dev)
+{
+	dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] |= BIT(27);
+	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+}
+
+static void msm_spm_drv_set_avs_vlevel(struct msm_spm_driver_data *dev,
+		unsigned int vlevel)
+{
+	vlevel &= 0x3f;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] &= ~0x7efc00;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] |= ((vlevel - 4) << 10);
+	dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] |= (vlevel << 17);
+	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+}
+
+#else
+
+static void msm_spm_drv_disable_avs(struct msm_spm_driver_data *dev) { }
+
+static void msm_spm_drv_enable_avs(struct msm_spm_driver_data *dev) { }
+
+static void msm_spm_drv_set_avs_vlevel(struct msm_spm_driver_data *dev,
+		unsigned int vlevel) { }
+#endif
+
 int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel)
 {
-	uint32_t timeout_us;
+	uint32_t timeout_us, new_level;
 
 	if (!dev)
 		return -EINVAL;
@@ -321,42 +355,46 @@
 		return -ENOSYS;
 
 	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
-		pr_info("%s: requesting vlevel 0x%x\n",
-			__func__, vlevel);
+		pr_info("%s: requesting vlevel %#x\n", __func__, vlevel);
+
+	msm_spm_drv_disable_avs(dev);
+
+	/* Kick the state machine back to idle */
+	dev->reg_shadow[MSM_SPM_REG_SAW2_RST] = 1;
+	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_RST);
 
 	msm_spm_drv_apcs_set_vctl(dev, vlevel);
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_VCTL);
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_0);
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_1);
-	mb();
 
-	/* Wait for PMIC state to return to idle or until timeout */
 	timeout_us = dev->vctl_timeout_us;
-	while (msm_spm_drv_get_sts_pmic_state(dev) != MSM_SPM_PMIC_STATE_IDLE) {
-		if (!timeout_us)
-			goto set_vdd_bail;
-
-		if (timeout_us > 10) {
-			udelay(10);
-			timeout_us -= 10;
-		} else {
-			udelay(timeout_us);
-			timeout_us = 0;
-		}
+	/* Confirm the voltage we set was what hardware sent */
+	do {
+		new_level = msm_spm_drv_get_sts_curr_pmic_data(dev);
+		if (new_level == vlevel)
+			break;
+		udelay(1);
+	} while (--timeout_us);
+	if (!timeout_us) {
+		pr_info("Wrong level %#x\n", new_level);
+		goto set_vdd_bail;
 	}
 
-	if (msm_spm_drv_get_sts_curr_pmic_data(dev) != vlevel)
-		goto set_vdd_bail;
+	/* Set AVS min/max */
+	msm_spm_drv_set_avs_vlevel(dev, vlevel);
 
 	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
 		pr_info("%s: done, remaining timeout %uus\n",
 			__func__, timeout_us);
 
+	msm_spm_drv_enable_avs(dev);
 	return 0;
 
 set_vdd_bail:
-	pr_err("%s: failed, remaining timeout %uus, vlevel 0x%x\n",
-	       __func__, timeout_us, msm_spm_drv_get_sts_curr_pmic_data(dev));
+	msm_spm_drv_enable_avs(dev);
+	pr_err("%s: failed %#x, remaining timeout %uus, vlevel %#x\n",
+		__func__, vlevel, timeout_us, new_level);
 	return -EIO;
 }
 
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 05d11d2..b87b0f1 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -38,16 +38,38 @@
 	uint32_t num_modes;
 };
 
+struct msm_spm_vdd_info {
+	uint32_t cpu;
+	uint32_t vlevel;
+	int err;
+};
+
 static struct msm_spm_device msm_spm_l2_device;
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_spm_device, msm_cpu_spm_device);
 
-int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
+
+/* Must be called on the same cpu as the one being set to */
+static void msm_spm_smp_set_vdd(void *data)
 {
 	struct msm_spm_device *dev;
-	int ret = -EIO;
+	struct msm_spm_vdd_info *info = (struct msm_spm_vdd_info *)data;
 
-	dev = &per_cpu(msm_cpu_spm_device, cpu);
-	ret = msm_spm_drv_set_vdd(&dev->reg_data, vlevel);
+	dev = &per_cpu(msm_cpu_spm_device, info->cpu);
+	info->err = msm_spm_drv_set_vdd(&dev->reg_data, info->vlevel);
+}
+
+int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
+{
+	struct msm_spm_vdd_info info;
+	int ret;
+
+	info.cpu = cpu;
+	info.vlevel = vlevel;
+
+	/* Set to true to block on vdd change */
+	ret = smp_call_function_single(cpu, msm_spm_smp_set_vdd, &info, true);
+	if (!ret)
+		ret = info.err;
 
 	return ret;
 }
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 0318a70..bae1ab0 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -58,11 +58,13 @@
 enum subsys_state {
 	SUBSYS_OFFLINE,
 	SUBSYS_ONLINE,
+	SUBSYS_CRASHED,
 };
 
 static const char * const subsys_states[] = {
 	[SUBSYS_OFFLINE] = "OFFLINE",
 	[SUBSYS_ONLINE] = "ONLINE",
+	[SUBSYS_CRASHED] = "CRASHED",
 };
 
 struct subsys_device {
@@ -71,7 +73,7 @@
 	char wlname[64];
 	struct work_struct work;
 	spinlock_t restart_lock;
-	int restart_count;
+	bool restarting;
 
 	void *notify;
 	struct device dev;
@@ -107,6 +109,21 @@
 	return snprintf(buf, PAGE_SIZE, "%s\n", subsys_states[state]);
 }
 
+static void subsys_set_state(struct subsys_device *subsys,
+			     enum subsys_state state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&subsys->restart_lock, flags);
+	if (subsys->state != state) {
+		subsys->state = state;
+		spin_unlock_irqrestore(&subsys->restart_lock, flags);
+		sysfs_notify(&subsys->dev.kobj, NULL, "state");
+		return;
+	}
+	spin_unlock_irqrestore(&subsys->restart_lock, flags);
+}
+
 static struct device_attribute subsys_attrs[] = {
 	__ATTR_RO(name),
 	__ATTR_RO(state),
@@ -333,6 +350,7 @@
 	if (dev->desc->shutdown(dev->desc) < 0)
 		panic("subsys-restart: [%p]: Failed to shutdown %s!",
 			current, name);
+	subsys_set_state(dev, SUBSYS_OFFLINE);
 }
 
 static void subsystem_ramdump(struct subsys_device *dev, void *data)
@@ -351,6 +369,7 @@
 	pr_info("[%p]: Powering up %s\n", current, name);
 	if (dev->desc->powerup(dev->desc) < 0)
 		panic("[%p]: Failed to powerup %s!", current, name);
+	subsys_set_state(dev, SUBSYS_ONLINE);
 }
 
 static int __find_subsys(struct device *dev, void *data)
@@ -418,7 +437,10 @@
 	 * Now that we've acquired the shutdown lock, either we're the first to
 	 * restart these subsystems or some other thread is doing the powerup
 	 * sequence for these subsystems. In the latter case, panic and bail
-	 * out, since a subsystem died in its powerup sequence.
+	 * out, since a subsystem died in its powerup sequence. This catches
+	 * the case where a subsystem in a restart order isn't the one
+	 * who initiated the original restart but has crashed while the restart
+	 * order is being rebooted.
 	 */
 	if (!mutex_trylock(powerup_lock))
 		panic("%s[%p]: Subsystem died during powerup!",
@@ -465,32 +487,36 @@
 
 out:
 	spin_lock_irqsave(&dev->restart_lock, flags);
-	dev->restart_count--;
-	if (!dev->restart_count)
-		wake_unlock(&dev->wake_lock);
+	dev->restarting = false;
+	wake_unlock(&dev->wake_lock);
 	spin_unlock_irqrestore(&dev->restart_lock, flags);
 }
 
 static void __subsystem_restart_dev(struct subsys_device *dev)
 {
 	struct subsys_desc *desc = dev->desc;
+	const char *name = dev->desc->name;
 	unsigned long flags;
 
 	pr_debug("Restarting %s [level=%d]!\n", desc->name, restart_level);
 
+	/*
+	 * We want to allow drivers to call subsystem_restart{_dev}() as many
+	 * times as they want up until the point where the subsystem is
+	 * shutdown.
+	 */
 	spin_lock_irqsave(&dev->restart_lock, flags);
-	if (!dev->restart_count)
-		wake_lock(&dev->wake_lock);
-	dev->restart_count++;
-	spin_unlock_irqrestore(&dev->restart_lock, flags);
-
-	if (!queue_work(ssr_wq, &dev->work)) {
-		spin_lock_irqsave(&dev->restart_lock, flags);
-		dev->restart_count--;
-		if (!dev->restart_count)
-			wake_unlock(&dev->wake_lock);
-		spin_unlock_irqrestore(&dev->restart_lock, flags);
+	if (dev->state != SUBSYS_CRASHED) {
+		if (dev->state == SUBSYS_ONLINE && !dev->restarting) {
+			dev->restarting = true;
+			dev->state = SUBSYS_CRASHED;
+			wake_lock(&dev->wake_lock);
+			queue_work(ssr_wq, &dev->work);
+		} else {
+			panic("Subsystem %s crashed during SSR!", name);
+		}
 	}
+	spin_unlock_irqrestore(&dev->restart_lock, flags);
 }
 
 int subsystem_restart_dev(struct subsys_device *dev)
@@ -644,6 +670,7 @@
 	subsys->dev.parent = desc->dev;
 	subsys->dev.bus = &subsys_bus_type;
 	subsys->dev.release = subsys_device_release;
+	subsys->state = SUBSYS_ONLINE; /* Until proper refcounting appears */
 
 	subsys->notify = subsys_notif_add_subsys(desc->name);
 	subsys->restart_order = update_restart_order(subsys);
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/diagchar.h b/drivers/char/diag/diagchar.h
index 1c14859..b18d709 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -279,12 +279,14 @@
 	struct diag_request *write_ptr_mdm;
 	/* HSIC variables */
 	int hsic_ch;
+	int hsic_inited;
 	int hsic_device_enabled;
 	int hsic_device_opened;
 	int hsic_suspend;
 	int in_busy_hsic_read_on_device;
 	int in_busy_hsic_write;
 	struct work_struct diag_read_hsic_work;
+	struct mutex bridge_mutex;
 	/* USB MDM channel variables */
 	int usb_mdm_connected;
 	int read_len_mdm;
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/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 52fd673..e417d5a 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -558,6 +558,7 @@
 
 	ret = scnprintf(buf, DEBUG_BUF_SIZE,
 		"hsic ch: %d\n"
+		"hsic_inited: %d\n"
 		"hsic enabled: %d\n"
 		"hsic_opened: %d\n"
 		"hsic_suspend: %d\n"
@@ -575,6 +576,7 @@
 		"diag_disconnect_work: %d\n"
 		"diag_usb_read_complete_work: %d\n",
 		driver->hsic_ch,
+		driver->hsic_inited,
 		driver->hsic_device_enabled,
 		driver->hsic_device_opened,
 		driver->hsic_suspend,
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 3878a82..56f2fae 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -236,20 +236,20 @@
 	.resume = diag_hsic_resume,
 };
 
-static int diag_hsic_close(void)
+static void diag_hsic_close(void)
 {
 	if (driver->hsic_device_enabled) {
 		driver->hsic_ch = 0;
 		if (driver->hsic_device_opened) {
 			driver->hsic_device_opened = 0;
 			diag_bridge_close();
+			pr_debug("diag: %s: closed successfully\n", __func__);
+		} else {
+			pr_debug("diag: %s: already closed\n", __func__);
 		}
-		pr_debug("diag: in %s: closed successfully\n", __func__);
 	} else {
-		pr_debug("diag: in %s: already closed\n", __func__);
+		pr_debug("diag: %s: HSIC device already removed\n", __func__);
 	}
-
-	return 0;
 }
 
 /* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
@@ -257,6 +257,7 @@
 {
 	int err;
 
+	mutex_lock(&driver->bridge_mutex);
 	if (driver->hsic_device_enabled) {
 		if (driver->hsic_device_opened) {
 			driver->hsic_ch = 0;
@@ -274,6 +275,7 @@
 		}
 	}
 
+	mutex_unlock(&driver->bridge_mutex);
 	return 0;
 }
 
@@ -284,6 +286,7 @@
 
 	pr_debug("diag: in %s\n", __func__);
 
+	mutex_lock(&driver->bridge_mutex);
 	/* If the usb cable is being connected */
 	if (process_cable) {
 		err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
@@ -301,6 +304,7 @@
 	} else if (driver->diag_smux_enabled) {
 		driver->in_busy_smux = 0;
 		diagfwd_connect_smux();
+		mutex_unlock(&driver->bridge_mutex);
 		return 0;
 	}
 
@@ -323,22 +327,24 @@
 		 * Turn on communication over usb mdm and hsic, if the hsic
 		 * device driver is enabled and opened
 		 */
-		if (driver->hsic_device_opened)
+		if (driver->hsic_device_opened) {
 			driver->hsic_ch = 1;
 
-		/* Poll USB mdm channel to check for data */
-		if (driver->logging_mode == USB_MODE)
-			queue_work(driver->diag_bridge_wq,
-					&driver->diag_read_mdm_work);
+			/* Poll USB mdm channel to check for data */
+			if (driver->logging_mode == USB_MODE)
+				queue_work(driver->diag_bridge_wq,
+						&driver->diag_read_mdm_work);
 
-		/* Poll HSIC channel to check for data */
-		queue_work(driver->diag_bridge_wq,
-				 &driver->diag_read_hsic_work);
+			/* Poll HSIC channel to check for data */
+			queue_work(driver->diag_bridge_wq,
+					 &driver->diag_read_hsic_work);
+		}
 	} else {
 		/* The hsic device driver has not yet been enabled */
 		pr_info("diag: HSIC channel not yet enabled\n");
 	}
 
+	mutex_unlock(&driver->bridge_mutex);
 	return 0;
 }
 
@@ -350,6 +356,8 @@
 {
 	pr_debug("diag: In %s, process_cable: %d\n", __func__, process_cable);
 
+	mutex_lock(&driver->bridge_mutex);
+
 	/* If the usb cable is being disconnected */
 	if (process_cable) {
 		driver->usb_mdm_connected = 0;
@@ -361,7 +369,7 @@
 		driver->in_busy_hsic_read_on_device = 1;
 		driver->in_busy_hsic_write = 1;
 		/* Turn off communication over usb mdm and hsic */
-		return diag_hsic_close();
+		diag_hsic_close();
 	} else if (driver->diag_smux_enabled &&
 		driver->logging_mode == USB_MODE) {
 		driver->in_busy_smux = 1;
@@ -370,6 +378,8 @@
 		/* Turn off communication over usb mdm and smux */
 		msm_smux_close(LCID_VALID);
 	}
+
+	mutex_unlock(&driver->bridge_mutex);
 	return 0;
 }
 
@@ -551,13 +561,15 @@
 {
 	int err = 0;
 	pr_debug("diag: in %s\n", __func__);
-	if (!driver->hsic_device_enabled) {
+	if (!driver->hsic_inited) {
 		diagmem_hsic_init(driver);
 		INIT_WORK(&(driver->diag_read_hsic_work),
 					 diag_read_hsic_work_fn);
-		driver->hsic_device_enabled = 1;
+		driver->hsic_inited = 1;
 	}
 
+	mutex_lock(&driver->bridge_mutex);
+
 	/*
 	 * The probe function was called after the usb was connected
 	 * on the legacy channel OR ODL is turned on. Communication over usb
@@ -565,11 +577,17 @@
 	 */
 	if (driver->usb_mdm_connected || (driver->logging_mode ==
 							 MEMORY_DEVICE_MODE)) {
-		/* The hsic (diag_bridge) platform device driver is enabled */
+		if (driver->hsic_device_opened) {
+			/* should not happen. close it before re-opening */
+			pr_warn("diag: HSIC channel already opened in probe\n");
+			diag_bridge_close();
+		}
+
 		err = diag_bridge_open(&hsic_diag_bridge_ops);
 		if (err) {
 			pr_err("diag: could not open HSIC, err: %d\n", err);
 			driver->hsic_device_opened = 0;
+			mutex_unlock(&driver->bridge_mutex);
 			return err;
 		}
 
@@ -591,13 +609,19 @@
 				 &driver->diag_read_hsic_work);
 	}
 
+	/* The hsic (diag_bridge) platform device driver is enabled */
+	driver->hsic_device_enabled = 1;
+	mutex_unlock(&driver->bridge_mutex);
 	return err;
 }
 
 static int diag_hsic_remove(struct platform_device *pdev)
 {
 	pr_debug("diag: %s called\n", __func__);
+	mutex_lock(&driver->bridge_mutex);
 	diag_hsic_close();
+	driver->hsic_device_enabled = 0;
+	mutex_unlock(&driver->bridge_mutex);
 	return 0;
 }
 
@@ -670,6 +694,7 @@
 	driver->itemsize_hsic_write = sizeof(struct diag_request);
 	driver->poolsize_hsic_write = N_MDM_WRITE;
 
+	mutex_init(&driver->bridge_mutex);
 #ifdef CONFIG_DIAG_OVER_USB
 	INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
 #endif
@@ -713,8 +738,9 @@
 	if (driver->hsic_device_enabled) {
 		diag_hsic_close();
 		driver->hsic_device_enabled = 0;
-		diagmem_exit(driver, POOL_TYPE_ALL);
 	}
+	driver->hsic_inited = 0;
+	diagmem_exit(driver, POOL_TYPE_ALL);
 	if (driver->diag_smux_enabled) {
 		driver->lcid = LCID_INVALID;
 		kfree(driver->buf_in_smux);
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index 82c47af..1a522d5 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -106,7 +106,7 @@
 			printk(KERN_ALERT "Unable to destroy STRUCT mempool");
 	}
 #ifdef CONFIG_DIAG_BRIDGE_CODE
-	if (driver->diag_hsic_pool && (driver->hsic_device_enabled == 0)) {
+	if (driver->diag_hsic_pool && (driver->hsic_inited == 0)) {
 		if (driver->count_hsic_pool == 0) {
 			mempool_destroy(driver->diag_hdlc_pool);
 			driver->diag_hdlc_pool = NULL;
@@ -114,8 +114,7 @@
 			pr_err("Unable to destroy HDLC mempool");
 	}
 
-	if (driver->diag_hsic_write_pool &&
-		(driver->hsic_device_enabled == 0)) {
+	if (driver->diag_hsic_write_pool && (driver->hsic_inited == 0)) {
 		/*
 		 * Free up struct pool ONLY if there are no outstanding
 		 * transactions(aggregation buffer) with USB
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/gpio/Kconfig b/drivers/gpio/Kconfig
index 03fdc5a..c799c1f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -556,7 +556,6 @@
 	  PMICs through RPC.
 
 config GPIO_QPNP_PIN
-	depends on ARCH_MSM8974
 	depends on SPMI
 	depends on OF_SPMI
 	depends on MSM_QPNP_INT
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 98254b5..7f760ed 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1391,8 +1391,10 @@
 				   sizeof(struct ion_fd_data)))
 			return -EFAULT;
 		data.handle = ion_import_dma_buf(client, data.fd);
-		if (IS_ERR(data.handle))
+		if (IS_ERR(data.handle)) {
+			ret = PTR_ERR(data.handle);
 			data.handle = NULL;
+		}
 		if (copy_to_user((void __user *)arg, &data,
 				 sizeof(struct ion_fd_data)))
 			return -EFAULT;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 1f32e54..2388fff 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1574,8 +1574,6 @@
 		return;
 	}
 
-	KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
-
 	cmds[0] = cp_nop_packet(1);
 	cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
@@ -1710,18 +1708,24 @@
 
 	if (status & CP_INT_CNTL__RB_INT_MASK) {
 		/* signal intr completion event */
-		unsigned int context_id;
-		kgsl_sharedmem_readl(&device->memstore,
-				&context_id,
+		unsigned int context_id, timestamp;
+		kgsl_sharedmem_readl(&device->memstore, &context_id,
 				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 					current_context));
+
+		kgsl_sharedmem_readl(&device->memstore, &timestamp,
+				KGSL_MEMSTORE_OFFSET(context_id,
+					eoptimestamp));
+
 		if (context_id < KGSL_MEMSTORE_MAX) {
 			kgsl_sharedmem_writel(&rb->device->memstore,
 					KGSL_MEMSTORE_OFFSET(context_id,
 						ts_cmp_enable), 0);
 			wmb();
 		}
-		KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
+
+		KGSL_CMD_WARN(device, "<%d:0x%x> ringbuffer interrupt\n",
+				context_id, timestamp);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
@@ -1743,7 +1747,6 @@
 	adreno_regwrite(device, REG_CP_INT_ACK, status);
 
 	if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
-		KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
 		queue_work(device->work_queue, &device->ts_expired_ws);
 		wake_up_interruptible_all(&device->wait_queue);
 		atomic_notifier_call_chain(&(device->ts_notifier_list),
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index d89e882..b8fca38 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2409,8 +2409,6 @@
 		return;
 	}
 
-	KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
-
 	cmds[0] = cp_nop_packet(1);
 	cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
@@ -2565,17 +2563,24 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 
 	if (irq == A3XX_INT_CP_RB_INT) {
-		unsigned int context_id;
+		unsigned int context_id, timestamp;
 		kgsl_sharedmem_readl(&device->memstore, &context_id,
 				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 					current_context));
+
+		kgsl_sharedmem_readl(&device->memstore, &timestamp,
+				KGSL_MEMSTORE_OFFSET(context_id,
+					eoptimestamp));
+
 		if (context_id < KGSL_MEMSTORE_MAX) {
 			kgsl_sharedmem_writel(&device->memstore,
 					KGSL_MEMSTORE_OFFSET(context_id,
 						ts_cmp_enable), 0);
 			wmb();
 		}
-		KGSL_CMD_WARN(device, "ringbuffer rb interrupt\n");
+
+		KGSL_CMD_WARN(device, "<%d:0x%x> ringbuffer interrupt\n",
+				context_id, timestamp);
 	}
 
 	wake_up_interruptible_all(&device->wait_queue);
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b51342f..70ad81c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -288,8 +288,10 @@
 		return;
 	}
 
-	KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
-			adreno_dev->drawctxt_active, drawctxt, flags);
+	KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
+		adreno_dev->drawctxt_active ?
+		adreno_dev->drawctxt_active->id : 0,
+		drawctxt ? drawctxt->id : 0, flags);
 
 	/* Save the old context */
 	adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 620b82c..daa78ed 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -50,6 +50,7 @@
 	{CP_DRAW_INDX,			"DRW_NDX_"},
 	{CP_DRAW_INDX_BIN,		"DRW_NDXB"},
 	{CP_EVENT_WRITE,		"EVENT_WT"},
+	{CP_MEM_WRITE,			"MEM_WRIT"},
 	{CP_IM_LOAD,			"IN__LOAD"},
 	{CP_IM_LOAD_IMMEDIATE,		"IM_LOADI"},
 	{CP_IM_STORE,			"IM_STORE"},
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index db913a5..1ff219b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -969,8 +969,8 @@
 					drawctxt, 0,
 					&link[0], (cmds - link));
 
-	KGSL_CMD_INFO(device, "ctxt %d g %08x numibs %d ts %d\n",
-		context->id, (unsigned int)ibdesc, numibs, *timestamp);
+	KGSL_CMD_INFO(device, "<%d:0x%x> g %08x numibs %d\n",
+		context->id, *timestamp, (unsigned int)ibdesc, numibs);
 
 	kfree(link);
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index f630f2a..21227a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1107,9 +1107,6 @@
 	}
 
 	if (param->flags & KGSL_CONTEXT_SUBMIT_IB_LIST) {
-		KGSL_DRV_INFO(dev_priv->device,
-			"Using IB list mode for ib submission, numibs: %d\n",
-			param->numibs);
 		if (!param->numibs) {
 			KGSL_DRV_ERR(dev_priv->device,
 				"Invalid numibs as parameter: %d\n",
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index 3969319..56b8841 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -102,8 +102,6 @@
 #define EPM_PSOC_BUFFERED_DATA_LENGTH			48
 #define EPM_PSOC_BUFFERED_DATA_LENGTH2			54
 
-#define EPM_SPI_NOR_CS_N_GPIO		53
-
 struct epm_adc_drv {
 	struct platform_device		*pdev;
 	struct device			*hwmon;
@@ -172,14 +170,6 @@
 {
 	int rc = 0;
 
-	rc = gpio_request(EPM_SPI_NOR_CS_N_GPIO, "SPI_NOR_CS_N");
-	if (!rc)
-		gpio_direction_output(EPM_SPI_NOR_CS_N_GPIO, 1);
-	else {
-		pr_err("Configure spi nor Failed\n");
-		return -EINVAL;
-	}
-
 	if (epm_adc_first_request) {
 		rc = gpio_request(GPIO_EPM_GLOBAL_ENABLE, "EPM_GLOBAL_EN");
 		if (!rc) {
@@ -521,27 +511,27 @@
 	struct epm_adc_platform_data *pdata = epm_adc->pdev->dev.platform_data;
 	uint32_t chan_idx = (conv->device_idx * pdata->chan_per_adc) +
 					conv->channel_idx;
-	int64_t *adc_scaled_data = 0;
+	int64_t adc_scaled_data = 0;
 
 	/* Get the channel number */
 	channel_num = (adc_raw_data[0] & EPM_ADC_ADS_CHANNEL_DATA_CHID);
 	sign_bit    = 1;
 	/* This is the 16-bit raw data */
-	*adc_scaled_data = ((adc_raw_data[1] << 8) | adc_raw_data[2]);
+	adc_scaled_data = ((adc_raw_data[1] << 8) | adc_raw_data[2]);
 	/* Obtain the internal system reading */
 	if (channel_num == EPM_ADC_ADS_CHANNEL_VCC) {
-		*adc_scaled_data *= EPM_ADC_SCALE_MILLI;
-		do_div(*adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
+		adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+		do_div(adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
 	} else if (channel_num == EPM_ADC_ADS_CHANNEL_GAIN) {
-		do_div(*adc_scaled_data, EPM_ADC_SCALE_CODE_GAIN);
+		do_div(adc_scaled_data, EPM_ADC_SCALE_CODE_GAIN);
 	} else if (channel_num == EPM_ADC_ADS_CHANNEL_REF) {
-		*adc_scaled_data *= EPM_ADC_SCALE_MILLI;
-		do_div(*adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
+		adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+		do_div(adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
 	} else if (channel_num == EPM_ADC_ADS_CHANNEL_TEMP) {
 		/* Convert Code to micro-volts */
 		/* Use this formula to get the temperature reading */
-		*adc_scaled_data -= EPM_ADC_TEMP_TO_DEGC_COEFF;
-		do_div(*adc_scaled_data, EPM_ADC_TEMP_SENSOR_COEFF);
+		adc_scaled_data -= EPM_ADC_TEMP_TO_DEGC_COEFF;
+		do_div(adc_scaled_data, EPM_ADC_TEMP_SENSOR_COEFF);
 	} else if (channel_num == EPM_ADC_ADS_CHANNEL_OFFSET) {
 		/* The offset should be zero */
 		pr_debug("%s: ADC Channel Offset\n", __func__);
@@ -553,31 +543,31 @@
 		 * mvVRef is in milli-volts and resistorvalue is in micro-ohms.
 		 * Hence, I = V/R gives us current in kilo-amps.
 		 */
-		if (*adc_scaled_data & EPM_ADC_MAX_NEGATIVE_SCALE_CODE) {
+		if (adc_scaled_data & EPM_ADC_MAX_NEGATIVE_SCALE_CODE) {
 			sign_bit = -1;
-			*adc_scaled_data = (~*adc_scaled_data
+			adc_scaled_data = (~adc_scaled_data
 				& EPM_ADC_NEG_LSB_CODE);
 		}
-		if (*adc_scaled_data != 0) {
-			*adc_scaled_data *= EPM_ADC_SCALE_FACTOR;
+		if (adc_scaled_data != 0) {
+			adc_scaled_data *= EPM_ADC_SCALE_FACTOR;
 			 /* Device is calibrated for 1LSB = VREF/7800h.*/
-			*adc_scaled_data *= EPM_ADC_MILLI_VOLTS_SOURCE;
-			do_div(*adc_scaled_data, EPM_ADC_VREF_CODE);
+			adc_scaled_data *= EPM_ADC_MILLI_VOLTS_SOURCE;
+			do_div(adc_scaled_data, EPM_ADC_VREF_CODE);
 			 /* Data will now be in micro-volts.*/
-			*adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+			adc_scaled_data *= EPM_ADC_SCALE_MILLI;
 			 /* Divide by amplifier gain value.*/
-			do_div(*adc_scaled_data, pdata->channel[chan_idx].gain);
+			do_div(adc_scaled_data, pdata->channel[chan_idx].gain);
 			 /* Data will now be in nano-volts.*/
-			do_div(*adc_scaled_data, EPM_ADC_SCALE_FACTOR);
-			*adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+			do_div(adc_scaled_data, EPM_ADC_SCALE_FACTOR);
+			adc_scaled_data *= EPM_ADC_SCALE_MILLI;
 			 /* Data is now in micro-amps.*/
-			do_div(*adc_scaled_data,
+			do_div(adc_scaled_data,
 				pdata->channel[chan_idx].resistorvalue);
 			 /* Set the sign bit for lekage current. */
-			*adc_scaled_data *= sign_bit;
+			adc_scaled_data *= sign_bit;
 		}
 	}
-	conv->physical = (int32_t) *adc_scaled_data;
+	conv->physical = (int32_t) adc_scaled_data;
 
 	return 0;
 }
@@ -1600,16 +1590,15 @@
 	struct device_node *node = spi->dev.of_node;
 	int rc = 0;
 
-	if (!node) {
-		dev_err(&spi->dev, "no platform data?\n");
-		pr_info("Error in the probe\n");
-		return -EINVAL;
-	}
-
 	if (node)
 		rc = get_device_tree_data(spi);
-	else
-		return -ENODEV;
+	else {
+		epm_adc = epm_adc_drv;
+		epm_adc_drv->epm_spi_client = spi;
+		epm_adc_drv->epm_spi_client->bits_per_word =
+				EPM_ADC_ADS_SPI_BITS_PER_WORD;
+		return rc;
+	}
 
 	epm_adc = epm_adc_drv;
 	epm_adc->misc.name = EPM_ADC_DRIVER_NAME;
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/media/video/msm/io/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
index 9549dcc..d508c1d 100644
--- a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
+++ b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
@@ -139,11 +139,11 @@
 	switch (perf_setting) {
 	case S_INIT:
 		add_axi_qos();
-		break;
-	case S_PREVIEW:
 		update_axi_qos(MSM_AXI_QOS_PREVIEW);
 		axi_allocate(AXI_FLOW_VIEWFINDER_HI);
 		break;
+	case S_PREVIEW:
+		break;
 	case S_VIDEO:
 		update_axi_qos(MSM_AXI_QOS_RECORDING);
 		break;
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 2613986..1e17c5c 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -555,6 +555,7 @@
 	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC:
 	case CMD_AXI_START:
 	case CMD_AXI_STOP:
+	case CMD_AXI_RESET:
 	case CMD_AXI_CFG_TERT1:
 	case CMD_AXI_CFG_TERT2:
 		/* Dont need to pass buffer information.
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index eb6a8b0..f6cf427 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -23,6 +23,8 @@
 
 static struct msm_camera_i2c_reg_conf ov5647_start_settings[] = {
 	{0x4202, 0x00},  /* streaming on */
+	{0x0100, 0x01},
+	{0x4800, 0x04},
 };
 
 static struct msm_camera_i2c_reg_conf ov5647_stop_settings[] = {
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index bb9a9b7..b78e20d 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1643,6 +1643,10 @@
 
 		rp = (struct msm_vfe_resp *)arg;
 		frame_info = rp->evt_msg.data;
+		if (!frame_info) {
+			interface = PIX_0;
+			break;
+		}
 		if (frame_info->inst_handle) {
 			vnode_id = GET_DEVID_MODE(frame_info->inst_handle);
 			if (vnode_id < MAX_NUM_ACTIVE_CAMERA &&
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 15c38af..9deae65 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -1561,6 +1561,11 @@
 	}
 		return 0;
 
+	case CMD_AXI_START:
+	case CMD_AXI_STOP:
+	case CMD_AXI_RESET:
+		return 0;
+
 	case CMD_CONFIG_FREE_BUF_ADDR: {
 		int path = *((int *)cmd->value);
 		struct buf_info *outch = vfe2x_get_ch(path);
@@ -1853,9 +1858,6 @@
 						flags);
 				if (op_mode & SNAPSHOT_MASK_MODE) {
 					vfe2x_ctrl->stop_pending = 0;
-					vfe2x_send_isp_msg(vfe2x_ctrl,
-						msgs_map[MSG_STOP_ACK].
-						isp_id);
 					spin_unlock_irqrestore(
 							&vfe2x_ctrl->table_lock,
 							flags);
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 170322c..a4c4b83 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -31,7 +31,6 @@
 #include "msm_smem.h"
 
 #define BASE_DEVICE_NUMBER 32
-#define MAX_EVENTS 30
 #define SHARED_QSIZE 0x1000000
 
 static struct msm_bus_vectors enc_ocmem_init_vectors[]  = {
@@ -451,7 +450,7 @@
 };
 
 struct msm_v4l2_vid_inst {
-	struct msm_vidc_inst vidc_inst;
+	struct msm_vidc_inst *vidc_inst;
 	void *mem_client;
 	struct list_head registered_bufs;
 };
@@ -468,22 +467,7 @@
 	struct msm_vidc_inst *vidc_inst;
 	vidc_inst = container_of(filp->private_data,
 			struct msm_vidc_inst, event_handler);
-	return container_of((void *)vidc_inst,
-			struct msm_v4l2_vid_inst, vidc_inst);
-}
-
-static int msm_vidc_v4l2_setup_event_queue(void *inst,
-				struct video_device *pvdev)
-{
-	int rc = 0;
-	struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
-	spin_lock_init(&pvdev->fh_lock);
-	INIT_LIST_HEAD(&pvdev->fh_list);
-
-	v4l2_fh_init(&vidc_inst->event_handler, pvdev);
-	v4l2_fh_add(&vidc_inst->event_handler);
-
-	return rc;
+	return (struct msm_v4l2_vid_inst *)vidc_inst->priv;
 }
 
 struct buffer_info *get_registered_buf(struct list_head *list,
@@ -556,7 +540,8 @@
 		rc = -ENOMEM;
 		goto fail_mem_client;
 	}
-	rc = msm_vidc_open(&v4l2_inst->vidc_inst, core->id, vid_dev->type);
+
+	v4l2_inst->vidc_inst = msm_vidc_open(core->id, vid_dev->type);
 	if (rc) {
 		dprintk(VIDC_ERR,
 		"Failed to create video instance, core: %d, type = %d\n",
@@ -565,9 +550,9 @@
 		goto fail_open;
 	}
 	INIT_LIST_HEAD(&v4l2_inst->registered_bufs);
-	rc = msm_vidc_v4l2_setup_event_queue(&v4l2_inst->vidc_inst, vdev);
+	v4l2_inst->vidc_inst->priv = v4l2_inst;
 	clear_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags);
-	filp->private_data = &(v4l2_inst->vidc_inst.event_handler);
+	filp->private_data = &(v4l2_inst->vidc_inst->event_handler);
 	return rc;
 fail_open:
 	msm_smem_delete_client(v4l2_inst->mem_client);
@@ -667,7 +652,7 @@
 					buffer_info.m.planes[0].reserved[0],
 					buffer_info.m.planes[0].reserved[1],
 					buffer_info.m.planes[0].length);
-				rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
+				rc = msm_vidc_release_buf(v4l2_inst->vidc_inst,
 					&buffer_info);
 				list_del(&bi->list);
 				if (bi->handle)
@@ -752,7 +737,7 @@
 		list_add_tail(&binfo->list, &v4l2_inst->registered_bufs);
 		b->m.planes[i].m.userptr = binfo->device_addr;
 	}
-	rc = msm_vidc_prepare_buf(&v4l2_inst->vidc_inst, b);
+	rc = msm_vidc_prepare_buf(v4l2_inst->vidc_inst, b);
 exit:
 	return rc;
 }
@@ -794,7 +779,7 @@
 			}
 		}
 	}
-	rc = msm_vidc_qbuf(&v4l2_inst->vidc_inst, b);
+	rc = msm_vidc_qbuf(v4l2_inst->vidc_inst, b);
 err_invalid_buff:
 	return rc;
 }
@@ -823,17 +808,17 @@
 static int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
 				struct v4l2_event_subscription *sub)
 {
-	int rc = 0;
-	rc = v4l2_event_subscribe(fh, sub, MAX_EVENTS);
-	return rc;
+	struct msm_vidc_inst *vidc_inst = container_of(fh,
+			struct msm_vidc_inst, event_handler);
+	return msm_vidc_subscribe_event((void *)vidc_inst, sub);
 }
 
 static int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
 				struct v4l2_event_subscription *sub)
 {
-	int rc = 0;
-	rc = v4l2_event_unsubscribe(fh, sub);
-	return rc;
+	struct msm_vidc_inst *vidc_inst = container_of(fh,
+			struct msm_vidc_inst, event_handler);
+	return msm_vidc_unsubscribe_event((void *)vidc_inst, sub);
 }
 
 static int msm_v4l2_decoder_cmd(struct file *file, void *fh,
@@ -936,7 +921,7 @@
 	struct msm_iova_layout layout;
 	int rc = 0;
 	int i;
-	struct iommu_info *io_map = core->resources.io_map;
+	struct msm_vidc_iommu_info *io_map = core->resources.io_map;
 	strlcpy(io_map[CP_MAP].name, "vidc-cp-map",
 			sizeof(io_map[CP_MAP].name));
 	strlcpy(io_map[CP_MAP].ctx, "venus_cp",
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 8240890..be2e848 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -229,6 +229,14 @@
 		.type = OUTPUT_PORT,
 	},
 	{
+		.name = "VC1 SP",
+		.description = "VC-1 compressed format G",
+		.fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+		.num_planes = 1,
+		.get_frame_size = get_frame_size_compressed,
+		.type = OUTPUT_PORT,
+	},
+	{
 		.name = "H264",
 		.description = "H264 compressed format",
 		.fourcc = V4L2_PIX_FMT_H264,
@@ -524,6 +532,8 @@
 			goto err_invalid_fmt;
 		}
 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		inst->prop.width = f->fmt.pix_mp.width;
+		inst->prop.height = f->fmt.pix_mp.height;
 		fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
 			ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
 			OUTPUT_PORT);
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 449dab2..ec9dac8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <media/msm_vidc.h>
 #include "msm_vidc_internal.h"
@@ -21,21 +22,21 @@
 #include "msm_smem.h"
 #include <linux/delay.h>
 
-int msm_vidc_poll(void *instance, struct file *filp,
-		struct poll_table_struct *wait)
+#define MAX_EVENTS 30
+
+static int get_poll_flags(void *instance)
 {
-	int rc = 0;
 	struct msm_vidc_inst *inst = instance;
 	struct vb2_queue *outq = &inst->vb2_bufq[OUTPUT_PORT];
 	struct vb2_queue *capq = &inst->vb2_bufq[CAPTURE_PORT];
 	struct vb2_buffer *out_vb = NULL;
 	struct vb2_buffer *cap_vb = NULL;
 	unsigned long flags;
-	poll_wait(filp, &inst->event_handler.wait, wait);
-	poll_wait(filp, &capq->done_wq, wait);
-	poll_wait(filp, &outq->done_wq, wait);
+	int rc = 0;
+
 	if (v4l2_event_pending(&inst->event_handler))
 		rc |= POLLPRI;
+
 	spin_lock_irqsave(&capq->done_lock, flags);
 	if (!list_empty(&capq->done_list))
 		cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer,
@@ -44,6 +45,7 @@
 				|| cap_vb->state == VB2_BUF_STATE_ERROR))
 		rc |= POLLIN | POLLRDNORM;
 	spin_unlock_irqrestore(&capq->done_lock, flags);
+
 	spin_lock_irqsave(&outq->done_lock, flags);
 	if (!list_empty(&outq->done_list))
 		out_vb = list_first_entry(&outq->done_list, struct vb2_buffer,
@@ -52,12 +54,55 @@
 				|| out_vb->state == VB2_BUF_STATE_ERROR))
 		rc |= POLLOUT | POLLWRNORM;
 	spin_unlock_irqrestore(&outq->done_lock, flags);
+
 	return rc;
 }
 
+int msm_vidc_poll(void *instance, struct file *filp,
+		struct poll_table_struct *wait)
+{
+	struct msm_vidc_inst *inst = instance;
+	struct vb2_queue *outq = &inst->vb2_bufq[OUTPUT_PORT];
+	struct vb2_queue *capq = &inst->vb2_bufq[CAPTURE_PORT];
+
+	poll_wait(filp, &inst->event_handler.wait, wait);
+	poll_wait(filp, &capq->done_wq, wait);
+	poll_wait(filp, &outq->done_wq, wait);
+	return get_poll_flags(inst);
+}
+
+/* Kernel client alternative for msm_vidc_poll */
+int msm_vidc_wait(void *instance)
+{
+	struct msm_vidc_inst *inst = instance;
+	int rc = 0;
+
+	wait_event(inst->kernel_event_queue, (rc = get_poll_flags(inst)));
+	return rc;
+}
+
+int msm_vidc_get_iommu_maps(void *instance,
+		struct msm_vidc_iommu_info maps[MAX_MAP])
+{
+	struct msm_vidc_inst *inst = instance;
+	int c = 0;
+
+	if (!inst || !maps)
+		return -EINVAL;
+
+	for (c = 0; c < MAX_MAP; ++c)
+		maps[c] = inst->core->resources.io_map[c];
+
+	return 0;
+}
+
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !cap)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_querycap(instance, cap);
 	else if (inst->session_type == MSM_VIDC_ENCODER)
@@ -67,6 +112,10 @@
 int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !f)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_enum_fmt(instance, f);
 	else if (inst->session_type == MSM_VIDC_ENCODER)
@@ -76,6 +125,10 @@
 int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !f)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_s_fmt(instance, f);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -85,6 +138,10 @@
 int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !f)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_g_fmt(instance, f);
 	else if (inst->session_type == MSM_VIDC_ENCODER)
@@ -94,6 +151,10 @@
 int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !control)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_s_ctrl(instance, control);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -103,6 +164,10 @@
 int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !control)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_g_ctrl(instance, control);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -112,6 +177,10 @@
 int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !b)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_reqbufs(instance, b);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -122,6 +191,10 @@
 int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !b)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_prepare_buf(instance, b);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -132,6 +205,10 @@
 int msm_vidc_release_buf(void *instance, struct v4l2_buffer *b)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !b)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_release_buf(instance, b);
 	return -EINVAL;
@@ -156,6 +233,10 @@
 int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !b)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_qbuf(instance, b);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -166,6 +247,10 @@
 int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !b)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_dqbuf(instance, b);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -176,6 +261,10 @@
 int msm_vidc_streamon(void *instance, enum v4l2_buf_type i)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_streamon(instance, i);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -186,6 +275,10 @@
 int msm_vidc_streamoff(void *instance, enum v4l2_buf_type i)
 {
 	struct msm_vidc_inst *inst = instance;
+
+	if (!inst)
+		return -EINVAL;
+
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_streamoff(instance, i);
 	if (inst->session_type == MSM_VIDC_ENCODER)
@@ -193,13 +286,13 @@
 	return -EINVAL;
 }
 
-void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+static void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 				unsigned long size, int write)
 {
 	return (void *)0xdeadbeef;
 }
 
-void vidc_put_userptr(void *buf_priv)
+static void vidc_put_userptr(void *buf_priv)
 {
 }
 
@@ -232,9 +325,60 @@
 	return vb2_queue_init(q);
 }
 
-int msm_vidc_open(void *vidc_inst, int core_id, int session_type)
+static int setup_event_queue(void *inst,
+				struct video_device *pvdev)
 {
-	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)vidc_inst;
+	int rc = 0;
+	struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+	spin_lock_init(&pvdev->fh_lock);
+	INIT_LIST_HEAD(&pvdev->fh_list);
+
+	v4l2_fh_init(&vidc_inst->event_handler, pvdev);
+	v4l2_fh_add(&vidc_inst->event_handler);
+
+	return rc;
+}
+
+int msm_vidc_subscribe_event(void *inst, struct v4l2_event_subscription *sub)
+{
+	int rc = 0;
+	struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+
+	if (!inst || !sub)
+		return -EINVAL;
+
+	rc = v4l2_event_subscribe(&vidc_inst->event_handler, sub, MAX_EVENTS);
+	return rc;
+}
+
+
+int msm_vidc_unsubscribe_event(void *inst, struct v4l2_event_subscription *sub)
+{
+	int rc = 0;
+	struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+
+	if (!inst || !sub)
+		return -EINVAL;
+
+	rc = v4l2_event_unsubscribe(&vidc_inst->event_handler, sub);
+	return rc;
+}
+
+int msm_vidc_dqevent(void *inst, struct v4l2_event *event)
+{
+	int rc = 0;
+	struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+
+	if (!inst || !event)
+		return -EINVAL;
+
+	rc = v4l2_event_dequeue(&vidc_inst->event_handler, event, false);
+	return rc;
+}
+
+void *msm_vidc_open(int core_id, int session_type)
+{
+	struct msm_vidc_inst *inst = NULL;
 	struct msm_vidc_core *core = NULL;
 	unsigned long flags;
 	int rc = 0;
@@ -252,14 +396,23 @@
 		goto err_invalid_core;
 	}
 
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst) {
+		pr_err("Failed to allocate memory\n")	;
+		rc = -ENOMEM;
+		goto err_invalid_core;
+	}
+
 	mutex_init(&inst->sync_lock);
 	spin_lock_init(&inst->lock);
 	inst->session_type = session_type;
 	INIT_LIST_HEAD(&inst->pendingq);
 	INIT_LIST_HEAD(&inst->internalbufs);
 	INIT_LIST_HEAD(&inst->persistbufs);
+	init_waitqueue_head(&inst->kernel_event_queue);
 	inst->state = MSM_VIDC_CORE_UNINIT_DONE;
 	inst->core = core;
+
 	for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
 		i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) {
 		init_completion(&inst->completions[i]);
@@ -276,6 +429,7 @@
 		msm_venc_inst_init(inst);
 		msm_venc_ctrl_init(inst);
 	}
+
 	rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 			session_type);
 	if (rc) {
@@ -298,17 +452,20 @@
 	}
 	inst->debugfs_root =
 		msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
+
+	setup_event_queue(inst, &core->vdev[core_id].vdev);
+
 	spin_lock_irqsave(&core->lock, flags);
 	list_add_tail(&inst->list, &core->instances);
 	spin_unlock_irqrestore(&core->lock, flags);
-	return rc;
+	return inst;
 fail_init:
 	msm_smem_delete_client(inst->mem_client);
 fail_mem_client:
 	kfree(inst);
 	inst = NULL;
 err_invalid_core:
-	return rc;
+	return inst;
 }
 
 static void cleanup_instance(struct msm_vidc_inst *inst)
@@ -360,6 +517,10 @@
 	struct msm_vidc_core *core;
 	struct list_head *ptr, *next;
 	int rc = 0;
+
+	if (!inst)
+		return -EINVAL;
+
 	core = inst->core;
 	mutex_lock(&core->sync_lock);
 	list_for_each_safe(ptr, next, &core->instances) {
@@ -373,6 +534,7 @@
 		dprintk(VIDC_ERR,
 			"Failed to move video instance to uninit state\n");
 	cleanup_instance(inst);
+	kfree(inst);
 	dprintk(VIDC_DBG, "Closed the instance\n");
 	return 0;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 5b83cfb..7f3096a 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -166,7 +166,7 @@
 	int rc;
 	struct iommu_domain *domain;
 	int i;
-	struct iommu_info *io_map;
+	struct msm_vidc_iommu_info *io_map;
 	struct device *dev;
 	for (i = 0; i < MAX_MAP; i++) {
 		io_map = &core->resources.io_map[i];
@@ -202,7 +202,7 @@
 {
 	struct device *dev;
 	struct iommu_domain *domain;
-	struct iommu_info *io_map;
+	struct msm_vidc_iommu_info *io_map;
 	int i;
 	if (!core) {
 		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
@@ -408,6 +408,7 @@
 		inst->reconfig_width = event_notify->width;
 		inst->in_reconfig = true;
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+		wake_up(&inst->kernel_event_queue);
 		return;
 	} else {
 		dprintk(VIDC_ERR,
@@ -501,6 +502,7 @@
 		dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
 		dqevent.id = 0;
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+		wake_up(&inst->kernel_event_queue);
 	} else {
 		dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
 	}
@@ -518,6 +520,7 @@
 		dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
 		dqevent.id = 0;
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+		wake_up(&inst->kernel_event_queue);
 	} else {
 		dprintk(VIDC_ERR,
 			"Failed to get valid response for session close\n");
@@ -552,13 +555,17 @@
 {
 	struct msm_vidc_cb_data_done *response = data;
 	struct vb2_buffer *vb;
+	struct msm_vidc_inst *inst;
 	if (!response) {
 		dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
 		return;
 	}
 	vb = response->clnt_data;
-	if (vb)
+	inst = (struct msm_vidc_inst *)response->session_id;
+	if (vb) {
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+		wake_up(&inst->kernel_event_queue);
+	}
 }
 
 static void handle_fbd(enum command_response cmd, void *data)
@@ -622,6 +629,7 @@
 				vb->v4l2_planes[0].bytesused,
 				vb->v4l2_buf.flags);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+		wake_up(&inst->kernel_event_queue);
 	} else {
 		/*
 		 * FIXME:
@@ -737,7 +745,7 @@
 		dprintk(VIDC_ERR, "Invalid args: %p\n", core);
 		return -EINVAL;
 	}
-	num_mbs_per_sec = 2 * msm_comm_get_load(core, MSM_VIDC_ENCODER);
+	num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER);
 	num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER);
 	dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec);
 	rc = clk_set_rate(core->resources.clock[VCODEC_CLK].clk,
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 55aec74..1f2eff8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/clk.h>
+#include <linux/wait.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
 #include <mach/ocmem.h>
@@ -141,20 +142,6 @@
 	void *cookie;
 };
 
-struct iommu_info {
-	u32 addr_range[2];
-	char name[MAX_NAME_LENGTH];
-	char ctx[MAX_NAME_LENGTH];
-	int domain;
-	int partition;
-};
-
-enum io_maps {
-	CP_MAP,
-	NS_MAP,
-	MAX_MAP
-};
-
 enum vidc_clocks {
 	VCODEC_CLK,
 	VCODEC_AHB_CLK,
@@ -188,7 +175,7 @@
 
 struct msm_vidc_resources {
 	struct msm_vidc_fw fw;
-	struct iommu_info io_map[MAX_MAP];
+	struct msm_vidc_iommu_info io_map[MAX_MAP];
 	struct core_clock clock[VCODEC_MAX_CLKS];
 	struct vidc_bus_info bus_info;
 	struct on_chip_mem ocmem;
@@ -240,6 +227,7 @@
 	struct completion completions[SESSION_MSG_END - SESSION_MSG_START + 1];
 	struct v4l2_fh event_handler;
 	struct msm_smem *extradata_handle;
+	wait_queue_head_t kernel_event_queue;
 	bool in_reconfig;
 	u32 reconfig_width;
 	u32 reconfig_height;
@@ -247,6 +235,7 @@
 	u32 ftb_count;
 	u32 fbd_count;
 	struct vb2_buffer *vb2_seq_hdr;
+	void *priv;
 };
 
 extern struct msm_vidc_drv *vidc_driver;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 12ba874..0639dea 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -608,6 +608,9 @@
 
 static void set_vbif_registers(struct hal_device *device)
 {
+	/*Disable Dynamic clock gating for Venus VBIF*/
+	write_register(device->hal_data->register_base_addr,
+				   VIDC_VENUS_VBIF_CLK_ON, 1, 0);
 	write_register(device->hal_data->register_base_addr,
 			VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00000FFF, 0);
 	write_register(device->hal_data->register_base_addr,
@@ -636,6 +639,8 @@
 			VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
 	write_register(device->hal_data->register_base_addr,
 			VIDC_VBIF_ARB_CTL, 0x00000030, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
 }
 
 int vidc_hal_core_init(void *device, int domain)
@@ -654,10 +659,6 @@
 	INIT_LIST_HEAD(&dev->sess_head);
 	spin_lock_init(&dev->read_lock);
 	spin_lock_init(&dev->write_lock);
-
-	/*Disable Dynamic clock gating for Venus VBIF*/
-	write_register(dev->hal_data->register_base_addr,
-				   VIDC_VENUS_VBIF_CLK_ON, 1, 0);
 	set_vbif_registers(dev);
 	if (!dev->hal_client) {
 		dev->hal_client = msm_smem_new_client(SMEM_ION);
diff --git a/drivers/media/video/msm_vidc/vidc_hal_io.h b/drivers/media/video/msm_vidc/vidc_hal_io.h
index c4b1e0c..b85e015 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_io.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_io.h
@@ -124,9 +124,9 @@
 #define VIDC_VBIF_AT_NEW_BASE           (VIDC_VBIF_BASE_OFFS + 0xC10)
 #define VIDC_VBIF_AT_NEW_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC18)
 
-#define VIDC_VENUS0_VENUS_WRAPPER_VBIF_REQ_PRIORITY \
+#define VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY \
 	(VIDC_WRAPPER_BASE_OFFS + 0x20)
-#define VIDC_VENUS0_VENUS_WRAPPER_VBIF_PRIORITY_LEVEL \
+#define VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL \
 	(VIDC_WRAPPER_BASE_OFFS + 0x24)
 #define VIDC_VENUS_VBIF_REQ_PRIORITY    (VIDC_WRAPPER_BASE_OFFS + 0x20)
 #define VIDC_VENUS_VBIF_PRIORITY_LEVEL  (VIDC_WRAPPER_BASE_OFFS + 0x24)
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 28abb36..48532e5 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -340,6 +340,7 @@
 		return -EINVAL;
 	}
 
+	vb->v4l2_buf.timestamp = b->timestamp;
 	list_add_tail(&vb->queued_entry, &q->queued_list);
 	vb->state = VB2_BUF_STATE_QUEUED;
 
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 78e108f..5ae362f 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -122,6 +122,17 @@
 	return 0;
 }
 
+static struct timeval interpolate_ts(struct timeval tv, uint32_t delta)
+{
+	if (tv.tv_usec < delta) {
+		tv.tv_sec--;
+		tv.tv_usec += VCAP_USEC - delta;
+	} else {
+		tv.tv_usec -= delta;
+	}
+	return tv;
+}
+
 irqreturn_t vc_handler(struct vcap_dev *dev)
 {
 	uint32_t irq, timestamp;
@@ -212,6 +223,20 @@
 
 	/* If here we know which buffers are done */
 	timestamp = readl_relaxed(VCAP_VC_TIMESTAMP);
+	if (timestamp < c_data->vc_action.last_ts) {
+		c_data->vc_action.vc_ts.tv_usec +=
+			(0xFFFFFFFF - c_data->vc_action.last_ts) +
+			timestamp + 1;
+	} else {
+		c_data->vc_action.vc_ts.tv_usec +=
+			timestamp - c_data->vc_action.last_ts;
+	}
+
+	c_data->vc_action.vc_ts.tv_sec +=
+		c_data->vc_action.vc_ts.tv_usec / VCAP_USEC;
+	c_data->vc_action.vc_ts.tv_usec =
+		c_data->vc_action.vc_ts.tv_usec % VCAP_USEC;
+	c_data->vc_action.last_ts = timestamp;
 
 	c_data->vc_action.buf_num = (buf_num + done_count) % tot;
 	for (i = 0; i < done_count; i++) {
@@ -232,9 +257,10 @@
 		/* Config vc with this new buffer */
 		config_buffer(c_data, buf, VCAP_VC_Y_ADDR_1 + 0x8 * idx,
 				VCAP_VC_C_ADDR_1 + 0x8 * idx);
-		vb->v4l2_buf.timestamp.tv_usec = timestamp -
+		vb->v4l2_buf.timestamp = interpolate_ts(
+			c_data->vc_action.vc_ts,
 			1000000 / c_data->vc_format.frame_rate *
-			(done_count - 1 - i);
+			(done_count - 1 - i));
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 		work_todo = true;
 		c_data->vc_action.buf[idx] = buf;
@@ -298,6 +324,12 @@
 			VCAP_VC_C_ADDR_1 + i * 8);
 	}
 
+	c_data->vc_action.last_ts = readl_relaxed(VCAP_VC_TIMESTAMP);
+	c_data->vc_action.vc_ts.tv_sec =
+		c_data->vc_action.last_ts / VCAP_USEC;
+	c_data->vc_action.vc_ts.tv_usec =
+		c_data->vc_action.last_ts % VCAP_USEC;
+
 	rc = 0;
 	for (i = 0; i < c_data->vc_action.tot_buf; i++)
 		rc = rc << 1 | 0x2;
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 139de28..c81206f 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -233,6 +233,10 @@
 			queue_work(dev->vcap_wq, &dev->vp_to_vc_work.work);
 	}
 
+	if (vp_act->bufT0 != NULL && vp_act->vp_state == VP_NORMAL) {
+		vp_act->bufOut->vb.v4l2_buf.timestamp =
+			vp_act->bufT0->vb.v4l2_buf.timestamp;
+	}
 	vb2_buffer_done(&vp_act->bufOut->vb, VB2_BUF_STATE_DONE);
 
 	/* Cycle to next state */
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 52fd5e8..b153b27 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -5798,6 +5798,7 @@
 	mmc->caps2 |= MMC_CAP2_PACKED_WR_CONTROL;
 	mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC | MMC_CAP2_DETECT_ON_ERR);
 	mmc->caps2 |= MMC_CAP2_SANITIZE;
+	mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
 
 	if (plat->nonremovable)
 		mmc->caps |= MMC_CAP_NONREMOVABLE;
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 996456f..33b12ae 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -35,6 +35,7 @@
 #define QPNP_PON_RESIN_S1_TIMER(base)	(base + 0x44)
 #define QPNP_PON_RESIN_S2_TIMER(base)	(base + 0x45)
 #define QPNP_PON_RESIN_S2_CNTL(base)	(base + 0x46)
+#define QPNP_PON_PS_HOLD_RST_CTL(base)	(base + 0x5A)
 
 #define QPNP_PON_RESIN_PULL_UP		BIT(0)
 #define QPNP_PON_KPDPWR_PULL_UP		BIT(1)
@@ -50,6 +51,10 @@
 #define QPNP_PON_RESIN_N_SET		BIT(1)
 #define QPNP_PON_RESIN_BARK_N_SET	BIT(4)
 
+#define QPNP_PON_RESET_EN		BIT(7)
+#define QPNP_PON_WARM_RESET		BIT(0)
+#define QPNP_PON_SHUTDOWN		BIT(2)
+
 /* Ranges */
 #define QPNP_PON_S1_TIMER_MAX		10256
 #define QPNP_PON_S2_TIMER_MAX		2000
@@ -84,6 +89,8 @@
 	struct delayed_work bark_work;
 };
 
+static struct qpnp_pon *sys_reset_dev;
+
 static u32 s1_delay[PON_S1_COUNT_MAX + 1] = {
 	0 , 32, 56, 80, 138, 184, 272, 408, 608, 904, 1352, 2048,
 	3072, 4480, 6720, 10256
@@ -113,6 +120,57 @@
 	return rc;
 }
 
+/**
+ * qpnp_pon_system_pwr_off - Configure system-reset PMIC for shutdown or reset
+ * @reset: Configures for shutdown if 0, or reset if 1.
+ *
+ * This function will only configure a single PMIC. The other PMICs in the
+ * system are slaved off of it and require no explicit configuration. Once
+ * the system-reset PMIC is configured properly, the MSM can drop PS_HOLD to
+ * activate the specified configuration.
+ */
+int qpnp_pon_system_pwr_off(bool reset)
+{
+	int rc;
+	struct qpnp_pon *pon = sys_reset_dev;
+
+	if (!pon)
+		return -ENODEV;
+
+	rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+							QPNP_PON_RESET_EN, 0);
+	if (rc)
+		dev_err(&pon->spmi->dev,
+			"Unable to write to addr=%x, rc(%d)\n",
+				QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+	/*
+	 * We need 10 sleep clock cycles here. But since the clock is
+	 * internally generated, we need to add 50% tolerance to be
+	 * conservative.
+	 */
+	udelay(500);
+
+	rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+			   QPNP_PON_WARM_RESET | QPNP_PON_SHUTDOWN,
+			   reset ? QPNP_PON_WARM_RESET : QPNP_PON_SHUTDOWN);
+	if (rc)
+		dev_err(&pon->spmi->dev,
+			"Unable to write to addr=%x, rc(%d)\n",
+				QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+	rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+							QPNP_PON_RESET_EN,
+							QPNP_PON_RESET_EN);
+	if (rc)
+		dev_err(&pon->spmi->dev,
+			"Unable to write to addr=%x, rc(%d)\n",
+				QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+	return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_system_pwr_off);
+
 static struct qpnp_pon_config *
 qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
 {
@@ -662,7 +720,7 @@
 	struct resource *pon_resource;
 	struct device_node *itr = NULL;
 	u32 delay = 0;
-	int rc = 0;
+	int rc, sys_reset;
 
 	pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
 							GFP_KERNEL);
@@ -671,6 +729,15 @@
 		return -ENOMEM;
 	}
 
+	sys_reset = of_property_read_bool(spmi->dev.of_node,
+						"qcom,system-reset");
+	if (sys_reset && sys_reset_dev) {
+		dev_err(&spmi->dev, "qcom,system-reset property can only be specified for one device on the system\n");
+		return -EINVAL;
+	} else if (sys_reset) {
+		sys_reset_dev = pon;
+	}
+
 	pon->spmi = spmi;
 
 	/* get the total number of pon configurations */
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index eb9e8ee..bcb4cdb 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -679,7 +679,7 @@
 	bam_write_reg_field(base, CTRL, BAM_EN, 1);
 
 #ifdef CONFIG_SPS_SUPPORT_NDP_BAM
-	bam_write_reg_field(base, CTRL, CACHE_MISS_ERR_RESP_EN, 1);
+	bam_write_reg_field(base, CTRL, CACHE_MISS_ERR_RESP_EN, 0);
 
 	bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
 #endif
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 da2a30d..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;
@@ -2641,7 +2657,15 @@
 		slc->state = SLIM_CH_SUSPENDED;
 	}
 
-	ret = slim_allocbw(sb, &subframe, &clkgear);
+	/*
+	 * Controller can override default channel scheduling algorithm.
+	 * (e.g. if controller needs to use fixed channel scheduling based
+	 * on number of channels)
+	 */
+	if (ctrl->allocbw)
+		ret = ctrl->allocbw(sb, &subframe, &clkgear);
+	else
+		ret = slim_allocbw(sb, &subframe, &clkgear);
 
 	if (!ret) {
 		ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 8724138..c32978e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -21,7 +21,6 @@
 
 config MSM_QPNP_INT
 	depends on SPARSE_IRQ
-	depends on ARCH_MSM8974
 	depends on SPMI
 	depends on OF_SPMI
 	bool "MSM QPNP INT"
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index cad411d..b1b7763 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -60,6 +60,11 @@
 		return -ENODEV;
 	}
 
+	if (dev->ops) {
+		pr_err("bridge already opened");
+		return -EALREADY;
+	}
+
 	dev->ops = ops;
 	dev->err = 0;
 
@@ -82,6 +87,16 @@
 {
 	struct diag_bridge	*dev = __dev;
 
+	if (!dev) {
+		pr_err("dev is null");
+		return;
+	}
+
+	if (!dev->ops) {
+		pr_err("can't close bridge that was not open");
+		return;
+	}
+
 	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
 
 	usb_kill_anchored_urbs(&dev->submitted);
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/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 5637f19..998978c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -69,6 +69,13 @@
 
 #define USB_SUSPEND_DELAY_TIME	(500 * HZ/1000) /* 500 msec */
 
+enum msm_otg_phy_reg_mode {
+	USB_PHY_REG_OFF,
+	USB_PHY_REG_ON,
+	USB_PHY_REG_LPM_ON,
+	USB_PHY_REG_LPM_OFF,
+};
+
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
@@ -168,7 +175,8 @@
 	return ret;
 }
 
-static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
+static int msm_hsusb_ldo_enable(struct msm_otg *motg,
+	enum msm_otg_phy_reg_mode mode)
 {
 	int ret = 0;
 
@@ -182,7 +190,8 @@
 		return -ENODEV;
 	}
 
-	if (on) {
+	switch (mode) {
+	case USB_PHY_REG_ON:
 		ret = regulator_set_optimum_mode(hsusb_1p8,
 				USB_PHY_1P8_HPM_LOAD);
 		if (ret < 0) {
@@ -219,7 +228,9 @@
 			return ret;
 		}
 
-	} else {
+		break;
+
+	case USB_PHY_REG_OFF:
 		ret = regulator_disable(hsusb_1p8);
 		if (ret) {
 			dev_err(motg->phy.dev, "%s: unable to disable the hsusb 1p8\n",
@@ -242,9 +253,55 @@
 		if (ret < 0)
 			pr_err("%s: Unable to set LPM of the regulator:"
 				"HSUSB_3p3\n", __func__);
+
+		break;
+
+	case USB_PHY_REG_LPM_ON:
+		ret = regulator_set_optimum_mode(hsusb_1p8,
+				USB_PHY_1P8_LPM_LOAD);
+		if (ret < 0) {
+			pr_err("%s: Unable to set LPM of the regulator: HSUSB_1p8\n",
+				__func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(hsusb_3p3,
+				USB_PHY_3P3_LPM_LOAD);
+		if (ret < 0) {
+			pr_err("%s: Unable to set LPM of the regulator: HSUSB_3p3\n",
+				__func__);
+			regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
+			return ret;
+		}
+
+		break;
+
+	case USB_PHY_REG_LPM_OFF:
+		ret = regulator_set_optimum_mode(hsusb_1p8,
+				USB_PHY_1P8_HPM_LOAD);
+		if (ret < 0) {
+			pr_err("%s: Unable to set HPM of the regulator: HSUSB_1p8\n",
+				__func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(hsusb_3p3,
+				USB_PHY_3P3_HPM_LOAD);
+		if (ret < 0) {
+			pr_err("%s: Unable to set HPM of the regulator: HSUSB_3p3\n",
+				__func__);
+			regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
+			return ret;
+		}
+
+		break;
+
+	default:
+		pr_err("%s: Unsupported mode (%d).", __func__, mode);
+		return -ENOTSUPP;
 	}
 
-	pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+	pr_debug("%s: USB reg mode (%d) (OFF/HPM/LPM)\n", __func__, mode);
 	return ret < 0 ? ret : 0;
 }
 
@@ -881,8 +938,12 @@
 
 	if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
 			!host_bus_suspend && !dcp) {
-		msm_hsusb_ldo_enable(motg, 0);
+		msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
 		motg->lpm_flags |= PHY_PWR_COLLAPSED;
+	} else if (motg->caps & ALLOW_PHY_REGULATORS_LPM &&
+			!host_bus_suspend && !device_bus_suspend && !dcp) {
+		msm_hsusb_ldo_enable(motg, USB_PHY_REG_LPM_ON);
+		motg->lpm_flags |= PHY_REGULATORS_LPM;
 	}
 
 	if (motg->lpm_flags & PHY_RETENTIONED) {
@@ -946,8 +1007,11 @@
 	}
 
 	if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
-		msm_hsusb_ldo_enable(motg, 1);
+		msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
 		motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
+	} else if (motg->lpm_flags & PHY_REGULATORS_LPM) {
+		msm_hsusb_ldo_enable(motg, USB_PHY_REG_LPM_OFF);
+		motg->lpm_flags &= ~PHY_REGULATORS_LPM;
 	}
 
 	if (motg->lpm_flags & PHY_RETENTIONED) {
@@ -3622,7 +3686,7 @@
 		}
 	}
 
-	ret = msm_hsusb_ldo_enable(motg, 1);
+	ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
 		goto free_ldo_init;
@@ -3724,7 +3788,8 @@
 				ALLOW_PHY_RETENTION;
 
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
-			motg->caps = ALLOW_PHY_RETENTION;
+			motg->caps = ALLOW_PHY_RETENTION |
+				ALLOW_PHY_REGULATORS_LPM;
 	}
 
 	if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -3756,7 +3821,7 @@
 destroy_wlock:
 	wake_lock_destroy(&motg->wlock);
 	clk_disable_unprepare(motg->core_clk);
-	msm_hsusb_ldo_enable(motg, 0);
+	msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
 free_ldo_init:
 	msm_hsusb_ldo_init(motg, 0);
 free_hsusb_vddcx:
@@ -3843,7 +3908,7 @@
 	clk_disable_unprepare(motg->pclk);
 	clk_disable_unprepare(motg->core_clk);
 	msm_xo_put(motg->xo_handle);
-	msm_hsusb_ldo_enable(motg, 0);
+	msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
 	msm_hsusb_ldo_init(motg, 0);
 	regulator_disable(hsusb_vddcx);
 	regulator_set_voltage(hsusb_vddcx,
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_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index 487e5d5..ee7e9ce 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -294,6 +294,7 @@
 	mdp4_mixer_stage_commit(pipe->mixer_num);
 
 	mdp4_writeback_overlay_kickoff(mfd, pipe);
+	mdp4_writeback_dma_busy_wait(mfd);
 
 	/* move current committed iommu to freelist */
 	mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
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/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index bd5f464..b0a67938 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -388,7 +388,7 @@
 		ret = -ENOBUFS;
 	}
 	mutex_unlock(&wb->lock);
-	return 0;
+	return ret;
 }
 
 static void mdss_mdp_wb_callback(void *arg)
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index f3b8cd1..6c0778f 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -62,6 +62,9 @@
 void (*notify_usb_online)(int online);
 static void mhl_drive_hpd(uint8_t to_state);
 static int mhl_send_msc_command(struct msc_command_struct *req);
+static void list_cmd_put(struct msc_command_struct *cmd);
+static struct msc_command_struct *list_cmd_get(void);
+static void mhl_msc_send_work(struct work_struct *work);
 
 static struct i2c_driver mhl_sii_i2c_driver = {
 	.driver = {
@@ -618,7 +621,7 @@
 	list_add_tail(&new_cmd->msc_queue_envelope, &mhl_msm_state->list_cmd);
 }
 
-struct msc_command_struct *list_cmd_get(void)
+static struct msc_command_struct *list_cmd_get(void)
 {
 	struct msc_cmd_envelope *cmd_env =
 		list_first_entry(&mhl_msm_state->list_cmd,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
index 3620f1a..2af76f3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
@@ -70,7 +70,6 @@
 	case VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED:
 	case VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE:
 	case VIDC_1080P_ERROR_DIVIDE_BY_ZERO:
-	case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
 	case VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE:
 	case VIDC_1080P_ERROR_VSP_NOT_READY:
 	case VIDC_1080P_ERROR_BUFFER_FULL_STATE:
@@ -242,6 +241,7 @@
 	case VIDC_1080P_ERROR_HEADER_NOT_FOUND:
 	case VIDC_1080P_ERROR_SLICE_PARSE_ERROR:
 	case VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED:
+	case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
 		vcd_status = VCD_ERR_BITSTREAM_ERR;
 		DDL_MSG_ERROR("VIDC_BIT_STREAM_ERR");
 		break;
diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h
new file mode 100644
index 0000000..85dbce9
--- /dev/null
+++ b/include/linux/qpnp/power-on.h
@@ -0,0 +1,24 @@
+/* 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 QPNP_PON_H
+#define QPNP_PON_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_POWER_ON
+int qpnp_pon_system_pwr_off(bool reset);
+#else
+static int qpnp_pon_system_pwr_off(bool reset) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index d365b15..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;
 };
 
 /*
@@ -498,6 +503,11 @@
  * @set_laddr: Setup logical address at laddr for the slave with elemental
  *	address e_addr. Drivers implementing controller will be expected to
  *	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.
@@ -542,6 +552,10 @@
 				struct slim_msg_txn *txn);
 	int			(*set_laddr)(struct slim_controller *ctrl,
 				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);
@@ -979,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/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index adcc450..8e6550f 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -348,7 +348,7 @@
 	/*
 	 * Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
 	 * analog regulators while going to low power mode.
-	 * Currently only 8960(28nm PHY) has the support to allowing PHY
+	 * Currently only 28nm PHY has the support to allowing PHY
 	 * power collapse since it doesn't have leakage currents while
 	 * turning off the power rails.
 	 */
@@ -362,12 +362,18 @@
 	   * Allow putting the core in Low Power mode, when
 	   * USB bus is suspended but cable is connected.
 	   */
-#define ALLOW_LPM_ON_DEV_SUSPEND	    BIT(2)
+#define ALLOW_LPM_ON_DEV_SUSPEND	BIT(2)
+	/*
+	 * Allowing PHY regulators LPM puts the HSUSB 3.3v and 1.8v
+	 * analog regulators into LPM while going to USB low power mode.
+	 */
+#define ALLOW_PHY_REGULATORS_LPM	BIT(3)
 	unsigned long lpm_flags;
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
 #define XO_SHUTDOWN			BIT(2)
 #define CLOCKS_DOWN			BIT(3)
+#define PHY_REGULATORS_LPM	BIT(4)
 	int reset_counter;
 	unsigned long b_last_se0_sess;
 	unsigned long tmouts;
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 2efe31c..34464c6 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -14,8 +14,8 @@
 #ifndef _MSM_VIDC_H_
 #define _MSM_VIDC_H_
 
-#include <linux/videodev2.h>
 #include <linux/poll.h>
+#include <linux/videodev2.h>
 
 enum core_id {
 	MSM_VIDC_CORE_0 = 0,
@@ -28,7 +28,21 @@
 	MSM_VIDC_MAX_DEVICES,
 };
 
-int msm_vidc_open(void *vidc_inst, int core_id, int session_type);
+struct msm_vidc_iommu_info {
+	u32 addr_range[2];
+	char name[64];
+	char ctx[64];
+	int domain;
+	int partition;
+};
+
+enum msm_vidc_io_maps {
+	CP_MAP,
+	NS_MAP,
+	MAX_MAP
+};
+
+void *msm_vidc_open(int core_id, int session_type);
 int msm_vidc_close(void *instance);
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
 int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f);
@@ -47,4 +61,12 @@
 int msm_vidc_encoder_cmd(void *instance, struct v4l2_encoder_cmd *enc);
 int msm_vidc_poll(void *instance, struct file *filp,
 		struct poll_table_struct *pt);
+int msm_vidc_get_iommu_maps(void *instance,
+		struct msm_vidc_iommu_info maps[MAX_MAP]);
+int msm_vidc_subscribe_event(void *instance,
+		struct v4l2_event_subscription *sub);
+int msm_vidc_unsubscribe_event(void *instance,
+		struct v4l2_event_subscription *sub);
+int msm_vidc_dqevent(void *instance, struct v4l2_event *event);
+int msm_vidc_wait(void *instance);
 #endif
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 1e18c9e..7b6d817 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -38,6 +38,7 @@
 		writel_relaxed(val, addr);	\
 	} while (0)
 
+#define VCAP_USEC (1000000)
 #define VCAP_BASE (dev->vcapbase)
 #define VCAP_OFFSET(off) (VCAP_BASE + off)
 
@@ -87,6 +88,9 @@
 	uint8_t					tot_buf;
 	uint8_t					buf_num;
 
+	struct timeval			vc_ts;
+	uint32_t				last_ts;
+
 	/* Buffers inside vc */
 	struct vcap_buffer      *buf[6];
 };
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/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 1041818..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)
 {
@@ -1739,6 +1757,48 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{
+		.name = "MSM8960 Media6",
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name   = "MultiMedia6",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
+	},
+	{
+		.name = "MSM8960 Compr2",
+		.stream_name = "COMPR2",
+		.cpu_dai_name   = "MultiMedia7",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+	},
+	{
+		.name = "MSM8960 Compr3",
+		.stream_name = "COMPR3",
+		.cpu_dai_name   = "MultiMedia8",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1960,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/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index a911d9d..78b3abc 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -354,13 +354,14 @@
 
 	switch (compr->info.codec_param.codec.id) {
 	case SND_AUDIOCODEC_MP3:
+		pr_debug("%s: SND_AUDIOCODEC_MP3\n", __func__);
 		ret = q6asm_media_format_block(prtd->audio_client,
 				compr->codec);
 		if (ret < 0)
 			pr_info("%s: CMD Format block failed\n", __func__);
 		break;
 	case SND_AUDIOCODEC_AAC:
-		pr_debug("SND_AUDIOCODEC_AAC\n");
+		pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__);
 		memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
 		aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
 		aac_cfg.format = 0x03;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 5b69da4..41f259d 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -74,6 +74,9 @@
 static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 
+static int msm_route_compressed2_vol_control;
+static const DECLARE_TLV_DB_LINEAR(compressed2_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
 static int msm_route_ec_ref_rx;
 
 /* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
@@ -869,6 +872,22 @@
 	return 0;
 }
 
+static int msm_routing_get_compressed2_vol_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm_route_compressed2_vol_control;
+	return 0;
+}
+
+static int msm_routing_set_compressed2_vol_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	if (!compressed_set_volume(ucontrol->value.integer.value[0]))
+		msm_route_compressed2_vol_control =
+			ucontrol->value.integer.value[0];
+	return 0;
+}
+
 static int msm_routing_get_srs_trumedia_control(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1838,6 +1857,12 @@
 	msm_routing_set_compressed_vol_mixer, compressed_rx_vol_gain),
 };
 
+static const struct snd_kcontrol_new compressed2_vol_mixer_controls[] = {
+	SOC_SINGLE_EXT_TLV("COMPRESSED2 RX Volume", SND_SOC_NOPM, 0,
+	INT_RX_VOL_GAIN, 0, msm_routing_get_compressed2_vol_mixer,
+	msm_routing_set_compressed2_vol_mixer, compressed2_rx_vol_gain),
+};
+
 static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
 	{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "SRS TruMedia",
@@ -2780,6 +2805,9 @@
 	snd_soc_add_platform_controls(platform,
 				compressed_vol_mixer_controls,
 			ARRAY_SIZE(compressed_vol_mixer_controls));
+	snd_soc_add_platform_controls(platform,
+				compressed2_vol_mixer_controls,
+			ARRAY_SIZE(compressed2_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
 				lpa_SRS_trumedia_controls,
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 6bd6adc..1338e2f 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1372,6 +1372,48 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{
+		.name = "MSM8960 Media6",
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name   = "MultiMedia6",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
+	},
+	{
+		.name = "MSM8960 Compr2",
+		.stream_name = "COMPR2",
+		.cpu_dai_name   = "MultiMedia7",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+	},
+	{
+		.name = "MSM8960 Compr3",
+		.stream_name = "COMPR3",
+		.cpu_dai_name   = "MultiMedia8",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
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) {