Merge "NFC: Add error handling to i2c access"
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index 2cb528c..6ef897a 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -39,7 +39,7 @@
         1200   -  WCN XO settling time (usec)
         1      -  WCN RPM power collapse enabled
         1      -  WCN standalone power collapse enabled
-
+        6      -  GPIO strength value
 
 Example:
 
@@ -64,5 +64,5 @@
         qcom,has-48mhz-xo;
         qcom,has-pronto-hw;
         qcom,wcnss-adc_tm = <&pm8226_adc_tm>;
-	qcom,wcnss-pm = <11 21 1200 1 1>;
+	qcom,wcnss-pm = <11 21 1200 1 1 6>;
     };
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 28b2195..6a71e36 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -23,7 +23,7 @@
 #include <linux/string.h>
 #include <linux/atomic.h>
 #include <linux/of.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm-generic/sizes.h>
 #include <mach/memory.h>
 #include <mach/msm_rtb.h>
@@ -38,18 +38,20 @@
 /* Write
  * 1) 3 bytes sentinel
  * 2) 1 bytes of log type
- * 3) 4 bytes of where the caller came from
+ * 3) 8 bytes of where the caller came from
  * 4) 4 bytes index
- * 4) 4 bytes extra data from the caller
+ * 4) 8 bytes extra data from the caller
+ * 5) 8 bytes for timestamp
  *
- * Total = 16 bytes.
+ * Total = 32 bytes.
  */
 struct msm_rtb_layout {
 	unsigned char sentinel[3];
 	unsigned char log_type;
-	void *caller;
-	unsigned long idx;
-	void *data;
+	uint32_t idx;
+	uint64_t caller;
+	uint64_t data;
+	uint64_t timestamp;
 } __attribute__ ((__packed__));
 
 
@@ -70,7 +72,7 @@
 static atomic_t msm_rtb_idx;
 #endif
 
-struct msm_rtb_state msm_rtb = {
+static struct msm_rtb_state msm_rtb = {
 	.filter = 1 << LOGK_LOGBUF,
 	.enabled = 1,
 };
@@ -109,24 +111,29 @@
 	start->log_type = (char)log_type;
 }
 
-static void msm_rtb_write_caller(void *caller, struct msm_rtb_layout *start)
+static void msm_rtb_write_caller(uint64_t caller, struct msm_rtb_layout *start)
 {
 	start->caller = caller;
 }
 
-static void msm_rtb_write_idx(unsigned long idx,
+static void msm_rtb_write_idx(uint32_t idx,
 				struct msm_rtb_layout *start)
 {
 	start->idx = idx;
 }
 
-static void msm_rtb_write_data(void *data, struct msm_rtb_layout *start)
+static void msm_rtb_write_data(uint64_t data, struct msm_rtb_layout *start)
 {
 	start->data = data;
 }
 
-static void uncached_logk_pc_idx(enum logk_event_type log_type, void *caller,
-				 void *data, int idx)
+static void msm_rtb_write_timestamp(struct msm_rtb_layout *start)
+{
+	start->timestamp = sched_clock();
+}
+
+static void uncached_logk_pc_idx(enum logk_event_type log_type, uint64_t caller,
+				 uint64_t data, int idx)
 {
 	struct msm_rtb_layout *start;
 
@@ -137,6 +144,7 @@
 	msm_rtb_write_caller(caller, start);
 	msm_rtb_write_idx(idx, start);
 	msm_rtb_write_data(data, start);
+	msm_rtb_write_timestamp(start);
 	mb();
 
 	return;
@@ -145,13 +153,10 @@
 static void uncached_logk_timestamp(int idx)
 {
 	unsigned long long timestamp;
-	void *timestamp_upper, *timestamp_lower;
 	timestamp = sched_clock();
-	timestamp_lower = (void *)lower_32_bits(timestamp);
-	timestamp_upper = (void *)upper_32_bits(timestamp);
-
-	uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC, timestamp_lower,
-			     timestamp_upper, idx);
+	uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC,
+			(uint64_t)lower_32_bits(timestamp),
+			(uint64_t)upper_32_bits(timestamp), idx);
 }
 
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
@@ -213,7 +218,8 @@
 
 	i = msm_rtb_get_idx();
 
-	uncached_logk_pc_idx(log_type, caller, data, i);
+	uncached_logk_pc_idx(log_type, (uint64_t)((unsigned long) caller),
+				(uint64_t)((unsigned long) data), i);
 
 	return 1;
 }
@@ -225,7 +231,7 @@
 }
 EXPORT_SYMBOL(uncached_logk);
 
-int msm_rtb_probe(struct platform_device *pdev)
+static int msm_rtb_probe(struct platform_device *pdev)
 {
 	struct msm_rtb_platform_data *d = pdev->dev.platform_data;
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
@@ -297,7 +303,6 @@
 	{.compatible = RTB_COMPAT_STR},
 	{},
 };
-EXPORT_COMPAT(RTB_COMPAT_STR);
 
 static struct platform_driver msm_rtb_driver = {
 	.driver         = {
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index bcab791..d79a169 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -221,13 +221,17 @@
 		struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch)
 {
 	unsigned int prev;
+	struct kgsl_device *device;
 	spin_lock(&drawctxt->lock);
 
 	if (kgsl_context_detached(&drawctxt->base) ||
 		drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
 		spin_unlock(&drawctxt->lock);
+		device = cmdbatch->device;
 		/* get rid of this cmdbatch since the context is bad */
+		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 		kgsl_cmdbatch_destroy(cmdbatch);
+		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 		return -EINVAL;
 	}
 
@@ -414,7 +418,10 @@
 		 */
 
 		if (cmdbatch->flags & KGSL_CONTEXT_SYNC) {
+			struct kgsl_device *device = cmdbatch->device;
+			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 			kgsl_cmdbatch_destroy(cmdbatch);
+			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 			continue;
 		}
 
@@ -931,11 +938,8 @@
 			drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
 			replay[i] = NULL;
 
-			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 			kgsl_cancel_events_timestamp(device, cmd->context,
 				cmd->timestamp);
-			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
-
 			kgsl_cmdbatch_destroy(cmd);
 		}
 	}
@@ -1084,7 +1088,8 @@
 		kgsl_device_snapshot(device, 1);
 	}
 
-	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+    kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+
 
 	/* Allocate memory to store the inflight commands */
 	replay = kzalloc(sizeof(*replay) * dispatcher->inflight, GFP_KERNEL);
@@ -1092,6 +1097,7 @@
 	if (replay == NULL) {
 		unsigned int ptr = dispatcher->head;
 
+		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 		/* Recovery failed - mark everybody guilty */
 		mark_guilty_context(device, 0);
 
@@ -1111,6 +1117,7 @@
 		 */
 
 		count = 0;
+		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 		goto replay;
 	}
 
@@ -1168,7 +1175,9 @@
 			cmdbatch->context->id, cmdbatch->timestamp);
 
 		mark_guilty_context(device, cmdbatch->context->id);
+		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 		adreno_drawctxt_invalidate(device, cmdbatch->context);
+		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 	}
 
 	/*
@@ -1277,7 +1286,9 @@
 	mark_guilty_context(device, cmdbatch->context->id);
 
 	/* Invalidate the context */
+	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 	adreno_drawctxt_invalidate(device, cmdbatch->context);
+	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 
 
 replay:
@@ -1296,8 +1307,10 @@
 	/* If adreno_reset() fails then what hope do we have for the future? */
 	BUG_ON(ret);
 
+	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 	/* Remove any pending command batches that have been invalidated */
 	remove_invalidated_cmdbatches(device, replay, count);
+	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 
 	/* Replay the pending command buffers */
 	for (i = 0; i < count; i++) {
@@ -1339,9 +1352,11 @@
 			/* Mark this context as guilty (failed recovery) */
 			mark_guilty_context(device, replay[i]->context->id);
 
+			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 			adreno_drawctxt_invalidate(device, replay[i]->context);
 			remove_invalidated_cmdbatches(device, &replay[i],
 				count - i);
+			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 		}
 	}
 
@@ -1449,8 +1464,10 @@
 			dispatcher->head = CMDQUEUE_NEXT(dispatcher->head,
 				ADRENO_DISPATCH_CMDQUEUE_SIZE);
 
+			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 			/* Destroy the retired command batch */
 			kgsl_cmdbatch_destroy(cmdbatch);
+			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 
 			/* Update the expire time for the next command batch */
 
@@ -1695,16 +1712,19 @@
 void adreno_dispatcher_close(struct adreno_device *adreno_dev)
 {
 	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
+	struct kgsl_device *device = &adreno_dev->dev;
 
 	mutex_lock(&dispatcher->mutex);
 	del_timer_sync(&dispatcher->timer);
 	del_timer_sync(&dispatcher->fault_timer);
 
+	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 	while (dispatcher->head != dispatcher->tail) {
 		kgsl_cmdbatch_destroy(dispatcher->cmdqueue[dispatcher->head]);
 		dispatcher->head = (dispatcher->head + 1)
 			% ADRENO_DISPATCH_CMDQUEUE_SIZE;
 	}
+	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 
 	mutex_unlock(&dispatcher->mutex);
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9adede8..a5b25a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1807,16 +1807,13 @@
 	list_for_each_entry_safe(event, tmp, &cancel_synclist, node) {
 
 		if (event->type == KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP) {
-			struct kgsl_device *device = cmdbatch->device;
 			/*
 			 * Timestamp events are guaranteed to signal
 			 * when canceled
 			 */
-			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
-			kgsl_cancel_event(device, event->context,
+			kgsl_cancel_event(cmdbatch->device, event->context,
 				event->timestamp, kgsl_cmdbatch_sync_func,
 				event);
-			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
 		} else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) {
 			/* Put events that are successfully canceled */
 			if (kgsl_sync_fence_async_cancel(event->handle))
@@ -2314,8 +2311,11 @@
 	 * -EPROTO is a "success" error - it just tells the user that the
 	 * context had previously faulted
 	 */
-	if (result && result != -EPROTO)
+	if (result && result != -EPROTO) {
+		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 		kgsl_cmdbatch_destroy(cmdbatch);
+		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+	}
 
 done:
 	kgsl_context_put(context);
@@ -2366,8 +2366,11 @@
 	 * -EPROTO is a "success" error - it just tells the user that the
 	 * context had previously faulted
 	 */
-	if (result && result != -EPROTO)
+	if (result && result != -EPROTO) {
+		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
 		kgsl_cmdbatch_destroy(cmdbatch);
+		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+	}
 
 done:
 	kgsl_context_put(context);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 4a4a88c..887bb72 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1948,13 +1948,13 @@
 		return;
 	}
 
-	pr_debug("%s:size=%d: <%d, %d, %d, %d, %d>\n", __func__,
+	pr_debug("%s:size=%d: <%d, %d, %d, %d, %d %d>\n", __func__,
 			prop_len, *payload, *(payload+1), *(payload+2),
-			*(payload+3), *(payload+4));
+			*(payload+3), *(payload+4), *(payload+5));
 
 	hdr = (struct smd_msg_hdr *)msg;
 	hdr->msg_type = WCNSS_PM_CONFIG_REQ;
-	hdr->msg_len = sizeof(struct smd_msg_hdr) + prop_len;
+	hdr->msg_len = sizeof(struct smd_msg_hdr) + (prop_len * sizeof(int));
 
 	rc = wcnss_smd_tx(msg, hdr->msg_len);
 	if (rc < 0)
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 592f70e..68c991c 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -653,14 +653,25 @@
 	return rc;
 }
 
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd = {
+	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
+	max_pktsize,
+};
+
 int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
 			struct dsi_buf *rp, int rlen)
 {
-	u32 *lp, data;
-	int i, off, cnt;
+	u32 *lp, data, *temp;
+	int i, j = 0, off, cnt;
 	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+	char reg[16];
+	int repeated_bytes = 0;
 
 	lp = (u32 *)rp->data;
+	temp = (u32 *)reg;
 	cnt = rlen;
 	cnt += 3;
 	cnt >>= 2;
@@ -668,16 +679,52 @@
 	if (cnt > 4)
 		cnt = 4; /* 4 x 32 bits registers only */
 
+	if (rlen == 4)
+		rp->read_cnt = 4;
+	else
+		rp->read_cnt = (max_pktsize[0] + 6);
+
+	if (rp->read_cnt > 16) {
+		int bytes_shifted, data_lost = 0, rem_header_bytes = 0;
+		/* Any data more than 16 bytes will be shifted out */
+		bytes_shifted = rp->read_cnt - rlen;
+		if (bytes_shifted >= 4)
+			data_lost = bytes_shifted - 4; /* remove dcs header */
+		else
+			rem_header_bytes = 4 - bytes_shifted; /* rem header */
+		/*
+		 * (rp->len - 4) -> current rx buffer data length.
+		 * If data_lost > 0, then ((rp->len - 4) - data_lost) will be
+		 * the number of repeating bytes.
+		 * If data_lost == 0, then ((rp->len - 4) + rem_header_bytes)
+		 * will be the number of bytes repeating in between rx buffer
+		 * and the current RDBK_DATA registers. We need to skip the
+		 * repeating bytes.
+		 */
+		repeated_bytes = (rp->len - 4) - data_lost + rem_header_bytes;
+	}
+
 	off = DSI_RDBK_DATA0;
 	off += ((cnt - 1) * 4);
 
 	for (i = 0; i < cnt; i++) {
 		data = (u32)MIPI_INP(ctrl_base + off);
-		*lp++ = ntohl(data); /* to network byte order */
+		/* to network byte order */
+		if (!repeated_bytes)
+			*lp++ = ntohl(data);
+		else
+			*temp++ = ntohl(data);
 		pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
 					 __func__, data, ntohl(data));
 		off -= 4;
-		rp->len += sizeof(*lp);
+		if (rlen == 4)
+			rp->len += sizeof(*lp);
+	}
+
+	/* Skip duplicates and append other data to the rx buffer */
+	if (repeated_bytes) {
+		for (i = repeated_bytes; i < 16; i++)
+			rp->data[j++] = reg[i];
 	}
 
 	return rlen;
@@ -769,14 +816,6 @@
 	return rc;
 }
 
-/* MIPI_DSI_MRPS, Maximum Return Packet Size */
-static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
-
-static struct dsi_cmd_desc pkt_size_cmd = {
-	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
-	max_pktsize,
-};
-
 static int msm_dsi_set_max_packet_size(struct mdss_dsi_ctrl_pdata *ctrl,
 						int size)
 {
@@ -814,10 +853,23 @@
 {
 	int rc;
 	struct dsi_buf *tp, *rp;
+	int rx_byte = 0;
+
+	if (rlen <= 2)
+		rx_byte = 4;
+	else
+		rx_byte = DSI_MAX_BYTES_TO_READ;
 
 	tp = &ctrl->tx_buf;
 	rp = &ctrl->rx_buf;
 	mdss_dsi_buf_init(rp);
+	rc = msm_dsi_set_max_packet_size(ctrl, rlen);
+	if (rc) {
+		pr_err("%s: dsi_set_max_pkt failed\n", __func__);
+		rc = -EINVAL;
+		goto dsi_cmds_rx_1_error;
+	}
+
 	mdss_dsi_buf_init(tp);
 
 	rc = mdss_dsi_cmd_dma_add(tp, cmds);
@@ -840,10 +892,12 @@
 	}
 
 	if (rlen <= DSI_SHORT_PKT_DATA_SIZE) {
-		msm_dsi_cmd_dma_rx(ctrl, rp, rlen);
+		msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
 	} else {
-		msm_dsi_cmd_dma_rx(ctrl, rp, rlen + DSI_HOST_HDR_SIZE);
-		rp->len = rlen + DSI_HOST_HDR_SIZE;
+		msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
+		rp->len = rx_byte - 2;	/*2 bytes for CRC*/
+		rp->len = rp->len - (DSI_MAX_PKT_SIZE - rlen);
+		rp->data = rp->start + (16 - (rlen + 2 + DSI_HOST_HDR_SIZE));
 	}
 	rc = msm_dsi_parse_rx_response(rp);
 
@@ -860,16 +914,15 @@
 {
 	int rc;
 	struct dsi_buf *tp, *rp;
-	int pkt_size, data_bytes, total;
+	int pkt_size, data_bytes, dlen, end = 0, diff;
 
 	tp = &ctrl->tx_buf;
 	rp = &ctrl->rx_buf;
 	mdss_dsi_buf_init(rp);
 	pkt_size = DSI_MAX_PKT_SIZE;
 	data_bytes = MDSS_DSI_LEN;
-	total = 0;
 
-	while (true) {
+	while (!end) {
 		rc = msm_dsi_set_max_packet_size(ctrl, pkt_size);
 		if (rc)
 			break;
@@ -880,7 +933,7 @@
 			pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
 			rc = -EINVAL;
 			break;
-	}
+		}
 		rc = msm_dsi_wait4video_eng_busy(ctrl);
 		if (rc) {
 			pr_err("%s: wait4video_eng failed\n", __func__);
@@ -894,19 +947,32 @@
 		}
 
 		msm_dsi_cmd_dma_rx(ctrl, rp, DSI_MAX_BYTES_TO_READ);
+		if (rlen <= data_bytes) {
+			diff = data_bytes - rlen;
+			end = 1;
+		} else {
+			diff = 0;
+			rlen -= data_bytes;
+		}
+		dlen = DSI_MAX_BYTES_TO_READ - 2;
+		dlen -= diff;
+		rp->data += dlen;
+		rp->len += dlen;
 
-		rp->data += DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
-		total += data_bytes;
-		if (total >= rlen)
-			break;
-
-		data_bytes = DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
-		pkt_size += data_bytes;
+		if (!end) {
+			data_bytes = 14;
+			if (rlen < data_bytes)
+				pkt_size += rlen;
+			else
+				pkt_size += data_bytes;
+		}
+		pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
+			 __func__, (int) (unsigned long) rp->data,
+			 rp->len, dlen, diff);
 	}
 
 	if (!rc) {
 		rp->data = rp->start;
-		rp->len = rlen + DSI_HOST_HDR_SIZE;
 		rc = msm_dsi_parse_rx_response(rp);
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.c b/drivers/video/msm/mdss/mdss_dsi_cmd.c
index 8fc1115c0..6d8f9e9 100644
--- a/drivers/video/msm/mdss/mdss_dsi_cmd.c
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -66,6 +66,7 @@
 		off = 8 - off;
 	dp->data += off;
 	dp->len = 0;
+	dp->read_cnt = 0;
 	return dp->data;
 }
 
@@ -86,6 +87,7 @@
 
 	dp->data = dp->start;
 	dp->len = 0;
+	dp->read_cnt = 0;
 	return size;
 }
 
@@ -574,6 +576,7 @@
 	/* strip out dcs type */
 	rp->data++;
 	rp->len = 1;
+	rp->read_cnt -= 3;
 	return rp->len;
 }
 
@@ -585,6 +588,7 @@
 	/* strip out dcs type */
 	rp->data++;
 	rp->len = 2;
+	rp->read_cnt -= 2;
 	return rp->len;
 }
 
@@ -593,6 +597,7 @@
 	/* strip out dcs header */
 	rp->data += 4;
 	rp->len -= 4;
+	rp->read_cnt -= 6;
 	return rp->len;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.h b/drivers/video/msm/mdss/mdss_dsi_cmd.h
index f806e78..3abe4fc 100644
--- a/drivers/video/msm/mdss/mdss_dsi_cmd.h
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -30,7 +30,7 @@
 
 #define MDSS_DSI_MRPS	0x04  /* Maximum Return Packet Size */
 
-#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
+#define MDSS_DSI_LEN 10 /* 4 x 4 - 4 - 2, bytes dcs header+crc-align  */
 
 struct dsi_buf {
 	u32 *hdr;	/* dsi host header */
@@ -40,6 +40,7 @@
 	char *data;	/* buffer */
 	int len;	/* data length */
 	dma_addr_t dmap; /* mapped dma addr */
+	int read_cnt;
 };
 
 /* dcs read/write */