Merge "msm: remove references to CONFIG_ANDROID_PMEM"
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 24b6b36..a0c7037 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -31,6 +31,10 @@
 				"HS200_1p2v" - indicates that host can support HS200 at 1.2v.
 				"DDR_1p8v" - indicates that host can support DDR mode at 1.8v.
 				"DDR_1p2v" - indicates that host can support DDR mode at 1.2v.
+	- qcom,cpu-dma-latency-us: specifies acceptable DMA latency in microseconds. There is
+				   no default value that the driver assumes if this property
+				   is not specified. So if this property is not specified,
+				   then SDHC driver will not vote for PM QOS.
 
 In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage).
 	- qcom,<supply>-always-on - specifies whether supply should be kept "on" always.
@@ -51,6 +55,18 @@
 	- qcom,pad-drv-off - Suspend drive strength configuration for sdc tlmm pins.
 	Tlmm pins are specified as <clk cmd data>
 
+	- qcom,bus-bw-vectors-bps: specifies array of throughput values in
+	Bytes/sec. The values in the array are determined according to
+	supported bus speed modes. For example, if host supports SDR12 mode,
+	value is 13631488 Bytes/sec.
+	- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
+	below optional properties:
+	- qcom,msm-bus,name
+	- qcom,msm-bus,num-cases
+	- qcom,msm-bus,active-only
+	- qcom,msm-bus,num-paths
+	- qcom,msm-bus,vectors-KBps
+
 Example:
 
 	aliases {
@@ -86,6 +102,7 @@
 			<&msmgpio 36 0>, /* DATA2 */
 			<&msmgpio 35 0>; /* DATA3 */
 		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+		qcom,cpu-dma-latency-us = <200>;
 	};
 
 	sdhc_2: qcom,sdhc@f98a4900 {
@@ -104,4 +121,18 @@
 		qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
 		qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
 		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+		qcom,cpu-dma-latency-us = <200>;
+		qcom,msm-bus,name = "sdhc2";
+		qcom,msm-bus,num-cases = <7>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+				<81 512 6656 13312>, /* 13 MB/s*/
+				<81 512 13312 26624>, /* 26 MB/s */
+				<81 512 26624 53248>, /* 52 MB/s */
+				<81 512 53248 106496>, /* 104 MB/s */
+				<81 512 106496 212992>, /* 208 MB/s */
+				<81 512 2147483647 4294967295>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 13631488 27262976 54525952 109051904 218103808 4294967295>;
 	};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 8f602b6..df3f71c 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -17,14 +17,14 @@
 - vdd_cx-supply:      Reference to the regulator that supplies the vdd_cx domain.
 - vdd_mx-supply:      Reference to the regulator that supplies the memory rail.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
-- qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
-		      images and self-authentication is not desired;
-		      <1> if the hardware requires self-authenticating images.
-- qcom,is-loadable:   if PIL is required to load the modem image
 
 Optional properties:
 - vdd_pll-supply:     Reference to the regulator that supplies the PLL's rail.
 - qcom,vdd_pll:       Voltage to be set for the PLL's rail.
+- reg-names:          "cxrail_bhs_reg" - control register for modem power
+		      domain.
+- qcom,is-loadable:   Boolean- Present if the image needs to be loaded.
+- qcom,pil-self-auth: Boolean- True if authentication is required.
 
 Example:
 	qcom,mss@fc880000 {
@@ -43,5 +43,5 @@
 
 		qcom,is-loadable;
 		qcom,firmware-name = "mba";
-		qcom,pil-self-auth = <1>;
+		qcom,pil-self-auth;
 	};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index a868b75..4590227 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -54,7 +54,7 @@
 	each should be their own subnode.
 
 Sub node required properties:
-- compatible:		Must be "qcom,charger".
+- compatible:		Must be "qcom,qpnp-charger".
 - reg:			Specifies the SPMI address and size for this peripheral.
 - interrupts:		Specifies the interrupt associated with the peripheral.
 - interrupt-names:	Specifies the interrupt names for the peripheral. Every
@@ -125,7 +125,7 @@
 Example:
 	pm8941-chg {
 		spmi-dev-container;
-		compatible = "qcom,charger";
+		compatible = "qcom,qpnp-charger";
 		#address-cells = <1>;
 		#size-cells = <1>;
 
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index c783ac8..aaa731e 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -9,6 +9,10 @@
 [First Level Nodes]
 Required properties:
 - compatible:			Must be "qcom,krait-pdn"
+- reg:				Specifies the physical address of the APCS GCC
+				register base
+- reg-names:			"apcs_gcc" -string to identify the area where
+				the APCS GCC registers reside.
 
 Optional properties:
 - qcom,use-phase-switching	indicates whether the driver should add/shed phases on the PMIC
@@ -42,7 +46,9 @@
 binding, defined in regulator.txt, can also be used.
 
 Example:
-	krait_pdn: krait-pdn {
+	krait_pdn: krait-pdn@f9011000 {
+		reg = <0xf9011000 0x1000>;
+		reg-names = "apcs_gcc";
 		compatible = "qcom,krait-pdn";
 		qcom,use-phase-switching;
 		#address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 2cdc7ff..6cf59ee 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -52,6 +52,8 @@
 - qcom,hsusb-otg-clk-always-on-workaround: If present then USB core clocks
 	    remain active upon receiving bus suspend and USB cable is connected.
 	    Used for allowing USB to respond for remote wakup.
+- qcom,hsusb-otg-delay-lpm: If present then USB core will wait one second
+	after disconnect before entering low power mode.
 - <supply-name>-supply: handle to the regulator device tree node
          Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
          "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
@@ -59,6 +61,9 @@
 - qcom,vdd-voltage-level: This property must be a list of three integer
 	values (no, min, max) where each value represents either a voltage
 	in microvolts or a value corresponding to voltage corner.
+- qcom,dp-manual-pullup: If present, vbus is not routed to USB controller/phy
+	and controller driver therefore enables pull-up explicitly before
+	starting controller using usbcmd run/stop bit.
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
@@ -83,7 +88,7 @@
                 HSUSB_1p8-supply = <&pm8226_l10>;
                 HSUSB_3p3-supply = <&pm8226_l20>;
 		qcom,vdd-voltage-level = <1 5 7>;
-
+		qcom,dp-manual-pullup;
 		qcom,msm_bus,name = "usb2";
 		qcom,msm_bus,num_cases = <2>;
 		qcom,msm_bus,active_only = <0>;
@@ -107,6 +112,8 @@
 
 Optional properties :
 - qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
+- qcom,pool-64-bit-align: If present then the pool's memory will be aligned
+  to 64 bits
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt
new file mode 100644
index 0000000..4627c42
--- /dev/null
+++ b/Documentation/hid/uhid.txt
@@ -0,0 +1,169 @@
+      UHID - User-space I/O driver support for HID subsystem
+     ========================================================
+
+The HID subsystem needs two kinds of drivers. In this document we call them:
+
+ 1. The "HID I/O Driver" is the driver that performs raw data I/O to the
+    low-level device. Internally, they register an hid_ll_driver structure with
+    the HID core. They perform device setup, read raw data from the device and
+    push it into the HID subsystem and they provide a callback so the HID
+    subsystem can send data to the device.
+
+ 2. The "HID Device Driver" is the driver that parses HID reports and reacts on
+    them. There are generic drivers like "generic-usb" and "generic-bluetooth"
+    which adhere to the HID specification and provide the standardizes features.
+    But there may be special drivers and quirks for each non-standard device out
+    there. Internally, they use the hid_driver structure.
+
+Historically, the USB stack was the first subsystem to provide an HID I/O
+Driver. However, other standards like Bluetooth have adopted the HID specs and
+may provide HID I/O Drivers, too. The UHID driver allows to implement HID I/O
+Drivers in user-space and feed the data into the kernel HID-subsystem.
+
+This allows user-space to operate on the same level as USB-HID, Bluetooth-HID
+and similar. It does not provide a way to write HID Device Drivers, though. Use
+hidraw for this purpose.
+
+There is an example user-space application in ./samples/uhid/uhid-example.c
+
+The UHID API
+------------
+
+UHID is accessed through a character misc-device. The minor-number is allocated
+dynamically so you need to rely on udev (or similar) to create the device node.
+This is /dev/uhid by default.
+
+If a new device is detected by your HID I/O Driver and you want to register this
+device with the HID subsystem, then you need to open /dev/uhid once for each
+device you want to register. All further communication is done by read()'ing or
+write()'ing "struct uhid_event" objects. Non-blocking operations are supported
+by setting O_NONBLOCK.
+
+struct uhid_event {
+        __u32 type;
+        union {
+                struct uhid_create_req create;
+                struct uhid_data_req data;
+                ...
+        } u;
+};
+
+The "type" field contains the ID of the event. Depending on the ID different
+payloads are sent. You must not split a single event across multiple read()'s or
+multiple write()'s. A single event must always be sent as a whole. Furthermore,
+only a single event can be sent per read() or write(). Pending data is ignored.
+If you want to handle multiple events in a single syscall, then use vectored
+I/O with readv()/writev().
+
+The first thing you should do is sending an UHID_CREATE event. This will
+register the device. UHID will respond with an UHID_START event. You can now
+start sending data to and reading data from UHID. However, unless UHID sends the
+UHID_OPEN event, the internally attached HID Device Driver has no user attached.
+That is, you might put your device asleep unless you receive the UHID_OPEN
+event. If you receive the UHID_OPEN event, you should start I/O. If the last
+user closes the HID device, you will receive an UHID_CLOSE event. This may be
+followed by an UHID_OPEN event again and so on. There is no need to perform
+reference-counting in user-space. That is, you will never receive multiple
+UHID_OPEN events without an UHID_CLOSE event. The HID subsystem performs
+ref-counting for you.
+You may decide to ignore UHID_OPEN/UHID_CLOSE, though. I/O is allowed even
+though the device may have no users.
+
+If you want to send data to the HID subsystem, you send an HID_INPUT event with
+your raw data payload. If the kernel wants to send data to the device, you will
+read an UHID_OUTPUT or UHID_OUTPUT_EV event.
+
+If your device disconnects, you should send an UHID_DESTROY event. This will
+unregister the device. You can now send UHID_CREATE again to register a new
+device.
+If you close() the fd, the device is automatically unregistered and destroyed
+internally.
+
+write()
+-------
+write() allows you to modify the state of the device and feed input data into
+the kernel. The following types are supported: UHID_CREATE, UHID_DESTROY and
+UHID_INPUT. The kernel will parse the event immediately and if the event ID is
+not supported, it will return -EOPNOTSUPP. If the payload is invalid, then
+-EINVAL is returned, otherwise, the amount of data that was read is returned and
+the request was handled successfully.
+
+  UHID_CREATE:
+  This creates the internal HID device. No I/O is possible until you send this
+  event to the kernel. The payload is of type struct uhid_create_req and
+  contains information about your device. You can start I/O now.
+
+  UHID_DESTROY:
+  This destroys the internal HID device. No further I/O will be accepted. There
+  may still be pending messages that you can receive with read() but no further
+  UHID_INPUT events can be sent to the kernel.
+  You can create a new device by sending UHID_CREATE again. There is no need to
+  reopen the character device.
+
+  UHID_INPUT:
+  You must send UHID_CREATE before sending input to the kernel! This event
+  contains a data-payload. This is the raw data that you read from your device.
+  The kernel will parse the HID reports and react on it.
+
+  UHID_FEATURE_ANSWER:
+  If you receive a UHID_FEATURE request you must answer with this request. You
+  must copy the "id" field from the request into the answer. Set the "err" field
+  to 0 if no error occured or to EIO if an I/O error occurred.
+  If "err" is 0 then you should fill the buffer of the answer with the results
+  of the feature request and set "size" correspondingly.
+
+read()
+------
+read() will return a queued ouput report. These output reports can be of type
+UHID_START, UHID_STOP, UHID_OPEN, UHID_CLOSE, UHID_OUTPUT or UHID_OUTPUT_EV. No
+reaction is required to any of them but you should handle them according to your
+needs. Only UHID_OUTPUT and UHID_OUTPUT_EV have payloads.
+
+  UHID_START:
+  This is sent when the HID device is started. Consider this as an answer to
+  UHID_CREATE. This is always the first event that is sent.
+
+  UHID_STOP:
+  This is sent when the HID device is stopped. Consider this as an answer to
+  UHID_DESTROY.
+  If the kernel HID device driver closes the device manually (that is, you
+  didn't send UHID_DESTROY) then you should consider this device closed and send
+  an UHID_DESTROY event. You may want to reregister your device, though. This is
+  always the last message that is sent to you unless you reopen the device with
+  UHID_CREATE.
+
+  UHID_OPEN:
+  This is sent when the HID device is opened. That is, the data that the HID
+  device provides is read by some other process. You may ignore this event but
+  it is useful for power-management. As long as you haven't received this event
+  there is actually no other process that reads your data so there is no need to
+  send UHID_INPUT events to the kernel.
+
+  UHID_CLOSE:
+  This is sent when there are no more processes which read the HID data. It is
+  the counterpart of UHID_OPEN and you may as well ignore this event.
+
+  UHID_OUTPUT:
+  This is sent if the HID device driver wants to send raw data to the I/O
+  device. You should read the payload and forward it to the device. The payload
+  is of type "struct uhid_data_req".
+  This may be received even though you haven't received UHID_OPEN, yet.
+
+  UHID_OUTPUT_EV:
+  Same as UHID_OUTPUT but this contains a "struct input_event" as payload. This
+  is called for force-feedback, LED or similar events which are received through
+  an input device by the HID subsystem. You should convert this into raw reports
+  and send them to your device similar to events of type UHID_OUTPUT.
+
+  UHID_FEATURE:
+  This event is sent if the kernel driver wants to perform a feature request as
+  described in the HID specs. The report-type and report-number are available in
+  the payload.
+  The kernel serializes feature requests so there will never be two in parallel.
+  However, if you fail to respond with a UHID_FEATURE_ANSWER in a time-span of 5
+  seconds, then the requests will be dropped and a new one might be sent.
+  Therefore, the payload also contains an "id" field that identifies every
+  request.
+
+Document by:
+  David Herrmann <dh.herrmann@googlemail.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index b362709..5f8ab49 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6855,6 +6855,13 @@
 F:	Documentation/filesystems/ufs.txt
 F:	fs/ufs/
 
+UHID USERSPACE HID IO DRIVER:
+M:	David Herrmann <dh.herrmann@googlemail.com>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	drivers/hid/uhid.c
+F:	include/linux/uhid.h
+
 ULTRA-WIDEBAND (UWB) SUBSYSTEM:
 L:	linux-usb@vger.kernel.org
 S:	Orphan
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index c776fab..44ece9e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -49,6 +49,109 @@
 			};
 		};
 
+		pm8226_chg: qcom,charger {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-charger";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+
+			qcom,chg-vddmax-mv = <4200>;
+			qcom,chg-vddsafe-mv = <4200>;
+			qcom,chg-vinmin-mv = <4200>;
+			qcom,chg-vbatdet-mv = <4100>;
+			qcom,chg-ibatmax-ma = <1500>;
+			qcom,chg-ibatterm-ma = <200>;
+			qcom,chg-ibatsafe-ma = <1500>;
+			qcom,chg-thermal-mitigation = <1500 700 600 325>;
+
+			qcom,chg-chgr@1000 {
+				status = "disabled";
+				reg = <0x1000 0x100>;
+				interrupts =	<0x0 0x10 0x0>,
+						<0x0 0x10 0x1>,
+						<0x0 0x10 0x2>,
+						<0x0 0x10 0x3>,
+						<0x0 0x10 0x4>,
+						<0x0 0x10 0x5>,
+						<0x0 0x10 0x6>,
+						<0x0 0x10 0x7>;
+
+				interrupt-names =	"vbat-det-lo",
+							"vbat-det-hi",
+							"chgwdog",
+							"state-change",
+							"trkl-chg-on",
+							"fast-chg-on",
+							"chg-failed",
+							"chg-done";
+			};
+
+			qcom,chg-buck@1100 {
+				status = "disabled";
+				reg = <0x1100 0x100>;
+				interrupts =	<0x0 0x11 0x0>,
+						<0x0 0x11 0x1>,
+						<0x0 0x11 0x2>,
+						<0x0 0x11 0x3>,
+						<0x0 0x11 0x4>,
+						<0x0 0x11 0x5>,
+						<0x0 0x11 0x6>;
+
+				interrupt-names =	"vbat-ov",
+							"vreg-ov",
+							"overtemp",
+							"vchg-loop",
+							"ichg-loop",
+							"ibat-loop",
+							"vdd-loop";
+			};
+
+			qcom,chg-bat-if@1200 {
+				status = "disabled";
+				reg = <0x1200 0x100>;
+				interrupts =	<0x0 0x12 0x0>,
+						<0x0 0x12 0x1>,
+						<0x0 0x12 0x2>,
+						<0x0 0x12 0x3>,
+						<0x0 0x12 0x4>;
+
+				interrupt-names =	"batt-pres",
+							"bat-temp-ok",
+							"bat-fet-on",
+							"vcp-on",
+							"psi";
+
+			};
+
+			qcom,chg-usb-chgpth@1300 {
+				status = "disabled";
+				reg = <0x1300 0x100>;
+				interrupts =	<0 0x13 0x0>,
+						<0 0x13 0x1>,
+						<0x0 0x13 0x2>;
+
+				interrupt-names =	"coarse-det-usb",
+							"usbin-valid",
+							"chg-gone";
+			};
+
+			qcom,chg-boost@1500 {
+				status = "disabled";
+				reg = <0x1500 0x100>;
+				interrupts =	<0x0 0x15 0x0>,
+						<0x0 0x15 0x1>;
+
+				interrupt-names =	"boost-pwr-ok",
+							"limit-error";
+			};
+
+			qcom,chg-misc@1600 {
+				status = "disabled";
+				reg = <0x1600 0x100>;
+			};
+		};
+
 		pm8226_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 0841c13..a2707ee 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -109,3 +109,55 @@
 		};
 	};
 };
+
+&pm8226_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+};
+
+&pm8226_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+	};
+
+	mpp@a500 { /* MPP 6 */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index d55a6bd..43f6685 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -106,3 +106,55 @@
 		};
 	};
 };
+
+&pm8226_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+};
+
+&pm8226_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+	};
+
+	mpp@a500 { /* MPP 6 */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index a192561..482a5da 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -109,3 +109,55 @@
 		};
 	};
 };
+
+&pm8226_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+};
+
+&pm8226_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+	};
+
+	mpp@a500 { /* MPP 6 */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 12f042b..1919cbc 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -96,6 +96,7 @@
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <2>;
 		qcom,hsusb-otg-disable-reset;
+		qcom,dp-manual-pullup;
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
@@ -541,6 +542,29 @@
 		qcom,firmware-name = "adsp";
 	};
 
+	qcom,mss@fc880000 {
+		compatible = "qcom,pil-q6v5-mss";
+		reg = <0xfc880000 0x100>,
+		      <0xfd485000 0x400>,
+		      <0xfc820000 0x020>,
+		      <0xfc401680 0x004>,
+		      <0x0d1fc000 0x4000>,
+		      <0xfd485194 0x4>;
+		reg-names = "qdsp6_base", "halt_base", "rmb_base",
+			    "restart_reg", "metadata_base", "cxrail_bhs_reg";
+
+		interrupts = <0 24 1>;
+		vdd_mss-supply = <&pm8226_s1>;
+		vdd_cx-supply = <&pm8226_s1_corner>;
+		vdd_mx-supply = <&pm8226_l3>;
+		vdd_pll-supply = <&pm8226_l8>;
+		qcom,vdd_pll = <1800000>;
+
+		qcom,is-loadable;
+		qcom,firmware-name = "mba";
+		qcom,pil-self-auth;
+	};
+
 	qcom,msm-mem-hole {
 		compatible = "qcom,msm-mem-hole";
 		qcom,memblock-remove = <0x8400000 0x7b00000>; /* Address and Size of Hole */
@@ -717,4 +741,32 @@
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
 	};
+
+};
+
+&pm8226_chg {
+	status = "ok";
+
+	qcom,chg-charging-disabled;
+	qcom,chg-use-default-batt-values;
+
+	qcom,chg-chgr@1000 {
+		status = "ok";
+	};
+
+	qcom,chg-buck@1100 {
+		status = "ok";
+	};
+
+	qcom,chg-usb-chgpth@1300 {
+		status = "ok";
+	};
+
+	qcom,chg-boost@1500 {
+		status = "ok";
+	};
+
+	qcom,chg-misc@1600 {
+		status = "ok";
+	};
 };
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 0abaca5..107961d 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -20,14 +20,6 @@
 			reg = <30>;
 		};
 
-		qcom,ion-heap@8 { /* CP_MM HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <8>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x3800000>;
-		};
-
 		qcom,ion-heap@25 { /* IOMMU HEAP */
 			reg = <25>;
 		};
@@ -37,7 +29,7 @@
 			reg = <27>;
 			qcom,heap-align = <0x1000>;
 			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x780000>;
+			qcom,memory-reservation-size = <0x100000>;
 		};
 
 		qcom,ion-heap@28 { /* AUDIO HEAP */
@@ -47,16 +39,6 @@
 			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
 			qcom,memory-reservation-size = <0x314000>;
 		};
-
-		qcom,ion-heap@29 { /* FIRMWARE HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <29>;
-			qcom,heap-align = <0x20000>;
-			qcom,heap-adjacent = <8>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0xA00000>;
-		};
-
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 2dad8e7..5eff79c 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -423,7 +423,9 @@
 };
 
 / {
-	krait_pdn: krait-pdn {
+	krait_pdn: krait-pdn@f9011000 {
+		reg = <0xf9011000 0x1000>;
+		reg-names = "apcs_gcc";
 		compatible = "qcom,krait-pdn";
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index ab6b7c8..1922591 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -344,6 +344,7 @@
 		interrupts = <0 123 0>, <0 138 0>;
 		interrupt-names = "hc_irq", "pwr_irq";
 		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+		qcom,cpu-dma-latency-us = <200>;
 		status = "disable";
 	};
 
@@ -355,6 +356,7 @@
 		interrupt-names = "hc_irq", "pwr_irq";
 
 		qcom,bus-width = <4>;
+		qcom,cpu-dma-latency-us = <200>;
 		status = "disable";
 	};
 
@@ -373,6 +375,7 @@
 		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
 		qcom,bus-width = <4>;
+		qcom,cpu-dma-latency-us = <200>;
 		status = "disable";
 	};
 
@@ -391,6 +394,7 @@
 		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
 		qcom,bus-width = <4>;
+		qcom,cpu-dma-latency-us = <200>;
 		status = "disable";
 	};
 
@@ -914,7 +918,7 @@
 		qcom,vdd_pll = <1800000>;
 		qcom,is-loadable;
 		qcom,firmware-name = "mba";
-		qcom,pil-self-auth = <1>;
+		qcom,pil-self-auth;
 	};
 
 	qcom,pronto@fb21b000 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 03eaaf3..e1501ac 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -91,6 +91,7 @@
 		qcom,hsusb-otg-disable-reset;
 		qcom,hsusb-otg-lpm-on-dev-suspend;
 		qcom,hsusb-otg-clk-always-on-workaround;
+		qcom,hsusb-otg-delay-lpm;
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 01d495f..14bd1b4 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -153,6 +153,9 @@
 CONFIG_WCD9306_CODEC=y
 CONFIG_GPIO_QPNP_PIN=y
 CONFIG_HWMON=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_CHARGER=y
+# CONFIG_HWMON is not set
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_REGULATOR=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index c6be3c5..4b7065b 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -460,6 +460,6 @@
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
-CONFIG_CRYPTO_DEV_QCE=m
-CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index f77f04f..6a4737c 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -485,6 +485,6 @@
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
-CONFIG_CRYPTO_DEV_QCE=m
-CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRC_CCITT=y
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 938be62..c1295c4 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -68,15 +68,18 @@
 #define __raw_writeb_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
 #define __raw_writew_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
 #define __raw_writel_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
+#define __raw_writell_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned long long __force *)(a) = (v))
 
 
 #define __raw_writeb(v, a)	__raw_write_logged((v), (a), b)
 #define __raw_writew(v, a)	__raw_write_logged((v), (a), w)
 #define __raw_writel(v, a)	__raw_write_logged((v), (a), l)
+#define __raw_writell(v, a)	__raw_write_logged((v), (a), ll)
 
 #define __raw_readb_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
 #define __raw_readw_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
 #define __raw_readl_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
+#define __raw_readll_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned long long __force *)(a))
 
 #define __raw_read_logged(a, _l, _t)		({ \
 	unsigned _t __a; \
@@ -94,6 +97,7 @@
 #define __raw_readb(a)		__raw_read_logged((a), b, char)
 #define __raw_readw(a)		__raw_read_logged((a), w, short)
 #define __raw_readl(a)		__raw_read_logged((a), l, int)
+#define __raw_readll(a)		__raw_read_logged((a), ll, long long)
 
 /*
  * Architecture ioremap implementation.
@@ -268,8 +272,12 @@
 					__raw_readw(c)); __r; })
 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
 					__raw_readl(c)); __r; })
+#define readll_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \
+					__raw_readll(c)); __r; })
 #define readl_relaxed_no_log(c) ({ u32 __r = le32_to_cpu((__force __le32) \
 					__raw_readl_no_log(c)); __r; })
+#define readll_relaxed_no_log(c) ({ u64 __r = le64_to_cpu((__force __le64) \
+					__raw_readll_no_log(c)); __r; })
 
 
 #define writeb_relaxed(v,c)	((void)__raw_writeb(v,c))
@@ -277,16 +285,22 @@
 					cpu_to_le16(v),c))
 #define writel_relaxed(v,c)	((void)__raw_writel((__force u32) \
 					cpu_to_le32(v),c))
+#define writell_relaxed(v, c)	((void)__raw_writell((__force u64) \
+					cpu_to_le64(v), c))
 #define writel_relaxed_no_log(v, c)  ((void)__raw_writel_no_log((__force u32) \
 					cpu_to_le32(v), c))
+#define writell_relaxed_no_log(v, c)  ((void)__raw_writell_no_log((__force u64) \
+					cpu_to_le64(v), c))
 
 #define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
 #define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+#define readll(c)		({ u64 __v = readll_relaxed(c); __iormb(); __v; })
 
 #define writeb(v,c)		({ __iowmb(); writeb_relaxed(v,c); })
 #define writew(v,c)		({ __iowmb(); writew_relaxed(v,c); })
 #define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })
+#define writell(v, c)		({ __iowmb(); writell_relaxed(v, c); })
 
 #define readsb(p,d,l)		__raw_readsb(p,d,l)
 #define readsw(p,d,l)		__raw_readsw(p,d,l)
@@ -316,22 +330,26 @@
 #define iounmap				__arm_iounmap
 
 /*
- * io{read,write}{8,16,32} macros
+ * io{read,write}{8,16,32,64} macros
  */
 #ifndef ioread8
 #define ioread8(p)	({ unsigned int __v = __raw_readb(p); __iormb(); __v; })
 #define ioread16(p)	({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32(p)	({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
+#define ioread64(p)	({ unsigned int __v = le64_to_cpu((__force __le64)__raw_readll(p)); __iormb(); __v; })
 
 #define ioread16be(p)	({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32be(p)	({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+#define ioread64be(p)	({ unsigned int __v = be64_to_cpu((__force __be64)__raw_readll(p)); __iormb(); __v; })
 
 #define iowrite8(v,p)	({ __iowmb(); (void)__raw_writeb(v, p); })
 #define iowrite16(v,p)	({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); })
 #define iowrite32(v,p)	({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); })
+#define iowrite64(v, p)	({ __iowmb(); (void)__raw_writell((__force __u64)cpu_to_le64(v), p); })
 
 #define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); })
 #define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); })
+#define iowrite64be(v, p) ({ __iowmb(); (void)__raw_writell((__force __u64)cpu_to_be64(v), p); })
 
 #define ioread8_rep(p,d,c)	__raw_readsb(p,d,c)
 #define ioread16_rep(p,d,c)	__raw_readsw(p,d,c)
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index dd117b9..c8bdb5d 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -107,7 +107,7 @@
 #define MSM_ION_MM_SIZE		0x3800000
 #define MSM_ION_SF_SIZE		0
 #define MSM_ION_QSECOM_SIZE	0x780000 /* (7.5MB) */
-#define MSM_ION_HEAP_NUM	7
+#define MSM_ION_HEAP_NUM	8
 #else
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
@@ -127,6 +127,7 @@
 #define MAX_FIXED_AREA_SIZE	0x10000000
 #define MSM_MM_FW_SIZE		(0x200000 - HOLE_SIZE)
 #define APQ8064_FW_START	APQ8064_FIXED_AREA_START
+#define MSM_ION_ADSP_SIZE	SZ_8M
 
 #define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB     (MSM_QFPROM_BASE + 0x23c)
 #define QFPROM_RAW_OEM_CONFIG_ROW0_LSB      (MSM_QFPROM_BASE + 0x220)
@@ -235,6 +236,14 @@
 	}
 };
 
+static struct platform_device ion_adsp_heap_device = {
+	.name = "ion-adsp-heap-device",
+	.id = -1,
+	.dev = {
+		.dma_mask = &msm_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	}
+};
 /**
  * These heaps are listed in the order they will be allocated. Due to
  * video hardware restrictions and content protection the FW heap has to
@@ -309,6 +318,15 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *) &co_apq8064_ion_pdata,
 		},
+		{
+			.id     = ION_ADSP_HEAP_ID,
+			.type   = ION_HEAP_TYPE_DMA,
+			.name   = ION_ADSP_HEAP_NAME,
+			.size   = MSM_ION_ADSP_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_apq8064_ion_pdata,
+			.priv = &ion_adsp_heap_device.dev,
+		},
 #endif
 };
 
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index ccda370..771e678 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -147,7 +147,7 @@
 #define MSM_ION_MM_SIZE            0x3800000 /* Need to be multiple of 64K */
 #define MSM_ION_SF_SIZE            0x0
 #define MSM_ION_QSECOM_SIZE	0x780000 /* (7.5MB) */
-#define MSM_ION_HEAP_NUM	7
+#define MSM_ION_HEAP_NUM	8
 #else
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
@@ -167,6 +167,7 @@
 								HOLE_SIZE))
 #define MAX_FIXED_AREA_SIZE	0x10000000
 #define MSM8930_FW_START	MSM8930_FIXED_AREA_START
+#define MSM_ION_ADSP_SIZE	SZ_8M
 
 #else
 #define MSM_CONTIG_MEM_SIZE  0x110C000
@@ -275,6 +276,14 @@
 	}
 };
 
+static struct platform_device ion_adsp_heap_device = {
+	.name = "ion-adsp-heap-device",
+	.id = -1,
+	.dev = {
+		.dma_mask = &msm_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	}
+};
 /**
  * These heaps are listed in the order they will be allocated. Due to
  * video hardware restrictions and content protection the FW heap has to
@@ -349,6 +358,15 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *) &co_msm8930_ion_pdata,
 		},
+		{
+			.id	= ION_ADSP_HEAP_ID,
+			.type	= ION_HEAP_TYPE_DMA,
+			.name	= ION_ADSP_HEAP_NAME,
+			.size	= MSM_ION_ADSP_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_msm8930_ion_pdata,
+			.priv	= &ion_adsp_heap_device.dev,
+		},
 #endif
 };
 
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 8983c13..78e3ca6 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -157,7 +157,7 @@
 #define MSM_ION_MM_SIZE            0x3800000 /* Need to be multiple of 64K */
 #define MSM_ION_SF_SIZE            0x0
 #define MSM_ION_QSECOM_SIZE        0x780000 /* (7.5MB) */
-#define MSM_ION_HEAP_NUM	7
+#define MSM_ION_HEAP_NUM	8
 #else
 #define MSM_ION_MM_SIZE            MSM_PMEM_ADSP_SIZE
 #define MSM_ION_SF_SIZE            MSM_PMEM_SIZE
@@ -177,6 +177,7 @@
 							HOLE_SIZE))
 #define MAX_FIXED_AREA_SIZE	0x10000000
 #define MSM8960_FW_START	MSM8960_FIXED_AREA_START
+#define MSM_ION_ADSP_SIZE	SZ_8M
 
 static unsigned msm_ion_sf_size = MSM_ION_SF_SIZE;
 #else
@@ -287,6 +288,15 @@
 	}
 };
 
+static struct platform_device ion_adsp_heap_device = {
+	.name = "ion-adsp-heap-device",
+	.id = -1,
+	.dev = {
+		.dma_mask = &msm_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	}
+};
+
 /**
  * These heaps are listed in the order they will be allocated. Due to
  * video hardware restrictions and content protection the FW heap has to
@@ -361,6 +371,15 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *) &co_msm8960_ion_pdata,
 		},
+		{
+			.id     = ION_ADSP_HEAP_ID,
+			.type   = ION_HEAP_TYPE_DMA,
+			.name   = ION_ADSP_HEAP_NAME,
+			.size   = MSM_ION_ADSP_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_msm8960_ion_pdata,
+			.priv	= &ion_adsp_heap_device.dev,
+		},
 #endif
 };
 
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index b40617c..898b7e0 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2559,7 +2559,7 @@
 
 static struct branch_clk oxili_gfx3d_clk = {
 	.cbcr_reg = OXILI_GFX3D_CBCR,
-	.has_sibling = 1,
+	.has_sibling = 0,
 	.max_div = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 214d1b7..c3b4ca7 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -805,7 +805,6 @@
 struct clk_ops clk_ops_rcg_hdmi = {
 	.enable = rcg_clk_prepare,
 	.set_rate = rcg_clk_set_rate_hdmi,
-	.set_rate = rcg_clk_set_rate,
 	.list_rate = rcg_clk_list_rate,
 	.round_rate = rcg_clk_round_rate,
 	.handoff = rcg_clk_handoff,
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index f2a4427..2010abb 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -355,36 +355,6 @@
 };
 
 /**
- * enum ipa_rm_resource_name - IPA RM clients identification names
- *
- * Add new mapping to ipa_rm_dep_prod_index() / ipa_rm_dep_cons_index()
- * when adding new entry to this enum.
- */
-enum ipa_rm_resource_name {
-	IPA_RM_RESOURCE_PROD = 0,
-	IPA_RM_RESOURCE_BRIDGE_PROD = IPA_RM_RESOURCE_PROD,
-	IPA_RM_RESOURCE_A2_PROD,
-	IPA_RM_RESOURCE_USB_PROD,
-	IPA_RM_RESOURCE_HSIC_PROD,
-	IPA_RM_RESOURCE_STD_ECM_PROD,
-	IPA_RM_RESOURCE_WWAN_0_PROD,
-	IPA_RM_RESOURCE_WWAN_1_PROD,
-	IPA_RM_RESOURCE_WWAN_2_PROD,
-	IPA_RM_RESOURCE_WWAN_3_PROD,
-	IPA_RM_RESOURCE_WWAN_4_PROD,
-	IPA_RM_RESOURCE_WWAN_5_PROD,
-	IPA_RM_RESOURCE_WWAN_6_PROD,
-	IPA_RM_RESOURCE_WWAN_7_PROD,
-	IPA_RM_RESOURCE_WLAN_PROD,
-	IPA_RM_RESOURCE_PROD_MAX,
-
-	IPA_RM_RESOURCE_A2_CONS = IPA_RM_RESOURCE_PROD_MAX,
-	IPA_RM_RESOURCE_USB_CONS,
-	IPA_RM_RESOURCE_HSIC_CONS,
-	IPA_RM_RESOURCE_MAX
-};
-
-/**
  * enum ipa_rm_event - IPA RM events
  *
  * Indicate the resource state change
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index a7f052e..b3fb8af 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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
@@ -163,12 +163,6 @@
  */
 int usb_bam_client_ready(bool ready);
 
-/**
- * Returns QDSS BAM connection number
- *
- */
-u8 usb_bam_get_qdss_num(void);
-
 #else
 static inline int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx)
 {
@@ -222,10 +216,5 @@
 	return -ENODEV;
 }
 
-static inline u8 usb_bam_get_qdss_num(void)
-{
-	return -ENODEV;
-}
-
 #endif
 #endif				/* _USB_BAM_H_ */
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index a08e7de..16b60a1 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -613,13 +613,14 @@
 void msm_ipc_router_ipc_log_init(void)
 {
 	ipc_req_resp_log_txt =
-		ipc_log_context_create(REQ_RESP_IPC_LOG_PAGES, "req_resp");
+		ipc_log_context_create(REQ_RESP_IPC_LOG_PAGES,
+			"ipc_rtr_req_resp");
 	if (!ipc_req_resp_log_txt) {
 		pr_err("%s: Unable to create IPC logging for Req/Resp",
 			__func__);
 	}
 	ipc_ind_log_txt =
-		ipc_log_context_create(IND_IPC_LOG_PAGES, "indication");
+		ipc_log_context_create(IND_IPC_LOG_PAGES, "ipc_rtr_ind");
 	if (!ipc_ind_log_txt) {
 		pr_err("%s: Unable to create IPC logging for Indications",
 			__func__);
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index dc0b755..8fe69d9 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -145,6 +145,7 @@
  *				regulator's callback functions to prevent
  *				simultaneous updates to the pmic's phase
  *				voltage.
+ * @apcs_gcc_base		virtual address of the APCS GCC registers
  */
 struct pmic_gang_vreg {
 	const char		*name;
@@ -156,6 +157,7 @@
 	int			pmic_min_uV_for_retention;
 	bool			retention_enabled;
 	bool			use_phase_switching;
+	void __iomem		*apcs_gcc_base;
 };
 
 static struct pmic_gang_vreg *the_gang;
@@ -890,12 +892,12 @@
 	mb();
 }
 
-static void glb_init(struct platform_device *pdev)
+static void glb_init(void __iomem *apcs_gcc_base)
 {
 	/* configure bi-modal switch */
-	writel_relaxed(0x0008736E, MSM_APCS_GCC_BASE + PWR_GATE_CONFIG);
+	writel_relaxed(0x0008736E, apcs_gcc_base + PWR_GATE_CONFIG);
 	/* read kpss version */
-	version = readl_relaxed(MSM_APCS_GCC_BASE + VERSION);
+	version = readl_relaxed(apcs_gcc_base + VERSION);
 	pr_debug("version= 0x%x\n", version);
 }
 
@@ -1117,6 +1119,7 @@
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	struct pmic_gang_vreg *pvreg;
+	struct resource *res;
 
 	if (!dev->of_node) {
 		dev_err(dev, "device tree information missing\n");
@@ -1132,6 +1135,18 @@
 		return 0;
 	}
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_gcc");
+	if (!res) {
+		dev_err(&pdev->dev, "missing apcs gcc base addresses\n");
+		return -EINVAL;
+	}
+
+	pvreg->apcs_gcc_base = devm_ioremap(&pdev->dev, res->start,
+					    resource_size(res));
+
+	if (pvreg->apcs_gcc_base == NULL)
+		return -ENOMEM;
+
 	pvreg->name = "pmic_gang";
 	pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
 	pvreg->pmic_phase_count = -EINVAL;
@@ -1146,7 +1161,7 @@
 	pr_debug("name=%s inited\n", pvreg->name);
 
 	/* global initializtion */
-	glb_init(pdev);
+	glb_init(pvreg->apcs_gcc_base);
 
 	rc = of_platform_populate(node, NULL, NULL, dev);
 	if (rc) {
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 539a4fe..8194721 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -205,6 +205,8 @@
 	int best_level_iter = msm_lpm_level_count + 1;
 	bool irqs_detect = false;
 	bool gpio_detect = false;
+	bool modify_event_timer;
+	uint32_t next_wakeup_us = time_param->sleep_us;
 
 	if (!msm_lpm_levels)
 		return NULL;
@@ -219,6 +221,8 @@
 	for (i = 0; i < msm_lpm_level_count; i++) {
 		struct msm_rpmrs_level *level = &msm_lpm_levels[i];
 
+		modify_event_timer = false;
+
 		if (!level->available)
 			continue;
 
@@ -228,6 +232,23 @@
 		if (time_param->latency_us < level->latency_us)
 			continue;
 
+		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 ((sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) &&
 			!msm_lpm_irqs_detectable(&level->rs_limits,
 				irqs_detect, gpio_detect))
@@ -238,19 +259,19 @@
 			if (!cpu && msm_rpm_waiting_for_ack())
 					break;
 
-		if (time_param->sleep_us <= 1) {
+		if (next_wakeup_us <= 1) {
 			pwr = level->energy_overhead;
-		} 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)
+		} 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) /
-						time_param->sleep_us;
-			pwr += level->energy_overhead / time_param->sleep_us;
+						next_wakeup_us;
+			pwr += level->energy_overhead / next_wakeup_us;
 		}
 
 		if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
@@ -261,6 +282,14 @@
 			best_level_iter = i;
 			if (power)
 				*power = pwr;
+			if (modify_event_timer &&
+				(sleep_mode !=
+					MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT))
+				time_param->modified_time_us =
+					time_param->next_event_us -
+						best_level->latency_us;
+			else
+				time_param->modified_time_us = 0;
 		}
 	}
 	if (best_level && !lpm_level_permitted(best_level_iter))
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index aa42f5b..1954ec3 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -70,6 +70,11 @@
 
 #define MAX_SSR_REASON_LEN 81U
 
+/* External BHS */
+#define EXTERNAL_BHS_ON			BIT(0)
+#define EXTERNAL_BHS_STATUS		BIT(4)
+#define BHS_TIMEOUT_US			50
+
 struct mba_data {
 	void __iomem *metadata_base;
 	void __iomem *rmb_base;
@@ -81,7 +86,7 @@
 	void *adsp_state_notifier;
 	u32 img_length;
 	struct q6v5_data *q6;
-	int self_auth;
+	bool self_auth;
 	void *ramdump_dev;
 	void *smem_ramdump_dev;
 	bool crash_shutdown;
@@ -99,16 +104,34 @@
 {
 	int ret;
 	struct device *dev = drv->desc.dev;
+	u32 regval;
 
 	ret = regulator_enable(drv->vreg);
 	if (ret)
 		dev_err(dev, "Failed to enable modem regulator.\n");
 
+	if (drv->cxrail_bhs) {
+		regval = readl_relaxed(drv->cxrail_bhs);
+		regval |= EXTERNAL_BHS_ON;
+		writel_relaxed(regval, drv->cxrail_bhs);
+
+		ret = readl_poll_timeout(drv->cxrail_bhs, regval,
+			regval & EXTERNAL_BHS_STATUS, 1, BHS_TIMEOUT_US);
+	}
+
 	return ret;
 }
 
 static int pil_mss_power_down(struct q6v5_data *drv)
 {
+	u32 regval;
+
+	if (drv->cxrail_bhs) {
+		regval = readl_relaxed(drv->cxrail_bhs);
+		regval &= ~EXTERNAL_BHS_ON;
+		writel_relaxed(regval, drv->cxrail_bhs);
+	}
+
 	return regulator_disable(drv->vreg);
 }
 
@@ -198,10 +221,15 @@
 	pil_q6v5_shutdown(pil);
 
 	pil_mss_disable_clks(drv);
-	pil_mss_power_down(drv);
 
 	writel_relaxed(1, drv->restart_reg);
 
+	/*
+	 * access to the cx_rail_bhs is restricted until after the gcc_mss
+	 * reset is asserted once the PBL starts executing.
+	 */
+	pil_mss_power_down(drv);
+
 	drv->is_booted = false;
 
 	return 0;
@@ -215,11 +243,6 @@
 	unsigned long start_addr = pil_get_entry_addr(pil);
 	int ret;
 
-	/* Deassert reset to subsystem and wait for propagation */
-	writel_relaxed(0, drv->restart_reg);
-	mb();
-	udelay(2);
-
 	/*
 	 * Bring subsystem out of reset and enable required
 	 * regulators and clocks.
@@ -228,6 +251,11 @@
 	if (ret)
 		goto err_power;
 
+	/* Deassert reset to subsystem and wait for propagation */
+	writel_relaxed(0, drv->restart_reg);
+	mb();
+	udelay(2);
+
 	ret = pil_mss_enable_clks(drv);
 	if (ret)
 		goto err_clks;
@@ -679,8 +707,8 @@
 	q6_desc->owner = THIS_MODULE;
 	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 
-	of_property_read_u32(pdev->dev.of_node, "qcom,pil-self-auth",
-			     &drv->self_auth);
+	drv->self_auth = of_property_read_bool(pdev->dev.of_node,
+							"qcom,pil-self-auth");
 	if (drv->self_auth) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						    "rmb_base");
@@ -721,6 +749,13 @@
 		return ret;
 	}
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+		"cxrail_bhs_reg");
+	if (res)
+		q6->cxrail_bhs = devm_ioremap(&pdev->dev, res->start,
+					  resource_size(res));
+
+
 	q6->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
 	if (IS_ERR(q6->ahb_clk))
 		return PTR_ERR(q6->ahb_clk);
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 0d986a6..48d10df 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -22,12 +22,13 @@
 
 struct q6v5_data {
 	void __iomem *reg_base;
-	struct clk *xo;		/* XO clock source */
-	struct clk *ahb_clk;	/* PIL access to registers */
-	struct clk *axi_clk;	/* CPU access to memory */
-	struct clk *core_clk;	/* CPU core */
-	struct clk *reg_clk;	/* CPU access registers */
-	struct clk *rom_clk;	/* Boot ROM */
+	void __iomem *cxrail_bhs;  /* External BHS register */
+	struct clk *xo;		   /* XO clock source */
+	struct clk *ahb_clk;	   /* PIL access to registers */
+	struct clk *axi_clk;	   /* CPU access to memory */
+	struct clk *core_clk;	   /* CPU core */
+	struct clk *reg_clk;	   /* CPU access registers */
+	struct clk *rom_clk;	   /* Boot ROM */
 	void __iomem *axi_halt_base;
 	void __iomem *restart_reg;
 	struct regulator *vreg;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 0867676..1c9f968 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -107,43 +107,40 @@
 			break;
 		}
 	}
-	if (index == -1)
+	if (index == -1) {
 		pr_alert("diag: No matching PID for DCI data\n");
+		return;
+	}
 	/* Using PID of client process, find client buffer */
-	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
-		if (driver->dci_client_tbl[i].client != NULL) {
-			if (curr_client_pid ==
-				driver->dci_client_tbl[i].client->tgid) {
-				/* copy pkt rsp in client buf */
-				entry = &(driver->dci_client_tbl[i]);
-				if (DCI_CHK_CAPACITY(entry, 8+write_len)) {
-					pr_alert("diag: create capacity for pkt rsp\n");
-					entry->total_capacity += 8+write_len;
-					temp_buf = krealloc(entry->dci_data,
-					entry->total_capacity, GFP_KERNEL);
-					if (!temp_buf) {
-						pr_err("diag: DCI realloc failed\n");
-						break;
-					} else {
-						entry->dci_data = temp_buf;
-					}
-				}
-				*(int *)(entry->dci_data+entry->data_len) =
-							DCI_PKT_RSP_TYPE;
-				entry->data_len += 4;
-				*(int *)(entry->dci_data+entry->data_len)
-								= write_len;
-				entry->data_len += 4;
-				memcpy(entry->dci_data+entry->data_len,
-					buf+4+cmd_code_len, write_len);
-				entry->data_len += write_len;
-				/* delete immediate response entry */
-				if (driver->smd_dci[MODEM_DATA].
-					buf_in_1[8+cmd_code_len] != 0x80)
-					driver->req_tracking_tbl[index].pid = 0;
-				break;
+	i = diag_dci_find_client_index(curr_client_pid);
+	if (i != DCI_CLIENT_INDEX_INVALID) {
+		/* copy pkt rsp in client buf */
+		entry = &(driver->dci_client_tbl[i]);
+		if (DCI_CHK_CAPACITY(entry, 8+write_len)) {
+			pr_alert("diag: create capacity for pkt rsp\n");
+			entry->total_capacity += 8+write_len;
+			temp_buf = krealloc(entry->dci_data,
+			entry->total_capacity, GFP_KERNEL);
+			if (!temp_buf) {
+				pr_err("diag: DCI realloc failed\n");
+				return;
+			} else {
+				entry->dci_data = temp_buf;
 			}
 		}
+		*(int *)(entry->dci_data+entry->data_len) =
+					DCI_PKT_RSP_TYPE;
+		entry->data_len += 4;
+		*(int *)(entry->dci_data+entry->data_len)
+						= write_len;
+		entry->data_len += 4;
+		memcpy(entry->dci_data+entry->data_len,
+			buf+4+cmd_code_len, write_len);
+		entry->data_len += write_len;
+		/* delete immediate response entry */
+		if (driver->smd_dci[MODEM_DATA].
+			buf_in_1[8+cmd_code_len] != 0x80)
+			driver->req_tracking_tbl[index].pid = 0;
 	}
 }
 
@@ -527,16 +524,8 @@
 		}
 	} else if (*(int *)temp == DCI_LOG_TYPE) {
 		/* find client id and table */
-		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
-			if (driver->dci_client_tbl[i].client != NULL) {
-				if (driver->dci_client_tbl[i].client->tgid ==
-							current->tgid) {
-					found = 1;
-					break;
-				}
-			}
-		}
-		if (!found) {
+		i = diag_dci_find_client_index(current->tgid);
+		if (i == DCI_CLIENT_INDEX_INVALID) {
 			pr_err("diag: dci client not registered/found\n");
 			return ret;
 		}
@@ -610,16 +599,8 @@
 		ret = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
 	} else if (*(int *)temp == DCI_EVENT_TYPE) {
 		/* find client id and table */
-		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
-			if (driver->dci_client_tbl[i].client != NULL) {
-				if (driver->dci_client_tbl[i].client->tgid ==
-							current->tgid) {
-					found = 1;
-					break;
-				}
-			}
-		}
-		if (!found) {
+		i = diag_dci_find_client_index(current->tgid);
+		if (i == DCI_CLIENT_INDEX_INVALID) {
 			pr_err("diag: dci client not registered/found\n");
 			return ret;
 		}
@@ -672,6 +653,22 @@
 	return ret;
 }
 
+int diag_dci_find_client_index(int client_id)
+{
+	int i, ret = DCI_CLIENT_INDEX_INVALID;
+
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		if (driver->dci_client_tbl[i].client != NULL) {
+			if (driver->dci_client_tbl[i].client->tgid ==
+					client_id) {
+				ret = i;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 void update_dci_cumulative_event_mask(int offset, uint8_t byte_mask)
 {
 	int i;
@@ -698,6 +695,69 @@
 	mutex_unlock(&dci_event_mask_mutex);
 }
 
+void clear_client_dci_cumulative_event_mask(int client_index)
+{
+	int i, j;
+	uint8_t *update_ptr = dci_cumulative_event_mask;
+	uint8_t *event_mask_ptr, *client_event_mask_ptr, byte_mask = 0;
+	bool is_set = false;
+
+	event_mask_ptr =
+		(driver->dci_client_tbl[client_index].dci_event_mask);
+
+	mutex_lock(&dci_event_mask_mutex);
+	for (i = 0; i < DCI_EVENT_MASK_SIZE; i++) {
+		is_set = false;
+		/* Already cleared event masks need not to be considered */
+		if (*event_mask_ptr != 0) {
+			byte_mask = *event_mask_ptr;
+		} else {
+			update_ptr++;
+			event_mask_ptr++;
+			continue;
+		}
+		for (j = 0; j < MAX_DCI_CLIENTS; j++) {
+			/* continue searching for valid client */
+			if (driver->dci_client_tbl[j].client == NULL ||
+				client_index == j)
+				continue;
+			client_event_mask_ptr =
+				(driver->dci_client_tbl[j].dci_event_mask);
+			client_event_mask_ptr += i;
+			if (*client_event_mask_ptr & byte_mask) {
+				/*
+				* Break if another client has same
+				* event mask set
+				*/
+				if ((*client_event_mask_ptr &
+					byte_mask) == byte_mask) {
+					is_set = true;
+					break;
+				} else {
+					byte_mask =
+					(~(*client_event_mask_ptr) &
+					byte_mask);
+					is_set = false;
+				}
+			}
+		}
+		/*
+		* Clear only if this client has event mask set else
+		* don't update cumulative event mask ptr
+		*/
+		if (is_set == false)
+			*update_ptr &= ~byte_mask;
+
+		update_ptr++;
+		event_mask_ptr++;
+	}
+	event_mask_ptr =
+		(driver->dci_client_tbl[client_index].dci_event_mask);
+	memset(event_mask_ptr, 0, DCI_EVENT_MASK_SIZE);
+	mutex_unlock(&dci_event_mask_mutex);
+}
+
+
 int diag_send_dci_event_mask(smd_channel_t *ch)
 {
 	void *buf = driver->buf_event_mask_update;
@@ -777,6 +837,87 @@
 	mutex_unlock(&dci_log_mask_mutex);
 }
 
+void clear_client_dci_cumulative_log_mask(int client_index)
+{
+	int i, j, k;
+	uint8_t *update_ptr = dci_cumulative_log_mask;
+	uint8_t *log_mask_ptr, *client_log_mask_ptr, byte_mask = 0;
+	bool is_set = false;
+
+	log_mask_ptr = driver->dci_client_tbl[client_index].dci_log_mask;
+
+	mutex_lock(&dci_log_mask_mutex);
+	*update_ptr = 0;
+	/* set the equipment IDs */
+	for (i = 0; i < 16; i++)
+		*(update_ptr + (i*514)) = i;
+
+	/* update cumulative log mask ptr*/
+	update_ptr += 2;
+	log_mask_ptr += 2;
+	for (i = 0; i < 16; i++) {
+		for (j = 0; j < 512; j++) {
+			is_set = false;
+			/*
+			* Already cleared log masks need
+			* not to be considered
+			*/
+			if (*log_mask_ptr != 0) {
+				byte_mask = *log_mask_ptr;
+			} else {
+				update_ptr++;
+				log_mask_ptr++;
+				continue;
+			}
+			for (k = 0; k < MAX_DCI_CLIENTS; k++) {
+				/* continue searching for valid client */
+				if (driver->dci_client_tbl[k].client == NULL ||
+					client_index == k)
+					continue;
+				client_log_mask_ptr =
+				 (driver->dci_client_tbl[k].dci_log_mask);
+				client_log_mask_ptr += (i*514) + 2 + j;
+				if (*client_log_mask_ptr & byte_mask) {
+					/*
+					* Break if another client has same
+					* log mask set
+					*/
+					if ((*client_log_mask_ptr &
+						byte_mask) == byte_mask) {
+						is_set = true;
+						break;
+					} else {
+						byte_mask =
+						 (~(*client_log_mask_ptr) &
+						 byte_mask);
+						is_set = false;
+					}
+				}
+			}
+			/*
+			* Clear only if this client has log mask set else
+			* don't update cumulative log mask ptr
+			*/
+			if (is_set == false) {
+				/*
+				* Update the dirty bit for the equipment
+				* whose mask is changing
+				*/
+				dci_cumulative_log_mask[1+(i*514)] = 1;
+				*update_ptr &= ~byte_mask;
+			}
+
+			update_ptr++;
+			log_mask_ptr++;
+		}
+		update_ptr += 2;
+		log_mask_ptr += 2;
+	}
+	log_mask_ptr = driver->dci_client_tbl[client_index].dci_log_mask;
+	memset(log_mask_ptr, 0, DCI_LOG_MASK_SIZE);
+	mutex_unlock(&dci_log_mask_mutex);
+}
+
 int diag_send_dci_log_mask(smd_channel_t *ch)
 {
 	void *buf = driver->buf_log_mask_update;
@@ -886,10 +1027,12 @@
 	mutex_init(&driver->dci_mutex);
 	mutex_init(&dci_log_mask_mutex);
 	mutex_init(&dci_event_mask_mutex);
-	success = diag_smd_constructor(&driver->smd_dci[MODEM_DATA],
-					MODEM_DATA, SMD_DCI_TYPE);
-	if (!success)
-		goto err;
+	for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
+		success = diag_smd_constructor(&driver->smd_dci[i],
+					i, SMD_DCI_TYPE);
+		if (!success)
+			goto err;
+	}
 
 	if (driver->req_tracking_tbl == NULL) {
 		driver->req_tracking_tbl = kzalloc(dci_max_reg *
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 0f47740..9187516 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -23,6 +23,8 @@
 #define SET_LOG_MASK		1
 #define DISABLE_LOG_MASK	0
 #define MAX_EVENT_SIZE		512
+#define DCI_CLIENT_INDEX_INVALID -1
+
 
 /* 16 log code categories, each has:
  * 1 bytes equip id + 1 dirty byte + 512 byte max log mask
@@ -86,14 +88,17 @@
 int diag_send_dci_pkt(struct diag_master_table entry, unsigned char *buf,
 							 int len, int index);
 void extract_dci_pkt_rsp(unsigned char *buf);
+int diag_dci_find_client_index(int client_id);
 /* DCI Log streaming functions */
 void create_dci_log_mask_tbl(unsigned char *tbl_buf);
 void update_dci_cumulative_log_mask(int offset, unsigned int byte_index,
 						uint8_t byte_mask);
+void clear_client_dci_cumulative_log_mask(int client_index);
 int diag_send_dci_log_mask(smd_channel_t *ch);
 void extract_dci_log(unsigned char *buf);
 /* DCI event streaming functions */
 void update_dci_cumulative_event_mask(int offset, uint8_t byte_mask);
+void clear_client_dci_cumulative_event_mask(int client_index);
 int diag_send_dci_event_mask(smd_channel_t *ch);
 void extract_dci_events(unsigned char *buf);
 void create_dci_event_mask_tbl(unsigned char *tbl_buf);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 13e52df..2809900 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -245,7 +245,7 @@
 
 static int diagchar_close(struct inode *inode, struct file *file)
 {
-	int i = 0;
+	int i = -1;
 	struct diagchar_priv *diagpriv_data = file->private_data;
 
 	pr_debug("diag: process exit %s\n", current->comm);
@@ -261,14 +261,9 @@
 	* This will specially help in case of ungraceful exit of any DCI client
 	* This call will remove any pending registrations of such client
 	*/
-	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
-		if (driver->dci_client_tbl[i].client &&
-			driver->dci_client_tbl[i].client->tgid ==
-							 current->tgid) {
-			diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
-			break;
-		}
-	}
+	if (diag_dci_find_client_index(current->tgid) !=
+		 DCI_CLIENT_INDEX_INVALID)
+		diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
 	/* If the exiting process is the socket process */
 	if (driver->socket_process &&
 		(driver->socket_process->tgid == current->tgid)) {
@@ -530,7 +525,7 @@
 long diagchar_ioctl(struct file *filp,
 			   unsigned int iocmd, unsigned long ioarg)
 {
-	int i, j, temp, success = -1, status;
+	int i, j, temp, success = -1, status, index = -1;
 	unsigned int count_entries = 0, interim_count = 0;
 	void *temp_buf;
 	uint16_t support_list = 0;
@@ -731,19 +726,40 @@
 		return driver->dci_client_id;
 	} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
 		success = -1;
-		/* Delete this process from DCI table */
+		/*
+		* Clear log/event masks and send updated
+		* masks to peripherals
+		*/
 		mutex_lock(&driver->dci_mutex);
+		index = diag_dci_find_client_index(current->tgid);
+		if (index != DCI_CLIENT_INDEX_INVALID) {
+			/* clear respective cumulative log masks */
+			clear_client_dci_cumulative_log_mask(index);
+			/* send updated log mask to peripherals */
+			success =
+			diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+			if (success != DIAG_DCI_NO_ERROR) {
+				mutex_unlock(&driver->dci_mutex);
+				return success;
+			}
+			/* clear respective cumulative event masks */
+			clear_client_dci_cumulative_event_mask(index);
+			/* send updated event mask to peripherals */
+			success =
+			diag_send_dci_event_mask(
+				driver->smd_cntl[MODEM_DATA].ch);
+			if (success != DIAG_DCI_NO_ERROR) {
+				mutex_unlock(&driver->dci_mutex);
+				return success;
+			}
+		}
+		/* Delete this process from DCI table */
 		for (i = 0; i < dci_max_reg; i++)
 			if (driver->req_tracking_tbl[i].pid == current->tgid)
 				driver->req_tracking_tbl[i].pid = 0;
-		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
-			if (driver->dci_client_tbl[i].client &&
-			driver->dci_client_tbl[i].client->tgid ==
-							 current->tgid) {
-				driver->dci_client_tbl[i].client = NULL;
-				success = i;
-				break;
-			}
+		if (index != DCI_CLIENT_INDEX_INVALID) {
+			driver->dci_client_tbl[index].client = NULL;
+			success = index;
 		}
 		if (success >= 0)
 			driver->num_dci_client--;
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b1cab9b..c1f2423 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -127,7 +127,7 @@
 	void (*irq_control)(struct adreno_device *, int);
 	unsigned int (*irq_pending)(struct adreno_device *);
 	void * (*snapshot)(struct adreno_device *, void *, int *, int);
-	void (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
+	int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
 	void (*start)(struct adreno_device *);
 	unsigned int (*busy_cycles)(struct adreno_device *);
 };
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 6db6e7b..335d407 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1825,13 +1825,16 @@
 		(mh & kgsl_mmu_get_int_mask())) ? 1 : 0;
 }
 
-static void a2xx_rb_init(struct adreno_device *adreno_dev,
+static int a2xx_rb_init(struct adreno_device *adreno_dev,
 			struct adreno_ringbuffer *rb)
 {
 	unsigned int *cmds, cmds_gpu;
 
 	/* ME_INIT */
 	cmds = adreno_ringbuffer_allocspace(rb, NULL, 19);
+	if (cmds == NULL)
+		return -ENOMEM;
+
 	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
 
 	GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18));
@@ -1884,6 +1887,8 @@
 	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
 
 	adreno_ringbuffer_submit(rb);
+
+	return 0;
 }
 
 static unsigned int a2xx_busy_cycles(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 73a7f52..08c800e 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2486,11 +2486,14 @@
 	}
 }
 
-static void a3xx_rb_init(struct adreno_device *adreno_dev,
+static int a3xx_rb_init(struct adreno_device *adreno_dev,
 			 struct adreno_ringbuffer *rb)
 {
 	unsigned int *cmds, cmds_gpu;
 	cmds = adreno_ringbuffer_allocspace(rb, NULL, 18);
+	if (cmds == NULL)
+		return -ENOMEM;
+
 	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint) * (rb->wptr - 18);
 
 	GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 17));
@@ -2514,6 +2517,8 @@
 	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
 
 	adreno_ringbuffer_submit(rb);
+
+	return 0;
 }
 
 static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit)
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1d25646..5cdf911 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -445,7 +445,9 @@
 	adreno_regwrite(device, REG_CP_ME_CNTL, 0);
 
 	/* ME init is GPU specific, so jump into the sub-function */
-	adreno_dev->gpudev->rb_init(adreno_dev, rb);
+	status = adreno_dev->gpudev->rb_init(adreno_dev, rb);
+	if (status)
+		return status;
 
 	/* idle device to validate ME INIT */
 	status = adreno_idle(device);
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 26be9da..c8229e7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -177,10 +177,11 @@
 	{ 8, 2 },
 };
 
-static void ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt,
+static int ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt,
 	unsigned int ptbase)
 {
 	unsigned int block, source, type;
+	int ret = 0;
 
 	/*
 	 * The object here is to find indirect shaders i.e - shaders loaded from
@@ -192,7 +193,7 @@
 	 */
 
 	if (type3_pkt_size(pkt[0]) < 2)
-		return;
+		return 0;
 
 	/*
 	 * pkt[1] 18:16 - source
@@ -220,8 +221,14 @@
 				pkt[2] & 0xFFFFFFFC,
 				(((pkt[1] >> 22) & 0x03FF) * unitsize) << 2,
 				SNAPSHOT_GPU_OBJECT_SHADER);
+
+		if (ret < 0)
+			return -EINVAL;
+
 		snapshot_frozen_objsize += ret;
 	}
+
+	return ret;
 }
 
 /*
@@ -229,23 +236,31 @@
  * visiblity stream size buffer.
  */
 
-static void ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt,
+static int ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt,
 	unsigned int ptbase)
 {
 	int ret;
 
 	if (type3_pkt_size(pkt[0]) < 2)
-		return;
+		return 0;
 
 	/* Visiblity stream buffer */
 	ret = kgsl_snapshot_get_object(device, ptbase, pkt[1], 0,
 			SNAPSHOT_GPU_OBJECT_GENERIC);
+
+	if (ret < 0)
+		return -EINVAL;
+
 	snapshot_frozen_objsize += ret;
 
 	/* visiblity stream size buffer (fixed size 8 dwords) */
 	ret = kgsl_snapshot_get_object(device, ptbase, pkt[2], 32,
 			SNAPSHOT_GPU_OBJECT_GENERIC);
-	snapshot_frozen_objsize += ret;
+
+	if (ret >= 0)
+		snapshot_frozen_objsize += ret;
+
+	return ret;
 }
 
 /*
@@ -254,13 +269,13 @@
  * buffers that are written to as frozen
  */
 
-static void ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt,
+static int ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt,
 	unsigned int ptbase)
 {
 	int ret;
 
 	if (type3_pkt_size(pkt[0]) < 1)
-		return;
+		return 0;
 
 	/*
 	 * The address is where the data in the rest of this packet is written
@@ -272,7 +287,10 @@
 	ret = kgsl_snapshot_get_object(device, ptbase, pkt[1] & 0xFFFFFFFC, 0,
 		SNAPSHOT_GPU_OBJECT_GENERIC);
 
-	snapshot_frozen_objsize += ret;
+	if (ret >= 0)
+		snapshot_frozen_objsize += ret;
+
+	return ret;
 }
 
 /*
@@ -282,19 +300,22 @@
  * frozen with the others
  */
 
-static void ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt,
+static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt,
 	unsigned int ptbase)
 {
-	int ret, i;
+	int ret = 0, i;
 
 	if (type3_pkt_size(pkt[0]) < 3)
-		return;
+		return 0;
 
 	/*  DRAW_IDX may have a index buffer pointer */
 
 	if (type3_pkt_size(pkt[0]) > 3) {
 		ret = kgsl_snapshot_get_object(device, ptbase, pkt[4], pkt[5],
 			SNAPSHOT_GPU_OBJECT_GENERIC);
+		if (ret < 0)
+			return -EINVAL;
+
 		snapshot_frozen_objsize += ret;
 	}
 
@@ -310,6 +331,9 @@
 			ret = kgsl_snapshot_get_object(device, ptbase,
 				vsc_pipe[i].base, vsc_pipe[i].size,
 				SNAPSHOT_GPU_OBJECT_GENERIC);
+			if (ret < 0)
+				return -EINVAL;
+
 			snapshot_frozen_objsize += ret;
 		}
 	}
@@ -320,6 +344,9 @@
 		ret = kgsl_snapshot_get_object(device, ptbase,
 				vsc_size_address, 32,
 				SNAPSHOT_GPU_OBJECT_GENERIC);
+		if (ret < 0)
+			return -EINVAL;
+
 		snapshot_frozen_objsize += ret;
 	}
 
@@ -328,6 +355,9 @@
 		ret = kgsl_snapshot_get_object(device, ptbase,
 				sp_vs_pvt_mem_addr, 8192,
 				SNAPSHOT_GPU_OBJECT_GENERIC);
+		if (ret < 0)
+			return -EINVAL;
+
 		snapshot_frozen_objsize += ret;
 		sp_vs_pvt_mem_addr = 0;
 	}
@@ -336,6 +366,9 @@
 		ret = kgsl_snapshot_get_object(device, ptbase,
 				sp_fs_pvt_mem_addr, 8192,
 				SNAPSHOT_GPU_OBJECT_GENERIC);
+		if (ret < 0)
+			return -EINVAL;
+
 		snapshot_frozen_objsize += ret;
 		sp_fs_pvt_mem_addr = 0;
 	}
@@ -358,6 +391,9 @@
 			ret = kgsl_snapshot_get_object(device, ptbase,
 				vbo[i].base,
 				0, SNAPSHOT_GPU_OBJECT_GENERIC);
+			if (ret < 0)
+				return -EINVAL;
+
 			snapshot_frozen_objsize += ret;
 		}
 
@@ -367,6 +403,8 @@
 
 	vfd_control_0 = 0;
 	vfd_index_max = 0;
+
+	return ret;
 }
 
 /*
@@ -374,23 +412,21 @@
  * such as additional GPU buffers to grab or a draw initator
  */
 
-static void ib_parse_type3(struct kgsl_device *device, unsigned int *ptr,
+static int ib_parse_type3(struct kgsl_device *device, unsigned int *ptr,
 	unsigned int ptbase)
 {
-	switch (cp_type3_opcode(*ptr)) {
-	case CP_LOAD_STATE:
-		ib_parse_load_state(device, ptr, ptbase);
-		break;
-	case CP_SET_BIN_DATA:
-		ib_parse_set_bin_data(device, ptr, ptbase);
-		break;
-	case CP_MEM_WRITE:
-		ib_parse_mem_write(device, ptr, ptbase);
-		break;
-	case CP_DRAW_INDX:
-		ib_parse_draw_indx(device, ptr, ptbase);
-		break;
-	}
+	int opcode = cp_type3_opcode(*ptr);
+
+	if (opcode == CP_LOAD_STATE)
+		return ib_parse_load_state(device, ptr, ptbase);
+	else if (opcode == CP_SET_BIN_DATA)
+		return ib_parse_set_bin_data(device, ptr, ptbase);
+	else if (opcode == CP_MEM_WRITE)
+		return ib_parse_mem_write(device, ptr, ptbase);
+	else if (opcode == CP_DRAW_INDX)
+		return ib_parse_draw_indx(device, ptr, ptbase);
+
+	return 0;
 }
 
 /*
@@ -474,9 +510,12 @@
 	}
 }
 
+static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase,
+		unsigned int gpuaddr, unsigned int dwords);
+
 /* Add an IB as a GPU object, but first, parse it to find more goodies within */
 
-static void ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase,
+static int ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase,
 		unsigned int gpuaddr, unsigned int dwords)
 {
 	int i, ret, rem = dwords;
@@ -487,13 +526,13 @@
 	 */
 
 	if (kgsl_snapshot_have_object(device, ptbase, gpuaddr, dwords << 2))
-		return;
+		return 0;
 
 	src = (unsigned int *) adreno_convertaddr(device, ptbase, gpuaddr,
 		dwords << 2);
 
 	if (src == NULL)
-		return;
+		return -EINVAL;
 
 	for (i = 0; rem > 0; rem--, i++) {
 		int pktsize;
@@ -513,26 +552,23 @@
 			if (adreno_cmd_is_ib(src[i])) {
 				unsigned int gpuaddr = src[i + 1];
 				unsigned int size = src[i + 2];
-				unsigned int ibbase;
 
-				/* Address of the last processed IB2 */
-				kgsl_regread(device, REG_CP_IB2_BASE, &ibbase);
+				ret = parse_ib(device, ptbase, gpuaddr, size);
 
+				/* If adding the IB failed then stop parsing */
+				if (ret < 0)
+					goto done;
+			} else {
+				ret = ib_parse_type3(device, &src[i], ptbase);
 				/*
-				 * If this is the last IB2 that was executed,
-				 * then push it to make sure it goes into the
-				 * static space
+				 * If the parse function failed (probably
+				 * because of a bad decode) then bail out and
+				 * just capture the binary IB data
 				 */
 
-				if (ibbase == gpuaddr)
-					push_object(device,
-						SNAPSHOT_OBJ_TYPE_IB, ptbase,
-						gpuaddr, size);
-				else
-					ib_add_gpu_object(device, ptbase,
-						gpuaddr, size);
-			} else
-				ib_parse_type3(device, &src[i], ptbase);
+				if (ret < 0)
+					goto done;
+			}
 		} else if (pkt_is_type0(src[i])) {
 			ib_parse_type0(device, &src[i], ptbase);
 		}
@@ -541,10 +577,44 @@
 		rem -= pktsize;
 	}
 
+done:
 	ret = kgsl_snapshot_get_object(device, ptbase, gpuaddr, dwords << 2,
 		SNAPSHOT_GPU_OBJECT_IB);
 
-	snapshot_frozen_objsize += ret;
+	if (ret >= 0)
+		snapshot_frozen_objsize += ret;
+
+	return ret;
+}
+
+/*
+ * We want to store the last executed IB1 and IB2 in the static region to ensure
+ * that we get at least some information out of the snapshot even if we can't
+ * access the dynamic data from the sysfs file.  Push all other IBs on the
+ * dynamic list
+ */
+static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase,
+		unsigned int gpuaddr, unsigned int dwords)
+{
+	unsigned int ib1base, ib2base;
+	int ret = 0;
+
+	/*
+	 * Check the IB address - if it is either the last executed IB1 or the
+	 * last executed IB2 then push it into the static blob otherwise put
+	 * it in the dynamic list
+	 */
+
+	kgsl_regread(device, REG_CP_IB1_BASE, &ib1base);
+	kgsl_regread(device, REG_CP_IB2_BASE, &ib2base);
+
+	if (gpuaddr == ib1base || gpuaddr == ib2base)
+		push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
+			gpuaddr, dwords);
+	else
+		ret = ib_add_gpu_object(device, ptbase, gpuaddr, dwords);
+
+	return ret;
 }
 
 /* Snapshot the ringbuffer memory */
@@ -697,12 +767,11 @@
 			 * others get marked at GPU objects
 			 */
 
-			if (ibaddr == ibbase || memdesc != NULL)
+			if (memdesc != NULL)
 				push_object(device, SNAPSHOT_OBJ_TYPE_IB,
 					ptbase, ibaddr, ibsize);
 			else
-				ib_add_gpu_object(device, ptbase, ibaddr,
-					ibsize);
+				parse_ib(device, ptbase, ibaddr, ibsize);
 		}
 
 		index = index + 1;
@@ -725,7 +794,7 @@
 	struct kgsl_snapshot_obj *obj = priv;
 	unsigned int *src = obj->ptr;
 	unsigned int *dst = snapshot + sizeof(*header);
-	int i;
+	int i, ret;
 
 	if (remain < (obj->dwords << 2) + sizeof(*header)) {
 		KGSL_DRV_ERR(device,
@@ -747,10 +816,14 @@
 				continue;
 
 			if (adreno_cmd_is_ib(*src))
-				push_object(device, SNAPSHOT_OBJ_TYPE_IB,
-					obj->ptbase, src[1], src[2]);
+				ret = parse_ib(device, obj->ptbase, src[1],
+					src[2]);
 			else
-				ib_parse_type3(device, src, obj->ptbase);
+				ret = ib_parse_type3(device, src, obj->ptbase);
+
+			/* Stop parsing if the type3 decode fails */
+			if (ret < 0)
+				break;
 		}
 	}
 
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index f967cd2..76998db 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2013, 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
@@ -247,8 +247,8 @@
 
 	kgsl_get_memory_usage(usage, sizeof(usage), m->flags);
 
-	seq_printf(s, "%08x %8d %5d %5s %10s %16s %5d\n",
-			m->gpuaddr, m->size, entry->id, flags,
+	seq_printf(s, "%08x %08lx %8d %5d %5s %10s %16s %5d\n",
+			m->gpuaddr, m->useraddr, m->size, entry->id, flags,
 			memtype_str(entry->memtype), usage, m->sglen);
 }
 
@@ -259,8 +259,9 @@
 	struct kgsl_process_private *private = s->private;
 	int next = 0;
 
-	seq_printf(s, "%8s %8s %5s %5s %10s %16s %5s\n",
-		   "gpuaddr", "size", "id", "flags", "type", "usage", "sglen");
+	seq_printf(s, "%8s %8s %8s %5s %5s %10s %16s %5s\n",
+		   "gpuaddr", "useraddr", "size", "id", "flags", "type",
+		   "usage", "sglen");
 
 	/* print all entries with a GPU address */
 	spin_lock(&private->mem_lock);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 18aed14..f71cf8c 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -68,8 +68,10 @@
 	device = kgsl_driver.devp[KGSL_DEVICE_3D0];
 	if (device->mmu.mmu_ops->mmu_setup_pt != NULL) {
 		status = device->mmu.mmu_ops->mmu_setup_pt(&device->mmu, pt);
-		if (status)
+		if (status) {
+			i = KGSL_DEVICE_MAX - 1;
 			goto error_pt;
+		}
 	}
 	return status;
 error_pt:
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index e9bbac8..0935f64 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -339,14 +339,14 @@
 	if (entry == NULL) {
 		KGSL_DRV_ERR(device, "Unable to find GPU buffer %8.8X\n",
 				gpuaddr);
-		return 0;
+		return -EINVAL;
 	}
 
 	/* We can't freeze external memory, because we don't own it */
 	if (entry->memtype != KGSL_MEM_ENTRY_KERNEL) {
 		KGSL_DRV_ERR(device,
 			"Only internal GPU buffers can be frozen\n");
-		return 0;
+		return -EINVAL;
 	}
 
 	/*
@@ -369,7 +369,7 @@
 	if (size + offset > entry->memdesc.size) {
 		KGSL_DRV_ERR(device, "Invalid size for GPU buffer %8.8X\n",
 				gpuaddr);
-		return 0;
+		return -EINVAL;
 	}
 
 	/* If the buffer is already on the list, skip it */
@@ -386,14 +386,14 @@
 	if (kgsl_memdesc_map(&entry->memdesc) == NULL) {
 		KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n",
 				gpuaddr);
-		return 0;
+		return -EINVAL;
 	}
 
 	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
 
 	if (obj == NULL) {
 		KGSL_DRV_ERR(device, "Unable to allocate memory\n");
-		return 0;
+		return -EINVAL;
 	}
 
 	/* Ref count the mem entry */
@@ -518,6 +518,7 @@
 	struct kgsl_snapshot_header *header = device->snapshot;
 	int remain = device->snapshot_maxsize - sizeof(*header);
 	void *snapshot;
+	struct timespec boot;
 
 	/*
 	 * The first hang is always the one we are interested in. To
@@ -559,7 +560,13 @@
 		snapshot = device->ftbl->snapshot(device, snapshot, &remain,
 			hang);
 
-	device->snapshot_timestamp = get_seconds();
+	/*
+	 * The timestamp is the seconds since boot so it is easier to match to
+	 * the kernel log
+	 */
+
+	getboottime(&boot);
+	device->snapshot_timestamp = get_seconds() - boot.tv_sec;
 	device->snapshot_size = (int) (snapshot - device->snapshot);
 
 	/* Freeze the snapshot on a hang until it gets read */
@@ -655,7 +662,7 @@
 /* Show the timestamp of the last collected snapshot */
 static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%x\n", device->snapshot_timestamp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_timestamp);
 }
 
 /* manually trigger a new snapshot to be collected */
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 31e8379..714cd8c 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -29,6 +29,11 @@
 
 struct uhid_device {
 	struct mutex devlock;
+	bool running;
+
+	__u8 *rd_data;
+	uint rd_size;
+
 	struct hid_device *hid;
 	struct uhid_event input_buf;
 
@@ -37,6 +42,12 @@
 	__u8 head;
 	__u8 tail;
 	struct uhid_event *outq[UHID_BUFSIZE];
+
+	struct mutex report_lock;
+	wait_queue_head_t report_wait;
+	atomic_t report_done;
+	atomic_t report_id;
+	struct uhid_event report_buf;
 };
 
 static struct miscdevice uhid_misc;
@@ -75,6 +86,316 @@
 	return 0;
 }
 
+static int uhid_hid_start(struct hid_device *hid)
+{
+	struct uhid_device *uhid = hid->driver_data;
+
+	return uhid_queue_event(uhid, UHID_START);
+}
+
+static void uhid_hid_stop(struct hid_device *hid)
+{
+	struct uhid_device *uhid = hid->driver_data;
+
+	hid->claimed = 0;
+	uhid_queue_event(uhid, UHID_STOP);
+}
+
+static int uhid_hid_open(struct hid_device *hid)
+{
+	struct uhid_device *uhid = hid->driver_data;
+
+	return uhid_queue_event(uhid, UHID_OPEN);
+}
+
+static void uhid_hid_close(struct hid_device *hid)
+{
+	struct uhid_device *uhid = hid->driver_data;
+
+	uhid_queue_event(uhid, UHID_CLOSE);
+}
+
+static int uhid_hid_input(struct input_dev *input, unsigned int type,
+			  unsigned int code, int value)
+{
+	struct hid_device *hid = input_get_drvdata(input);
+	struct uhid_device *uhid = hid->driver_data;
+	unsigned long flags;
+	struct uhid_event *ev;
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return -ENOMEM;
+
+	ev->type = UHID_OUTPUT_EV;
+	ev->u.output_ev.type = type;
+	ev->u.output_ev.code = code;
+	ev->u.output_ev.value = value;
+
+	spin_lock_irqsave(&uhid->qlock, flags);
+	uhid_queue(uhid, ev);
+	spin_unlock_irqrestore(&uhid->qlock, flags);
+
+	return 0;
+}
+
+static int uhid_hid_parse(struct hid_device *hid)
+{
+	struct uhid_device *uhid = hid->driver_data;
+
+	return hid_parse_report(hid, uhid->rd_data, uhid->rd_size);
+}
+
+static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum,
+			    __u8 *buf, size_t count, unsigned char rtype)
+{
+	struct uhid_device *uhid = hid->driver_data;
+	__u8 report_type;
+	struct uhid_event *ev;
+	unsigned long flags;
+	int ret;
+	size_t uninitialized_var(len);
+	struct uhid_feature_answer_req *req;
+
+	if (!uhid->running)
+		return -EIO;
+
+	switch (rtype) {
+	case HID_FEATURE_REPORT:
+		report_type = UHID_FEATURE_REPORT;
+		break;
+	case HID_OUTPUT_REPORT:
+		report_type = UHID_OUTPUT_REPORT;
+		break;
+	case HID_INPUT_REPORT:
+		report_type = UHID_INPUT_REPORT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&uhid->report_lock);
+	if (ret)
+		return ret;
+
+	ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+	if (!ev) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	spin_lock_irqsave(&uhid->qlock, flags);
+	ev->type = UHID_FEATURE;
+	ev->u.feature.id = atomic_inc_return(&uhid->report_id);
+	ev->u.feature.rnum = rnum;
+	ev->u.feature.rtype = report_type;
+
+	atomic_set(&uhid->report_done, 0);
+	uhid_queue(uhid, ev);
+	spin_unlock_irqrestore(&uhid->qlock, flags);
+
+	ret = wait_event_interruptible_timeout(uhid->report_wait,
+				atomic_read(&uhid->report_done), 5 * HZ);
+
+	/*
+	 * Make sure "uhid->running" is cleared on shutdown before
+	 * "uhid->report_done" is set.
+	 */
+	smp_rmb();
+	if (!ret || !uhid->running) {
+		ret = -EIO;
+	} else if (ret < 0) {
+		ret = -ERESTARTSYS;
+	} else {
+		spin_lock_irqsave(&uhid->qlock, flags);
+		req = &uhid->report_buf.u.feature_answer;
+
+		if (req->err) {
+			ret = -EIO;
+		} else {
+			ret = 0;
+			len = min(count,
+				min_t(size_t, req->size, UHID_DATA_MAX));
+			memcpy(buf, req->data, len);
+		}
+
+		spin_unlock_irqrestore(&uhid->qlock, flags);
+	}
+
+	atomic_set(&uhid->report_done, 1);
+
+unlock:
+	mutex_unlock(&uhid->report_lock);
+	return ret ? ret : len;
+}
+
+static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
+			       unsigned char report_type)
+{
+	struct uhid_device *uhid = hid->driver_data;
+	__u8 rtype;
+	unsigned long flags;
+	struct uhid_event *ev;
+
+	switch (report_type) {
+	case HID_FEATURE_REPORT:
+		rtype = UHID_FEATURE_REPORT;
+		break;
+	case HID_OUTPUT_REPORT:
+		rtype = UHID_OUTPUT_REPORT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (count < 1 || count > UHID_DATA_MAX)
+		return -EINVAL;
+
+	ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+	if (!ev)
+		return -ENOMEM;
+
+	ev->type = UHID_OUTPUT;
+	ev->u.output.size = count;
+	ev->u.output.rtype = rtype;
+	memcpy(ev->u.output.data, buf, count);
+
+	spin_lock_irqsave(&uhid->qlock, flags);
+	uhid_queue(uhid, ev);
+	spin_unlock_irqrestore(&uhid->qlock, flags);
+
+	return count;
+}
+
+static struct hid_ll_driver uhid_hid_driver = {
+	.start = uhid_hid_start,
+	.stop = uhid_hid_stop,
+	.open = uhid_hid_open,
+	.close = uhid_hid_close,
+	.hidinput_input_event = uhid_hid_input,
+	.parse = uhid_hid_parse,
+};
+
+static int uhid_dev_create(struct uhid_device *uhid,
+			   const struct uhid_event *ev)
+{
+	struct hid_device *hid;
+	int ret;
+
+	if (uhid->running)
+		return -EALREADY;
+
+	uhid->rd_size = ev->u.create.rd_size;
+	if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE)
+		return -EINVAL;
+
+	uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL);
+	if (!uhid->rd_data)
+		return -ENOMEM;
+
+	if (copy_from_user(uhid->rd_data, ev->u.create.rd_data,
+			   uhid->rd_size)) {
+		ret = -EFAULT;
+		goto err_free;
+	}
+
+	hid = hid_allocate_device();
+	if (IS_ERR(hid)) {
+		ret = PTR_ERR(hid);
+		goto err_free;
+	}
+
+	strncpy(hid->name, ev->u.create.name, 127);
+	hid->name[127] = 0;
+	strncpy(hid->phys, ev->u.create.phys, 63);
+	hid->phys[63] = 0;
+	strncpy(hid->uniq, ev->u.create.uniq, 63);
+	hid->uniq[63] = 0;
+
+	hid->ll_driver = &uhid_hid_driver;
+	hid->hid_get_raw_report = uhid_hid_get_raw;
+	hid->hid_output_raw_report = uhid_hid_output_raw;
+	hid->bus = ev->u.create.bus;
+	hid->vendor = ev->u.create.vendor;
+	hid->product = ev->u.create.product;
+	hid->version = ev->u.create.version;
+	hid->country = ev->u.create.country;
+	hid->driver_data = uhid;
+	hid->dev.parent = uhid_misc.this_device;
+
+	uhid->hid = hid;
+	uhid->running = true;
+
+	ret = hid_add_device(hid);
+	if (ret) {
+		hid_err(hid, "Cannot register HID device\n");
+		goto err_hid;
+	}
+
+	return 0;
+
+err_hid:
+	hid_destroy_device(hid);
+	uhid->hid = NULL;
+	uhid->running = false;
+err_free:
+	kfree(uhid->rd_data);
+	return ret;
+}
+
+static int uhid_dev_destroy(struct uhid_device *uhid)
+{
+	if (!uhid->running)
+		return -EINVAL;
+
+	/* clear "running" before setting "report_done" */
+	uhid->running = false;
+	smp_wmb();
+	atomic_set(&uhid->report_done, 1);
+	wake_up_interruptible(&uhid->report_wait);
+
+	hid_destroy_device(uhid->hid);
+	kfree(uhid->rd_data);
+
+	return 0;
+}
+
+static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
+{
+	if (!uhid->running)
+		return -EINVAL;
+
+	hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data,
+			 min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
+
+	return 0;
+}
+
+static int uhid_dev_feature_answer(struct uhid_device *uhid,
+				   struct uhid_event *ev)
+{
+	unsigned long flags;
+
+	if (!uhid->running)
+		return -EINVAL;
+
+	spin_lock_irqsave(&uhid->qlock, flags);
+
+	/* id for old report; drop it silently */
+	if (atomic_read(&uhid->report_id) != ev->u.feature_answer.id)
+		goto unlock;
+	if (atomic_read(&uhid->report_done))
+		goto unlock;
+
+	memcpy(&uhid->report_buf, ev, sizeof(*ev));
+	atomic_set(&uhid->report_done, 1);
+	wake_up_interruptible(&uhid->report_wait);
+
+unlock:
+	spin_unlock_irqrestore(&uhid->qlock, flags);
+	return 0;
+}
+
 static int uhid_char_open(struct inode *inode, struct file *file)
 {
 	struct uhid_device *uhid;
@@ -84,8 +405,12 @@
 		return -ENOMEM;
 
 	mutex_init(&uhid->devlock);
+	mutex_init(&uhid->report_lock);
 	spin_lock_init(&uhid->qlock);
 	init_waitqueue_head(&uhid->waitq);
+	init_waitqueue_head(&uhid->report_wait);
+	uhid->running = false;
+	atomic_set(&uhid->report_done, 1);
 
 	file->private_data = uhid;
 	nonseekable_open(inode, file);
@@ -98,6 +423,8 @@
 	struct uhid_device *uhid = file->private_data;
 	unsigned int i;
 
+	uhid_dev_destroy(uhid);
+
 	for (i = 0; i < UHID_BUFSIZE; ++i)
 		kfree(uhid->outq[i]);
 
@@ -138,7 +465,7 @@
 		goto try_again;
 	} else {
 		len = min(count, sizeof(**uhid->outq));
-		if (copy_to_user(buffer, &uhid->outq[uhid->tail], len)) {
+		if (copy_to_user(buffer, uhid->outq[uhid->tail], len)) {
 			ret = -EFAULT;
 		} else {
 			kfree(uhid->outq[uhid->tail]);
@@ -177,6 +504,18 @@
 	}
 
 	switch (uhid->input_buf.type) {
+	case UHID_CREATE:
+		ret = uhid_dev_create(uhid, &uhid->input_buf);
+		break;
+	case UHID_DESTROY:
+		ret = uhid_dev_destroy(uhid);
+		break;
+	case UHID_INPUT:
+		ret = uhid_dev_input(uhid, &uhid->input_buf);
+		break;
+	case UHID_FEATURE_ANSWER:
+		ret = uhid_dev_feature_answer(uhid, &uhid->input_buf);
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 	}
diff --git a/drivers/iommu/msm_iommu_pagetable.c b/drivers/iommu/msm_iommu_pagetable.c
index 99841cd..b32bd26 100644
--- a/drivers/iommu/msm_iommu_pagetable.c
+++ b/drivers/iommu/msm_iommu_pagetable.c
@@ -357,14 +357,14 @@
 	return ret;
 }
 
-static unsigned int get_phys_addr(struct scatterlist *sg)
+static phys_addr_t get_phys_addr(struct scatterlist *sg)
 {
 	/*
 	 * Try sg_dma_address first so that we can
 	 * map carveout regions that do not have a
 	 * struct page associated with them.
 	 */
-	unsigned int pa = sg_dma_address(sg);
+	phys_addr_t pa = sg_dma_address(sg);
 	if (pa == 0)
 		pa = sg_phys(sg);
 	return pa;
@@ -380,7 +380,7 @@
 int msm_iommu_pagetable_map_range(struct iommu_pt *pt, unsigned int va,
 		       struct scatterlist *sg, unsigned int len, int prot)
 {
-	unsigned int pa;
+	phys_addr_t pa;
 	unsigned int offset = 0;
 	unsigned long *fl_pte;
 	unsigned long fl_offset;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 0641162..499b36c 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -95,6 +95,10 @@
 static int mpq_sdmx_proc_limit = MAX_TS_PACKETS_FOR_SDMX_PROCESS;
 module_param(mpq_sdmx_proc_limit, int, S_IRUGO | S_IWUSR);
 
+/* Debug flag for secure demux process */
+static int mpq_sdmx_debug;
+module_param(mpq_sdmx_debug, int, S_IRUGO | S_IWUSR);
+
 
 /**
  * Maximum allowed framing pattern size
@@ -4454,7 +4458,8 @@
 {
 	struct sdmx_filter_status *sts;
 	struct mpq_feed *mpq_feed;
-	u8 flags = 0;	/* MPQ_TODO: EOS handling */
+	/* MPQ_TODO: EOS handling */
+	u8 flags = mpq_sdmx_debug ? SDMX_INPUT_FLAG_DBG_ENABLE : 0;
 	u32 errors;
 	u32 status;
 	u32 prev_read_offset;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
index 5b91436..f9d85aa 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
@@ -52,7 +52,8 @@
 #define SDMX_INVALID_FILTER_HANDLE		(-1)
 
 /* Input flags */
-#define SDMX_INPUT_FLAG_EOS BIT(0)
+#define SDMX_INPUT_FLAG_EOS		BIT(0)
+#define SDMX_INPUT_FLAG_DBG_ENABLE	BIT(1)
 
 
 enum sdmx_buf_mode {
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index bbc18a4..1f3dc2f 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -3749,6 +3749,31 @@
 	return retval;
 }
 
+static int iris_fops_release(struct file *file)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	int retval = 0;
+
+	FMDBG("Enter %s ", __func__);
+	if (radio == NULL)
+		return -EINVAL;
+
+	if (radio->mode == FM_OFF)
+		return 0;
+
+	if (radio->mode == FM_RECV)
+		retval = hci_cmd(HCI_FM_DISABLE_RECV_CMD,
+						radio->fm_hdev);
+	else if (radio->mode == FM_TRANS)
+		retval = hci_cmd(HCI_FM_DISABLE_TRANS_CMD,
+					radio->fm_hdev);
+	if (retval < 0)
+		FMDERR("Err on disable FM %d\n", retval);
+
+	radio->mode = FM_OFF;
+	return retval;
+}
+
 static int iris_vidioc_dqbuf(struct file *file, void *priv,
 				struct v4l2_buffer *buffer)
 {
@@ -3843,6 +3868,7 @@
 static const struct v4l2_file_operations iris_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = video_ioctl2,
+	.release        = iris_fops_release,
 };
 
 static struct video_device iris_viddev_template = {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index be4315e..b395fc8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1907,6 +1907,14 @@
 	mmc_host_clk_release(host);
 }
 
+void mmc_power_cycle(struct mmc_host *host)
+{
+	mmc_power_off(host);
+	/* Wait at least 1 ms according to SD spec */
+	mmc_delay(1);
+	mmc_power_up(host);
+}
+
 /*
  * Cleanup when the last reference to the bus operator is dropped.
  */
@@ -2571,7 +2579,7 @@
 	if (!host->bus_ops->power_restore)
 		return -EOPNOTSUPP;
 
-	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+	if (!(host->caps & MMC_CAP_HW_RESET))
 		return -EOPNOTSUPP;
 
 	if (!card)
@@ -2583,7 +2591,10 @@
 	mmc_host_clk_hold(host);
 	mmc_set_clock(host, host->f_init);
 
-	host->ops->hw_reset(host);
+	if (mmc_card_sd(card))
+		mmc_power_cycle(host);
+	else if (host->ops->hw_reset)
+		host->ops->hw_reset(host);
 
 	/* If the reset has happened, then a status command will fail */
 	if (check) {
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 6fa51e0..153c821 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -48,6 +48,7 @@
 void mmc_set_timing(struct mmc_host *host, unsigned int timing);
 void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
 void mmc_power_off(struct mmc_host *host);
+void mmc_power_cycle(struct mmc_host *host);
 
 static inline void mmc_delay(unsigned int ms)
 {
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 550d90f..27e6c79 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/mmc/mmc.h>
 #include <mach/gpio.h>
+#include <mach/msm_bus.h>
 
 #include "sdhci-pltfm.h"
 
@@ -76,6 +77,10 @@
 #define CORE_CLK_PWRSAVE	(1 << 1)
 #define CORE_IO_PAD_PWR_SWITCH	(1 << 16)
 
+/* 8KB descriptors */
+#define SDHCI_MSM_MAX_SEGMENTS  (1 << 13)
+#define SDHCI_MSM_MMC_CLK_GATE_DELAY	200 /* msecs */
+
 static const u32 tuning_block_64[] = {
 	0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
 	0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
@@ -176,6 +181,12 @@
 	struct sdhci_msm_pad_data *pad_data;
 };
 
+struct sdhci_msm_bus_voting_data {
+	struct msm_bus_scale_pdata *bus_pdata;
+	unsigned int *bw_vecs;
+	unsigned int bw_vecs_size;
+};
+
 struct sdhci_msm_pltfm_data {
 	/* Supported UHS-I Modes */
 	u32 caps;
@@ -188,17 +199,32 @@
 	struct sdhci_msm_slot_reg_data *vreg_data;
 	bool nonremovable;
 	struct sdhci_msm_pin_data *pin_data;
+	u32 cpu_dma_latency_us;
+	struct sdhci_msm_bus_voting_data *voting_data;
+};
+
+struct sdhci_msm_bus_vote {
+	uint32_t client_handle;
+	uint32_t curr_vote;
+	int min_bw_vote;
+	int max_bw_vote;
+	bool is_max_bw_needed;
+	struct delayed_work vote_work;
+	struct device_attribute max_bus_bw;
 };
 
 struct sdhci_msm_host {
+	struct platform_device	*pdev;
 	void __iomem *core_mem;    /* MSM SDCC mapped address */
 	struct clk	 *clk;     /* main SD/MMC bus clock */
 	struct clk	 *pclk;    /* SDHC peripheral bus clock */
 	struct clk	 *bus_clk; /* SDHC bus voter clock */
+	atomic_t clks_on; /* Set if clocks are enabled */
 	struct sdhci_msm_pltfm_data *pdata;
 	struct mmc_host  *mmc;
 	struct sdhci_pltfm_data sdhci_msm_pdata;
 	wait_queue_head_t pwr_irq_wait;
+	struct sdhci_msm_bus_vote msm_bus_vote;
 };
 
 enum vdd_io_level {
@@ -1040,6 +1066,7 @@
 	struct sdhci_msm_pltfm_data *pdata = NULL;
 	struct device_node *np = dev->of_node;
 	u32 bus_width = 0;
+	u32 cpu_dma_latency;
 	int len, i;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -1058,6 +1085,10 @@
 		pdata->mmc_bus_width = 0;
 	}
 
+	if (!of_property_read_u32(np, "qcom,cpu-dma-latency-us",
+				&cpu_dma_latency))
+		pdata->cpu_dma_latency_us = cpu_dma_latency;
+
 	pdata->vreg_data = devm_kzalloc(dev, sizeof(struct
 						    sdhci_msm_slot_reg_data),
 					GFP_KERNEL);
@@ -1115,6 +1146,218 @@
 	return NULL;
 }
 
+/* Returns required bandwidth in Bytes per Sec */
+static unsigned int sdhci_get_bw_required(struct sdhci_host *host,
+					struct mmc_ios *ios)
+{
+	unsigned int bw;
+
+	bw = host->clock;
+	/*
+	 * For DDR mode, SDCC controller clock will be at
+	 * the double rate than the actual clock that goes to card.
+	 */
+	if (ios->bus_width == MMC_BUS_WIDTH_4)
+		bw /= 2;
+	else if (ios->bus_width == MMC_BUS_WIDTH_1)
+		bw /= 8;
+
+	return bw;
+}
+
+static int sdhci_msm_bus_get_vote_for_bw(struct sdhci_msm_host *host,
+					   unsigned int bw)
+{
+	unsigned int *table = host->pdata->voting_data->bw_vecs;
+	unsigned int size = host->pdata->voting_data->bw_vecs_size;
+	int i;
+
+	if (host->msm_bus_vote.is_max_bw_needed && bw)
+		return host->msm_bus_vote.max_bw_vote;
+
+	for (i = 0; i < size; i++) {
+		if (bw <= table[i])
+			break;
+	}
+
+	if (i && (i == size))
+		i--;
+
+	return i;
+}
+
+/*
+ * This function must be called with host lock acquired.
+ * Caller of this function should also ensure that msm bus client
+ * handle is not null.
+ */
+static inline int sdhci_msm_bus_set_vote(struct sdhci_msm_host *msm_host,
+					     int vote,
+					     unsigned long flags)
+{
+	struct sdhci_host *host =  platform_get_drvdata(msm_host->pdev);
+	int rc = 0;
+
+	if (vote != msm_host->msm_bus_vote.curr_vote) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		rc = msm_bus_scale_client_update_request(
+				msm_host->msm_bus_vote.client_handle, vote);
+		spin_lock_irqsave(&host->lock, flags);
+		if (rc) {
+			pr_err("%s: msm_bus_scale_client_update_request() failed: bus_client_handle=0x%x, vote=%d, err=%d\n",
+				mmc_hostname(host->mmc),
+				msm_host->msm_bus_vote.client_handle, vote, rc);
+			goto out;
+		}
+		msm_host->msm_bus_vote.curr_vote = vote;
+	}
+out:
+	return rc;
+}
+
+/*
+ * Internal work. Work to set 0 bandwidth for msm bus.
+ */
+static void sdhci_msm_bus_work(struct work_struct *work)
+{
+	struct sdhci_msm_host *msm_host;
+	struct sdhci_host *host;
+	unsigned long flags;
+
+	msm_host = container_of(work, struct sdhci_msm_host,
+				msm_bus_vote.vote_work.work);
+	host =  platform_get_drvdata(msm_host->pdev);
+
+	if (!msm_host->msm_bus_vote.client_handle)
+		return;
+
+	spin_lock_irqsave(&host->lock, flags);
+	/* don't vote for 0 bandwidth if any request is in progress */
+	if (!host->mrq) {
+		sdhci_msm_bus_set_vote(msm_host,
+			msm_host->msm_bus_vote.min_bw_vote, flags);
+	} else
+		pr_warning("%s: %s: Transfer in progress. skipping bus voting to 0 bandwidth\n",
+			   mmc_hostname(host->mmc), __func__);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*
+ * This function cancels any scheduled delayed work and sets the bus
+ * vote based on bw (bandwidth) argument.
+ */
+static void sdhci_msm_bus_cancel_work_and_set_vote(struct sdhci_host *host,
+						unsigned int bw)
+{
+	int vote;
+	unsigned long flags;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
+	cancel_delayed_work_sync(&msm_host->msm_bus_vote.vote_work);
+	spin_lock_irqsave(&host->lock, flags);
+	vote = sdhci_msm_bus_get_vote_for_bw(msm_host, bw);
+	sdhci_msm_bus_set_vote(msm_host, vote, flags);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+#define MSM_MMC_BUS_VOTING_DELAY	200 /* msecs */
+
+/* This function queues a work which will set the bandwidth requiement to 0 */
+static void sdhci_msm_bus_queue_work(struct sdhci_host *host)
+{
+	unsigned long flags;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (msm_host->msm_bus_vote.min_bw_vote !=
+		msm_host->msm_bus_vote.curr_vote)
+		queue_delayed_work(system_nrt_wq,
+				   &msm_host->msm_bus_vote.vote_work,
+				   msecs_to_jiffies(MSM_MMC_BUS_VOTING_DELAY));
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static int sdhci_msm_bus_register(struct sdhci_msm_host *host,
+				struct platform_device *pdev)
+{
+	int rc = 0;
+	struct msm_bus_scale_pdata *bus_pdata;
+
+	struct sdhci_msm_bus_voting_data *data;
+	struct device *dev = &pdev->dev;
+
+	data = devm_kzalloc(dev,
+		sizeof(struct sdhci_msm_bus_voting_data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&pdev->dev,
+			"%s: failed to allocate memory\n", __func__);
+		rc = -ENOMEM;
+		goto out;
+	}
+	data->bus_pdata = msm_bus_cl_get_pdata(pdev);
+	if (data->bus_pdata) {
+		rc = sdhci_msm_dt_get_array(dev, "qcom,bus-bw-vectors-bps",
+				&data->bw_vecs, &data->bw_vecs_size, 0);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"%s: Failed to get bus-bw-vectors-bps\n",
+				__func__);
+			goto out;
+		}
+		host->pdata->voting_data = data;
+	}
+	if (host->pdata->voting_data &&
+		host->pdata->voting_data->bus_pdata &&
+		host->pdata->voting_data->bw_vecs &&
+		host->pdata->voting_data->bw_vecs_size) {
+
+		bus_pdata = host->pdata->voting_data->bus_pdata;
+		host->msm_bus_vote.client_handle =
+				msm_bus_scale_register_client(bus_pdata);
+		if (!host->msm_bus_vote.client_handle) {
+			dev_err(&pdev->dev, "msm_bus_scale_register_client()\n");
+			rc = -EFAULT;
+			goto out;
+		}
+		/* cache the vote index for minimum and maximum bandwidth */
+		host->msm_bus_vote.min_bw_vote =
+				sdhci_msm_bus_get_vote_for_bw(host, 0);
+		host->msm_bus_vote.max_bw_vote =
+				sdhci_msm_bus_get_vote_for_bw(host, UINT_MAX);
+	} else {
+		devm_kfree(dev, data);
+	}
+
+out:
+	return rc;
+}
+
+static void sdhci_msm_bus_unregister(struct sdhci_msm_host *host)
+{
+	if (host->msm_bus_vote.client_handle)
+		msm_bus_scale_unregister_client(
+			host->msm_bus_vote.client_handle);
+}
+
+static void sdhci_msm_bus_voting(struct sdhci_host *host, u32 enable)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	struct mmc_ios *ios = &host->mmc->ios;
+	unsigned int bw;
+
+	if (!msm_host->msm_bus_vote.client_handle)
+		return;
+
+	bw = sdhci_get_bw_required(host, ios);
+	if (enable)
+		sdhci_msm_bus_cancel_work_and_set_vote(host, bw);
+	else
+		sdhci_msm_bus_queue_work(host);
+}
+
 /* Regulator utility functions */
 static int sdhci_msm_vreg_init_reg(struct device *dev,
 					struct sdhci_msm_reg_data *vreg)
@@ -1477,6 +1720,35 @@
 	else
 		return 0;
 }
+static ssize_t
+show_sdhci_max_bus_bw(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			msm_host->msm_bus_vote.is_max_bw_needed);
+}
+
+static ssize_t
+store_sdhci_max_bus_bw(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	uint32_t value;
+	unsigned long flags;
+
+	if (!kstrtou32(buf, 0, &value)) {
+		spin_lock_irqsave(&host->lock, flags);
+		msm_host->msm_bus_vote.is_max_bw_needed = !!value;
+		spin_unlock_irqrestore(&host->lock, flags);
+	}
+	return count;
+}
 
 static void sdhci_msm_check_power_status(struct sdhci_host *host)
 {
@@ -1511,10 +1783,79 @@
 			       host->ioaddr + CORE_DLL_CONFIG);
 }
 
+static unsigned int sdhci_msm_max_segs(void)
+{
+	return SDHCI_MSM_MAX_SEGMENTS;
+}
+
+void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	int rc;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	unsigned long flags;
+
+	if (clock && !atomic_read(&msm_host->clks_on)) {
+		pr_debug("%s: request to enable clock at rate %u\n",
+				mmc_hostname(host->mmc), clock);
+		if (!IS_ERR_OR_NULL(msm_host->bus_clk)) {
+			rc = clk_prepare_enable(msm_host->bus_clk);
+			if (rc) {
+				pr_err("%s: %s: failed to enable the bus-clock with error %d\n",
+					mmc_hostname(host->mmc), __func__, rc);
+				goto out;
+			}
+		}
+		if (!IS_ERR(msm_host->pclk)) {
+			rc = clk_prepare_enable(msm_host->pclk);
+			if (rc) {
+				pr_err("%s: %s: failed to enable the pclk with error %d\n",
+					mmc_hostname(host->mmc), __func__, rc);
+				goto disable_bus_clk;
+			}
+		}
+		rc = clk_prepare_enable(msm_host->clk);
+		if (rc) {
+			pr_err("%s: %s: failed to enable the host-clk with error %d\n",
+				mmc_hostname(host->mmc), __func__, rc);
+			goto disable_pclk;
+		}
+		mb();
+		atomic_set(&msm_host->clks_on, 1);
+
+	} else if (!clock && atomic_read(&msm_host->clks_on)) {
+		pr_debug("%s: request to disable clocks\n",
+				mmc_hostname(host->mmc));
+		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+		mb();
+		clk_disable_unprepare(msm_host->clk);
+		if (!IS_ERR(msm_host->pclk))
+			clk_disable_unprepare(msm_host->pclk);
+		if (!IS_ERR_OR_NULL(msm_host->bus_clk))
+			clk_disable_unprepare(msm_host->bus_clk);
+		atomic_set(&msm_host->clks_on, 0);
+	}
+	spin_lock_irqsave(&host->lock, flags);
+	host->clock = clock;
+	spin_unlock_irqrestore(&host->lock, flags);
+	goto out;
+disable_pclk:
+	if (!IS_ERR_OR_NULL(msm_host->pclk))
+		clk_disable_unprepare(msm_host->pclk);
+disable_bus_clk:
+	if (!IS_ERR_OR_NULL(msm_host->bus_clk))
+		clk_disable_unprepare(msm_host->bus_clk);
+out:
+	return;
+}
+
 static struct sdhci_ops sdhci_msm_ops = {
 	.check_power_status = sdhci_msm_check_power_status,
 	.execute_tuning = sdhci_msm_execute_tuning,
 	.toggle_cdr = sdhci_msm_toggle_cdr,
+	.get_max_segments = sdhci_msm_max_segs,
+	.set_clock = sdhci_msm_set_clock,
+	.platform_bus_voting = sdhci_msm_bus_voting,
 };
 
 static int __devinit sdhci_msm_probe(struct platform_device *pdev)
@@ -1546,6 +1887,7 @@
 	pltfm_host = sdhci_priv(host);
 	pltfm_host->priv = msm_host;
 	msm_host->mmc = host->mmc;
+	msm_host->pdev = pdev;
 
 	/* Extract platform data */
 	if (pdev->dev.of_node) {
@@ -1592,6 +1934,7 @@
 	if (ret)
 		goto pclk_disable;
 
+	atomic_set(&msm_host->clks_on, 1);
 	/* Setup regulators */
 	ret = sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, true);
 	if (ret) {
@@ -1662,6 +2005,9 @@
 	/* Enable pwr irq interrupts */
 	writel_relaxed(INT_MASK, (msm_host->core_mem + CORE_PWRCTL_MASK));
 
+	/* Set clock gating delay to be used when CONFIG_MMC_CLKGATE is set */
+	msm_host->mmc->clkgate_delay = SDHCI_MSM_MMC_CLK_GATE_DELAY;
+
 	/* Set host capabilities */
 	msm_host->mmc->caps |= msm_host->pdata->mmc_bus_width;
 	msm_host->mmc->caps |= msm_host->pdata->caps;
@@ -1681,6 +2027,7 @@
 					MMC_CAP_SET_XPC_300|
 					MMC_CAP_SET_XPC_330;
 
+	msm_host->mmc->caps |= MMC_CAP_HW_RESET;
 	msm_host->mmc->caps2 |= msm_host->pdata->caps2;
 	msm_host->mmc->caps2 |= MMC_CAP2_PACKED_WR;
 	msm_host->mmc->caps2 |= MMC_CAP2_PACKED_WR_CONTROL;
@@ -1694,10 +2041,20 @@
 	if (msm_host->pdata->nonremovable)
 		msm_host->mmc->caps |= MMC_CAP_NONREMOVABLE;
 
+	host->cpu_dma_latency_us = msm_host->pdata->cpu_dma_latency_us;
+
+	ret = sdhci_msm_bus_register(msm_host, pdev);
+	if (ret)
+		goto vreg_deinit;
+
+	if (msm_host->msm_bus_vote.client_handle)
+		INIT_DELAYED_WORK(&msm_host->msm_bus_vote.vote_work,
+				  sdhci_msm_bus_work);
+
 	ret = sdhci_add_host(host);
 	if (ret) {
 		dev_err(&pdev->dev, "Add host failed (%d)\n", ret);
-		goto vreg_deinit;
+		goto bus_unregister;
 	}
 
 	 /* Set core clk rate, optionally override from dts */
@@ -1709,12 +2066,24 @@
 		goto remove_host;
 	}
 
+	msm_host->msm_bus_vote.max_bus_bw.show = show_sdhci_max_bus_bw;
+	msm_host->msm_bus_vote.max_bus_bw.store = store_sdhci_max_bus_bw;
+	sysfs_attr_init(&msm_host->msm_bus_vote.max_bus_bw.attr);
+	msm_host->msm_bus_vote.max_bus_bw.attr.name = "max_bus_bw";
+	msm_host->msm_bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(&pdev->dev,
+			&msm_host->msm_bus_vote.max_bus_bw);
+	if (ret)
+		goto remove_host;
+
 	/* Successful initialization */
 	goto out;
 
 remove_host:
 	dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 	sdhci_remove_host(host, dead);
+bus_unregister:
+	sdhci_msm_bus_unregister(msm_host);
 vreg_deinit:
 	sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, false);
 clk_disable:
@@ -1743,17 +2112,18 @@
 			0xffffffff);
 
 	pr_debug("%s: %s\n", dev_name(&pdev->dev), __func__);
+	device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
 	sdhci_remove_host(host, dead);
 	sdhci_pltfm_free(pdev);
 	sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, false);
-	if (!IS_ERR(msm_host->clk))
-		clk_disable_unprepare(msm_host->clk);
-	if (!IS_ERR(msm_host->pclk))
-		clk_disable_unprepare(msm_host->pclk);
-	if (!IS_ERR_OR_NULL(msm_host->bus_clk))
-		clk_disable_unprepare(msm_host->bus_clk);
+
 	if (pdata->pin_data)
 		sdhci_msm_setup_pins(pdata, false);
+
+	if (msm_host->msm_bus_vote.client_handle) {
+		sdhci_msm_bus_cancel_work_and_set_vote(host, 0);
+		sdhci_msm_bus_unregister(msm_host);
+	}
 	return 0;
 }
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b9bd3a1..97c1013 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -483,9 +483,10 @@
 	 * The ADMA descriptor table is mapped further down as we
 	 * need to fill it with data first.
 	 */
-
 	host->align_addr = dma_map_single(mmc_dev(host->mmc),
-		host->align_buffer, 128 * 4, direction);
+					  host->align_buffer,
+					  host->align_buf_sz,
+					  direction);
 	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
 		goto fail;
 	BUG_ON(host->align_addr & 0x3);
@@ -544,7 +545,8 @@
 		 * If this triggers then we have a calculation bug
 		 * somewhere. :/
 		 */
-		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
+		WARN_ON((desc - host->adma_desc) > host->adma_desc_sz);
+
 	}
 
 	if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
@@ -569,11 +571,15 @@
 	 */
 	if (data->flags & MMC_DATA_WRITE) {
 		dma_sync_single_for_device(mmc_dev(host->mmc),
-			host->align_addr, 128 * 4, direction);
+					   host->align_addr,
+					   host->align_buf_sz,
+					   direction);
 	}
 
 	host->adma_addr = dma_map_single(mmc_dev(host->mmc),
-		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
+					 host->adma_desc,
+					 host->adma_desc_sz,
+					 DMA_TO_DEVICE);
 	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
 		goto unmap_entries;
 	BUG_ON(host->adma_addr & 0x3);
@@ -585,7 +591,7 @@
 		data->sg_len, direction);
 unmap_align:
 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
-		128 * 4, direction);
+			 host->align_buf_sz, direction);
 fail:
 	return -EINVAL;
 }
@@ -607,10 +613,10 @@
 		direction = DMA_TO_DEVICE;
 
 	dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
-		(128 * 2 + 1) * 4, DMA_TO_DEVICE);
+			 host->adma_desc_sz, DMA_TO_DEVICE);
 
 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
-		128 * 4, direction);
+			 host->align_buf_sz, direction);
 
 	if (data->flags & MMC_DATA_READ) {
 		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
@@ -721,7 +727,7 @@
 		return;
 
 	/* Sanity checks */
-	BUG_ON(data->blksz * data->blocks > 524288);
+	BUG_ON(data->blksz * data->blocks > host->mmc->max_req_size);
 	BUG_ON(data->blksz > host->mmc->max_blk_size);
 	BUG_ON(data->blocks > 65535);
 
@@ -962,6 +968,8 @@
 		tasklet_schedule(&host->finish_tasklet);
 }
 
+#define SDHCI_REQUEST_TIMEOUT	10 /* Default request timeout in seconds */
+
 static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	int flags;
@@ -995,7 +1003,11 @@
 		mdelay(1);
 	}
 
-	mod_timer(&host->timer, jiffies + 10 * HZ);
+	mod_timer(&host->timer, jiffies + SDHCI_REQUEST_TIMEOUT * HZ);
+
+	if (cmd->cmd_timeout_ms > SDHCI_REQUEST_TIMEOUT * MSEC_PER_SEC)
+		mod_timer(&host->timer, jiffies +
+				(msecs_to_jiffies(cmd->cmd_timeout_ms * 2)));
 
 	host->cmd = cmd;
 
@@ -1082,19 +1094,24 @@
 	int real_div = div, clk_mul = 1;
 	u16 clk = 0;
 	unsigned long timeout;
+	unsigned long flags;
 
+	spin_lock_irqsave(&host->lock, flags);
 	if (clock && clock == host->clock)
-		return;
+		goto ret;
 
 	host->mmc->actual_clock = 0;
 
 	if (host->ops->set_clock) {
+		spin_unlock_irqrestore(&host->lock, flags);
 		host->ops->set_clock(host, clock);
+		spin_lock_irqsave(&host->lock, flags);
 		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
-			return;
+			goto ret;
 	}
 
-	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+	if (host->clock)
+		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
 		goto out;
@@ -1170,7 +1187,7 @@
 			pr_err("%s: Internal clock never "
 				"stabilised.\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
-			return;
+			goto ret;
 		}
 		timeout--;
 		mdelay(1);
@@ -1181,6 +1198,8 @@
 
 out:
 	host->clock = clock;
+ret:
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
@@ -1259,6 +1278,32 @@
  *                                                                           *
 \*****************************************************************************/
 
+static int sdhci_enable(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (host->cpu_dma_latency_us)
+		pm_qos_update_request(&host->pm_qos_req_dma,
+					host->cpu_dma_latency_us);
+	if (host->ops->platform_bus_voting)
+		host->ops->platform_bus_voting(host, 1);
+
+	return 0;
+}
+
+static int sdhci_disable(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (host->cpu_dma_latency_us)
+		pm_qos_update_request(&host->pm_qos_req_dma,
+					PM_QOS_DEFAULT_VALUE);
+	if (host->ops->platform_bus_voting)
+		host->ops->platform_bus_voting(host, 0);
+
+	return 0;
+}
+
 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host;
@@ -1341,20 +1386,17 @@
 		return;
 	}
 
-	/*
-	 * Reset the chip on each power off.
-	 * Should clear out any weird states.
-	 */
-	if (ios->power_mode == MMC_POWER_OFF) {
-		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
-		sdhci_reinit(host);
+	if (ios->clock)
+		sdhci_set_clock(host, ios->clock);
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->clock) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
 	}
+	spin_unlock_irqrestore(&host->lock, flags);
 
-	sdhci_set_clock(host, ios->clock);
-
-	if (ios->power_mode == MMC_POWER_OFF)
-		vdd_bit = sdhci_set_power(host, -1);
-	else
+	if (ios->power_mode & (MMC_POWER_UP | MMC_POWER_ON))
 		vdd_bit = sdhci_set_power(host, ios->vdd);
 
 	if (host->vmmc && vdd_bit != -1)
@@ -1442,10 +1484,11 @@
 			/* Re-enable SD Clock */
 			clock = host->clock;
 			host->clock = 0;
+			spin_unlock_irqrestore(&host->lock, flags);
 			sdhci_set_clock(host, clock);
+			spin_lock_irqsave(&host->lock, flags);
 		}
 
-
 		/* Reset SD Clock Enable */
 		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
 		clk &= ~SDHCI_CLOCK_CARD_EN;
@@ -1475,10 +1518,13 @@
 		/* Re-enable SD Clock */
 		clock = host->clock;
 		host->clock = 0;
+		spin_unlock_irqrestore(&host->lock, flags);
 		sdhci_set_clock(host, clock);
+		spin_lock_irqsave(&host->lock, flags);
 	} else
 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
+	spin_unlock_irqrestore(&host->lock, flags);
 	/*
 	 * Some (ENE) controllers go apeshit on some ios operation,
 	 * signalling timeout and CRC errors even on CMD0. Resetting
@@ -1487,8 +1533,21 @@
 	if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
 		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
 
+	/*
+	 * Reset the chip on each power off.
+	 * Should clear out any weird states.
+	 */
+	if (ios->power_mode == MMC_POWER_OFF) {
+		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+		sdhci_reinit(host);
+		vdd_bit = sdhci_set_power(host, -1);
+		if (host->vmmc && vdd_bit != -1)
+			mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
+	}
+	if (!ios->clock)
+		sdhci_set_clock(host, ios->clock);
+
 	mmiowb();
-	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -1965,6 +2024,8 @@
 	.start_signal_voltage_switch	= sdhci_start_signal_voltage_switch,
 	.execute_tuning			= sdhci_execute_tuning,
 	.enable_preset_value		= sdhci_enable_preset_value,
+	.enable		= sdhci_enable,
+	.disable	= sdhci_disable,
 };
 
 /*****************************************************************************\
@@ -2042,7 +2103,9 @@
 			/* This is to force an update */
 			clock = host->clock;
 			host->clock = 0;
+			spin_unlock_irqrestore(&host->lock, flags);
 			sdhci_set_clock(host, clock);
+			spin_lock_irqsave(&host->lock, flags);
 		}
 
 		/* Spec says we should do both at the same time, but Ricoh
@@ -2715,11 +2778,23 @@
 	if (host->flags & SDHCI_USE_ADMA) {
 		/*
 		 * We need to allocate descriptors for all sg entries
-		 * (128) and potentially one alignment transfer for
+		 * (128/max_segments) and potentially one alignment transfer for
 		 * each of those entries.
 		 */
-		host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
-		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
+		if (host->ops->get_max_segments)
+			host->adma_max_desc = host->ops->get_max_segments();
+		else
+			host->adma_max_desc = 128;
+
+		host->adma_desc_sz = (host->adma_max_desc * 2 + 1) * 4;
+		host->align_buf_sz = host->adma_max_desc * 4;
+
+		pr_debug("%s: %s: dma_desc_size: %d\n",
+			mmc_hostname(host->mmc), __func__, host->adma_desc_sz);
+		host->adma_desc = kmalloc(host->adma_desc_sz,
+					  GFP_KERNEL);
+		host->align_buffer = kmalloc(host->align_buf_sz,
+					     GFP_KERNEL);
 		if (!host->adma_desc || !host->align_buffer) {
 			kfree(host->adma_desc);
 			kfree(host->align_buffer);
@@ -2973,17 +3048,21 @@
 	 * can do scatter/gather or not.
 	 */
 	if (host->flags & SDHCI_USE_ADMA)
-		mmc->max_segs = 128;
+		mmc->max_segs = host->adma_max_desc;
 	else if (host->flags & SDHCI_USE_SDMA)
 		mmc->max_segs = 1;
-	else /* PIO */
-		mmc->max_segs = 128;
+	else/* PIO */
+		mmc->max_segs = host->adma_max_desc;
 
 	/*
 	 * Maximum number of sectors in one transfer. Limited by DMA boundary
-	 * size (512KiB).
+	 * size (512KiB), unless specified by platform specific driver. Each
+	 * descriptor can transfer a maximum of 64KB.
 	 */
-	mmc->max_req_size = 524288;
+	if (host->ops->get_max_segments)
+		mmc->max_req_size = (host->adma_max_desc * 65536);
+	else
+		mmc->max_req_size = 524288;
 
 	/*
 	 * Maximum segment size. Could be one segment with the maximum number
@@ -3073,6 +3152,9 @@
 
 	mmiowb();
 
+	if (host->cpu_dma_latency_us)
+		pm_qos_add_request(&host->pm_qos_req_dma,
+				PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 	mmc_add_host(mmc);
 
 	pr_info("%s: SDHCI controller on %s [%s] using %s\n",
@@ -3120,6 +3202,8 @@
 
 	sdhci_disable_card_detection(host);
 
+	if (host->cpu_dma_latency_us)
+		pm_qos_remove_request(&host->pm_qos_req_dma);
 	mmc_remove_host(host->mmc);
 
 #ifdef SDHCI_USE_LEDS_CLASS
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 4f8d01d..49d7957 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -280,6 +280,8 @@
 	void	(*check_power_status)(struct sdhci_host *host);
 	int	(*execute_tuning)(struct sdhci_host *host, u32 opcode);
 	void	(*toggle_cdr)(struct sdhci_host *host, bool enable);
+	unsigned int	(*get_max_segments)(void);
+	void	(*platform_bus_voting)(struct sdhci_host *host, u32 enable);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index edf3a60..1142094 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -161,6 +161,7 @@
 	struct ipa_ioc_nat_alloc_mem nat_mem;
 	struct ipa_ioc_v4_nat_init nat_init;
 	struct ipa_ioc_v4_nat_del nat_del;
+	struct ipa_ioc_rm_dependency rm_depend;
 	size_t sz;
 
 	IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd));
@@ -593,6 +594,24 @@
 			break;
 		}
 		break;
+	case IPA_IOC_RM_ADD_DEPENDENCY:
+		if (copy_from_user((u8 *)&rm_depend, (u8 *)arg,
+				sizeof(struct ipa_ioc_rm_dependency))) {
+			retval = -EFAULT;
+			break;
+		}
+		retval = ipa_rm_add_dependency(rm_depend.resource_name,
+						rm_depend.depends_on_name);
+		break;
+	case IPA_IOC_RM_DEL_DEPENDENCY:
+		if (copy_from_user((u8 *)&rm_depend, (u8 *)arg,
+				sizeof(struct ipa_ioc_rm_dependency))) {
+			retval = -EFAULT;
+			break;
+		}
+		retval = ipa_rm_delete_dependency(rm_depend.resource_name,
+						rm_depend.depends_on_name);
+		break;
 	default:        /* redundant, as cmd was checked against MAXNR */
 		return -ENOTTY;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_rm.c b/drivers/platform/msm/ipa/ipa_rm.c
index 99b19cc..1fdd300 100644
--- a/drivers/platform/msm/ipa/ipa_rm.c
+++ b/drivers/platform/msm/ipa/ipa_rm.c
@@ -48,7 +48,7 @@
 	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 					  create_params->name,
 					  &resource) == 0) {
-		result = -EPERM;
+		result = -EEXIST;
 		goto bail;
 	}
 	result = ipa_rm_resource_create(create_params,
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index 3ba8e84..0a6771c 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -451,7 +451,7 @@
 			resource->name,
 			depends_on->peers_list,
 			depends_on->name))
-		return -EINVAL;
+		return -EEXIST;
 	ipa_rm_peers_list_add_peer(resource->peers_list, depends_on);
 	ipa_rm_peers_list_add_peer(depends_on->peers_list, resource);
 	spin_lock_irqsave(&resource->state_lock, flags);
@@ -507,7 +507,7 @@
 	unsigned long flags;
 	if (!resource || !depends_on)
 		return -EINVAL;
-	if (ipa_rm_peers_list_check_dependency(resource->peers_list,
+	if (!ipa_rm_peers_list_check_dependency(resource->peers_list,
 			resource->name,
 			depends_on->peers_list,
 			depends_on->name))
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index c841575..a9a850c 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -472,6 +472,63 @@
 	return 0;
 }
 
+static void usb_prod_notify_cb(void *user_data, enum ipa_rm_event event,
+	unsigned long data)
+{
+	switch (event) {
+	case IPA_RM_RESOURCE_GRANTED:
+		pr_debug("USB_PROD resource granted\n");
+		break;
+	case IPA_RM_RESOURCE_RELEASED:
+		pr_debug("USB_PROD resource released\n");
+		break;
+	default:
+		break;
+	}
+	return;
+}
+
+static int usb_cons_request_resource(void)
+{
+	pr_debug(": Requesting USB_CONS resource\n");
+	return 0;
+}
+
+static int usb_cons_release_resource(void)
+{
+	pr_debug(": Releasing USB_CONS resource\n");
+	return 0;
+}
+
+static void usb_bam_ipa_create_resources(void)
+{
+	struct ipa_rm_create_params usb_prod_create_params;
+	struct ipa_rm_create_params usb_cons_create_params;
+	int ret;
+
+	/* Create USB_PROD entity */
+	memset(&usb_prod_create_params, 0, sizeof(usb_prod_create_params));
+	usb_prod_create_params.name = IPA_RM_RESOURCE_USB_PROD;
+	usb_prod_create_params.reg_params.notify_cb = usb_prod_notify_cb;
+	usb_prod_create_params.reg_params.user_data = NULL;
+	ret = ipa_rm_create_resource(&usb_prod_create_params);
+	if (ret) {
+		pr_err("%s: Failed to create USB_PROD resource\n", __func__);
+		return;
+	}
+
+	/* Create USB_CONS entity */
+	memset(&usb_cons_create_params, 0, sizeof(usb_cons_create_params));
+	usb_cons_create_params.name = IPA_RM_RESOURCE_USB_CONS;
+	usb_cons_create_params.request_resource = usb_cons_request_resource;
+	usb_cons_create_params.release_resource = usb_cons_release_resource;
+	ret = ipa_rm_create_resource(&usb_cons_create_params);
+	if (ret) {
+		pr_err("%s: Failed to create USB_CONS resource\n", __func__);
+		return ;
+	}
+}
+
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	u8 idx = ipa_params->idx;
@@ -500,6 +557,8 @@
 
 	connection->idx = idx;
 
+	ipa_rm_request_resource(IPA_CLIENT_USB_PROD);
+
 	ret = connect_pipe_ipa(ipa_params);
 	if (ret) {
 		pr_err("%s: dst pipe connection failure\n", __func__);
@@ -779,6 +838,7 @@
 		}
 	}
 
+	ipa_rm_release_resource(IPA_CLIENT_USB_PROD);
 	return 0;
 
 }
@@ -925,14 +985,6 @@
 	return 0;
 }
 
-static u8 qdss_conn_num;
-
-u8 usb_bam_get_qdss_num(void)
-{
-	return qdss_conn_num;
-}
-EXPORT_SYMBOL(usb_bam_get_qdss_num);
-
 static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
 	struct platform_device *pdev)
 {
@@ -1055,11 +1107,6 @@
 			!strcmp(str, "usb-to-peri-qdss-hsusb") ||
 			!strcmp(str, "peri-to-usb-qdss-hsusb"))
 				conn_num = 0;
-		else if (!strcmp(str, "usb-to-qdss-hsusb") ||
-			!strcmp(str, "qdss-to-usb-hsusb")) {
-				conn_num = 1;
-				qdss_conn_num = 1;
-		}
 		else
 			goto err;
 
@@ -1094,8 +1141,6 @@
 	struct resource *res, *ram_resource;
 	int irq;
 
-	qdss_conn_num = 0;
-
 	res = platform_get_resource_byname(usb_bam_pdev, IORESOURCE_MEM,
 				bam_enable_strings[pdata->usb_active_bam]);
 	if (!res) {
@@ -1276,6 +1321,8 @@
 		return -ENOMEM;
 	}
 
+	usb_bam_ipa_create_resources();
+
 	return ret;
 }
 
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index a4742a5..ccede0c 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, 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
@@ -61,6 +61,49 @@
 	}
 }
 
+static void ci13xxx_msm_disconnect(void)
+{
+	struct ci13xxx *udc = _udc;
+	struct usb_phy *phy = udc->transceiver;
+
+	if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP))
+		usb_phy_io_write(phy,
+				ULPI_MISC_A_VBUSVLDEXT |
+				ULPI_MISC_A_VBUSVLDEXTSEL,
+				ULPI_CLR(ULPI_MISC_A));
+}
+
+static void ci13xxx_msm_connect(void)
+{
+	struct ci13xxx *udc = _udc;
+	struct usb_phy *phy = udc->transceiver;
+
+	if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) {
+		int	temp;
+
+		usb_phy_io_write(phy,
+			ULPI_MISC_A_VBUSVLDEXT |
+			ULPI_MISC_A_VBUSVLDEXTSEL,
+			ULPI_SET(ULPI_MISC_A));
+
+		temp = readl_relaxed(USB_GENCONFIG2);
+		temp |= GENCFG2_SESS_VLD_CTRL_EN;
+		writel_relaxed(temp, USB_GENCONFIG2);
+
+		temp = readl_relaxed(USB_USBCMD);
+		temp |= USBCMD_SESS_VLD_CTRL;
+		writel_relaxed(temp, USB_USBCMD);
+
+		/*
+		 * Add memory barrier as it is must to complete
+		 * above USB PHY and Link register writes before
+		 * moving ahead with USB peripheral mode enumeration,
+		 * otherwise USB peripheral mode may not work.
+		 */
+		mb();
+	}
+}
+
 static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
 {
 	struct device *dev = udc->gadget.dev.parent;
@@ -73,8 +116,13 @@
 		break;
 	case CI13XXX_CONTROLLER_DISCONNECT_EVENT:
 		dev_info(dev, "CI13XXX_CONTROLLER_DISCONNECT_EVENT received\n");
+		ci13xxx_msm_disconnect();
 		ci13xxx_msm_resume();
 		break;
+	case CI13XXX_CONTROLLER_CONNECT_EVENT:
+		dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
+		ci13xxx_msm_connect();
+		break;
 	case CI13XXX_CONTROLLER_SUSPEND_EVENT:
 		dev_info(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
 		ci13xxx_msm_suspend();
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 4254c3a..c02c8e4 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -379,6 +379,11 @@
 			hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
 
 		hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
+
+		if (udc->udc_driver->notify_event)
+			udc->udc_driver->notify_event(udc,
+				CI13XXX_CONTROLLER_CONNECT_EVENT);
+
 		/* interrupt, error, port change, reset, sleep/suspend */
 		hw_cwrite(CAP_USBINTR, ~0,
 			     USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
@@ -3267,12 +3272,8 @@
 	}
 	spin_unlock_irqrestore(udc->lock, flags);
 
-	if (is_active) {
+	if (is_active)
 		hw_device_state(udc->ep0out.qh.dma);
-		if (udc->udc_driver->notify_event)
-			udc->udc_driver->notify_event(udc,
-				CI13XXX_CONTROLLER_CONNECT_EVENT);
-	}
 	else
 		hw_device_state(0);
 
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index a2997e9..5a6faf2 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -667,7 +667,7 @@
 		if (ret)
 			pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
 				__func__, ret);
-		rmnet_bridge_disconnect();
+		teth_bridge_disconnect();
 	}
 }
 
@@ -707,8 +707,11 @@
 static void gbam2bam_connect_work(struct work_struct *w)
 {
 	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
+	struct teth_bridge_connect_params connect_params;
 	struct bam_ch_info *d = &port->data_ch;
 	u32 sps_params;
+	ipa_notify_cb usb_notify_cb;
+	void *priv;
 	int ret;
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM) {
@@ -720,6 +723,15 @@
 			return;
 		}
 	} else if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		ret = teth_bridge_init(&usb_notify_cb, &priv);
+		if (ret) {
+			pr_err("%s:teth_bridge_init() failed\n", __func__);
+			return;
+		}
+		d->ipa_params.notify = usb_notify_cb;
+		d->ipa_params.priv = priv;
+		d->ipa_params.ipa_ep_cfg.mode.mode = IPA_BASIC;
+
 		d->ipa_params.client = IPA_CLIENT_USB_CONS;
 		d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
 		ret = usb_bam_connect_ipa(&d->ipa_params);
@@ -731,18 +743,21 @@
 
 		d->ipa_params.client = IPA_CLIENT_USB_PROD;
 		d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
-		/* Currently only DMA mode is supported */
-		d->ipa_params.ipa_ep_cfg.mode.mode = IPA_DMA;
-		d->ipa_params.ipa_ep_cfg.mode.dst =
-				IPA_CLIENT_A2_TETHERED_CONS;
 		ret = usb_bam_connect_ipa(&d->ipa_params);
 		if (ret) {
 			pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
 				__func__, ret);
 			return;
 		}
-		rmnet_bridge_connect(d->ipa_params.prod_clnt_hdl,
-				d->ipa_params.cons_clnt_hdl, 0);
+
+		connect_params.ipa_usb_pipe_hdl = d->ipa_params.prod_clnt_hdl;
+		connect_params.usb_ipa_pipe_hdl = d->ipa_params.cons_clnt_hdl;
+		connect_params.tethering_mode = TETH_TETHERING_MODE_RMNET;
+		ret = teth_bridge_connect(&connect_params);
+		if (ret) {
+			pr_err("%s:teth_bridge_connect() failed\n", __func__);
+			return;
+		}
 	}
 
 	d->rx_req = usb_ep_alloc_request(port->port_usb->out, GFP_KERNEL);
diff --git a/drivers/usb/gadget/u_qdss.c b/drivers/usb/gadget/u_qdss.c
index 2931ace..028d5e6 100644
--- a/drivers/usb/gadget/u_qdss.c
+++ b/drivers/usb/gadget/u_qdss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, Code Aurora Forum. 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
@@ -15,6 +15,8 @@
 #include <linux/usb/msm_hsusb.h>
 #include <mach/usb_bam.h>
 
+#define BAM_CONNC_IDX 0 /* USB bam connection index */
+
 struct  usb_qdss_bam_connect_info {
 	u32 usb_bam_pipe_idx;
 	u32 peer_pipe_idx;
@@ -55,18 +57,17 @@
 		pr_err("send_sps_req: usb_ep_queue error\n");
 		return -EIO;
 	}
-
 	return 0;
 }
 
 int set_qdss_data_connection(struct usb_ep *data_ep, u8 data_addr, int enable)
 {
 	int res = 0;
-	u8 conn_num = usb_bam_get_qdss_num();
+
 	pr_debug("set_qdss_data_connection\n");
 
 	if (enable) {
-		res = usb_bam_connect(conn_num, NULL,
+		res = usb_bam_connect(BAM_CONNC_IDX, NULL,
 			&(bam_info.usb_bam_pipe_idx));
 		if (res) {
 			pr_err("usb_bam_connection error\n");
@@ -79,7 +80,7 @@
 			pr_err("qdss_data_connection: memory alloc failed\n");
 			return -ENOMEM;
 		}
-		get_bam2bam_connection_info(conn_num,
+		get_bam2bam_connection_info(BAM_CONNC_IDX,
 			PEER_PERIPHERAL_TO_USB, &bam_info.usb_bam_handle,
 			&bam_info.usb_bam_pipe_idx, &bam_info.peer_pipe_idx,
 			NULL, bam_info.data_fifo);
@@ -88,7 +89,7 @@
 			bam_info.data_fifo->size, bam_info.usb_bam_pipe_idx);
 	} else {
 		kfree(bam_info.data_fifo);
-		res = usb_bam_disconnect_pipe(conn_num);
+		res = usb_bam_disconnect_pipe(BAM_CONNC_IDX);
 		if (res) {
 			pr_err("usb_bam_disconnection error\n");
 			return res;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index f1f6962..ea5484b 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1776,6 +1776,9 @@
 
 	pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
 
+	pdata->pool_64_bit_align = of_property_read_bool(node,
+				"qcom,pool-64-bit-align");
+
 	return pdata;
 }
 
@@ -1853,6 +1856,7 @@
 	mehci->ehci.reset_sof_bug = 1;
 
 	mehci->ehci.resume_sof_bug = 1;
+	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 
 	if (pdata)
 		mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 07a232a..d238b4e2 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -30,7 +30,6 @@
 
 	hcd->has_tt = pdata->has_tt;
 	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
-	ehci->pool_64_bit_align = pdata->pool_64_bit_align;
 	ehci->big_endian_desc = pdata->big_endian_desc;
 	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 6ef4f3d..1c7d928 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3794,6 +3794,10 @@
 				"qcom,hsusb-otg-lpm-on-dev-suspend");
 	pdata->core_clk_always_on_workaround = of_property_read_bool(node,
 				"qcom,hsusb-otg-clk-always-on-workaround");
+	pdata->delay_lpm_on_disconnect = of_property_read_bool(node,
+				"qcom,hsusb-otg-delay-lpm");
+	pdata->dp_manual_pullup = of_property_read_bool(node,
+				"qcom,dp-manual-pullup");
 
 	return pdata;
 }
@@ -4073,6 +4077,8 @@
 	phy->otg->set_peripheral = msm_otg_set_peripheral;
 	phy->otg->start_hnp = msm_otg_start_hnp;
 	phy->otg->start_srp = msm_otg_start_srp;
+	if (pdata->dp_manual_pullup)
+		phy->flags |= ENABLE_DP_MANUAL_PULLUP;
 
 	ret = usb_set_transceiver(&motg->phy);
 	if (ret) {
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index bde7340..1c8664c 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -379,7 +379,7 @@
 		list_add_tail(&urb->urb_list, &portdata->in_urb_list);
 		spin_unlock_irqrestore(&portdata->in_lock, flags);
 
-		schedule_work(&portdata->in_work);
+		queue_work(system_nrt_wq, &portdata->in_work);
 
 		return;
 	}
@@ -498,7 +498,7 @@
 	port->throttle_req = false;
 	port->throttled = false;
 
-	schedule_work(&portdata->in_work);
+	queue_work(system_nrt_wq, &portdata->in_work);
 }
 EXPORT_SYMBOL(usb_wwan_unthrottle);
 
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 565d6b5..bd24575 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -16,6 +16,7 @@
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/mmc/host.h>
+#include <linux/pm_qos.h>
 
 struct sdhci_host {
 	/* Data set by hardware interface driver */
@@ -161,6 +162,10 @@
 	u8 *adma_desc;		/* ADMA descriptor table */
 	u8 *align_buffer;	/* Bounce buffer */
 
+	unsigned int adma_desc_sz; /* ADMA descriptor table size */
+	unsigned int align_buf_sz; /* Bounce buffer size */
+	unsigned int adma_max_desc; /* Max ADMA descriptos (max sg segments) */
+
 	dma_addr_t adma_addr;	/* Mapped ADMA descr. table */
 	dma_addr_t align_addr;	/* Mapped bounce buffer */
 
@@ -183,6 +188,9 @@
 #define SDHCI_TUNING_MODE_1	0
 	struct timer_list	tuning_timer;	/* Timer for tuning */
 
+	unsigned int cpu_dma_latency_us;
+	struct pm_qos_request pm_qos_req_dma;
+
 	unsigned long private[0] ____cacheline_aligned;
 };
 #endif /* LINUX_MMC_SDHCI_H */
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 2593154..ff22e12 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -40,6 +40,7 @@
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+	ION_ADSP_HEAP_ID = 22,
 	ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
 	ION_SF_HEAP_ID = 24,
 	ION_IOMMU_HEAP_ID = 25,
@@ -87,6 +88,7 @@
  */
 #define ION_HEAP(bit) (1 << (bit))
 
+#define ION_ADSP_HEAP_NAME	"adsp"
 #define ION_VMALLOC_HEAP_NAME	"vmalloc"
 #define ION_AUDIO_HEAP_NAME	"audio"
 #define ION_SF_HEAP_NAME	"sf"
diff --git a/include/linux/msm_ipa.h b/include/linux/msm_ipa.h
index 30bf4f2..b377a6c 100644
--- a/include/linux/msm_ipa.h
+++ b/include/linux/msm_ipa.h
@@ -49,7 +49,9 @@
 #define IPA_IOCTL_V4_DEL_NAT     26
 #define IPA_IOCTL_PULL_MSG       27
 #define IPA_IOCTL_GET_NAT_OFFSET 28
-#define IPA_IOCTL_MAX            29
+#define IPA_IOCTL_RM_ADD_DEPENDENCY 29
+#define IPA_IOCTL_RM_DEL_DEPENDENCY 30
+#define IPA_IOCTL_MAX            31
 
 /**
  * max size of the header to be inserted
@@ -173,6 +175,35 @@
 	WLAN_STA_DISCONNECT,
 };
 
+/**
+ * enum ipa_rm_resource_name - IPA RM clients identification names
+ *
+ * Add new mapping to ipa_rm_dep_prod_index() / ipa_rm_dep_cons_index()
+ * when adding new entry to this enum.
+ */
+enum ipa_rm_resource_name {
+	IPA_RM_RESOURCE_PROD = 0,
+	IPA_RM_RESOURCE_BRIDGE_PROD = IPA_RM_RESOURCE_PROD,
+	IPA_RM_RESOURCE_A2_PROD,
+	IPA_RM_RESOURCE_USB_PROD,
+	IPA_RM_RESOURCE_HSIC_PROD,
+	IPA_RM_RESOURCE_STD_ECM_PROD,
+	IPA_RM_RESOURCE_WWAN_0_PROD,
+	IPA_RM_RESOURCE_WWAN_1_PROD,
+	IPA_RM_RESOURCE_WWAN_2_PROD,
+	IPA_RM_RESOURCE_WWAN_3_PROD,
+	IPA_RM_RESOURCE_WWAN_4_PROD,
+	IPA_RM_RESOURCE_WWAN_5_PROD,
+	IPA_RM_RESOURCE_WWAN_6_PROD,
+	IPA_RM_RESOURCE_WWAN_7_PROD,
+	IPA_RM_RESOURCE_WLAN_PROD,
+	IPA_RM_RESOURCE_PROD_MAX,
+
+	IPA_RM_RESOURCE_A2_CONS = IPA_RM_RESOURCE_PROD_MAX,
+	IPA_RM_RESOURCE_USB_CONS,
+	IPA_RM_RESOURCE_HSIC_CONS,
+	IPA_RM_RESOURCE_MAX
+};
 
 /**
  * struct ipa_rule_attrib - attributes of a routing/filtering
@@ -682,6 +713,15 @@
 	uint8_t mac_addr[IPA_MAC_ADDR_SIZE];
 };
 
+/**
+ * struct ipa_ioc_rm_dependency - parameters for add/delete dependency
+ * @resource_name: name of dependent resource
+ * @depends_on_name: name of its dependency
+ */
+struct ipa_ioc_rm_dependency {
+	enum ipa_rm_resource_name resource_name;
+	enum ipa_rm_resource_name depends_on_name;
+};
 
 
 /**
@@ -768,6 +808,12 @@
 #define IPA_IOC_PULL_MSG _IOWR(IPA_IOC_MAGIC, \
 				IPA_IOCTL_PULL_MSG, \
 				struct ipa_msg_meta *)
+#define IPA_IOC_RM_ADD_DEPENDENCY _IOWR(IPA_IOC_MAGIC, \
+				IPA_IOCTL_RM_ADD_DEPENDENCY, \
+				struct ipa_ioc_rm_dependency *)
+#define IPA_IOC_RM_DEL_DEPENDENCY _IOWR(IPA_IOC_MAGIC, \
+				IPA_IOCTL_RM_DEL_DEPENDENCY, \
+				struct ipa_ioc_rm_dependency *)
 
 /*
  * unique magic number of the Tethering bridge ioctls
diff --git a/include/linux/uhid.h b/include/linux/uhid.h
index 16b786a..9c6974f 100644
--- a/include/linux/uhid.h
+++ b/include/linux/uhid.h
@@ -23,11 +23,82 @@
 #include <linux/types.h>
 
 enum uhid_event_type {
-	UHID_DUMMY,
+	UHID_CREATE,
+	UHID_DESTROY,
+	UHID_START,
+	UHID_STOP,
+	UHID_OPEN,
+	UHID_CLOSE,
+	UHID_OUTPUT,
+	UHID_OUTPUT_EV,
+	UHID_INPUT,
+	UHID_FEATURE,
+	UHID_FEATURE_ANSWER,
+};
+
+struct uhid_create_req {
+	__u8 name[128];
+	__u8 phys[64];
+	__u8 uniq[64];
+	__u8 __user *rd_data;
+	__u16 rd_size;
+
+	__u16 bus;
+	__u32 vendor;
+	__u32 product;
+	__u32 version;
+	__u32 country;
+} __attribute__((__packed__));
+
+#define UHID_DATA_MAX 4096
+
+enum uhid_report_type {
+	UHID_FEATURE_REPORT,
+	UHID_OUTPUT_REPORT,
+	UHID_INPUT_REPORT,
+};
+
+struct uhid_input_req {
+	__u8 data[UHID_DATA_MAX];
+	__u16 size;
+} __attribute__((__packed__));
+
+struct uhid_output_req {
+	__u8 data[UHID_DATA_MAX];
+	__u16 size;
+	__u8 rtype;
+} __attribute__((__packed__));
+
+struct uhid_output_ev_req {
+	__u16 type;
+	__u16 code;
+	__s32 value;
+} __attribute__((__packed__));
+
+struct uhid_feature_req {
+	__u32 id;
+	__u8 rnum;
+	__u8 rtype;
+} __attribute__((__packed__));
+
+struct uhid_feature_answer_req {
+	__u32 id;
+	__u16 err;
+	__u16 size;
+	__u8 data[UHID_DATA_MAX];
 };
 
 struct uhid_event {
 	__u32 type;
+
+	union {
+		struct uhid_create_req create;
+		struct uhid_input_req input;
+		struct uhid_output_req output;
+		struct uhid_output_ev_req output_ev;
+		struct uhid_feature_req feature;
+		struct uhid_feature_answer_req feature_answer;
+	} u;
 } __attribute__((__packed__));
 
 #endif /* __UHID_H_ */
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
index 4c1b7a0..1894f42 100644
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -41,7 +41,6 @@
 	unsigned	big_endian_mmio:1;
 	unsigned	port_power_on:1;
 	unsigned	port_power_off:1;
-	unsigned	pool_64_bit_align:1;
 };
 
 #endif /* __USB_CORE_EHCI_PDRIVER_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index e249953..c7c6b05 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -221,10 +221,14 @@
 	bool enable_lpm_on_dev_suspend;
 	bool core_clk_always_on_workaround;
 	bool delay_lpm_on_disconnect;
+	bool dp_manual_pullup;
 	struct msm_bus_scale_pdata *bus_scale_table;
 	const char *mhl_dev_name;
 };
 
+/* phy related flags */
+#define ENABLE_DP_MANUAL_PULLUP		BIT(0)
+
 /* Timeout (in msec) values (min - max) associated with OTG timers */
 
 #define TA_WAIT_VRISE	100	/* ( - 100)  */
@@ -407,6 +411,7 @@
 
 	/*standalone latency is required when HSCI is active*/
 	u32 standalone_latency;
+	bool pool_64_bit_align;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 900fc00..0d57d93 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -19,9 +19,12 @@
 #define USB_AHBBURST         (MSM_USB_BASE + 0x0090)
 #define USB_AHBMODE          (MSM_USB_BASE + 0x0098)
 #define USB_GENCONFIG        (MSM_USB_BASE + 0x009C)
+#define USB_GENCONFIG2       (MSM_USB_BASE + 0x00A0)
 #define USB_CAPLENGTH        (MSM_USB_BASE + 0x0100) /* 8 bit */
 #define USB_HS_GPTIMER_BASE  (MSM_USB_BASE + 0x80)
 
+#define GENCFG2_SESS_VLD_CTRL_EN	BIT(7)
+
 #define USB_USBCMD           (MSM_USB_BASE + 0x0140)
 #define USB_USBSTS           (MSM_USB_BASE + 0x0144)
 #define USB_PORTSC           (MSM_USB_BASE + 0x0184)
@@ -30,7 +33,9 @@
 #define USB_PHY_CTRL         (MSM_USB_BASE + 0x0240)
 #define USB_PHY_CTRL2        (MSM_USB_BASE + 0x0278)
 
-#define USBCMD_RESET   2
+#define USBCMD_RESET		2
+#define USBCMD_SESS_VLD_CTRL	BIT(25)
+
 #define USB_USBINTR          (MSM_USB_BASE + 0x0148)
 #define USB_FRINDEX          (MSM_USB_BASE + 0x014C)
 
@@ -57,6 +62,11 @@
 #define ULPI_PWR_CLK_MNG_REG	0x88
 #define OTG_COMP_DISABLE	BIT(0)
 
+/* ulpi manual dp registers */
+#define ULPI_MISC_A			0x96
+#define ULPI_MISC_A_VBUSVLDEXT		BIT(0)
+#define ULPI_MISC_A_VBUSVLDEXTSEL	BIT(1)
+
 #define PHY_ALT_INT		(1 << 28) /* PHY alternate interrupt */
 #define ASYNC_INTR_CTRL         (1 << 29) /* Enable async interrupt */
 #define ULPI_STP_CTRL           (1 << 30) /* Block communication with PHY */
diff --git a/samples/uhid/Makefile b/samples/uhid/Makefile
new file mode 100644
index 0000000..c95a696
--- /dev/null
+++ b/samples/uhid/Makefile
@@ -0,0 +1,10 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+# List of programs to build
+hostprogs-y := uhid-example
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
+
+HOSTCFLAGS_uhid-example.o += -I$(objtree)/usr/include
diff --git a/samples/uhid/uhid-example.c b/samples/uhid/uhid-example.c
new file mode 100644
index 0000000..03ce3c0
--- /dev/null
+++ b/samples/uhid/uhid-example.c
@@ -0,0 +1,381 @@
+/*
+ * UHID Example
+ *
+ * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using uhid.
+ */
+
+/* UHID Example
+ * This example emulates a basic 3 buttons mouse with wheel over UHID. Run this
+ * program as root and then use the following keys to control the mouse:
+ *   q: Quit the application
+ *   1: Toggle left button (down, up, ...)
+ *   2: Toggle right button
+ *   3: Toggle middle button
+ *   a: Move mouse left
+ *   d: Move mouse right
+ *   w: Move mouse up
+ *   s: Move mouse down
+ *   r: Move wheel up
+ *   f: Move wheel down
+ *
+ * If uhid is not available as /dev/uhid, then you can pass a different path as
+ * first argument.
+ * If <linux/uhid.h> is not installed in /usr, then compile this with:
+ *   gcc -o ./uhid_test -Wall -I./include ./samples/uhid/uhid-example.c
+ * And ignore the warning about kernel headers. However, it is recommended to
+ * use the installed uhid.h if available.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <linux/uhid.h>
+
+/* HID Report Desciptor
+ * We emulate a basic 3 button mouse with wheel. This is the report-descriptor
+ * as the kernel will parse it:
+ *
+ * INPUT[INPUT]
+ *   Field(0)
+ *     Physical(GenericDesktop.Pointer)
+ *     Application(GenericDesktop.Mouse)
+ *     Usage(3)
+ *       Button.0001
+ *       Button.0002
+ *       Button.0003
+ *     Logical Minimum(0)
+ *     Logical Maximum(1)
+ *     Report Size(1)
+ *     Report Count(3)
+ *     Report Offset(0)
+ *     Flags( Variable Absolute )
+ *   Field(1)
+ *     Physical(GenericDesktop.Pointer)
+ *     Application(GenericDesktop.Mouse)
+ *     Usage(3)
+ *       GenericDesktop.X
+ *       GenericDesktop.Y
+ *       GenericDesktop.Wheel
+ *     Logical Minimum(-128)
+ *     Logical Maximum(127)
+ *     Report Size(8)
+ *     Report Count(3)
+ *     Report Offset(8)
+ *     Flags( Variable Relative )
+ *
+ * This is the mapping that we expect:
+ *   Button.0001 ---> Key.LeftBtn
+ *   Button.0002 ---> Key.RightBtn
+ *   Button.0003 ---> Key.MiddleBtn
+ *   GenericDesktop.X ---> Relative.X
+ *   GenericDesktop.Y ---> Relative.Y
+ *   GenericDesktop.Wheel ---> Relative.Wheel
+ *
+ * This information can be verified by reading /sys/kernel/debug/hid/<dev>/rdesc
+ * This file should print the same information as showed above.
+ */
+
+static unsigned char rdesc[] = {
+	0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01,
+	0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
+	0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
+	0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
+	0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38,
+	0x15, 0x80, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03,
+	0x81, 0x06, 0xc0, 0xc0,
+};
+
+static int uhid_write(int fd, const struct uhid_event *ev)
+{
+	ssize_t ret;
+
+	ret = write(fd, ev, sizeof(*ev));
+	if (ret < 0) {
+		fprintf(stderr, "Cannot write to uhid: %m\n");
+		return -errno;
+	} else if (ret != sizeof(*ev)) {
+		fprintf(stderr, "Wrong size written to uhid: %ld != %lu\n",
+			ret, sizeof(ev));
+		return -EFAULT;
+	} else {
+		return 0;
+	}
+}
+
+static int create(int fd)
+{
+	struct uhid_event ev;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_CREATE;
+	strcpy((char*)ev.u.create.name, "test-uhid-device");
+	ev.u.create.rd_data = rdesc;
+	ev.u.create.rd_size = sizeof(rdesc);
+	ev.u.create.bus = BUS_USB;
+	ev.u.create.vendor = 0x15d9;
+	ev.u.create.product = 0x0a37;
+	ev.u.create.version = 0;
+	ev.u.create.country = 0;
+
+	return uhid_write(fd, &ev);
+}
+
+static void destroy(int fd)
+{
+	struct uhid_event ev;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_DESTROY;
+
+	uhid_write(fd, &ev);
+}
+
+static int event(int fd)
+{
+	struct uhid_event ev;
+	ssize_t ret;
+
+	memset(&ev, 0, sizeof(ev));
+	ret = read(fd, &ev, sizeof(ev));
+	if (ret == 0) {
+		fprintf(stderr, "Read HUP on uhid-cdev\n");
+		return -EFAULT;
+	} else if (ret < 0) {
+		fprintf(stderr, "Cannot read uhid-cdev: %m\n");
+		return -errno;
+	} else if (ret != sizeof(ev)) {
+		fprintf(stderr, "Invalid size read from uhid-dev: %ld != %lu\n",
+			ret, sizeof(ev));
+		return -EFAULT;
+	}
+
+	switch (ev.type) {
+	case UHID_START:
+		fprintf(stderr, "UHID_START from uhid-dev\n");
+		break;
+	case UHID_STOP:
+		fprintf(stderr, "UHID_STOP from uhid-dev\n");
+		break;
+	case UHID_OPEN:
+		fprintf(stderr, "UHID_OPEN from uhid-dev\n");
+		break;
+	case UHID_CLOSE:
+		fprintf(stderr, "UHID_CLOSE from uhid-dev\n");
+		break;
+	case UHID_OUTPUT:
+		fprintf(stderr, "UHID_OUTPUT from uhid-dev\n");
+		break;
+	case UHID_OUTPUT_EV:
+		fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev\n");
+		break;
+	default:
+		fprintf(stderr, "Invalid event from uhid-dev: %u\n", ev.type);
+	}
+
+	return 0;
+}
+
+static bool btn1_down;
+static bool btn2_down;
+static bool btn3_down;
+static signed char abs_hor;
+static signed char abs_ver;
+static signed char wheel;
+
+static int send_event(int fd)
+{
+	struct uhid_event ev;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_INPUT;
+	ev.u.input.size = 4;
+
+	if (btn1_down)
+		ev.u.input.data[0] |= 0x1;
+	if (btn2_down)
+		ev.u.input.data[0] |= 0x2;
+	if (btn3_down)
+		ev.u.input.data[0] |= 0x4;
+
+	ev.u.input.data[1] = abs_hor;
+	ev.u.input.data[2] = abs_ver;
+	ev.u.input.data[3] = wheel;
+
+	return uhid_write(fd, &ev);
+}
+
+static int keyboard(int fd)
+{
+	char buf[128];
+	ssize_t ret, i;
+
+	ret = read(STDIN_FILENO, buf, sizeof(buf));
+	if (ret == 0) {
+		fprintf(stderr, "Read HUP on stdin\n");
+		return -EFAULT;
+	} else if (ret < 0) {
+		fprintf(stderr, "Cannot read stdin: %m\n");
+		return -errno;
+	}
+
+	for (i = 0; i < ret; ++i) {
+		switch (buf[i]) {
+		case '1':
+			btn1_down = !btn1_down;
+			ret = send_event(fd);
+			if (ret)
+				return ret;
+			break;
+		case '2':
+			btn2_down = !btn2_down;
+			ret = send_event(fd);
+			if (ret)
+				return ret;
+			break;
+		case '3':
+			btn3_down = !btn3_down;
+			ret = send_event(fd);
+			if (ret)
+				return ret;
+			break;
+		case 'a':
+			abs_hor = -20;
+			ret = send_event(fd);
+			abs_hor = 0;
+			if (ret)
+				return ret;
+			break;
+		case 'd':
+			abs_hor = 20;
+			ret = send_event(fd);
+			abs_hor = 0;
+			if (ret)
+				return ret;
+			break;
+		case 'w':
+			abs_ver = -20;
+			ret = send_event(fd);
+			abs_ver = 0;
+			if (ret)
+				return ret;
+			break;
+		case 's':
+			abs_ver = 20;
+			ret = send_event(fd);
+			abs_ver = 0;
+			if (ret)
+				return ret;
+			break;
+		case 'r':
+			wheel = 1;
+			ret = send_event(fd);
+			wheel = 0;
+			if (ret)
+				return ret;
+			break;
+		case 'f':
+			wheel = -1;
+			ret = send_event(fd);
+			wheel = 0;
+			if (ret)
+				return ret;
+			break;
+		case 'q':
+			return -ECANCELED;
+		default:
+			fprintf(stderr, "Invalid input: %c\n", buf[i]);
+		}
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int fd;
+	const char *path = "/dev/uhid";
+	struct pollfd pfds[2];
+	int ret;
+	struct termios state;
+
+	ret = tcgetattr(STDIN_FILENO, &state);
+	if (ret) {
+		fprintf(stderr, "Cannot get tty state\n");
+	} else {
+		state.c_lflag &= ~ICANON;
+		state.c_cc[VMIN] = 1;
+		ret = tcsetattr(STDIN_FILENO, TCSANOW, &state);
+		if (ret)
+			fprintf(stderr, "Cannot set tty state\n");
+	}
+
+	if (argc >= 2) {
+		if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
+			fprintf(stderr, "Usage: %s [%s]\n", argv[0], path);
+			return EXIT_SUCCESS;
+		} else {
+			path = argv[1];
+		}
+	}
+
+	fprintf(stderr, "Open uhid-cdev %s\n", path);
+	fd = open(path, O_RDWR | O_CLOEXEC);
+	if (fd < 0) {
+		fprintf(stderr, "Cannot open uhid-cdev %s: %m\n", path);
+		return EXIT_FAILURE;
+	}
+
+	fprintf(stderr, "Create uhid device\n");
+	ret = create(fd);
+	if (ret) {
+		close(fd);
+		return EXIT_FAILURE;
+	}
+
+	pfds[0].fd = STDIN_FILENO;
+	pfds[0].events = POLLIN;
+	pfds[1].fd = fd;
+	pfds[1].events = POLLIN;
+
+	fprintf(stderr, "Press 'q' to quit...\n");
+	while (1) {
+		ret = poll(pfds, 2, -1);
+		if (ret < 0) {
+			fprintf(stderr, "Cannot poll for fds: %m\n");
+			break;
+		}
+		if (pfds[0].revents & POLLHUP) {
+			fprintf(stderr, "Received HUP on stdin\n");
+			break;
+		}
+		if (pfds[1].revents & POLLHUP) {
+			fprintf(stderr, "Received HUP on uhid-cdev\n");
+			break;
+		}
+
+		if (pfds[0].revents & POLLIN) {
+			ret = keyboard(fd);
+			if (ret)
+				break;
+		}
+		if (pfds[1].revents & POLLIN) {
+			ret = event(fd);
+			if (ret)
+				break;
+		}
+	}
+
+	fprintf(stderr, "Destroy uhid device\n");
+	destroy(fd);
+	return EXIT_SUCCESS;
+}